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
@@ -5,87 +5,114 @@ include Numerals
5
5
 
6
6
  class TestFltConversions < Test::Unit::TestCase # < Minitest::Test
7
7
 
8
- def test_special_binary
8
+ def test_write_special_binary
9
+ context = Flt::BinNum.context = Flt::BinNum::FloatContext
10
+ type = Flt::BinNum
9
11
 
12
+ assert_equal Numeral.nan, Conversions.write(context.nan)
13
+ assert_equal Numeral.nan, Conversions.write(context.nan, rounding: Rounding[:short, base: 2])
14
+ assert_equal Numeral.nan, Conversions.write(context.nan, rounding: Rounding[:short, base: 10])
15
+ assert_equal Numeral.nan, Conversions.write(context.nan, rounding: Rounding[precision: 10, base: 10])
16
+ assert_equal Numeral.nan, Conversions.write(context.nan, rounding: Rounding[:short])
17
+ assert_equal Numeral.nan, Conversions.write(context.nan, rounding: Rounding[:free])
18
+
19
+ assert_equal Numeral.infinity, Conversions.write(context.infinity)
20
+ assert_equal Numeral.infinity, Conversions.write(context.infinity, rounding: Rounding[:short, base: 2])
21
+ assert_equal Numeral.infinity, Conversions.write(context.infinity, rounding: Rounding[:short, base: 10])
22
+ assert_equal Numeral.infinity, Conversions.write(context.infinity, rounding: Rounding[precision: 10, base: 10])
23
+ assert_equal Numeral.infinity, Conversions.write(context.infinity)
24
+
25
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1))
26
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1), rounding: Rounding[:short, base: 2])
27
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1), rounding: Rounding[:short, base: 10])
28
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1), rounding: Rounding[precision: 10, base: 10])
29
+ assert_equal Numeral.infinity(-1), Conversions.write(context.infinity(-1))
30
+ end
31
+
32
+ def test_read_special
10
33
  context = Flt::BinNum.context = Flt::BinNum::FloatContext
11
34
  type = Flt::BinNum
12
35
 
13
- assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan)
14
- assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan, :fixed, Rounding[:exact, base: 2])
15
- assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan, :fixed, Rounding[:exact, base: 10])
16
- assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan, :fixed, Rounding[precision: 10, base: 10])
17
- assert_equal Numeral.nan, Conversions.number_to_numeral(context.nan, :free)
18
-
19
- assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity)
20
- assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity, :fixed, Rounding[:exact, base: 2])
21
- assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity, :fixed, Rounding[:exact, base: 10])
22
- assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity, :fixed, Rounding[precision: 10, base: 10])
23
- assert_equal Numeral.infinity, Conversions.number_to_numeral(context.infinity, :free)
24
-
25
- assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1))
26
- assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1), :fixed, Rounding[:exact, base: 2])
27
- assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1), :fixed, Rounding[:exact, base: 10])
28
- assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1), :fixed, Rounding[precision: 10, base: 10])
29
- assert_equal Numeral.infinity(-1), Conversions.number_to_numeral(context.infinity(-1), :free)
30
-
31
- assert Conversions.numeral_to_number(Numeral.nan, type).nan?
32
- assert_equal context.infinity, Conversions.numeral_to_number(Numeral.infinity, type)
33
- assert_equal context.infinity(-1), Conversions.numeral_to_number(Numeral.infinity(-1), type)
36
+ assert Conversions.read(Numeral.nan, type: type).nan?
37
+ assert_equal context.infinity, Conversions.read(Numeral.infinity, type: type)
38
+ assert_equal context.infinity(-1), Conversions.read(Numeral.infinity(-1), type: type)
39
+ end
40
+
41
+ def test_write_preserved
42
+ assert_equal Numeral[1,2,3,4,5,6,0,0,0, base: 10, point: 3, sign: -1],
43
+ Conversions.write(Flt::DecNum('-123.456000'), rounding: :free)
44
+ assert_equal Numeral[1,2,3,4,5,6,0,0,0, base: 10, point: 3, sign: +1],
45
+ Conversions.write(Flt::DecNum('+123.456000'), rounding: :free)
46
+ assert_equal Numeral[1,2,3,4,5,6, base: 10, point: 3, sign: -1],
47
+ Conversions.write(Flt::DecNum('-123.456'), rounding: :free)
48
+ assert_equal Numeral[1,2,3,4,5,6, base: 10, point: 3, sign: +1],
49
+ Conversions.write(Flt::DecNum('+123.456'), rounding: :free)
34
50
  end
35
51
 
36
- def test_exact_binary
52
+ def test_write_exact_binary
37
53
  one = nil
38
54
  context = Flt::BinNum::FloatContext
39
55
  Flt::BinNum.context(context) do
40
56
  one = Flt::BinNum(1, :fixed)
41
57
  end
42
- rounding = Rounding[:exact, base: 10]
58
+ rounding = Rounding[:short, base: 10]
43
59
  assert_equal Numeral[1, point: 1],
44
- Conversions.number_to_numeral(one, :fixed, rounding)
60
+ Conversions.write(one, rounding: rounding, exact: true)
45
61
  assert_equal Numeral[1, point: 1, sign: -1],
46
- Conversions.number_to_numeral(-one, :fixed, rounding)
62
+ Conversions.write(-one, rounding: rounding, exact: true)
47
63
 
48
- rounding_2 = Rounding[:exact, base: 2]
64
+ rounding_2 = Rounding[:short, base: 2]
49
65
  assert_equal Numeral[1, point: 1, base: 2],
50
- Conversions.number_to_numeral(one, :fixed, rounding_2)
66
+ Conversions.write(one, rounding: rounding_2, exact: true)
51
67
  assert_equal Numeral[1, point: 1, sign: -1, base: 2],
52
- Conversions.number_to_numeral(-one, :fixed, rounding_2)
68
+ Conversions.write(-one, rounding: rounding_2, exact: true)
53
69
 
54
70
  [0.1, 0.01, 0.001, 1/3.0, 10/3.0, 100/3.0, Math::PI,
55
71
  0.5, 123.0, 123.45, 1.23E32, 1.23E-32].each do |x|
56
72
  [x, -x].each do |y|
57
73
  y = Flt::BinNum(y)
58
74
  numeral = exact_decimal(y)
59
- rounding = Rounding[:exact, base: 10]
60
- assert_equal numeral, Conversions.number_to_numeral(y, :fixed, rounding),
75
+ rounding = Rounding[:short, base: 10]
76
+ assert_equal numeral, Conversions.write(y, rounding: rounding, exact: true),
61
77
  "#{y} to base 10 exact numeral"
62
- assert_equal y, Conversions.numeral_to_number(numeral, context),
78
+ end
79
+ end
80
+ end
81
+
82
+ def test_read_exact_binary
83
+ context = Flt::BinNum::FloatContext
84
+ [0.1, 0.01, 0.001, 1/3.0, 10/3.0, 100/3.0, Math::PI,
85
+ 0.5, 123.0, 123.45, 1.23E32, 1.23E-32].each do |x|
86
+ [x, -x].each do |y|
87
+ y = Flt::BinNum(y)
88
+ numeral = exact_decimal(y)
89
+ rounding = Rounding[:short, base: 10]
90
+ assert_equal y, Conversions.read(numeral, context: context),
63
91
  "#{x} base 10 numeral to float"
64
92
  end
65
93
  end
66
94
  end
67
95
 
68
- def test_conversions_by_context
96
+ def test_read_by_context
69
97
  Flt::DecNum.context(precision: 20) do
70
98
  numeral = Numeral[1, point: 0]
71
99
  context = Flt::DecNum::ExtendedContext
72
- converted = Conversions.numeral_to_number(numeral, context, :fixed)
100
+ converted = Conversions.read(numeral, context: context)
73
101
  assert_equal Flt::DecNum('0.100000000'), converted
74
102
  assert_equal 9, converted.number_of_digits
75
103
  end
76
104
  end
77
105
 
78
- def test_conversions_by_class
106
+ def test_read_by_class
79
107
  Flt::DecNum.context(precision: 9) do
80
108
  numeral = Numeral[1, point: 0]
81
- converted = Conversions.numeral_to_number(numeral, Flt::DecNum, :fixed)
109
+ converted = Conversions.read(numeral, type: Flt::DecNum)
82
110
  assert_equal Flt::DecNum('0.100000000'), converted
83
111
  assert_equal 9, converted.number_of_digits
84
112
  end
85
113
  end
86
114
 
87
-
88
- def test_equidistiant_nearest
115
+ def test_read_write_equidistiant_nearest
89
116
  # In IEEEDoubleContext
90
117
  # 1E23 is equidistant from 2 Floats: lo & hi
91
118
  # one or the other will be chosen based on the rounding mode
@@ -105,82 +132,252 @@ class TestFltConversions < Test::Unit::TestCase # < Minitest::Test
105
132
  hi = Flt::BinNum('0x1.52d02c7e14af7p+76', :fixed)
106
133
  end
107
134
 
135
+ # Input (read)
136
+ assert_equal(
137
+ lo,
138
+ Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :half_even })
139
+ )
140
+ assert_equal(
141
+ lo,
142
+ Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :half_down })
143
+ )
144
+ assert_equal(
145
+ hi,
146
+ Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :half_up })
147
+ )
148
+ assert_equal(
149
+ -lo,
150
+ Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :half_even })
151
+ )
152
+ assert_equal(
153
+ -lo,
154
+ Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :half_down })
155
+ )
156
+ assert_equal(
157
+ -hi,
158
+ Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :half_up })
159
+ )
160
+
161
+ # Output (write)
162
+ rounding = Rounding[:short]
163
+
164
+ assert_equal(
165
+ numeral,
166
+ Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :half_down })
167
+ )
168
+ assert_equal(
169
+ numeral_lo,
170
+ Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :half_up })
171
+ )
172
+ assert_equal(
173
+ numeral,
174
+ Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :half_even })
175
+ )
176
+ assert_equal(
177
+ numeral,
178
+ Conversions.write(hi, rounding: rounding, type_options: { input_rounding: :half_up })
179
+ )
180
+ assert_equal(
181
+ numeral_hi,
182
+ Conversions.write(hi, rounding: rounding, type_options: { input_rounding: :half_down })
183
+ )
184
+ assert_equal(
185
+ numeral_hi,
186
+ Conversions.write(hi, rounding: rounding, type_options: { input_rounding: :half_even })
187
+ )
188
+ assert_equal(
189
+ -numeral,
190
+ Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :half_down })
191
+ )
192
+ assert_equal(
193
+ -numeral_lo,
194
+ Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :half_up })
195
+ )
196
+ assert_equal(
197
+ -numeral,
198
+ Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :half_even })
199
+ )
200
+ assert_equal(
201
+ -numeral,
202
+ Conversions.write(-hi, rounding: rounding, type_options: { input_rounding: :half_up })
203
+ )
204
+ assert_equal(
205
+ -numeral_hi,
206
+ Conversions.write(-hi, rounding: rounding, type_options: { input_rounding: :half_down })
207
+ )
208
+ assert_equal(
209
+ -numeral_hi,
210
+ Conversions.write(-hi, rounding: rounding, type_options: { input_rounding: :half_even })
211
+ )
212
+
213
+ # For input, if no input_roundig is established, the Num context is used
214
+
215
+ Flt::BinNum.context(context, rounding: :half_even) do
216
+ x = Conversions.read(numeral, type: Flt::BinNum)
217
+ assert_equal lo, x
218
+ end
219
+ # x = Conversions.read(numeral, type: context[:half_even])
220
+
221
+ Flt::BinNum.context(context, rounding: :half_down) do
222
+ x = Conversions.read(numeral, type: Flt::BinNum)
223
+ assert_equal lo, x
224
+ end
225
+
226
+ Flt::BinNum.context(context, rounding: :half_up) do
227
+ x = Conversions.read(numeral, type: Flt::BinNum)
228
+ assert_equal hi, x
229
+ end
230
+
231
+ Flt::BinNum.context(context, rounding: :half_even) do
232
+ x = Conversions.read(-numeral, type: Flt::BinNum)
233
+ assert_equal -lo, x
234
+ end
235
+ # x = Conversions.read(numeral, type: context[:half_even])
236
+
237
+ Flt::BinNum.context(context, rounding: :half_down) do
238
+ x = Conversions.read(-numeral, type: Flt::BinNum)
239
+ assert_equal -lo, x
240
+ end
241
+
242
+ Flt::BinNum.context(context, rounding: :half_up) do
243
+ x = Conversions.read(-numeral, type: Flt::BinNum)
244
+ assert_equal -hi, x
245
+ end
246
+
247
+ # we can also be explicit to use the @context for rounding:
248
+
108
249
  Flt::BinNum.context(context, rounding: :half_even) do
109
- x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
250
+ x = Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
110
251
  assert_equal lo, x
111
252
  end
112
- # x = Conversions.numeral_to_number(numeral, context[rounding: :half_even], :fixed)
253
+ # x = Conversions.read(numeral, type: context[:half_even])
113
254
 
114
255
  Flt::BinNum.context(context, rounding: :half_down) do
115
- x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
256
+ x = Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
116
257
  assert_equal lo, x
117
258
  end
118
259
 
119
260
  Flt::BinNum.context(context, rounding: :half_up) do
120
- x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
261
+ x = Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
121
262
  assert_equal hi, x
122
263
  end
123
264
 
124
265
  Flt::BinNum.context(context, rounding: :half_even) do
125
- x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
266
+ x = Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
126
267
  assert_equal -lo, x
127
268
  end
128
- # x = Conversions.numeral_to_number(numeral, context[rounding: :half_even], :fixed)
269
+ # x = Conversions.read(numeral, type: context[:half_even])
129
270
 
130
271
  Flt::BinNum.context(context, rounding: :half_down) do
131
- x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
272
+ x = Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
132
273
  assert_equal -lo, x
133
274
  end
134
275
 
135
276
  Flt::BinNum.context(context, rounding: :half_up) do
136
- x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
277
+ x = Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
137
278
  assert_equal -hi, x
138
279
  end
139
280
 
140
- rounding = Rounding[:exact]
281
+ # for output we must be explicit to use context as the input rounding mode:
282
+
283
+ rounding = Rounding[:short]
141
284
 
142
285
  Flt::BinNum.context(context, rounding: :half_down) do
143
- assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
286
+ assert_equal numeral, Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :context })
144
287
  end
145
288
  Flt::BinNum.context(context, rounding: :half_up) do
146
- assert_equal numeral_lo, Conversions.number_to_numeral(lo, :free, rounding)
289
+ assert_equal numeral_lo, Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :context })
147
290
  end
148
291
  Flt::BinNum.context(context, rounding: :half_even) do
149
- assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
292
+ assert_equal numeral, Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :context })
150
293
  end
151
294
 
152
295
  Flt::BinNum.context(context, rounding: :half_up) do
153
- assert_equal numeral, Conversions.number_to_numeral(hi, :free, rounding)
296
+ assert_equal numeral, Conversions.write(hi, rounding: rounding, type_options: { input_rounding: :context })
154
297
  end
155
298
  Flt::BinNum.context(context, rounding: :half_down) do
156
- assert_equal numeral_hi, Conversions.number_to_numeral(hi, :free, rounding)
299
+ assert_equal numeral_hi, Conversions.write(hi, rounding: rounding, type_options: { input_rounding: :context })
157
300
  end
158
301
  Flt::BinNum.context(context, rounding: :half_even) do
159
- assert_equal numeral_hi, Conversions.number_to_numeral(hi, :free, rounding)
302
+ assert_equal numeral_hi, Conversions.write(hi, rounding: rounding, type_options: { input_rounding: :context })
160
303
  end
161
304
 
162
305
  Flt::BinNum.context(context, rounding: :half_down) do
163
- assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
306
+ assert_equal -numeral, Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :context })
164
307
  end
165
308
  Flt::BinNum.context(context, rounding: :half_up) do
166
- assert_equal -numeral_lo, Conversions.number_to_numeral(-lo, :free, rounding)
309
+ assert_equal -numeral_lo, Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :context })
167
310
  end
168
311
  Flt::BinNum.context(context, rounding: :half_even) do
169
- assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
312
+ assert_equal -numeral, Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :context })
170
313
  end
171
314
 
172
315
  Flt::BinNum.context(context, rounding: :half_up) do
173
- assert_equal -numeral, Conversions.number_to_numeral(-hi, :free, rounding)
316
+ assert_equal -numeral, Conversions.write(-hi, rounding: rounding, type_options: { input_rounding: :context })
174
317
  end
175
318
  Flt::BinNum.context(context, rounding: :half_down) do
176
- assert_equal -numeral_hi, Conversions.number_to_numeral(-hi, :free, rounding)
319
+ assert_equal -numeral_hi, Conversions.write(-hi, rounding: rounding, type_options: { input_rounding: :context })
177
320
  end
178
321
  Flt::BinNum.context(context, rounding: :half_even) do
179
- assert_equal -numeral_hi, Conversions.number_to_numeral(-hi, :free, rounding)
180
- end
322
+ assert_equal -numeral_hi, Conversions.write(-hi, rounding: rounding, type_options: { input_rounding: :context })
323
+ end
324
+
325
+ # Finally, for output we can omit the input rounding and let it use the output rounding
326
+
327
+ rounding = Rounding[:short]
328
+
329
+ assert_equal(
330
+ numeral,
331
+ Conversions.write(lo, rounding: rounding[:half_down])
332
+ )
333
+ assert_equal(
334
+ numeral_lo,
335
+ Conversions.write(lo, rounding: rounding[:half_up])
336
+ )
337
+ assert_equal(
338
+ numeral,
339
+ Conversions.write(lo, rounding: rounding[:half_even])
340
+ )
341
+ assert_equal(
342
+ numeral,
343
+ Conversions.write(hi, rounding: rounding[:half_up])
344
+ )
345
+ assert_equal(
346
+ numeral_hi,
347
+ Conversions.write(hi, rounding: rounding[:half_down])
348
+ )
349
+ assert_equal(
350
+ numeral_hi,
351
+ Conversions.write(hi, rounding: rounding[:half_even])
352
+ )
353
+ assert_equal(
354
+ -numeral,
355
+ Conversions.write(-lo, rounding: rounding[:half_down])
356
+ )
357
+ assert_equal(
358
+ -numeral_lo,
359
+ Conversions.write(-lo, rounding: rounding[:half_up])
360
+ )
361
+ assert_equal(
362
+ -numeral,
363
+ Conversions.write(-lo, rounding: rounding[:half_even])
364
+ )
365
+ assert_equal(
366
+ -numeral,
367
+ Conversions.write(-hi, rounding: rounding[:half_up])
368
+ )
369
+ assert_equal(
370
+ -numeral_hi,
371
+ Conversions.write(-hi, rounding: rounding[:half_down])
372
+ )
373
+ assert_equal(
374
+ -numeral_hi,
375
+ Conversions.write(-hi, rounding: rounding[:half_even])
376
+ )
377
+
181
378
  end
182
379
 
183
- def test_single_nearest
380
+ def test_read_write_single_nearest
184
381
  # In IEEEDoubleContext
185
382
  # 64.1 between the floats lo, hi, but is closer to lo
186
383
  # So there's a closet Float that should be chosen for rounding
@@ -196,74 +393,222 @@ class TestFltConversions < Test::Unit::TestCase # < Minitest::Test
196
393
  hi = Flt::BinNum('0x1.0066666666667p+6', :fixed)
197
394
  end
198
395
 
396
+ assert_equal(
397
+ lo,
398
+ Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :half_even })
399
+ )
400
+ assert_equal(
401
+ lo,
402
+ Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :half_down })
403
+ )
404
+ assert_equal(
405
+ lo,
406
+ Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :half_up })
407
+ )
408
+
409
+ assert_equal(
410
+ -lo,
411
+ Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :half_even })
412
+ )
413
+ assert_equal(
414
+ -lo,
415
+ Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :half_down })
416
+ )
417
+ assert_equal(
418
+ -lo,
419
+ Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :half_up })
420
+ )
421
+
422
+ rounding = Rounding[:short]
423
+ rounding_16 = Rounding[:half_even, precision: 16]
424
+
425
+ assert_equal(
426
+ numeral,
427
+ Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :half_even })
428
+ )
429
+ assert_equal(
430
+ numeral_lo,
431
+ Conversions.write(lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :half_even })
432
+ )
433
+ assert_equal(
434
+ numeral,
435
+ Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :half_down })
436
+ )
437
+ assert_equal(
438
+ numeral_lo,
439
+ Conversions.write(lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :half_down })
440
+ )
441
+ assert_equal(
442
+ numeral,
443
+ Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :half_up })
444
+ )
445
+ assert_equal(
446
+ numeral_lo,
447
+ Conversions.write(lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :half_up })
448
+ )
449
+
450
+ assert_equal(
451
+ -numeral,
452
+ Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :half_even })
453
+ )
454
+ assert_equal(
455
+ -numeral_lo,
456
+ Conversions.write(-lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :half_even })
457
+ )
458
+ assert_equal(
459
+ -numeral,
460
+ Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :half_down })
461
+ )
462
+ assert_equal(
463
+ -numeral_lo,
464
+ Conversions.write(-lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :half_down })
465
+ )
466
+ assert_equal(
467
+ -numeral,
468
+ Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :half_up })
469
+ )
470
+ assert_equal(
471
+ -numeral_lo,
472
+ Conversions.write(-lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :half_up })
473
+ )
474
+
475
+ # Let it use the context as default input rounding:
476
+
477
+ Flt::BinNum.context(context, rounding: :half_even) do
478
+ x = Conversions.read(numeral, type: Flt::BinNum)
479
+ assert_equal lo, x
480
+ end
481
+ Flt::BinNum.context(context, rounding: :half_down) do
482
+ x = Conversions.read(numeral, type: Flt::BinNum)
483
+ assert_equal lo, x
484
+ end
485
+ Flt::BinNum.context(context, rounding: :half_up) do
486
+ x = Conversions.read(numeral, type: Flt::BinNum)
487
+ assert_equal lo, x
488
+ end
489
+
490
+ Flt::BinNum.context(context, rounding: :half_even) do
491
+ x = Conversions.read(-numeral, type: Flt::BinNum)
492
+ assert_equal -lo, x
493
+ end
494
+ Flt::BinNum.context(context, rounding: :half_down) do
495
+ x = Conversions.read(-numeral, type: Flt::BinNum)
496
+ assert_equal -lo, x
497
+ end
498
+ Flt::BinNum.context(context, rounding: :half_up) do
499
+ x = Conversions.read(-numeral, type: Flt::BinNum)
500
+ assert_equal -lo, x
501
+ end
502
+
503
+ # Now set explicitly the context as input rounding
504
+
199
505
  Flt::BinNum.context(context, rounding: :half_even) do
200
- x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
506
+ x = Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
201
507
  assert_equal lo, x
202
508
  end
203
509
  Flt::BinNum.context(context, rounding: :half_down) do
204
- x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
510
+ x = Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
205
511
  assert_equal lo, x
206
512
  end
207
513
  Flt::BinNum.context(context, rounding: :half_up) do
208
- x = Conversions.numeral_to_number(numeral, Flt::BinNum, :fixed)
514
+ x = Conversions.read(numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
209
515
  assert_equal lo, x
210
516
  end
211
517
 
212
518
  Flt::BinNum.context(context, rounding: :half_even) do
213
- x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
519
+ x = Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
214
520
  assert_equal -lo, x
215
521
  end
216
522
  Flt::BinNum.context(context, rounding: :half_down) do
217
- x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
523
+ x = Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
218
524
  assert_equal -lo, x
219
525
  end
220
526
  Flt::BinNum.context(context, rounding: :half_up) do
221
- x = Conversions.numeral_to_number(-numeral, Flt::BinNum, :fixed)
527
+ x = Conversions.read(-numeral, type: Flt::BinNum, type_options: { input_rounding: :context })
222
528
  assert_equal -lo, x
223
529
  end
224
530
 
225
- rounding = Rounding[:exact]
531
+ # Now try output using the context for input rounding
532
+
533
+ rounding = Rounding[:short]
226
534
  rounding_16 = Rounding[:half_even, precision: 16]
227
535
 
228
536
  Flt::BinNum.context(context, rounding: :half_even) do
229
- assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
537
+ assert_equal numeral, Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :context })
230
538
  end
231
539
  Flt::BinNum.context(context, rounding: :half_even) do
232
- assert_equal numeral_lo, Conversions.number_to_numeral(lo, :free, rounding_16)
540
+ assert_equal numeral_lo, Conversions.write(lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :context })
233
541
  end
234
542
  Flt::BinNum.context(context, rounding: :half_down) do
235
- assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
543
+ assert_equal numeral, Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :context })
236
544
  end
237
545
  Flt::BinNum.context(context, rounding: :half_down) do
238
- assert_equal numeral_lo, Conversions.number_to_numeral(lo, :free, rounding_16)
546
+ assert_equal numeral_lo, Conversions.write(lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :context })
239
547
  end
240
548
  Flt::BinNum.context(context, rounding: :half_up) do
241
- assert_equal numeral, Conversions.number_to_numeral(lo, :free, rounding)
549
+ assert_equal numeral, Conversions.write(lo, rounding: rounding, type_options: { input_rounding: :context })
242
550
  end
243
551
  Flt::BinNum.context(context, rounding: :half_up) do
244
- assert_equal numeral_lo, Conversions.number_to_numeral(lo, :free, rounding_16)
552
+ assert_equal numeral_lo, Conversions.write(lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :context })
245
553
  end
246
554
 
247
555
  Flt::BinNum.context(context, rounding: :half_even) do
248
- assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
556
+ assert_equal -numeral, Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :context })
249
557
  end
250
558
  Flt::BinNum.context(context, rounding: :half_even) do
251
- assert_equal -numeral_lo, Conversions.number_to_numeral(-lo, :free, rounding_16)
559
+ assert_equal -numeral_lo, Conversions.write(-lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :context })
252
560
  end
253
561
  Flt::BinNum.context(context, rounding: :half_down) do
254
- assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
562
+ assert_equal -numeral, Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :context })
255
563
  end
256
564
  Flt::BinNum.context(context, rounding: :half_down) do
257
- assert_equal -numeral_lo, Conversions.number_to_numeral(-lo, :free, rounding_16)
565
+ assert_equal -numeral_lo, Conversions.write(-lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :context })
258
566
  end
259
567
  Flt::BinNum.context(context, rounding: :half_up) do
260
- assert_equal -numeral, Conversions.number_to_numeral(-lo, :free, rounding)
568
+ assert_equal -numeral, Conversions.write(-lo, rounding: rounding, type_options: { input_rounding: :context })
261
569
  end
262
570
  Flt::BinNum.context(context, rounding: :half_up) do
263
- assert_equal -numeral_lo, Conversions.number_to_numeral(-lo, :free, rounding_16)
571
+ assert_equal -numeral_lo, Conversions.write(-lo, rounding: rounding_16, exact: true, type_options: { input_rounding: :context })
264
572
  end
573
+
574
+ # And finally, use the output rounding as input too:
575
+
576
+ rounding = Rounding[:short]
577
+ rounding_16 = Rounding[:half_even, precision: 16]
578
+
579
+ assert_equal numeral, Conversions.write(lo, rounding: rounding[:half_even])
580
+ assert_equal numeral_lo, Conversions.write(lo, rounding: rounding_16[:half_even], exact: true)
581
+ assert_equal numeral, Conversions.write(lo, rounding: rounding[:half_down])
582
+ assert_equal numeral_lo, Conversions.write(lo, rounding: rounding_16[:half_down], exact: true)
583
+ assert_equal numeral, Conversions.write(lo, rounding: rounding[:half_up])
584
+ assert_equal numeral_lo, Conversions.write(lo, rounding: rounding_16[:half_up], exact: true)
585
+
586
+ assert_equal -numeral, Conversions.write(-lo, rounding: rounding[:half_even])
587
+ assert_equal -numeral_lo, Conversions.write(-lo, rounding: rounding_16[:half_even], exact: true)
588
+ assert_equal -numeral, Conversions.write(-lo, rounding: rounding[:half_down])
589
+ assert_equal -numeral_lo, Conversions.write(-lo, rounding: rounding_16[:half_down], exact: true)
590
+ assert_equal -numeral, Conversions.write(-lo, rounding: rounding[:half_up])
591
+ assert_equal -numeral_lo, Conversions.write(-lo, rounding: rounding_16[:half_up], exact: true)
265
592
  end
266
593
 
594
+ def test_read_short
595
+ assert_equal Flt::DecNum('1'),
596
+ Conversions.read(Numeral[1,0,0,0,0,0,0, point: 1, base: 10, normalize: :approximate], simplify: true, type: Flt::DecNum)
597
+
598
+ assert_equal Flt::BinNum('0.000110011', base: 2),
599
+ Conversions.read(Numeral[1,0, point: 0, base: 10, normalize: :approximate], simplify: false, type: Flt::BinNum)
600
+ assert_equal Flt::BinNum('0.0001100110011', base: 2),
601
+ Conversions.read(Numeral[1,0,0, point: 0, base: 10, normalize: :approximate], simplify: false, type: Flt::BinNum)
602
+ assert_equal Flt::BinNum('0.00011001100110011', base: 2),
603
+ Conversions.read(Numeral[1,0,0,0, point: 0, base: 10, normalize: :approximate], simplify: false, type: Flt::BinNum)
604
+
605
+ assert_equal Flt::BinNum('0.0001101', base: 2),
606
+ Conversions.read(Numeral[1,0, point: 0, base: 10, normalize: :approximate], simplify: true, type: Flt::BinNum)
607
+ assert_equal Flt::BinNum('0.00011001101', base: 2),
608
+ Conversions.read(Numeral[1,0,0, point: 0, base: 10, normalize: :approximate], simplify: true, type: Flt::BinNum)
609
+ assert_equal Flt::BinNum('0.00011001100111', base: 2),
610
+ Conversions.read(Numeral[1,0,0,0, point: 0, base: 10, normalize: :approximate], simplify: true, type: Flt::BinNum)
611
+ end
267
612
 
268
613
  def exact_decimal(x)
269
614
  Flt::DecNum.context(exact: true){
@@ -274,4 +619,55 @@ class TestFltConversions < Test::Unit::TestCase # < Minitest::Test
274
619
  }
275
620
  end
276
621
 
622
+ def test_read_same_base_rounding
623
+ numeral = Numeral[6,6,6,6,6,6,6,6,6, point: 0]
624
+ assert_equal(
625
+ Flt::DecNum('0.66667'),
626
+ Conversions.read(numeral, context: Flt::DecNum.context(precision: 5, rounding: :half_even))
627
+ )
628
+ assert_equal(
629
+ Flt::DecNum('0.66666'),
630
+ Conversions.read(numeral, context: Flt::DecNum.context(precision: 5, rounding: :down))
631
+ )
632
+ end
633
+
634
+ def test_type_parameters
635
+ c = Conversions[Flt::DecNum]
636
+ assert_nil c.input_rounding
637
+ c = Conversions[Flt::DecNum, input_rounding: :down]
638
+ assert_equal Rounding[:down], c.input_rounding
639
+ c = Conversions[Flt::DecNum, input_rounding: :half_even]
640
+ assert_equal Rounding[:half_even], c.input_rounding
641
+ c = Conversions[Flt::DecNum, input_rounding: Rounding[:half_up, precision: 7]]
642
+ assert_equal Rounding[:half_up, precision: 7], c.input_rounding
643
+ c = Conversions[Flt::DecNum, input_rounding: Rounding[:half_up, precision: 7, base: 3]]
644
+ assert_equal Rounding[:half_up], c.input_rounding
645
+
646
+ Flt::DecNum.context(rounding: :half_down, precision: 10) do
647
+ c = Conversions[Flt::DecNum, input_rounding: :context]
648
+ assert_equal :half_down, c.input_rounding.mode
649
+ assert_equal 10, c.input_rounding.precision
650
+ end
651
+ Flt::DecNum.context(rounding: :up, precision: 11) do
652
+ c = Conversions[Flt::DecNum, input_rounding: :context]
653
+ assert_equal :up, c.input_rounding.mode
654
+ assert_equal 11, c.input_rounding.precision
655
+ end
656
+ context = Flt::DecNum.context(rounding: :down, precision: 9)
657
+ c = Conversions[context, input_rounding: :context]
658
+ assert_equal :down, c.input_rounding.mode
659
+ assert_equal 9, c.input_rounding.precision
660
+ assert_equal 10, c.input_rounding.base
661
+ context = Flt::BinNum.context(rounding: :up05, precision: 20)
662
+ c = Conversions[context, input_rounding: :context]
663
+ assert_equal :up05, c.input_rounding.mode
664
+ assert_equal 20, c.input_rounding.precision
665
+ assert_equal 2, c.input_rounding.base
666
+
667
+ c = Conversions[Flt::DecNum.context, input_rounding: :down]
668
+ assert_equal Rounding[:down], c.input_rounding
669
+ c = Conversions[Flt::DecNum.context, input_rounding: :half_even]
670
+ assert_equal Rounding[:half_even], c.input_rounding
671
+ end
672
+
277
673
  end