numerals 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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