numerals 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +149 -5
  3. data/lib/numerals/conversions/bigdecimal.rb +209 -9
  4. data/lib/numerals/conversions/context_conversion.rb +40 -0
  5. data/lib/numerals/conversions/float.rb +106 -71
  6. data/lib/numerals/conversions/flt.rb +115 -44
  7. data/lib/numerals/conversions/integer.rb +32 -3
  8. data/lib/numerals/conversions/rational.rb +27 -3
  9. data/lib/numerals/conversions.rb +74 -33
  10. data/lib/numerals/digits.rb +8 -5
  11. data/lib/numerals/format/base_scaler.rb +160 -0
  12. data/lib/numerals/format/exp_setter.rb +218 -0
  13. data/lib/numerals/format/format.rb +257 -0
  14. data/lib/numerals/format/input.rb +140 -0
  15. data/lib/numerals/format/mode.rb +157 -0
  16. data/lib/numerals/format/notation.rb +51 -0
  17. data/lib/numerals/format/notations/html.rb +53 -0
  18. data/lib/numerals/format/notations/latex.rb +48 -0
  19. data/lib/numerals/format/notations/text.rb +141 -0
  20. data/lib/numerals/format/output.rb +167 -0
  21. data/lib/numerals/format/symbols.rb +565 -0
  22. data/lib/numerals/format/text_parts.rb +35 -0
  23. data/lib/numerals/format.rb +25 -0
  24. data/lib/numerals/formatting_aspect.rb +36 -0
  25. data/lib/numerals/numeral.rb +34 -21
  26. data/lib/numerals/repeat_detector.rb +99 -0
  27. data/lib/numerals/rounding.rb +340 -181
  28. data/lib/numerals/version.rb +1 -1
  29. data/lib/numerals.rb +4 -2
  30. data/numerals.gemspec +1 -1
  31. data/test/test_base_scaler.rb +189 -0
  32. data/test/test_big_conversions.rb +105 -0
  33. data/test/test_digits_definition.rb +23 -28
  34. data/test/test_exp_setter.rb +732 -0
  35. data/test/test_float_conversions.rb +48 -30
  36. data/test/test_flt_conversions.rb +476 -80
  37. data/test/test_format.rb +124 -0
  38. data/test/test_format_input.rb +226 -0
  39. data/test/test_format_mode.rb +124 -0
  40. data/test/test_format_output.rb +789 -0
  41. data/test/test_integer_conversions.rb +22 -22
  42. data/test/test_numeral.rb +35 -0
  43. data/test/test_rational_conversions.rb +28 -28
  44. data/test/test_repeat_detector.rb +72 -0
  45. data/test/test_rounding.rb +158 -0
  46. data/test/test_symbols.rb +32 -0
  47. metadata +38 -5
  48. data/lib/numerals/formatting/digits_definition.rb +0 -75
@@ -0,0 +1,189 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+ require 'numerals'
4
+ include Numerals
5
+
6
+ class TestBaseScaler < Test::Unit::TestCase # < Minitest::Test
7
+
8
+ def digits_string(part, base)
9
+ part.map{|d| d.to_s(base)}.join
10
+ end
11
+
12
+ def check_scaler(scaler)
13
+ "#{digits_string(scaler.integer_part, scaler.scaled_base)}.#{digits_string(scaler.fractional_part, scaler.scaled_base)}<#{digits_string(scaler.repeat_part, scaler.scaled_base)}>E#{scaler.exponent}"
14
+ end
15
+
16
+ def test_special
17
+ numeral = Numeral[:nan]
18
+ setter = Format::ExpSetter[numeral]
19
+ scaler = Format::BaseScaler[setter, 4]
20
+
21
+ assert_equal setter.base, scaler.exponent_base
22
+ assert_equal setter.sign, scaler.sign
23
+ assert_equal setter.exponent, scaler.exponent
24
+ assert_equal setter.special?, scaler.special?
25
+ assert_equal setter.special, scaler.special
26
+ end
27
+
28
+
29
+ def test_non_repeat
30
+ digits = [1,1,0,0]*12 + [1,1,0,1,0]
31
+ numeral = Numeral[digits, base: 2, point: -3]
32
+ setter = Format::ExpSetter[numeral]
33
+ setter.integer_part_size = 1
34
+ scaler = Format::BaseScaler[setter, 4]
35
+ assert_equal "1.999999999999a<>E-4", check_scaler(scaler)
36
+ setter.integer_part_size = 2
37
+ scaler = Format::BaseScaler[setter, 4]
38
+ assert_equal "3.3333333333334<>E-5", check_scaler(scaler)
39
+ setter.integer_part_size = 0
40
+ scaler = Format::BaseScaler[setter, 4]
41
+ assert_equal ".ccccccccccccd<>E-3", check_scaler(scaler)
42
+ setter.integer_part_size = 3
43
+ scaler = Format::BaseScaler[setter, 4]
44
+ assert_equal "6.6666666666668<>E-6", check_scaler(scaler)
45
+ setter.integer_part_size = 4
46
+ scaler = Format::BaseScaler[setter, 4]
47
+ assert_equal "c.cccccccccccd<>E-7", check_scaler(scaler)
48
+
49
+ assert_equal 16, scaler.scaled_base
50
+ assert_equal setter.base, scaler.exponent_base
51
+ assert_equal setter.sign, scaler.sign
52
+ assert_equal setter.exponent, scaler.exponent
53
+ assert_equal setter.special?, scaler.special?
54
+ assert_equal setter.special, scaler.special
55
+ end
56
+
57
+ def test_approx
58
+ digits = [1,1,0,0]*12 + [1,1,0,1,0]
59
+ numeral = Numeral[digits, base: 2, point: -3, normalize: :approximate]
60
+ setter = Format::ExpSetter[numeral]
61
+ setter.integer_part_size = 1
62
+ scaler = Format::BaseScaler[setter, 4]
63
+ assert_equal "1.999999999999a<>E-4", check_scaler(scaler)
64
+ setter.integer_part_size = 2
65
+ scaler = Format::BaseScaler[setter, 4]
66
+ assert_equal "3.3333333333334<>E-5", check_scaler(scaler)
67
+ setter.integer_part_size = 0
68
+ scaler = Format::BaseScaler[setter, 4]
69
+ assert_equal ".ccccccccccccd0<>E-3", check_scaler(scaler)
70
+ setter.integer_part_size = 3
71
+ scaler = Format::BaseScaler[setter, 4]
72
+ assert_equal "6.6666666666668<>E-6", check_scaler(scaler)
73
+ setter.integer_part_size = 4
74
+ scaler = Format::BaseScaler[setter, 4]
75
+ assert_equal "c.cccccccccccd0<>E-7", check_scaler(scaler)
76
+
77
+ assert_equal 16, scaler.scaled_base
78
+ assert_equal setter.base, scaler.exponent_base
79
+ assert_equal setter.sign, scaler.sign
80
+ assert_equal setter.exponent, scaler.exponent
81
+ assert_equal setter.special?, scaler.special?
82
+ assert_equal setter.special, scaler.special
83
+ end
84
+
85
+ def test_repeating_4
86
+ # 4 repeating bits
87
+ numeral = Numeral[1, 0, 1, 1, 1, 0, base: 2, point: 2, repeat: 2, normalize: false]
88
+ setter = Format::ExpSetter[numeral]
89
+ setter.integer_part_size = 2
90
+ scaler = Format::BaseScaler[setter, 4]
91
+ assert_equal '2.<e>E0', check_scaler(scaler)
92
+ setter.integer_part_size = 1
93
+ scaler = Format::BaseScaler[setter, 4]
94
+ # Next: not 1.<7> because we weren't eager defining binary repetition
95
+ # (we could have defined repetition one bit earlier)
96
+ assert_equal '1.7<7>E1', check_scaler(scaler)
97
+
98
+ numeral = Numeral[1, 0, 1, 1, 1, base: 2, point: 2, repeat: 1]
99
+ setter = Format::ExpSetter[numeral]
100
+ setter.integer_part_size = 2
101
+ scaler = Format::BaseScaler[setter, 4]
102
+ assert_equal '2.<e>E0', check_scaler(scaler)
103
+ setter.integer_part_size = 1
104
+ scaler = Format::BaseScaler[setter, 4]
105
+ assert_equal '1.<7>E1', check_scaler(scaler)
106
+
107
+ numeral = Numeral[1, 0, 1, 1, 1, base: 2, point: 0, repeat: 1]
108
+ setter = Format::ExpSetter[numeral]
109
+ setter.integer_part_size = 2
110
+ scaler = Format::BaseScaler[setter, 4]
111
+ assert_equal '2.<e>E-2', check_scaler(scaler)
112
+ setter.integer_part_size = 1
113
+ scaler = Format::BaseScaler[setter, 4]
114
+ assert_equal '1.<7>E-1', check_scaler(scaler)
115
+
116
+ numeral = Numeral[1, 0, 0, 1, 1, 1, base: 2, point: 2, repeat: 2]
117
+ setter = Format::ExpSetter[numeral]
118
+ setter.integer_part_size = 2
119
+ scaler = Format::BaseScaler[setter, 4]
120
+ assert_equal '2.<7>E0', check_scaler(scaler)
121
+ setter.integer_part_size = 1
122
+ scaler = Format::BaseScaler[setter, 4]
123
+ assert_equal '1.3<b>E1', check_scaler(scaler)
124
+
125
+ numeral = Numeral[1, 0, 0, 1, 1, 1, base: 2, point: 3, repeat: 2]
126
+ setter = Format::ExpSetter[numeral]
127
+ setter.integer_part_size = 2
128
+ scaler = Format::BaseScaler[setter, 4]
129
+ assert_equal '2.<7>E1', check_scaler(scaler)
130
+ setter.integer_part_size = 1
131
+ scaler = Format::BaseScaler[setter, 4]
132
+ assert_equal '1.3<b>E2', check_scaler(scaler)
133
+
134
+ numeral = Numeral[1, 0, 0, 1, 1, 1, base: 2, point: 1, repeat: 2]
135
+ setter = Format::ExpSetter[numeral]
136
+ setter.integer_part_size = 2
137
+ scaler = Format::BaseScaler[setter, 4]
138
+ assert_equal '2.<7>E-1', check_scaler(scaler)
139
+ setter.integer_part_size = 1
140
+ scaler = Format::BaseScaler[setter, 4]
141
+ assert_equal '1.3<b>E0', check_scaler(scaler)
142
+
143
+ assert_equal 16, scaler.scaled_base
144
+ assert_equal setter.base, scaler.exponent_base
145
+ assert_equal setter.sign, scaler.sign
146
+ assert_equal setter.exponent, scaler.exponent
147
+ assert_equal setter.special?, scaler.special?
148
+ assert_equal setter.special, scaler.special
149
+ end
150
+
151
+ def test_repeating_2
152
+ # 2 repeating bits
153
+ numeral = Numeral[1, 0, 1, 1, 1, 0, base: 2, point: 2, repeat: 4]
154
+ setter = Format::ExpSetter[numeral]
155
+ setter.integer_part_size = 2
156
+ scaler = Format::BaseScaler[setter, 4]
157
+ assert_equal '2.e<a>E0', check_scaler(scaler)
158
+ setter.integer_part_size = 1
159
+ scaler = Format::BaseScaler[setter, 4]
160
+ assert_equal '1.7<5>E1', check_scaler(scaler)
161
+
162
+ assert_equal 16, scaler.scaled_base
163
+ assert_equal setter.base, scaler.exponent_base
164
+ assert_equal setter.sign, scaler.sign
165
+ assert_equal setter.exponent, scaler.exponent
166
+ assert_equal setter.special?, scaler.special?
167
+ assert_equal setter.special, scaler.special
168
+ end
169
+
170
+ def test_repeating_3
171
+ # 3 repeating bits
172
+ numeral = Numeral[1, 0, 1, 1, 1, 0, 1, base: 2, point: 2, repeat: 4]
173
+ setter = Format::ExpSetter[numeral]
174
+ setter.integer_part_size = 2
175
+ scaler = Format::BaseScaler[setter, 4]
176
+ assert_equal '2.e<db6>E0', check_scaler(scaler)
177
+ setter.integer_part_size = 1
178
+ scaler = Format::BaseScaler[setter, 4]
179
+ assert_equal '1.7<6db>E1', check_scaler(scaler)
180
+
181
+ assert_equal 16, scaler.scaled_base
182
+ assert_equal setter.base, scaler.exponent_base
183
+ assert_equal setter.sign, scaler.sign
184
+ assert_equal setter.exponent, scaler.exponent
185
+ assert_equal setter.special?, scaler.special?
186
+ assert_equal setter.special, scaler.special
187
+ end
188
+
189
+ end
@@ -0,0 +1,105 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+ require 'numerals'
4
+ require 'flt/bigdecimal'
5
+ include Numerals
6
+
7
+ class TestBigConversions < Test::Unit::TestCase # < Minitest::Test
8
+
9
+
10
+ def test_write_special
11
+ context = BigDecimal.context
12
+ type = BigDecimal
13
+
14
+ assert_equal Numeral.nan, Conversions.write(context.nan)
15
+ assert_equal Numeral.nan, Conversions.write(context.nan, rounding: Rounding[:short, base: 2])
16
+ assert_equal Numeral.nan, Conversions.write(context.nan, rounding: Rounding[:short, base: 10])
17
+ assert_equal Numeral.nan, Conversions.write(context.nan, rounding: Rounding[precision: 10, base: 10])
18
+ assert_equal Numeral.nan, Conversions.write(context.nan)
19
+
20
+ assert_equal Numeral.infinity, Conversions.write(context.infinity)
21
+ assert_equal Numeral.infinity, Conversions.write(context.infinity, rounding: Rounding[:short, base: 2])
22
+ assert_equal Numeral.infinity, Conversions.write(context.infinity, rounding: Rounding[:short, base: 10])
23
+ assert_equal Numeral.infinity, Conversions.write(context.infinity, rounding: Rounding[precision: 10, base: 10])
24
+ assert_equal Numeral.infinity, Conversions.write(context.infinity)
25
+
26
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1))
27
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1), rounding: Rounding[:short, base: 2])
28
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1), rounding: Rounding[:short, base: 10])
29
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1), rounding: Rounding[precision: 10, base: 10])
30
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1))
31
+ end
32
+
33
+ def test_read_special
34
+ context = BigDecimal.context
35
+ type = BigDecimal
36
+
37
+ assert Conversions.read(Numeral.nan, type: type).nan?
38
+ assert_equal context.infinity, Conversions.read(Numeral.infinity, type: type)
39
+ assert_equal context.infinity(-1), Conversions.read(Numeral.infinity(-1), type: type)
40
+ end
41
+
42
+ def test_write_exact
43
+ l = BigDecimal.limit(9)
44
+
45
+ assert_equal Numeral[1,2,3,4,5,6,7,0,0, point: 3, normalize: :approximate],
46
+ Conversions.write(BigDecimal('123.4567'))
47
+ assert_equal Numeral[1,2,3,4,5,6,7,0,0, point: 3, sign: -1, normalize: :approximate],
48
+ Conversions.write(BigDecimal('-123.4567'))
49
+
50
+ BigDecimal.limit 0
51
+
52
+ assert_equal Numeral[1,2,3,4,5,6,7, point: 3],
53
+ Conversions.write(BigDecimal('123.4567'))
54
+ assert_equal Numeral[1,2,3,4,5,6,7, point: 3, sign: -1],
55
+ Conversions.write(BigDecimal('-123.4567'))
56
+
57
+ BigDecimal.limit l
58
+ end
59
+
60
+ def test_write_simple
61
+ l = BigDecimal.limit(9)
62
+
63
+ assert_equal Numeral[1,2,3,4,5,6,7, point: 3],
64
+ Conversions.write(BigDecimal('123.4567'))
65
+ assert_equal Numeral[1,2,3,4,5,6,7, point: 3, sign: -1],
66
+ Conversions.write(BigDecimal('-123.4567'))
67
+
68
+ BigDecimal.limit 0
69
+
70
+ assert_equal Numeral[1,2,3,4,5,6,7, point: 3],
71
+ Conversions.write(BigDecimal('123.4567'))
72
+ assert_equal Numeral[1,2,3,4,5,6,7, point: 3, sign: -1],
73
+ Conversions.write(BigDecimal('-123.4567'))
74
+
75
+ BigDecimal.limit l
76
+ end
77
+
78
+ def test_read
79
+
80
+ assert_equal BigDecimal('123.4567'),
81
+ Conversions.read(
82
+ Numeral[1,2,3,4,5,6,7, point: 3], type: BigDecimal
83
+ )
84
+ assert_equal BigDecimal('123.4567'),
85
+ Conversions.read(
86
+ Numeral[1,2,3,4,5,6,7, point: 3, normalize: :approximate],
87
+ type: BigDecimal
88
+ )
89
+ end
90
+
91
+ def test_type_parameters
92
+ c = Conversions[BigDecimal, input_rounding: :down]
93
+ assert_equal Rounding[:down], c.input_rounding
94
+ c = Conversions[BigDecimal, input_rounding: :half_even]
95
+ assert_equal Rounding[:half_even], c.input_rounding
96
+
97
+ c = Conversions[BigDecimal, input_rounding: :half_even]
98
+ assert_equal Rounding[:half_even], c.input_rounding
99
+ c = Conversions[BigDecimal, input_rounding: Rounding[:half_up, precision: 7]]
100
+ assert_equal Rounding[:half_up, precision: 7], c.input_rounding
101
+ c = Conversions[BigDecimal, input_rounding: Rounding[:half_up, precision: 7, base: 3]]
102
+ assert_equal Rounding[:half_up], c.input_rounding
103
+ end
104
+
105
+ end
@@ -15,23 +15,19 @@ class TestDigitsDefinition < Test::Unit::TestCase
15
15
  end
16
16
 
17
17
  def define_from_digits(b)
18
- DigitsDefinition[default_digits(b)]
19
- end
20
-
21
- def define_from_base(b)
22
- DigitsDefinition[base: b]
18
+ Format::Symbols::Digits[default_digits(b)]
23
19
  end
24
20
 
25
21
  def check_base(b, digits)
26
- assert_equal b, digits.radix
22
+ assert_equal b, digits.max_base
27
23
  (0...b).each do |digit_value|
28
- digit_char = default_digits(b)[digit_value]
29
- assert_equal digit_char, digits.digit_char(digit_value)
30
- assert_equal digit_value, digits.digit_value(digit_char)
31
- assert digits.is_digit?(digit_char)
24
+ digit_symbol = default_digits(b)[digit_value]
25
+ assert_equal digit_symbol, digits.digit_symbol(digit_value)
26
+ assert_equal digit_value, digits.digit_value(digit_symbol)
27
+ assert digits.is_digit?(digit_symbol)
32
28
  end
33
29
  [-10,-5,-2,-1,b,b+1,b+2,b+10].each do |invalid_digit_value|
34
- assert_nil digits.digit_char(invalid_digit_value)
30
+ assert_nil digits.digit_symbol(invalid_digit_value)
35
31
  end
36
32
  invalid_chars = %w(- / & ñ)
37
33
  if b < MAX_TEST_BASE
@@ -48,12 +44,11 @@ class TestDigitsDefinition < Test::Unit::TestCase
48
44
  def test_digits_definition
49
45
  (0..MAX_TEST_BASE).each do |base|
50
46
  check_base base, define_from_digits(base)
51
- check_base base, define_from_base(base)
52
47
  end
53
48
  end
54
49
 
55
50
  def test_digits_case
56
- uppercase_digits = DigitsDefinition[base: 16, downcase: false]
51
+ uppercase_digits = Format::Symbols::Digits[uppercase: true]
57
52
 
58
53
  assert_equal 10, uppercase_digits.digit_value('A')
59
54
  assert_equal 11, uppercase_digits.digit_value('B')
@@ -63,11 +58,11 @@ class TestDigitsDefinition < Test::Unit::TestCase
63
58
  assert_equal 11, uppercase_digits.digit_value('b')
64
59
  assert_equal 15, uppercase_digits.digit_value('f')
65
60
 
66
- assert_equal 'A', uppercase_digits.digit_char(10)
67
- assert_equal 'B', uppercase_digits.digit_char(11)
68
- assert_equal 'F', uppercase_digits.digit_char(15)
61
+ assert_equal 'A', uppercase_digits.digit_symbol(10)
62
+ assert_equal 'B', uppercase_digits.digit_symbol(11)
63
+ assert_equal 'F', uppercase_digits.digit_symbol(15)
69
64
 
70
- downcase_digits = DigitsDefinition[base: 16, downcase: true]
65
+ downcase_digits = Format::Symbols::Digits[lowercase: true]
71
66
 
72
67
  assert_equal 10, downcase_digits.digit_value('A')
73
68
  assert_equal 11, downcase_digits.digit_value('B')
@@ -77,12 +72,12 @@ class TestDigitsDefinition < Test::Unit::TestCase
77
72
  assert_equal 11, downcase_digits.digit_value('b')
78
73
  assert_equal 15, downcase_digits.digit_value('f')
79
74
 
80
- assert_equal 'a', downcase_digits.digit_char(10)
81
- assert_equal 'b', downcase_digits.digit_char(11)
82
- assert_equal 'f', downcase_digits.digit_char(15)
75
+ assert_equal 'a', downcase_digits.digit_symbol(10)
76
+ assert_equal 'b', downcase_digits.digit_symbol(11)
77
+ assert_equal 'f', downcase_digits.digit_symbol(15)
83
78
 
84
79
 
85
- cs_uppercase_digits = DigitsDefinition[base: 16, downcase: false, case_sensitive: true]
80
+ cs_uppercase_digits = Format::Symbols::Digits[uppercase: true, case_sensitive: true]
86
81
 
87
82
  assert_equal 10, cs_uppercase_digits.digit_value('A')
88
83
  assert_equal 11, cs_uppercase_digits.digit_value('B')
@@ -90,11 +85,11 @@ class TestDigitsDefinition < Test::Unit::TestCase
90
85
  assert_nil cs_uppercase_digits.digit_value('a')
91
86
  assert_nil cs_uppercase_digits.digit_value('b')
92
87
  assert_nil cs_uppercase_digits.digit_value('f')
93
- assert_equal 'A', cs_uppercase_digits.digit_char(10)
94
- assert_equal 'B', cs_uppercase_digits.digit_char(11)
95
- assert_equal 'F', cs_uppercase_digits.digit_char(15)
88
+ assert_equal 'A', cs_uppercase_digits.digit_symbol(10)
89
+ assert_equal 'B', cs_uppercase_digits.digit_symbol(11)
90
+ assert_equal 'F', cs_uppercase_digits.digit_symbol(15)
96
91
 
97
- cs_downcase_digits = DigitsDefinition[base: 16, downcase: true, case_sensitive: true]
92
+ cs_downcase_digits = Format::Symbols::Digits[lowercase: true, case_sensitive: true]
98
93
 
99
94
  assert_equal 10, cs_downcase_digits.digit_value('a')
100
95
  assert_equal 11, cs_downcase_digits.digit_value('b')
@@ -102,9 +97,9 @@ class TestDigitsDefinition < Test::Unit::TestCase
102
97
  assert_nil cs_downcase_digits.digit_value('A')
103
98
  assert_nil cs_downcase_digits.digit_value('B')
104
99
  assert_nil cs_downcase_digits.digit_value('F')
105
- assert_equal 'a', cs_downcase_digits.digit_char(10)
106
- assert_equal 'b', cs_downcase_digits.digit_char(11)
107
- assert_equal 'f', cs_downcase_digits.digit_char(15)
100
+ assert_equal 'a', cs_downcase_digits.digit_symbol(10)
101
+ assert_equal 'b', cs_downcase_digits.digit_symbol(11)
102
+ assert_equal 'f', cs_downcase_digits.digit_symbol(15)
108
103
  end
109
104
 
110
105
  end