flt 1.0.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 (56) hide show
  1. data/History.txt +41 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +42 -0
  4. data/README.txt +557 -0
  5. data/Rakefile +34 -0
  6. data/lib/flt.rb +9 -0
  7. data/lib/flt/b.rb +6 -0
  8. data/lib/flt/bigdecimal.rb +151 -0
  9. data/lib/flt/bin_num.rb +250 -0
  10. data/lib/flt/d.rb +6 -0
  11. data/lib/flt/dec_num.rb +1239 -0
  12. data/lib/flt/float.rb +458 -0
  13. data/lib/flt/math.rb +66 -0
  14. data/lib/flt/num.rb +4211 -0
  15. data/lib/flt/sugar.rb +102 -0
  16. data/lib/flt/support.rb +1335 -0
  17. data/lib/flt/tolerance.rb +561 -0
  18. data/lib/flt/tolerance/sugar.rb +77 -0
  19. data/lib/flt/version.rb +9 -0
  20. data/setup.rb +1585 -0
  21. data/tasks/ann.rake +80 -0
  22. data/tasks/bones.rake +20 -0
  23. data/tasks/gem.rake +192 -0
  24. data/tasks/git.rake +40 -0
  25. data/tasks/manifest.rake +48 -0
  26. data/tasks/notes.rake +27 -0
  27. data/tasks/post_load.rake +39 -0
  28. data/tasks/rdoc.rake +50 -0
  29. data/tasks/rubyforge.rake +55 -0
  30. data/tasks/setup.rb +279 -0
  31. data/tasks/spec.rake +54 -0
  32. data/tasks/svn.rake +47 -0
  33. data/tasks/test.rake +40 -0
  34. data/test/all_tests.rb +23 -0
  35. data/test/helper.rb +101 -0
  36. data/test/reader.rb +68 -0
  37. data/test/test_basic.rb +396 -0
  38. data/test/test_bin.rb +245 -0
  39. data/test/test_bin_arithmetic.rb +94 -0
  40. data/test/test_binfloat_conversion.rb +24 -0
  41. data/test/test_coercion.rb +22 -0
  42. data/test/test_comparisons.rb +53 -0
  43. data/test/test_dectest.rb +216 -0
  44. data/test/test_define_conversions.rb +144 -0
  45. data/test/test_epsilon.rb +55 -0
  46. data/test/test_exact.rb +147 -0
  47. data/test/test_flags.rb +34 -0
  48. data/test/test_multithreading.rb +32 -0
  49. data/test/test_num_constructor.rb +133 -0
  50. data/test/test_odd_even.rb +78 -0
  51. data/test/test_round.rb +104 -0
  52. data/test/test_to_int.rb +104 -0
  53. data/test/test_to_rf.rb +36 -0
  54. data/test/test_tol.rb +102 -0
  55. data/test/test_ulp.rb +127 -0
  56. metadata +147 -0
data/lib/flt/math.rb ADDED
@@ -0,0 +1,66 @@
1
+ require 'flt/dec_num'
2
+
3
+ module Flt
4
+ class DecNum
5
+ module Math
6
+
7
+ extend Flt # to access constructor methods DecNum
8
+
9
+ module_function
10
+
11
+ # Trinogometry
12
+
13
+ # Pi
14
+ def pi(decimals=nil)
15
+ three = DecNum(3)
16
+ lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
17
+ Flt::DecNum.context(:precision=>decimals) do |local_context|
18
+ local_context.precision += 2 # extra digits for intermediate steps
19
+ while s != lasts
20
+ lasts = s
21
+ n, na = n+na, na+8
22
+ d, da = d+da, da+32
23
+ t = (t * n) / d
24
+ s += t
25
+ end
26
+ end
27
+ return +s
28
+ end
29
+
30
+ # Cosine of angle in radians
31
+ def cos(x)
32
+ i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 1
33
+ DecNum.context do |local_context|
34
+ local_context.precision += 2 # extra digits for intermediate steps
35
+ while s != lasts
36
+ lasts = s
37
+ i += 2
38
+ fact *= i * (i-1)
39
+ num *= x * x
40
+ sign *= -1
41
+ s += num / fact * sign
42
+ end
43
+ end
44
+ return +s
45
+ end
46
+
47
+ # Sine of angle in radians
48
+ def sin(x)
49
+ i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 1
50
+ DecNum.context do |local_context|
51
+ local_context.precision += 2 # extra digits for intermediate steps
52
+ while s != lasts
53
+ lasts = s
54
+ i += 2
55
+ fact *= i * (i-1)
56
+ num *= x * x
57
+ sign *= -1
58
+ s += num / fact * sign
59
+ end
60
+ end
61
+ return +s
62
+ end
63
+
64
+ end # Math
65
+ end # DecNum
66
+ end # Flt
data/lib/flt/num.rb ADDED
@@ -0,0 +1,4211 @@
1
+ # Base classes for floating-point numbers and contexts.
2
+
3
+ #--
4
+ # =Notes on the representation of Flt::Num numbers.
5
+ #
6
+ # @sign is +1 for plus and -1 for minus
7
+ # @coeff is the integral significand stored as an integer (so leading zeros cannot be kept)
8
+ # @exp is the exponent to be applied to @coeff as an integer or one of :inf, :nan, :snan for special values
9
+ #
10
+ # The original Python Decimal representation has these slots:
11
+ # _sign is 1 for minus, 0 for plus
12
+ # _int is the integral significand as a string of digits (leading zeroes are not kept)
13
+ # _exp is the exponent as an integer or 'F' for infinity, 'n' for NaN , 'N' for sNaN
14
+ # _is_especial is true for special values (infinity, NaN, sNaN)
15
+ # An additional class _WorkRep is used in Python for non-special decimal values with:
16
+ # sign
17
+ # int (significand as an integer)
18
+ # exp
19
+ #
20
+ # =Exponent values
21
+ #
22
+ # In GDAS (General Decimal Arithmetic Specification) numbers are represented by an unnormalized integral
23
+ # significand and an exponent (also called 'scale'.)
24
+ #
25
+ # The reduce operation (originally called 'normalize') removes trailing 0s and increments the exponent if necessary;
26
+ # the representation is rescaled to use the maximum exponent possible (while maintaining an integral significand.)
27
+ #
28
+ # A classical floating-point normalize opwration would remove leading 0s and decrement the exponent instead,
29
+ # rescaling to the minimum exponent theat maintains the significand value under some conventional limit (1 or the radix).
30
+ #
31
+ # The logb and adjusted operations return the exponent that applies to the most significand digit (logb as a Decimal
32
+ # and adjusted as an integer.) This is the normalized scientific exponent.
33
+ #
34
+ # The most common normalized exponent is the normalized integral exponent for a fixed number of precision digits.
35
+ #
36
+ # The normalized fractional exponent is what BigDecima#exponent returns.
37
+ #
38
+ # ==Relations between exponent values
39
+ #
40
+ # The number of (kept) significand digits is s = a - e + 1
41
+ # where a is the adjusted exponent and e is the internal exponent (the unnormalized integral exponent.)
42
+ #
43
+ # The number of significant digits (excluding leading and trailing zeroes) is sr = a - re + 1
44
+ # where re is the internal exponent of the reduced value.
45
+ #
46
+ # The normalized integral exponent is e - (p - s) = a - p + 1
47
+ # where p is the fixed precision.
48
+ #
49
+ # The normalized fractional exponent is e + s = a + 1
50
+ #
51
+ # ==Example: 0.01204
52
+ #
53
+ # * The integral significand is 120400 and the internal exponent that applies to it is e = -7
54
+ # * The number of significand digits is s = 6
55
+ # * The reduced representation is 1204 with internal exponent re = -5
56
+ # * The number of significant digits sr = 4
57
+ # * The adjusted exponent is a = -2 (the adjusted representation is 1.204 with exponent -2)
58
+ # * Given a precision p = 8, the normalized integral representation is 12040000 with exponent -9
59
+ # * The normalized fractional representation is 0.1204 with exponent -1
60
+ #
61
+ # ==Exponent limits
62
+ #
63
+ # The (integral) exponent e must be within this limits: etiny <= e <= etop
64
+ # The adjusted exponent a must: emin <= a <= emax
65
+ # emin, emax are the limite of the exponent shown in scientific notation and are use to defined
66
+ # the exponent limits in the contexts.
67
+ # etiny = emin-precision+1 and etop=emax-precision+1 are the limits of the internal exponent.
68
+ # Note that for significands with less than precision digits we can use exponents greater than etop
69
+ # without causing overflow: +Decimal(+1,1,emax) == Decimal(+1,K,etop) where K=10**(precision-1)
70
+ #
71
+ # =Interoperatibility with other numeric types
72
+ #
73
+ # For some numeric types implicit conversion to DecNum is defined through these methods:
74
+ # * DecNum#coerce() is used when a Decimal is the right hand of an operator
75
+ # and the left hand is another numeric type
76
+ # * DecNum#_bin_op() used internally to define binary operators and use the Ruby coerce protocol:
77
+ # if the right-hand operand is of known type it is converted with Decimal; otherwise use coerce
78
+ # * _convert() converts known types to Decimal with Decimal() or raises an exception.
79
+ # * DecNum() casts known types and text representations of numbers to Decimal using the constructor.
80
+ # * DecNum#initialize performs the actual type conversion
81
+ #
82
+ # The known or 'coercible' types for DecNum are initially Integer and Rational, but this can be extended to
83
+ # other types using define_conversion_from() in a Context object.
84
+ #++
85
+
86
+ #--
87
+ # TODO: selecting the kind of ulp is awkward; consider one of these options:
88
+ # * don't support variant ulps; always use Muller's ulp
89
+ # * use an options hash for the kind of ulp parameter
90
+ # * keep the kind of ulp in the context
91
+ # also, note that Tolerance uses only the Muller king of ulp.
92
+ # TODO: move the exception classes from Flt::Num to Flt ? move also Flt::Num::ContextBas to Flt ?
93
+ # TODO: find better name for :all_digits (:preserve_precision, :mantain_precision, ...) ?
94
+ # TODO: should the context determine the mode for cross-base literal-to-Num conversion (:free, :fixed)?
95
+ # BinNum.context.input = :fixed; x = BinNum('0.1')
96
+ #++
97
+
98
+ require 'flt/support'
99
+ require 'flt/version'
100
+
101
+ require 'bigdecimal'
102
+ require 'forwardable'
103
+ require 'rational'
104
+ require 'monitor'
105
+ require 'ostruct'
106
+
107
+ module Flt
108
+
109
+ # Generic radix arbitrary-precision, floating-point numbers. This is a base class for
110
+ # floating point types of specific radix.
111
+ #
112
+ # The implementation of floating-point arithmetic is largely based on the Decimal module of Python,
113
+ # written by Eric Price, Facundo Batista, Raymond Hettinger, Aahz and Tim Peters.
114
+ class Num < Numeric
115
+
116
+ extend Support # allows use of unqualified FlagValues(), Flags(), etc.
117
+ include Support::AuxiliarFunctions # make auxiliar functions available unqualified to instance menthods
118
+
119
+ ROUND_HALF_EVEN = :half_even
120
+ ROUND_HALF_DOWN = :half_down
121
+ ROUND_HALF_UP = :half_up
122
+ ROUND_FLOOR = :floor
123
+ ROUND_CEILING = :ceiling
124
+ ROUND_DOWN = :down
125
+ ROUND_UP = :up
126
+ ROUND_05UP = :up05
127
+
128
+ # Numerical conversion base support
129
+ # base (default) coercible types associated to procedures for numerical conversion
130
+ @_base_coercible_types = {
131
+ Integer=>lambda{|x, context| x>=0 ? [+1,x,0] : [-1,-x,0]},
132
+ Rational=>lambda{|x, context|
133
+ x, y = context.num_class.new(x.numerator), context.num_class.new(x.denominator)
134
+ z = x.divide(y, context)
135
+ z
136
+ }
137
+ }
138
+ @_base_conversions = {
139
+ Integer=>:to_i, Rational=>:to_r, Float=>:to_f
140
+ }
141
+ class <<self
142
+ attr_reader :_base_coercible_types
143
+ attr_reader :_base_conversions
144
+ def base_coercible_types
145
+ Num._base_coercible_types
146
+ end
147
+ def base_conversions
148
+ Num._base_conversions
149
+ end
150
+ # We use this two level scheme to acces base_... because we're using instance variables of the object
151
+ # Num to store the base_... objects (and we store them to avoid generating them each time) and to access
152
+ # them would requiere that derived classes define their own versios of the accesors, even if they
153
+ # only call super.
154
+ end
155
+
156
+ # Base class for errors.
157
+ class Error < StandardError
158
+ end
159
+
160
+ # Base class for exceptions.
161
+ #
162
+ # All exception conditions derive from this class.
163
+ # The exception classes also define the values returned when trapping is disable for
164
+ # a particular exception.
165
+ class Exception < StandardError
166
+ attr :context
167
+ def initialize(context=nil)
168
+ @context = context
169
+ end
170
+
171
+ # Defines the value returned when trapping is inactive
172
+ # for the condition. The arguments are those passed to
173
+ # Context#exception after the message.
174
+ def self.handle(context, *args)
175
+ end
176
+ end
177
+
178
+ # Invalid operation exception.
179
+ #
180
+ # The result of the operation is a quiet positive NaN,
181
+ # except when the cause is a signaling NaN, in which case the result is
182
+ # also a quiet NaN, but with the original sign, and an optional
183
+ # diagnostic information.
184
+ class InvalidOperation < Exception
185
+ def self.handle(context, *args)
186
+ if args.size>0
187
+ sign, coeff, exp = args.first.split
188
+ context.num_class.new([sign, coeff, :nan])._fix_nan(context)
189
+ else
190
+ context.num_class.nan
191
+ end
192
+ end
193
+ def initialize(context=nil, *args)
194
+ @value = args.first if args.size>0
195
+ super context
196
+ end
197
+ end
198
+
199
+ # Division by zero exception.
200
+ #
201
+ # The result of the operation is +/-Infinity, where the sign is the product
202
+ # of the signs of the operands for divide, or 1 for an odd power of -0.
203
+ class DivisionByZero < Exception
204
+ def self.handle(context,sign,*args)
205
+ context.num_class.infinity(sign)
206
+ end
207
+ def initialize(context=nil, sign=nil, *args)
208
+ @sign = sign
209
+ super context
210
+ end
211
+ end
212
+
213
+ # Cannot perform the division adequately exception.
214
+ #
215
+ # This occurs and signals invalid-operation if the integer result of a
216
+ # divide-integer or remainder operation had too many digits (would be
217
+ # longer than precision).
218
+ # The result is NaN.
219
+ class DivisionImpossible < Exception
220
+ def self.handle(context,*args)
221
+ context.num_class.nan
222
+ end
223
+ end
224
+
225
+ # Undefined result of division exception.
226
+ #
227
+ # This occurs and signals invalid-operation if division by zero was
228
+ # attempted (during a divide-integer, divide, or remainder operation), and
229
+ # the dividend is also zero.
230
+ # The result is NaN.
231
+ class DivisionUndefined < Exception
232
+ def self.handle(context,*args)
233
+ context.num_class.nan
234
+ end
235
+ end
236
+
237
+ # Inexact Exception.
238
+ #
239
+ # This occurs and signals inexact whenever the result of an operation is
240
+ # not exact (that is, it needed to be rounded and any discarded digits
241
+ # were non-zero), or if an overflow or underflow condition occurs. The
242
+ # result in all cases is unchanged unless the context has exact precision,
243
+ # in which case the result is Nan
244
+ class Inexact < Exception
245
+ def self.handle(context, *args)
246
+ context.num_class.nan if context.exact?
247
+ end
248
+ end
249
+
250
+ # Overflow Exception.
251
+ #
252
+ # This occurs and signals overflow if the adjusted exponent of a result
253
+ # (from a conversion or from an operation that is not an attempt to divide
254
+ # by zero), after rounding, would be greater than the largest value that
255
+ # can be handled by the implementation (the value Emax).
256
+ #
257
+ # The result depends on the rounding mode:
258
+ #
259
+ # For round-half-up and round-half-even (and for round-half-down and
260
+ # round-up, if implemented), the result of the operation is +/-Infinity,
261
+ # where the sign is that of the intermediate result. For round-down, the
262
+ # result is the largest finite number that can be represented in the
263
+ # current precision, with the sign of the intermediate result. For
264
+ # round-ceiling, the result is the same as for round-down if the sign of
265
+ # the intermediate result is 1, or is +Infinity otherwise. For round-floor,
266
+ # the result is the same as for round-down if the sign of the intermediate
267
+ # result is 0, or is -Infinity otherwise. In all cases, Inexact and Rounded
268
+ # will also be raised.
269
+ class Overflow < Exception
270
+ def self.handle(context, sign, *args)
271
+ if [:half_up, :half_even, :half_down, :up].include?(context.rounding)
272
+ context.num_class.infinity(sign)
273
+ elsif sign==+1
274
+ if context.rounding == :ceiling
275
+ context.num_class.infinity(sign)
276
+ else
277
+ context.num_class.new([sign, context.num_class.int_radix_power(context.precision) - 1, context.emax - context.precision + 1])
278
+ end
279
+ elsif sign==-1
280
+ if context.rounding == :floor
281
+ context.num_class.infinity(sign)
282
+ else
283
+ context.num_class.new([sign, context.num_class.int_radix_power(context.precision) - 1, context.emax - context.precision + 1])
284
+ end
285
+ end
286
+ end
287
+ def initialize(context=nil, sign=nil, *args)
288
+ @sign = sign
289
+ super context
290
+ end
291
+ end
292
+
293
+ # Numerical Underflow with result rounded to 0 exception.
294
+ #
295
+ # This occurs and signals underflow if a result is inexact and the
296
+ # adjusted exponent of the result would be smaller (more negative) than
297
+ # the smallest value that can be handled by the implementation (the value
298
+ # emin). That is, the result is both inexact and subnormal.
299
+ #
300
+ # The result after an underflow will be a subnormal number rounded, if
301
+ # necessary, so that its exponent is not less than Etiny. This may result
302
+ # in 0 with the sign of the intermediate result and an exponent of etiny.
303
+ #
304
+ # In all cases, Inexact, Rounded, and Subnormal will also be raised.
305
+ class Underflow < Exception
306
+ end
307
+
308
+ # Clamped exception: exponent of a 0 changed to fit bounds.
309
+ #
310
+ # This occurs and signals clamped if the exponent of a result has been
311
+ # altered in order to fit the constraints of a specific concrete
312
+ # representation. This may occur when the exponent of a zero result would
313
+ # be outside the bounds of a representation, or when a large normal
314
+ # number would have an encoded exponent that cannot be represented. In
315
+ # this latter case, the exponent is reduced to fit and the corresponding
316
+ # number of zero digits are appended to the coefficient ("fold-down").
317
+ class Clamped < Exception
318
+ end
319
+
320
+ # Invalid context exception.
321
+ #
322
+ # This occurs and signals invalid-operation if an invalid context was
323
+ # detected during an operation. This can occur if contexts are not checked
324
+ # on creation and either the precision exceeds the capability of the
325
+ # underlying concrete representation or an unknown or unsupported rounding
326
+ # was specified. These aspects of the context need only be checked when
327
+ # the values are required to be used. The result is NaN.
328
+ class InvalidContext < Exception
329
+ def self.handle(context,*args)
330
+ context.num_class.nan
331
+ end
332
+ end
333
+
334
+ # Number got rounded exception (not necessarily changed during rounding).
335
+ #
336
+ # This occurs and signals rounded whenever the result of an operation is
337
+ # rounded (that is, some zero or non-zero digits were discarded from the
338
+ # coefficient), or if an overflow or underflow condition occurs. The
339
+ # result in all cases is unchanged.
340
+ class Rounded < Exception
341
+ end
342
+
343
+ # Exponent < emin before rounding exception.
344
+ #
345
+ # This occurs and signals subnormal whenever the result of a conversion or
346
+ # operation is subnormal (that is, its adjusted exponent is less than
347
+ # Emin, before any rounding). The result in all cases is unchanged.
348
+ class Subnormal < Exception
349
+ end
350
+
351
+ # Conversion syntax error exception (Trying to convert badly formed string.)
352
+ #
353
+ # This occurs and signals invalid-operation if an string is being
354
+ # converted to a number and it does not conform to the numeric string
355
+ # syntax. The result is NaN.
356
+ class ConversionSyntax < InvalidOperation
357
+ def self.handle(context, *args)
358
+ context.num_class.nan
359
+ end
360
+ end
361
+
362
+ EXCEPTIONS = FlagValues(Clamped, InvalidOperation, DivisionByZero, Inexact, Overflow, Underflow,
363
+ Rounded, Subnormal, DivisionImpossible, ConversionSyntax)
364
+
365
+ def self.Flags(*values)
366
+ Flt::Support::Flags(EXCEPTIONS,*values)
367
+ end
368
+
369
+ # Base class for Context classes.
370
+ #
371
+ # Derived classes will implement Floating-Point contexts for the specific
372
+ # floating-point types (DecNum, BinNum)
373
+ class ContextBase
374
+ # If an options hash is passed, the options are
375
+ # applied to the default context; if a Context is passed as the first
376
+ # argument, it is used as the base instead of the default context.
377
+ #
378
+ # The valid options are:
379
+ # * :rounding : one of :half_even, :half_down, :half_up, :floor,
380
+ # :ceiling, :down, :up, :up05
381
+ # * :precision : number of digits (or 0 for exact precision)
382
+ # * :exact : if true precision is ignored and Inexact conditions are trapped,
383
+ # if :quiet it set exact precision but no trapping;
384
+ # * :traps : a Flags object with the exceptions to be trapped
385
+ # * :flags : a Flags object with the raised flags
386
+ # * :ignored_flags : a Flags object with the exceptions to be ignored
387
+ # * :emin, :emax : minimum and maximum adjusted exponents
388
+ # * :elimit : the exponent limits can also be defined by a single value;
389
+ # if positive it is taken as emax and emin=1-emax; otherwiae it is
390
+ # taken as emin and emax=1-emin. Such limits comply with IEEE 754-2008
391
+ # * :capitals : (true or false) to use capitals in text representations
392
+ # * :clamp : (true or false) enables clamping
393
+ #
394
+ # See also the context constructor method Flt::Num.Context().
395
+ def initialize(num_class, *options)
396
+ @num_class = num_class
397
+
398
+ if options.first.kind_of?(ContextBase)
399
+ base = options.shift
400
+ copy_from base
401
+ else
402
+ @exact = false
403
+ @rounding = @emin = @emax = nil
404
+ @capitals = false
405
+ @clamp = false
406
+ @ignored_flags = Num::Flags()
407
+ @traps = Num::Flags()
408
+ @flags = Num::Flags()
409
+ @coercible_type_handlers = num_class.base_coercible_types.dup
410
+ @conversions = num_class.base_conversions.dup
411
+ end
412
+ assign options.first
413
+
414
+ end
415
+
416
+ # This gives access to the numeric class (Flt::Num-derived) this context is for.
417
+ def num_class
418
+ @num_class
419
+ end
420
+
421
+ # Constructor for the associated numeric class
422
+ def Num(*args)
423
+ num_class.Num(*args)
424
+ end
425
+
426
+ def radix
427
+ @num_class.radix
428
+ end
429
+
430
+ # Integral power of the base: radix**n for integer n; returns an integer.
431
+ def int_radix_power(n)
432
+ @num_class.int_radix_power(n)
433
+ end
434
+
435
+ # Multiply by an integral power of the base: x*(radix**n) for x,n integer;
436
+ # returns an integer.
437
+ def int_mult_radix_power(x,n)
438
+ @num_class.int_mult_radix_power(x,n)
439
+ end
440
+
441
+ # Divide by an integral power of the base: x/(radix**n) for x,n integer;
442
+ # returns an integer.
443
+ def int_div_radix_power(x,n)
444
+ @num_class.int_div_radix_power(x,n)
445
+ end
446
+
447
+ attr_accessor :rounding, :emin, :emax, :flags, :traps, :ignored_flags, :capitals, :clamp
448
+
449
+ # TODO: consider the convenience of adding accessors of this kind:
450
+ # def rounding(new_rounding=nil)
451
+ # old_rounding = @rounding
452
+ # @rounding = new_rounding unless new_rounding.nil?
453
+ # old_rounding
454
+ # end
455
+
456
+ # Ignore all flags if they are raised
457
+ def ignore_all_flags
458
+ #@ignored_flags << EXCEPTIONS
459
+ @ignored_flags.set!
460
+ end
461
+
462
+ # Ignore a specified set of flags if they are raised
463
+ def ignore_flags(*flags)
464
+ #@ignored_flags << flags
465
+ @ignored_flags.set(*flags)
466
+ end
467
+
468
+ # Stop ignoring a set of flags, if they are raised
469
+ def regard_flags(*flags)
470
+ @ignored_flags.clear(*flags)
471
+ end
472
+
473
+ # 'tiny' exponent (emin - precision + 1)
474
+ # is the minimum valid value for the (integral) exponent
475
+ def etiny
476
+ emin - precision + 1
477
+ end
478
+
479
+ # top exponent (emax - precision + 1)
480
+ # is the maximum valid value for the (integral) exponent
481
+ def etop
482
+ emax - precision + 1
483
+ end
484
+
485
+ # Set the exponent limits, according to IEEE 754-2008
486
+ # if e > 0 it is taken as emax and emin=1-emax
487
+ # if e < 0 it is taken as emin and emax=1-emin
488
+ def elimit=(e)
489
+ @emin, @emax = [elimit, 1-elimit].sort
490
+ end
491
+
492
+ # synonym for precision()
493
+ def digits
494
+ self.precision
495
+ end
496
+
497
+ # synonym for precision=()
498
+ def digits=(n)
499
+ self.precision=n
500
+ end
501
+
502
+ # synonym for precision()
503
+ def prec
504
+ self.precision
505
+ end
506
+
507
+ # synonym for precision=()
508
+ def prec=(n)
509
+ self.precision = n
510
+ end
511
+
512
+ # is clamping enabled?
513
+ def clamp?
514
+ @clamp
515
+ end
516
+
517
+ # Set the number of digits of precision.
518
+ # If 0 is set the precision turns to be exact.
519
+ def precision=(n)
520
+ @precision = n
521
+ @exact = false unless n==0
522
+ update_precision
523
+ n
524
+ end
525
+
526
+ # Number of digits of precision
527
+ def precision
528
+ @precision
529
+ end
530
+
531
+ # Enables or disables the exact precision
532
+ def exact=(v)
533
+ @exact = v
534
+ update_precision
535
+ v
536
+ end
537
+
538
+ # Returns true if the precision is exact
539
+ def exact
540
+ @exact
541
+ end
542
+
543
+ # Returns true if the precision is exact
544
+ def exact?
545
+ @exact
546
+ end
547
+
548
+ # Alters the contexts by assigning options from a Hash. See DecNum#new() for the valid options.
549
+ def assign(options)
550
+ if options
551
+ @rounding = options[:rounding] unless options[:rounding].nil?
552
+ @precision = options[:precision] unless options[:precision].nil?
553
+ @traps = DecNum::Flags(options[:traps]) unless options[:traps].nil?
554
+ @flags = DecNum::Flags(options[:flags]) unless options[:flags].nil?
555
+ @ignored_flags = DecNum::Flags(options[:ignored_flags]) unless options[:ignored_flags].nil?
556
+ if elimit=options[:elimit]
557
+ @emin, @emax = [elimit, 1-elimit].sort
558
+ end
559
+ @emin = options[:emin] unless options[:emin].nil?
560
+ @emax = options[:emax] unless options[:emax].nil?
561
+ @capitals = options[:capitals ] unless options[:capitals ].nil?
562
+ @clamp = options[:clamp ] unless options[:clamp ].nil?
563
+ @exact = options[:exact ] unless options[:exact ].nil?
564
+ update_precision
565
+ end
566
+ end
567
+
568
+ attr_reader :coercible_type_handlers, :conversions
569
+ protected :coercible_type_handlers, :conversions
570
+
571
+ # Copy the state from other Context object.
572
+ def copy_from(other)
573
+ raise TypeError, "Assign #{other.num_class} context to #{self.num_class} context" if other.num_class != self.num_class
574
+ @rounding = other.rounding
575
+ @precision = other.precision
576
+ @traps = other.traps.dup
577
+ @flags = other.flags.dup
578
+ @ignored_flags = other.ignored_flags.dup
579
+ @emin = other.emin
580
+ @emax = other.emax
581
+ @capitals = other.capitals
582
+ @clamp = other.clamp
583
+ @exact = other.exact
584
+ @coercible_type_handlers = other.coercible_type_handlers.dup
585
+ @conversions = other.conversions.dup
586
+ end
587
+
588
+ def dup
589
+ self.class.new(self)
590
+ end
591
+
592
+ CONDITION_MAP = {
593
+ #ConversionSyntax=>InvalidOperation,
594
+ #DivisionImpossible=>InvalidOperation,
595
+ DivisionUndefined=>InvalidOperation,
596
+ InvalidContext=>InvalidOperation
597
+ }
598
+
599
+ # Raises a flag (unless it is being ignores) and raises and
600
+ # exceptioin if the trap for it is enabled.
601
+ def exception(cond, msg='', *params)
602
+ err = (CONDITION_MAP[cond] || cond)
603
+ return err.handle(self, *params) if @ignored_flags[err]
604
+ @flags << err # @flags[err] = true
605
+ return cond.handle(self, *params) if !@traps[err]
606
+ raise err.new(*params), msg
607
+ end
608
+
609
+ # Addition of two decimal numbers
610
+ def add(x,y)
611
+ _convert(x).add(y,self)
612
+ end
613
+
614
+ # Subtraction of two decimal numbers
615
+ def subtract(x,y)
616
+ _convert(x).subtract(y,self)
617
+ end
618
+
619
+ # Multiplication of two decimal numbers
620
+ def multiply(x,y)
621
+ _convert(x).multiply(y,self)
622
+ end
623
+
624
+ # Division of two decimal numbers
625
+ def divide(x,y)
626
+ _convert(x).divide(y,self)
627
+ end
628
+
629
+ # Absolute value of a decimal number
630
+ def abs(x)
631
+ _convert(x).abs(self)
632
+ end
633
+
634
+ # Unary prefix plus operator
635
+ def plus(x)
636
+ _convert(x).plus(self)
637
+ end
638
+
639
+ # Unary prefix minus operator
640
+ def minus(x)
641
+ _convert(x)._neg(self)
642
+ end
643
+
644
+ # Converts a number to a string
645
+ def to_string(x, eng=false)
646
+ _convert(x)._fix(self).to_s(eng, self)
647
+ end
648
+
649
+ # Converts a number to a string, using scientific notation
650
+ def to_sci_string(x)
651
+ to_string x, false
652
+ end
653
+
654
+ # Converts a number to a string, using engineering notation
655
+ def to_eng_string(x)
656
+ to_string x, true
657
+ end
658
+
659
+ # Reduces an operand to its simplest form
660
+ # by removing trailing 0s and incrementing the exponent.
661
+ # (formerly called normalize in GDAS)
662
+ def reduce(x)
663
+ _convert(x).reduce(self)
664
+ end
665
+
666
+ # Normalizes (changes quantum) so that the coefficient has precision digits, unless it is subnormal.
667
+ # For surnormal numbers the Subnormal flag is raised an a subnormal is returned with the smallest
668
+ # possible exponent.
669
+ #
670
+ # This is different from reduce GDAS function which was formerly called normalize, and corresponds
671
+ # to the classic meaning of floating-point normalization.
672
+ #
673
+ # Note that the number is also rounded (precision is reduced) if it had more precision than the context.
674
+ def normalize(x)
675
+ _convert(x).normalize(self)
676
+ end
677
+
678
+ # Adjusted exponent of x returned as a DecNum value.
679
+ def logb(x)
680
+ _convert(x).logb(self)
681
+ end
682
+
683
+ # Adds the second value to the exponent of the first: x*(radix**y)
684
+ #
685
+ # y must be an integer
686
+ def scaleb(x, y)
687
+ _convert(x).scaleb(y,self)
688
+ end
689
+
690
+ # Exponent in relation to the significand as an integer
691
+ # normalized to precision digits. (minimum exponent)
692
+ def normalized_integral_exponent(x)
693
+ x = _convert(x)
694
+ x.exponent - (precision - x.number_of_digits)
695
+ end
696
+
697
+ # Significand normalized to precision digits
698
+ # x == normalized_integral_significand(x) * radix**(normalized_integral_exponent)
699
+ def normalized_integral_significand(x)
700
+ x = _convert(x)
701
+ x.coefficient*(num_class.int_radix_power(precision - x.number_of_digits))
702
+ end
703
+
704
+ # Returns both the (signed) normalized integral significand and the corresponding exponent
705
+ def to_normalized_int_scale(x)
706
+ x = _convert(x)
707
+ [x.sign*normalized_integral_significand(x), normalized_integral_exponent(x)]
708
+ end
709
+
710
+ # Is a normal number?
711
+ def normal?(x)
712
+ _convert(x).normal?(self)
713
+ end
714
+
715
+ # Is a subnormal number?
716
+ def subnormal?(x)
717
+ _convert(x).subnormal?(self)
718
+ end
719
+
720
+ # Classifies a number as one of
721
+ # 'sNaN', 'NaN', '-Infinity', '-Normal', '-Subnormal', '-Zero',
722
+ # '+Zero', '+Subnormal', '+Normal', '+Infinity'
723
+ def number_class(x)
724
+ _convert(x).number_class(self)
725
+ end
726
+
727
+ # Square root of a decimal number
728
+ def sqrt(x)
729
+ _convert(x).sqrt(self)
730
+ end
731
+
732
+ # Ruby-style integer division: (x/y).floor
733
+ def div(x,y)
734
+ _convert(x).div(y,self)
735
+ end
736
+
737
+ # Ruby-style modulo: x - y*div(x,y)
738
+ def modulo(x,y)
739
+ _convert(x).modulo(y,self)
740
+ end
741
+
742
+ # Ruby-style integer division and modulo: (x/y).floor, x - y*(x/y).floor
743
+ def divmod(x,y)
744
+ _convert(x).divmod(y,self)
745
+ end
746
+
747
+ # General Decimal Arithmetic Specification integer division: (x/y).truncate
748
+ def divide_int(x,y)
749
+ _convert(x).divide_int(y,self)
750
+ end
751
+
752
+ # General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)
753
+ def remainder(x,y)
754
+ _convert(x).remainder(y,self)
755
+ end
756
+
757
+ # General Decimal Arithmetic Specification remainder-near
758
+ # x - y*round_half_even(x/y)
759
+ def remainder_near(x,y)
760
+ _convert(x).remainder_near(y,self)
761
+ end
762
+
763
+ # General Decimal Arithmetic Specification integer division and remainder:
764
+ # (x/y).truncate, x - y*(x/y).truncate
765
+ def divrem(x,y)
766
+ _convert(x).divrem(y,self)
767
+ end
768
+
769
+ # Fused multiply-add.
770
+ #
771
+ # Computes (x*y+z) with no rounding of the intermediate product x*y.
772
+ def fma(x,y,z)
773
+ _convert(x).fma(y,z,self)
774
+ end
775
+
776
+ # Compares like <=> but returns a DecNum value.
777
+ # * -1 if x < y
778
+ # * 0 if x == b
779
+ # * +1 if x > y
780
+ # * NaN if x or y is NaN
781
+ def compare(x,y)
782
+ _convert(x).compare(y, self)
783
+ end
784
+
785
+ # Returns a copy of x with the sign set to +
786
+ def copy_abs(x)
787
+ _convert(x).copy_abs
788
+ end
789
+
790
+ # Returns a copy of x with the sign inverted
791
+ def copy_negate(x)
792
+ _convert(x).copy_negate
793
+ end
794
+
795
+ # Returns a copy of x with the sign of y
796
+ def copy_sign(x,y)
797
+ _convert(x).copy_sign(y)
798
+ end
799
+
800
+ # Rescale x so that the exponent is exp, either by padding with zeros
801
+ # or by truncating digits.
802
+ def rescale(x, exp, watch_exp=true)
803
+ _convert(x).rescale(exp, self, watch_exp)
804
+ end
805
+
806
+ # Quantize x so its exponent is the same as that of y.
807
+ def quantize(x, y, watch_exp=true)
808
+ _convert(x).quantize(y, self, watch_exp)
809
+ end
810
+
811
+ # Return true if x and y have the same exponent.
812
+ #
813
+ # If either operand is a special value, the following rules are used:
814
+ # * return true if both operands are infinities
815
+ # * return true if both operands are NaNs
816
+ # * otherwise, return false.
817
+ def same_quantum?(x,y)
818
+ _convert(x).same_quantum?(y)
819
+ end
820
+
821
+ # Rounds to a nearby integer.
822
+ #
823
+ # See also: DecNum#to_integral_value(), which does exactly the same as
824
+ # this method except that it doesn't raise Inexact or Rounded.
825
+ def to_integral_exact(x)
826
+ _convert(x).to_integral_exact(self)
827
+ end
828
+
829
+ # Rounds to a nearby integerwithout raising inexact, rounded.
830
+ #
831
+ # See also: DecNum#to_integral_exact(), which does exactly the same as
832
+ # this method except that it may raise Inexact or Rounded.
833
+ def to_integral_value(x)
834
+ _convert(x).to_integral_value(self)
835
+ end
836
+
837
+ # Returns the largest representable number smaller than x.
838
+ def next_minus(x)
839
+ _convert(x).next_minus(self)
840
+ end
841
+
842
+ # Returns the smallest representable number larger than x.
843
+ def next_plus(x)
844
+ _convert(x).next_plus(self)
845
+ end
846
+
847
+ # Returns the number closest to x, in the direction towards y.
848
+ #
849
+ # The result is the closest representable number to x
850
+ # (excluding x) that is in the direction towards y,
851
+ # unless both have the same value. If the two operands are
852
+ # numerically equal, then the result is a copy of x with the
853
+ # sign set to be the same as the sign of y.
854
+ def next_toward(x, y)
855
+ _convert(x).next_toward(y, self)
856
+ end
857
+
858
+ # ulp (unit in the last place) according to the definition proposed by J.M. Muller in
859
+ # "On the definition of ulp(x)" INRIA No. 5504
860
+ def ulp(x=nil, mode=:low)
861
+ x ||= 1
862
+ _convert(x).ulp(self, mode)
863
+ end
864
+
865
+ # Some singular DecNum values that depend on the context
866
+
867
+ # Maximum finite number
868
+ def maximum_finite(sign=+1)
869
+ return exception(InvalidOperation, "Exact context maximum finite value") if exact?
870
+ # equals +Num(+1, 1, emax)
871
+ # equals Num.infinity.next_minus(self)
872
+ Num(sign, num_class.int_radix_power(precision)-1, etop)
873
+ end
874
+
875
+ # Minimum positive normal number
876
+ def minimum_normal(sign=+1)
877
+ return exception(InvalidOperation, "Exact context maximum normal value") if exact?
878
+ #Num(sign, 1, emin).normalize(self)
879
+ Num(sign, minimum_normalized_coefficient, etiny)
880
+ end
881
+
882
+ # Maximum subnormal number
883
+ def maximum_subnormal(sign=+1)
884
+ return exception(InvalidOperation, "Exact context maximum subnormal value") if exact?
885
+ # equals mininum_normal.next_minus(self)
886
+ Num(sign, num_class.int_radix_power(precision-1)-1, etiny)
887
+ end
888
+
889
+ # Minimum nonzero positive number (minimum positive subnormal)
890
+ def minimum_nonzero(sign=+1)
891
+ return exception(InvalidOperation, "Exact context minimum nonzero value") if exact?
892
+ Num(sign, 1, etiny)
893
+ end
894
+
895
+ # This is the difference between 1 and the smallest DecNum
896
+ # value greater than 1: (DecNum(1).next_plus - DecNum(1))
897
+ def epsilon(sign=+1)
898
+ return exception(InvalidOperation, "Exact context epsilon") if exact?
899
+ Num(sign, 1, 1-precision)
900
+ end
901
+
902
+ # The strict epsilon is the smallest value that produces something different from 1
903
+ # wehen added to 1. It may be smaller than the general epsilon, because
904
+ # of the particular rounding rules used.
905
+ def strict_epsilon(sign=+1)
906
+ return exception(InvalidOperation, "Exact context strict epsilon") if exact?
907
+ # assume radix is even (num_class.radix%2 == 0)
908
+ case rounding
909
+ when :down, :floor
910
+ # largest epsilon: 0.0...10 (precision digits shown to the right of the decimal point)
911
+ exp = 1-precision
912
+ coeff = 1
913
+ when :half_even, :half_down
914
+ # next largest: 0.0...050...1 (+precision-1 additional digits here)
915
+ exp = 1-2*precision
916
+ coeff = 1 + num_class.int_radix_power(precision)/2
917
+ when :half_up
918
+ # next largest: 0.0...05 (precision digits shown to the right of the decimal point)
919
+ exp = 1-2*precision
920
+ coeff = num_class.int_radix_power(precision)/2
921
+ when :up, :ceiling, :up05
922
+ # smallest epsilon
923
+ return minimum_nonzero(sign)
924
+ end
925
+ return Num(sign, coeff, exp)
926
+ end
927
+
928
+ # This is the maximum relative error corresponding to 1/2 ulp:
929
+ # (radix/2)*radix**(-precision) == epsilon/2
930
+ # This is called "machine epsilon" in Goldberg's "What Every Computer Scientist..."
931
+ def half_epsilon(sign=+1)
932
+ Num(sign, num_class.radix/2, -precision)
933
+ end
934
+
935
+ def to_s
936
+ inspect
937
+ end
938
+
939
+ def inspect
940
+ class_name = self.class.to_s.split('::').last
941
+ "<#{class_name}:\n" +
942
+ instance_variables.map { |v| " #{v}: #{eval(v).inspect}"}.join("\n") +
943
+ ">\n"
944
+ end
945
+
946
+ # Maximum integral significand value for numbers using this context's precision.
947
+ def maximum_coefficient
948
+ if exact?
949
+ exception(InvalidOperation, 'Exact maximum coefficient')
950
+ nil
951
+ else
952
+ num_class.int_radix_power(precision)-1
953
+ end
954
+ end
955
+
956
+ # Minimum value of a normalized coefficient (normalized unit)
957
+ def minimum_normalized_coefficient
958
+ if exact?
959
+ exception(InvalidOperation, 'Exact maximum coefficient')
960
+ nil
961
+ else
962
+ num_class.int_radix_power(precision-1)
963
+ end
964
+ end
965
+
966
+ # Maximum number of diagnostic digits in NaNs for numbers using this context's precision.
967
+ def maximum_nan_diagnostic_digits
968
+ if exact?
969
+ nil # ?
970
+ else
971
+ precision - (clamp ? 1 : 0)
972
+ end
973
+ end
974
+
975
+ # Internal use: array of numeric types that be coerced to DecNum.
976
+ def coercible_types
977
+ @coercible_type_handlers.keys
978
+ end
979
+
980
+ # Internal use: array of numeric types that be coerced to DecNum, including DecNum
981
+ def coercible_types_or_num
982
+ [num_class] + coercible_types
983
+ end
984
+
985
+ # Internally used to convert numeric types to DecNum (or to an array [sign,coefficient,exponent])
986
+ def _coerce(x)
987
+ c = x.class
988
+ while c!=Object && (h=@coercible_type_handlers[c]).nil?
989
+ c = c.superclass
990
+ end
991
+ if h
992
+ h.call(x, self)
993
+ else
994
+ nil
995
+ end
996
+ end
997
+
998
+ # Define a numerical conversion from type to DecNum.
999
+ # The block that defines the conversion has two parameters: the value to be converted and the context and
1000
+ # must return either a DecNum or [sign,coefficient,exponent]
1001
+ def define_conversion_from(type, &blk)
1002
+ @coercible_type_handlers[type] = blk
1003
+ end
1004
+
1005
+ # Define a numerical conversion from DecNum to type as an instance method of DecNum
1006
+ def define_conversion_to(type, &blk)
1007
+ @conversions[type] = blk
1008
+ end
1009
+
1010
+ # Convert a DecNum x to other numerical type
1011
+ def convert_to(type, x)
1012
+ converter = @conversions[type]
1013
+ if converter.nil?
1014
+ raise TypeError, "Undefined conversion from DecNum to #{type}."
1015
+ elsif converter.is_a?(Symbol)
1016
+ x.send converter
1017
+ else
1018
+ converter.call(x)
1019
+ end
1020
+ end
1021
+
1022
+ # Simply calls x.split; implemented to ease handling Float and BigDecimal as Nums withoug
1023
+ # having to add methods like split to those classes.
1024
+ def split(x)
1025
+ _convert(x).split
1026
+ end
1027
+
1028
+ def to_int_scale(x)
1029
+ _convert(x).to_int_scale
1030
+ end
1031
+
1032
+ def sign(x)
1033
+ _convert(x).sign
1034
+ end
1035
+
1036
+ def coefficient(x)
1037
+ _convert(x).coefficient
1038
+ end
1039
+
1040
+ def exponent(x)
1041
+ _convert(x).exponent
1042
+ end
1043
+
1044
+ def nan?(x)
1045
+ _convert(x).nan?
1046
+ end
1047
+
1048
+ def infinite?(x)
1049
+ _convert(x).infinite?
1050
+ end
1051
+
1052
+ def zero?(x)
1053
+ _convert(x).zero?
1054
+ end
1055
+
1056
+ private
1057
+
1058
+ def _convert(x)
1059
+ # cannot call AuxiliarFunctions._convert now because it needs num_class
1060
+ # alternatives:
1061
+ # num_class.send(:_convert, x) # cannot num_class._convert because it is private
1062
+ # extend ContextBase with AuxiliarFunctions
1063
+ @num_class.send :_convert, x
1064
+ end
1065
+
1066
+ def update_precision
1067
+ if @emax && !@emin
1068
+ @emin = 1 - @emax
1069
+ elsif @emin && !@emax
1070
+ @emax = 1 - @emin
1071
+ end
1072
+ if @exact || @precision==0
1073
+ quiet = (@exact == :quiet)
1074
+ @exact = true
1075
+ @precision = 0
1076
+ @traps << Inexact unless quiet
1077
+ @ignored_flags[Inexact] = false
1078
+ else
1079
+ @traps[Inexact] = false
1080
+ end
1081
+ end
1082
+
1083
+ end
1084
+
1085
+ # Context constructor; if an options hash is passed, the options are
1086
+ # applied to the default context; if a Context is passed as the first
1087
+ # argument, it is used as the base instead of the default context.
1088
+ #
1089
+ # Note that this method should be called on concrete floating point types such as
1090
+ # Flt::DecNum and Flt::BinNum, and not in the abstract base class Flt::Num.
1091
+ #
1092
+ # See Flt::Num::ContextBase#new() for the valid options
1093
+ def self.Context(*args)
1094
+ case args.size
1095
+ when 0
1096
+ base = self::DefaultContext
1097
+ when 1
1098
+ arg = args.first
1099
+ if arg.instance_of?(self::Context)
1100
+ base = arg
1101
+ options = nil
1102
+ elsif arg.instance_of?(Hash)
1103
+ base = self::DefaultContext
1104
+ options = arg
1105
+ else
1106
+ raise TypeError,"invalid argument for #{num_class}.Context"
1107
+ end
1108
+ when 2
1109
+ base = args.first
1110
+ options = args.last
1111
+ else
1112
+ raise ArgumentError,"wrong number of arguments (#{args.size} for 0, 1 or 2)"
1113
+ end
1114
+
1115
+ if options.nil? || options.empty?
1116
+ base
1117
+ else
1118
+ self::Context.new(base, options)
1119
+ end
1120
+
1121
+ end
1122
+
1123
+ # Define a context by passing either of:
1124
+ # * A Context object (of the same type)
1125
+ # * A hash of options (or nothing) to alter a copy of the current context.
1126
+ # * A Context object and a hash of options to alter a copy of it
1127
+ def self.define_context(*options)
1128
+ context = options.shift if options.first.instance_of?(self::Context)
1129
+ if context && options.empty?
1130
+ context
1131
+ else
1132
+ context ||= self.context
1133
+ self.Context(context, *options)
1134
+ end
1135
+ end
1136
+
1137
+ # This makes the class define context accesible to instance methods
1138
+ def define_context(*options)
1139
+ self.class.define_context(*options)
1140
+ end
1141
+ private :define_context
1142
+
1143
+ # The current context (thread-local).
1144
+ # If arguments are passed they are interpreted as in Num.define_context() to change
1145
+ # the current context.
1146
+ # If a block is given, this method is a synonym for Num.local_context().
1147
+ def self.context(*args, &blk)
1148
+ if blk
1149
+ # setup a local context
1150
+ local_context(*args, &blk)
1151
+ elsif args.empty?
1152
+ # return the current context
1153
+ # return the current context
1154
+ self._context = self::DefaultContext.dup if _context.nil?
1155
+ _context
1156
+ else
1157
+ # change the current context
1158
+ # TODO: consider doing self._context = ... here
1159
+ # so we would have DecNum.context = c that assigns a duplicate of c
1160
+ # and DecNum.context c to set alias c
1161
+ self.context = define_context(*args)
1162
+ end
1163
+ end
1164
+
1165
+ # Change the current context (thread-local).
1166
+ def self.context=(c)
1167
+ self._context = c.dup
1168
+ end
1169
+
1170
+ # Defines a scope with a local context. A context can be passed which will be
1171
+ # set a the current context for the scope; also a hash can be passed with
1172
+ # options to apply to the local scope.
1173
+ # Changes done to the current context are reversed when the scope is exited.
1174
+ def self.local_context(*args)
1175
+ keep = self.context # use this so _context is initialized if necessary
1176
+ self.context = define_context(*args) # this dups the assigned context
1177
+ result = yield _context
1178
+ # TODO: consider the convenience of copying the flags from DecNum.context to keep
1179
+ # This way a local context does not affect the settings of the previous context,
1180
+ # but flags are transferred.
1181
+ # (this could be done always or be controlled by some option)
1182
+ # keep.flags = DecNum.context.flags
1183
+ # Another alternative to consider: logically or the flags:
1184
+ # keep.flags ||= DecNum.context.flags # (this requires implementing || in Flags)
1185
+ self._context = keep
1186
+ result
1187
+ end
1188
+
1189
+ class <<self
1190
+ # This is the thread-local context storage low level interface
1191
+ protected
1192
+ def _context #:nodoc:
1193
+ # TODO: memoize the variable id
1194
+ Thread.current["Flt::#{self}.context"]
1195
+ end
1196
+ def _context=(c) #:nodoc:
1197
+ Thread.current["Flt::#{self}.context"] = c
1198
+ end
1199
+ end
1200
+
1201
+ def num_class
1202
+ self.class
1203
+ end
1204
+
1205
+ class <<self
1206
+ def num_class
1207
+ self
1208
+ end
1209
+ end
1210
+
1211
+ class << self
1212
+ # A floating-point number with value zero and the specified sign
1213
+ def zero(sign=+1)
1214
+ new [sign, 0, 0]
1215
+ end
1216
+
1217
+ # A floating-point infinite number with the specified sign
1218
+ def infinity(sign=+1)
1219
+ new [sign, 0, :inf]
1220
+ end
1221
+
1222
+ # A floating-point NaN (not a number)
1223
+ def nan()
1224
+ new [+1, nil, :nan]
1225
+ end
1226
+ end
1227
+
1228
+
1229
+ class <<self
1230
+ def int_radix_power(n)
1231
+ self.radix**n
1232
+ end
1233
+
1234
+ def int_mult_radix_power(x,n)
1235
+ x * self.radix**n
1236
+ end
1237
+
1238
+ def int_div_radix_power(x,n)
1239
+ x / self.radix**n
1240
+ end
1241
+ end
1242
+
1243
+ # A floating point-number value can be defined by:
1244
+ # * A String containing a text representation of the number
1245
+ # * An Integer
1246
+ # * A Rational
1247
+ # * For binary floating point: a Float
1248
+ # * A Value of a type for which conversion is defined in the context.
1249
+ # * Another floating-point value of the same type.
1250
+ # * A sign, coefficient and exponent (either as separate arguments, as an array or as a Hash with symbolic keys),
1251
+ # or a signed coefficient and an exponent.
1252
+ # This is the internal representation of Num, as returned by Num#split.
1253
+ # The sign is +1 for plus and -1 for minus; the coefficient and exponent are
1254
+ # integers, except for special values which are defined by :inf, :nan or :snan for the exponent.
1255
+ #
1256
+ # An optional Context can be passed after the value-definint argument to override the current context
1257
+ # and options can be passed in a last hash argument; alternatively context options can be overriden
1258
+ # by options of the hash argument.
1259
+ #
1260
+ # When the number is defined by a numeric literal (a String), it can be followed by a symbol that specifies
1261
+ # the mode used to convert the literal to a floating-point value:
1262
+ # * :free is currently the default for all cases. The precision of the input literal (including trailing zeros)
1263
+ # is preserved and the precision of the context is ignored.
1264
+ # When the literal is in the same base as the floating-point radix, (which, by default, is the case for
1265
+ # DecNum only), the literal is preserved exactly in floating-point.
1266
+ # Otherwise, all significative digits that can be derived from the literal are generanted, significative
1267
+ # meaning here that if the digit is changed and the value converted back to a literal of the same base and
1268
+ # precision, the original literal will not be obtained.
1269
+ # * :short is a variation of :free in which only the minimun number of digits that are necessary to
1270
+ # produce the original literal when the value is converted back with the same original precision.
1271
+ # * :fixed will round and normalize the value to the precision specified by the context (normalize meaning
1272
+ # that exaclty the number of digits specified by the precision will be generated, even if the original
1273
+ # literal has fewer digits.) This may fail returning NaN (and raising Inexact) if the context precision is
1274
+ # :exact, but not if the floating-point radix is a multiple of the input base.
1275
+ #
1276
+ # Options that can be passed for construction from literal:
1277
+ # * :base is the numeric base of the input, 10 by default.
1278
+ def initialize(*args)
1279
+ options = args.pop if args.last.is_a?(Hash)
1280
+ context = args.pop if args.size>0 && (args.last.kind_of?(ContextBase) || args.last.nil?)
1281
+ context ||= options && options.delete(:context)
1282
+ mode = args.pop if args.last.is_a?(Symbol) && ![:inf, :nan, :snan].include?(args.last)
1283
+ args = args.first if args.size==1 && args.first.is_a?(Array)
1284
+ if args.empty? && options
1285
+ args = [options.delete(:sign)||+1,
1286
+ options.delete(:coefficient) || 0,
1287
+ options.delete(:exponent) || 0]
1288
+ end
1289
+ mode ||= options && options.delete(:mode)
1290
+ base = (options && options.delete(:base)) || 10
1291
+ context = options if context.nil? && options && !options.empty?
1292
+ context = define_context(context)
1293
+
1294
+ case args.size
1295
+ when 3
1296
+ # internal representation
1297
+ @sign, @coeff, @exp = args
1298
+ # TO DO: validate
1299
+
1300
+ when 2
1301
+ # signed integer and scale
1302
+ @coeff, @exp = args
1303
+ if @coeff < 0
1304
+ @sign = -1
1305
+ @coeff = -@coeff
1306
+ else
1307
+ @sign = +1
1308
+ end
1309
+
1310
+ when 1
1311
+ arg = args.first
1312
+ case arg
1313
+
1314
+ when num_class
1315
+ @sign, @coeff, @exp = arg.split
1316
+
1317
+ when *context.coercible_types
1318
+ v = context._coerce(arg)
1319
+ @sign, @coeff, @exp = v.is_a?(Num) ? v.split : v
1320
+
1321
+ when String
1322
+ if arg.strip != arg
1323
+ @sign,@coeff,@exp = context.exception(ConversionSyntax, "no trailing or leading whitespace is permitted").split
1324
+ return
1325
+ end
1326
+ m = _parser(arg)
1327
+ if m.nil?
1328
+ @sign,@coeff,@exp = context.exception(ConversionSyntax, "Invalid literal for DecNum: #{arg.inspect}").split
1329
+ return
1330
+ end
1331
+ @sign = (m.sign == '-') ? -1 : +1
1332
+ if m.int || m.onlyfrac
1333
+ sign = @sign
1334
+ if m.int
1335
+ intpart = m.int
1336
+ fracpart = m.frac
1337
+ else
1338
+ intpart = ''
1339
+ fracpart = m.onlyfrac
1340
+ end
1341
+ exp = m.exp.to_i
1342
+ if fracpart
1343
+ coeff = (intpart+fracpart).to_i(base)
1344
+ exp -= fracpart.size
1345
+ else
1346
+ coeff = intpart.to_i(base)
1347
+ end
1348
+
1349
+ if false
1350
+ # Old behaviour: use :fixed format when num_class.radix != base
1351
+ # Advantages:
1352
+ # * Behaviour similar to Float: BinFloat(txt) == Float(txt)
1353
+ mode ||= ((num_class.radix == base) ? :free : :fixed)
1354
+ else
1355
+ # New behaviour: the default is always :free
1356
+ # Advantages:
1357
+ # * Is coherent with construction of DecNum from decimal literal:
1358
+ # preserve precision of the literal with independence of context.
1359
+ mode ||= :free
1360
+ end
1361
+
1362
+ if [:free, :short].include?(mode) && base == num_class.radix
1363
+ # simple case, the job is already done
1364
+ else
1365
+ rounding = context.rounding
1366
+ reader = Support::Reader.new(:mode=>mode)
1367
+ ans = reader.read(context, rounding, sign, coeff, exp, base)
1368
+ context.exception(Inexact,"Inexact decimal to radix #{num_class.radix} conversion") if !reader.exact?
1369
+ if !reader.exact? && context.exact?
1370
+ sign, coeff, exp = num_class.nan.split
1371
+ else
1372
+ sign, coeff, exp = ans.split
1373
+ end
1374
+ end
1375
+ @sign, @coeff, @exp = sign, coeff, exp
1376
+ else
1377
+ if m.diag
1378
+ # NaN
1379
+ @coeff = (m.diag.nil? || m.diag.empty?) ? nil : m.diag.to_i
1380
+ @coeff = nil if @coeff==0
1381
+ if @coeff
1382
+ max_diag_len = context.maximum_nan_diagnostic_digits
1383
+ if max_diag_len && @coeff >= context.int_radix_power(max_diag_len)
1384
+ @sign,@coeff,@exp = context.exception(ConversionSyntax, "diagnostic info too long in NaN").split
1385
+ return
1386
+ end
1387
+ end
1388
+ @exp = m.signal ? :snan : :nan
1389
+ else
1390
+ # Infinity
1391
+ @coeff = 0
1392
+ @exp = :inf
1393
+ end
1394
+ end
1395
+ else
1396
+ raise TypeError, "invalid argument #{arg.inspect}"
1397
+ end
1398
+ else
1399
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 1, 2 or 3)"
1400
+ end
1401
+ end
1402
+
1403
+ # shortcut constructor:
1404
+ def Num(*args)
1405
+ self.class.Num(*args)
1406
+ end
1407
+ private :Num
1408
+
1409
+ class <<self
1410
+ # Num is the general constructor that can be invoked on specific Flt::Num-derived classes.
1411
+ def Num(*args)
1412
+ if args.size==1 && args.first.instance_of?(self)
1413
+ args.first
1414
+ else
1415
+ new(*args)
1416
+ end
1417
+ end
1418
+ end
1419
+
1420
+ # Returns the internal representation of the number, composed of:
1421
+ # * a sign which is +1 for plus and -1 for minus
1422
+ # * a coefficient (significand) which is a nonnegative integer
1423
+ # * an exponent (an integer) or :inf, :nan or :snan for special values
1424
+ # The value of non-special numbers is sign*coefficient*10^exponent
1425
+ def split
1426
+ [@sign, @coeff, @exp]
1427
+ end
1428
+
1429
+ # Returns whether the number is a special value (NaN or Infinity).
1430
+ def special?
1431
+ @exp.instance_of?(Symbol)
1432
+ end
1433
+
1434
+ # Returns whether the number is not actualy one (NaN, not a number).
1435
+ def nan?
1436
+ @exp==:nan || @exp==:snan
1437
+ end
1438
+
1439
+ # Returns whether the number is a quite NaN (non-signaling)
1440
+ def qnan?
1441
+ @exp == :nan
1442
+ end
1443
+
1444
+ # Returns whether the number is a signaling NaN
1445
+ def snan?
1446
+ @exp == :snan
1447
+ end
1448
+
1449
+ # Returns whether the number is infinite
1450
+ def infinite?
1451
+ @exp == :inf
1452
+ end
1453
+
1454
+ # Returns whether the number is finite
1455
+ def finite?
1456
+ !special?
1457
+ end
1458
+
1459
+ # Returns whether the number is zero
1460
+ def zero?
1461
+ @coeff==0 && !special?
1462
+ end
1463
+
1464
+ # Returns whether the number not zero
1465
+ def nonzero?
1466
+ special? || @coeff>0
1467
+ end
1468
+
1469
+ # Returns whether the number is subnormal
1470
+ def subnormal?(context=nil)
1471
+ return false if special? || zero?
1472
+ context = define_context(context)
1473
+ self.adjusted_exponent < context.emin
1474
+ end
1475
+
1476
+ # Returns whether the number is normal
1477
+ def normal?(context=nil)
1478
+ return false if special? || zero?
1479
+ context = define_context(context)
1480
+ (context.emin <= self.adjusted_exponent) && (self.adjusted_exponent <= context.emax)
1481
+ end
1482
+
1483
+ # Classifies a number as one of
1484
+ # 'sNaN', 'NaN', '-Infinity', '-Normal', '-Subnormal', '-Zero',
1485
+ # '+Zero', '+Subnormal', '+Normal', '+Infinity'
1486
+ def number_class(context=nil)
1487
+ return "sNaN" if snan?
1488
+ return "NaN" if nan?
1489
+ if infinite?
1490
+ return '+Infinity' if @sign==+1
1491
+ return '-Infinity' # if @sign==-1
1492
+ end
1493
+ if zero?
1494
+ return '+Zero' if @sign==+1
1495
+ return '-Zero' # if @sign==-1
1496
+ end
1497
+ define_context(context)
1498
+ if subnormal?(context)
1499
+ return '+Subnormal' if @sign==+1
1500
+ return '-Subnormal' # if @sign==-1
1501
+ end
1502
+ return '+Normal' if @sign==+1
1503
+ return '-Normal' if @sign==-1
1504
+ end
1505
+
1506
+ # Used internally to convert numbers to be used in an operation to a suitable numeric type
1507
+ def coerce(other)
1508
+ case other
1509
+ when *num_class.context.coercible_types_or_num
1510
+ [Num(other),self]
1511
+ when Float
1512
+ [other, self.to_f]
1513
+ else
1514
+ super
1515
+ end
1516
+ end
1517
+
1518
+ # Used internally to define binary operators
1519
+ def _bin_op(op, meth, other, context=nil)
1520
+ context = define_context(context)
1521
+ case other
1522
+ when *context.coercible_types_or_num
1523
+ self.send meth, Num(other, context), context
1524
+ else
1525
+ x, y = other.coerce(self)
1526
+ x.send op, y
1527
+ end
1528
+ end
1529
+ private :_bin_op
1530
+
1531
+ # Unary minus operator
1532
+ def -@(context=nil)
1533
+ #(context || num_class.context).minus(self)
1534
+ _neg(context)
1535
+ end
1536
+
1537
+ # Unary plus operator
1538
+ def +@(context=nil)
1539
+ #(context || num_class.context).plus(self)
1540
+ _pos(context)
1541
+ end
1542
+
1543
+ # Addition of two decimal numbers
1544
+ def +(other, context=nil)
1545
+ _bin_op :+, :add, other, context
1546
+ end
1547
+
1548
+ # Subtraction of two decimal numbers
1549
+ def -(other, context=nil)
1550
+ _bin_op :-, :subtract, other, context
1551
+ end
1552
+
1553
+ # Multiplication of two decimal numbers
1554
+ def *(other, context=nil)
1555
+ _bin_op :*, :multiply, other, context
1556
+ end
1557
+
1558
+ # Division of two decimal numbers
1559
+ def /(other, context=nil)
1560
+ _bin_op :/, :divide, other, context
1561
+ end
1562
+
1563
+ # Modulo of two decimal numbers
1564
+ def %(other, context=nil)
1565
+ _bin_op :%, :modulo, other, context
1566
+ end
1567
+
1568
+ # Power
1569
+ def **(other, context=nil)
1570
+ _bin_op :**, :power, other, context
1571
+ end
1572
+
1573
+ # Addition
1574
+ def add(other, context=nil)
1575
+
1576
+ context = define_context(context)
1577
+ other = _convert(other)
1578
+
1579
+ if self.special? || other.special?
1580
+ ans = _check_nans(context,other)
1581
+ return ans if ans
1582
+
1583
+ if self.infinite?
1584
+ if self.sign != other.sign && other.infinite?
1585
+ return context.exception(InvalidOperation, '-INF + INF')
1586
+ end
1587
+ return Num(self)
1588
+ end
1589
+
1590
+ return Num(other) if other.infinite?
1591
+ end
1592
+
1593
+ exp = [self.exponent, other.exponent].min
1594
+ negativezero = (context.rounding == ROUND_FLOOR && self.sign != other.sign)
1595
+
1596
+ if self.zero? && other.zero?
1597
+ sign = [self.sign, other.sign].max
1598
+ sign = -1 if negativezero
1599
+ ans = Num([sign, 0, exp])._fix(context)
1600
+ return ans
1601
+ end
1602
+
1603
+ if self.zero?
1604
+ exp = [exp, other.exponent - context.precision - 1].max unless context.exact?
1605
+ return other._rescale(exp, context.rounding)._fix(context)
1606
+ end
1607
+
1608
+ if other.zero?
1609
+ exp = [exp, self.exponent - context.precision - 1].max unless context.exact?
1610
+ return self._rescale(exp, context.rounding)._fix(context)
1611
+ end
1612
+
1613
+ op1, op2 = _normalize(self, other, context.precision)
1614
+
1615
+ result_sign = result_coeff = result_exp = nil
1616
+ if op1.sign != op2.sign
1617
+ return ans = Num(negativezero ? -1 : +1, 0, exp)._fix(context) if op1.coefficient == op2.coefficient
1618
+ op1,op2 = op2,op1 if op1.coefficient < op2.coefficient
1619
+ result_sign = op1.sign
1620
+ op1,op2 = op1.copy_negate, op2.copy_negate if result_sign < 0
1621
+ elsif op1.sign < 0
1622
+ result_sign = -1
1623
+ op1,op2 = op1.copy_negate, op2.copy_negate
1624
+ else
1625
+ result_sign = +1
1626
+ end
1627
+
1628
+ if op2.sign == +1
1629
+ result_coeff = op1.coefficient + op2.coefficient
1630
+ else
1631
+ result_coeff = op1.coefficient - op2.coefficient
1632
+ end
1633
+
1634
+ result_exp = op1.exponent
1635
+
1636
+ return Num(result_sign, result_coeff, result_exp)._fix(context)
1637
+
1638
+ end
1639
+
1640
+ # Subtraction
1641
+ def subtract(other, context=nil)
1642
+
1643
+ context = define_context(context)
1644
+ other = _convert(other)
1645
+
1646
+ if self.special? || other.special?
1647
+ ans = _check_nans(context,other)
1648
+ return ans if ans
1649
+ end
1650
+ return add(other.copy_negate, context)
1651
+ end
1652
+
1653
+ # Multiplication
1654
+ def multiply(other, context=nil)
1655
+ context = define_context(context)
1656
+ other = _convert(other)
1657
+ resultsign = self.sign * other.sign
1658
+ if self.special? || other.special?
1659
+ ans = _check_nans(context,other)
1660
+ return ans if ans
1661
+
1662
+ if self.infinite?
1663
+ return context.exception(InvalidOperation,"(+-)INF * 0") if other.zero?
1664
+ return num_class.infinity(resultsign)
1665
+ end
1666
+ if other.infinite?
1667
+ return context.exception(InvalidOperation,"0 * (+-)INF") if self.zero?
1668
+ return num_class.infinity(resultsign)
1669
+ end
1670
+ end
1671
+
1672
+ resultexp = self.exponent + other.exponent
1673
+
1674
+ return Num(resultsign, 0, resultexp)._fix(context) if self.zero? || other.zero?
1675
+ #return Num(resultsign, other.coefficient, resultexp)._fix(context) if self.coefficient==1
1676
+ #return Num(resultsign, self.coefficient, resultexp)._fix(context) if other.coefficient==1
1677
+
1678
+ return Num(resultsign, other.coefficient*self.coefficient, resultexp)._fix(context)
1679
+
1680
+ end
1681
+
1682
+ # Division
1683
+ def divide(other, context=nil)
1684
+ context = define_context(context)
1685
+ other = _convert(other)
1686
+ resultsign = self.sign * other.sign
1687
+ if self.special? || other.special?
1688
+ ans = _check_nans(context,other)
1689
+ return ans if ans
1690
+ if self.infinite?
1691
+ return context.exception(InvalidOperation,"(+-)INF/(+-)INF") if other.infinite?
1692
+ return num_class.infinity(resultsign)
1693
+ end
1694
+ if other.infinite?
1695
+ context.exception(Clamped,"Division by infinity")
1696
+ return num_class.new([resultsign, 0, context.etiny])
1697
+ end
1698
+ end
1699
+
1700
+ if other.zero?
1701
+ return context.exception(DivisionUndefined, '0 / 0') if self.zero?
1702
+ return context.exception(DivisionByZero, 'x / 0', resultsign)
1703
+ end
1704
+
1705
+ if self.zero?
1706
+ exp = self.exponent - other.exponent
1707
+ coeff = 0
1708
+ else
1709
+ prec = context.exact? ? self.number_of_digits + 4*other.number_of_digits : context.precision
1710
+ shift = other.number_of_digits - self.number_of_digits + prec
1711
+ shift += 1
1712
+ exp = self.exponent - other.exponent - shift
1713
+ if shift >= 0
1714
+ coeff, remainder = (self.coefficient*num_class.int_radix_power(shift)).divmod(other.coefficient)
1715
+ else
1716
+ coeff, remainder = self.coefficient.divmod(other.coefficient*num_class.int_radix_power(-shift))
1717
+ end
1718
+ if remainder != 0
1719
+ return context.exception(Inexact) if context.exact?
1720
+ # result is not exact; adjust to ensure correct rounding
1721
+ if num_class.radix == 10
1722
+ # perform 05up rounding so the the final rounding will be correct
1723
+ coeff += 1 if (coeff%5) == 0
1724
+ else
1725
+ # since we will round to less digits and there is a remainder, we just need
1726
+ # to append some nonzero digit; but we must avoid producing a tie (adding a single
1727
+ # digit whose value is radix/2), so we append two digits, 01, that will be rounded away
1728
+ coeff = num_class.int_mult_radix_power(coeff, 2) + 1
1729
+ exp -= 2
1730
+ end
1731
+ else
1732
+ # result is exact; get as close to idaal exponent as possible
1733
+ ideal_exp = self.exponent - other.exponent
1734
+ while (exp < ideal_exp) && ((coeff % num_class.radix)==0)
1735
+ coeff /= num_class.radix
1736
+ exp += 1
1737
+ end
1738
+ end
1739
+
1740
+ end
1741
+ return Num(resultsign, coeff, exp)._fix(context)
1742
+
1743
+ end
1744
+
1745
+ # Square root
1746
+ def sqrt(context=nil)
1747
+ context = define_context(context)
1748
+ if special?
1749
+ ans = _check_nans(context)
1750
+ return ans if ans
1751
+ return Num(self) if infinite? && @sign==+1
1752
+ end
1753
+ return Num(@sign, 0, @exp/2)._fix(context) if zero?
1754
+ return context.exception(InvalidOperation, 'sqrt(-x), x>0') if @sign<0
1755
+ prec = context.precision + 1
1756
+
1757
+ # express the number in radix**2 base
1758
+ e = (@exp >> 1)
1759
+ if (@exp & 1)!=0
1760
+ c = @coeff*num_class.radix
1761
+ l = (number_of_digits >> 1) + 1
1762
+ else
1763
+ c = @coeff
1764
+ l = (number_of_digits+1) >> 1
1765
+ end
1766
+ shift = prec - l
1767
+ if shift >= 0
1768
+ c = num_class.int_mult_radix_power(c, (shift<<1))
1769
+ exact = true
1770
+ else
1771
+ c, remainder = c.divmod(num_class.int_radix_power((-shift)<<1))
1772
+ exact = (remainder==0)
1773
+ end
1774
+ e -= shift
1775
+
1776
+ n = num_class.int_radix_power(prec)
1777
+ while true
1778
+ q = c / n
1779
+ break if n <= q
1780
+ n = ((n + q) >> 1)
1781
+ end
1782
+ exact = exact && (n*n == c)
1783
+
1784
+ if exact
1785
+ if shift >= 0
1786
+ n = num_class.int_div_radix_power(n, shift)
1787
+ else
1788
+ n = num_class.int_mult_radix_power(n, -shift)
1789
+ end
1790
+ e += shift
1791
+ else
1792
+ return context.exception(Inexact) if context.exact?
1793
+ # result is not exact; adjust to ensure correct rounding
1794
+ if num_class.radix == 10
1795
+ n += 1 if (n%5)==0
1796
+ else
1797
+ n = num_class.int_mult_radix_power(n, 2) + 1
1798
+ e -= 2
1799
+ end
1800
+ end
1801
+ ans = Num(+1,n,e)
1802
+ num_class.local_context(:rounding=>:half_even) do
1803
+ ans = ans._fix(context)
1804
+ end
1805
+ return ans
1806
+ end
1807
+
1808
+ # Absolute value
1809
+ def abs(context=nil)
1810
+ if special?
1811
+ ans = _check_nans(context)
1812
+ return ans if ans
1813
+ end
1814
+ sign<0 ? _neg(context) : _pos(context)
1815
+ end
1816
+
1817
+ # Unary prefix plus operator
1818
+ def plus(context=nil)
1819
+ _pos(context)
1820
+ end
1821
+
1822
+ # Unary prefix minus operator
1823
+ def minus(context=nil)
1824
+ _neg(context)
1825
+ end
1826
+
1827
+ # Largest representable number smaller than itself
1828
+ def next_minus(context=nil)
1829
+ context = define_context(context)
1830
+ if special?
1831
+ ans = _check_nans(context)
1832
+ return ans if ans
1833
+ if infinite?
1834
+ return Num(self) if @sign == -1
1835
+ # @sign == +1
1836
+ if context.exact?
1837
+ return context.exception(InvalidOperation, 'Exact +INF next minus')
1838
+ else
1839
+ return Num(+1, context.maximum_coefficient, context.etop)
1840
+ end
1841
+ end
1842
+ end
1843
+
1844
+ return context.exception(InvalidOperation, 'Exact next minus') if context.exact?
1845
+
1846
+ result = nil
1847
+ num_class.local_context(context) do |local|
1848
+ local.rounding = :floor
1849
+ local.ignore_all_flags
1850
+ result = self._fix(local)
1851
+ if result == self
1852
+ result = self - Num(+1, 1, local.etiny-1)
1853
+ end
1854
+ end
1855
+ result
1856
+ end
1857
+
1858
+ # Smallest representable number larger than itself
1859
+ def next_plus(context=nil)
1860
+ context = define_context(context)
1861
+
1862
+ if special?
1863
+ ans = _check_nans(context)
1864
+ return ans if ans
1865
+ if infinite?
1866
+ return Num(self) if @sign == +1
1867
+ # @sign == -1
1868
+ if context.exact?
1869
+ return context.exception(InvalidOperation, 'Exact -INF next plus')
1870
+ else
1871
+ return Num(-1, context.maximum_coefficient, context.etop)
1872
+ end
1873
+ end
1874
+ end
1875
+
1876
+ return context.exception(InvalidOperation, 'Exact next plus') if context.exact?
1877
+
1878
+ result = nil
1879
+ num_class.local_context(context) do |local|
1880
+ local.rounding = :ceiling
1881
+ local.ignore_all_flags
1882
+ result = self._fix(local)
1883
+ if result == self
1884
+ result = self + Num(+1, 1, local.etiny-1)
1885
+ end
1886
+ end
1887
+ result
1888
+
1889
+ end
1890
+
1891
+ # Returns the number closest to self, in the direction towards other.
1892
+ def next_toward(other, context=nil)
1893
+ context = define_context(context)
1894
+ other = _convert(other)
1895
+ ans = _check_nans(context,other)
1896
+ return ans if ans
1897
+
1898
+ return context.exception(InvalidOperation, 'Exact next_toward') if context.exact?
1899
+
1900
+ comparison = self <=> other
1901
+ return self.copy_sign(other) if comparison == 0
1902
+
1903
+ if comparison == -1
1904
+ result = self.next_plus(context)
1905
+ else # comparison == 1
1906
+ result = self.next_minus(context)
1907
+ end
1908
+
1909
+ # decide which flags to raise using value of ans
1910
+ if result.infinite?
1911
+ context.exception Overflow, 'Infinite result from next_toward', result.sign
1912
+ context.exception Rounded
1913
+ context.exception Inexact
1914
+ elsif result.adjusted_exponent < context.emin
1915
+ context.exception Underflow
1916
+ context.exception Subnormal
1917
+ context.exception Rounded
1918
+ context.exception Inexact
1919
+ # if precision == 1 then we don't raise Clamped for a
1920
+ # result 0E-etiny.
1921
+ context.exception Clamped if result.zero?
1922
+ end
1923
+
1924
+ result
1925
+ end
1926
+
1927
+ # General Decimal Arithmetic Specification integer division and remainder:
1928
+ # (x/y).truncate, x - y*(x/y).truncate
1929
+ def divrem(other, context=nil)
1930
+ context = define_context(context)
1931
+ other = _convert(other)
1932
+
1933
+ ans = _check_nans(context,other)
1934
+ return [ans,ans] if ans
1935
+
1936
+ sign = self.sign * other.sign
1937
+
1938
+ if self.infinite?
1939
+ if other.infinite?
1940
+ ans = context.exception(InvalidOperation, 'divmod(INF,INF)')
1941
+ return [ans,ans]
1942
+ else
1943
+ return [num_class.infinity(sign), context.exception(InvalidOperation, 'INF % x')]
1944
+ end
1945
+ end
1946
+
1947
+ if other.zero?
1948
+ if self.zero?
1949
+ ans = context.exception(DivisionUndefined, 'divmod(0,0)')
1950
+ return [ans,ans]
1951
+ else
1952
+ return [context.exception(DivisionByZero, 'x // 0', sign),
1953
+ context.exception(InvalidOperation, 'x % 0')]
1954
+ end
1955
+ end
1956
+
1957
+ quotient, remainder = self._divide_truncate(other, context)
1958
+ return [quotient, remainder._fix(context)]
1959
+ end
1960
+
1961
+ # Ruby-style integer division and modulo: (x/y).floor, x - y*(x/y).floor
1962
+ def divmod(other, context=nil)
1963
+ context = define_context(context)
1964
+ other = _convert(other)
1965
+
1966
+ ans = _check_nans(context,other)
1967
+ return [ans,ans] if ans
1968
+
1969
+ sign = self.sign * other.sign
1970
+
1971
+ if self.infinite?
1972
+ if other.infinite?
1973
+ ans = context.exception(InvalidOperation, 'divmod(INF,INF)')
1974
+ return [ans,ans]
1975
+ else
1976
+ return [num_class.infinity(sign), context.exception(InvalidOperation, 'INF % x')]
1977
+ end
1978
+ end
1979
+
1980
+ if other.zero?
1981
+ if self.zero?
1982
+ ans = context.exception(DivisionUndefined, 'divmod(0,0)')
1983
+ return [ans,ans]
1984
+ else
1985
+ return [context.exception(DivisionByZero, 'x // 0', sign),
1986
+ context.exception(InvalidOperation, 'x % 0')]
1987
+ end
1988
+ end
1989
+
1990
+ quotient, remainder = self._divide_floor(other, context)
1991
+ return [quotient, remainder._fix(context)]
1992
+ end
1993
+
1994
+
1995
+ # General Decimal Arithmetic Specification integer division: (x/y).truncate
1996
+ def divide_int(other, context=nil)
1997
+ context = define_context(context)
1998
+ other = _convert(other)
1999
+
2000
+ ans = _check_nans(context,other)
2001
+ return ans if ans
2002
+
2003
+ sign = self.sign * other.sign
2004
+
2005
+ if self.infinite?
2006
+ return context.exception(InvalidOperation, 'INF // INF') if other.infinite?
2007
+ return num_class.infinity(sign)
2008
+ end
2009
+
2010
+ if other.zero?
2011
+ if self.zero?
2012
+ return context.exception(DivisionUndefined, '0 // 0')
2013
+ else
2014
+ return context.exception(DivisionByZero, 'x // 0', sign)
2015
+ end
2016
+ end
2017
+ return self._divide_truncate(other, context).first
2018
+ end
2019
+
2020
+ # Ruby-style integer division: (x/y).floor
2021
+ def div(other, context=nil)
2022
+ context = define_context(context)
2023
+ other = _convert(other)
2024
+
2025
+ ans = _check_nans(context,other)
2026
+ return [ans,ans] if ans
2027
+
2028
+ sign = self.sign * other.sign
2029
+
2030
+ if self.infinite?
2031
+ return context.exception(InvalidOperation, 'INF // INF') if other.infinite?
2032
+ return num_class.infinity(sign)
2033
+ end
2034
+
2035
+ if other.zero?
2036
+ if self.zero?
2037
+ return context.exception(DivisionUndefined, '0 // 0')
2038
+ else
2039
+ return context.exception(DivisionByZero, 'x // 0', sign)
2040
+ end
2041
+ end
2042
+ return self._divide_floor(other, context).first
2043
+ end
2044
+
2045
+
2046
+ # Ruby-style modulo: x - y*div(x,y)
2047
+ def modulo(other, context=nil)
2048
+ context = define_context(context)
2049
+ other = _convert(other)
2050
+
2051
+ ans = _check_nans(context,other)
2052
+ return ans if ans
2053
+
2054
+ #sign = self.sign * other.sign
2055
+
2056
+ if self.infinite?
2057
+ return context.exception(InvalidOperation, 'INF % x')
2058
+ elsif other.zero?
2059
+ if self.zero?
2060
+ return context.exception(DivisionUndefined, '0 % 0')
2061
+ else
2062
+ return context.exception(InvalidOperation, 'x % 0')
2063
+ end
2064
+ end
2065
+
2066
+ return self._divide_floor(other, context).last._fix(context)
2067
+ end
2068
+
2069
+ # General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)
2070
+ def remainder(other, context=nil)
2071
+ context = define_context(context)
2072
+ other = _convert(other)
2073
+
2074
+ ans = _check_nans(context,other)
2075
+ return ans if ans
2076
+
2077
+ #sign = self.sign * other.sign
2078
+
2079
+ if self.infinite?
2080
+ return context.exception(InvalidOperation, 'INF % x')
2081
+ elsif other.zero?
2082
+ if self.zero?
2083
+ return context.exception(DivisionUndefined, '0 % 0')
2084
+ else
2085
+ return context.exception(InvalidOperation, 'x % 0')
2086
+ end
2087
+ end
2088
+
2089
+ return self._divide_truncate(other, context).last._fix(context)
2090
+ end
2091
+
2092
+ # General Decimal Arithmetic Specification remainder-near:
2093
+ # x - y*round_half_even(x/y)
2094
+ def remainder_near(other, context=nil)
2095
+ context = define_context(context)
2096
+ other = _convert(other)
2097
+
2098
+ ans = _check_nans(context,other)
2099
+ return ans if ans
2100
+
2101
+ sign = self.sign * other.sign
2102
+
2103
+ if self.infinite?
2104
+ return context.exception(InvalidOperation, 'remainder_near(INF,x)')
2105
+ elsif other.zero?
2106
+ if self.zero?
2107
+ return context.exception(DivisionUndefined, 'remainder_near(0,0)')
2108
+ else
2109
+ return context.exception(InvalidOperation, 'remainder_near(x,0)')
2110
+ end
2111
+ end
2112
+
2113
+ if other.infinite?
2114
+ return Num(self)._fix(context)
2115
+ end
2116
+
2117
+ ideal_exp = [self.exponent, other.exponent].min
2118
+ if self.zero?
2119
+ return Num(self.sign, 0, ideal_exp)._fix(context)
2120
+ end
2121
+
2122
+ expdiff = self.adjusted_exponent - other.adjusted_exponent
2123
+ if (expdiff >= context.precision+1) && !context.exact?
2124
+ return context.exception(DivisionImpossible)
2125
+ elsif expdiff <= -2
2126
+ return self._rescale(ideal_exp, context.rounding)._fix(context)
2127
+ end
2128
+
2129
+ self_coeff = self.coefficient
2130
+ other_coeff = other.coefficient
2131
+ de = self.exponent - other.exponent
2132
+ if de >= 0
2133
+ self_coeff = num_class.int_mult_radix_power(self_coeff, de)
2134
+ else
2135
+ other_coeff = num_class.int_mult_radix_power(other_coeff, -de)
2136
+ end
2137
+ q, r = self_coeff.divmod(other_coeff)
2138
+ if 2*r + (q&1) > other_coeff
2139
+ r -= other_coeff
2140
+ q += 1
2141
+ end
2142
+
2143
+ return context.exception(DivisionImpossible) if q >= num_class.int_radix_power(context.precision) && !context.exact?
2144
+
2145
+ sign = self.sign
2146
+ if r < 0
2147
+ sign = -sign
2148
+ r = -r
2149
+ end
2150
+
2151
+ return Num(sign, r, ideal_exp)._fix(context)
2152
+
2153
+ end
2154
+
2155
+ # Reduces an operand to its simplest form
2156
+ # by removing trailing 0s and incrementing the exponent.
2157
+ # (formerly called normalize in GDAS)
2158
+ def reduce(context=nil)
2159
+ context = define_context(context)
2160
+ if special?
2161
+ ans = _check_nans(context)
2162
+ return ans if ans
2163
+ end
2164
+ dup = _fix(context)
2165
+ return dup if dup.infinite?
2166
+
2167
+ return Num(dup.sign, 0, 0) if dup.zero?
2168
+
2169
+ exp_max = context.clamp? ? context.etop : context.emax
2170
+ end_d = nd = dup.number_of_digits
2171
+ exp = dup.exponent
2172
+ coeff = dup.coefficient
2173
+ dgs = dup.digits
2174
+ while (dgs[end_d-1]==0) && (exp < exp_max)
2175
+ exp += 1
2176
+ end_d -= 1
2177
+ end
2178
+ return Num(dup.sign, coeff/num_class.int_radix_power(nd-end_d), exp)
2179
+ end
2180
+
2181
+ # Normalizes (changes quantum) so that the coefficient has precision digits, unless it is subnormal.
2182
+ # For surnormal numbers the Subnormal flag is raised an a subnormal is returned with the smallest
2183
+ # possible exponent.
2184
+ #
2185
+ # This is different from reduce GDAS function which was formerly called normalize, and corresponds
2186
+ # to the classic meaning of floating-point normalization.
2187
+ #
2188
+ # Note that the number is also rounded (precision is reduced) if it had more precision than the context.
2189
+ def normalize(context=nil)
2190
+ context = define_context(context)
2191
+ return Num(self) if self.special? || self.zero? || context.exact?
2192
+ sign, coeff, exp = self._fix(context).split
2193
+ if self.subnormal?
2194
+ context.exception Subnormal
2195
+ if exp > context.etiny
2196
+ coeff = num_class.int_mult_radix_power(coeff, exp - context.etiny)
2197
+ exp = context.etiny
2198
+ end
2199
+ else
2200
+ min_normal_coeff = context.minimum_normalized_coefficient
2201
+ while coeff < min_normal_coeff
2202
+ coeff = num_class.int_mult_radix_power(coeff, 1)
2203
+ exp -= 1
2204
+ end
2205
+ end
2206
+ Num(sign, coeff, exp)
2207
+ end
2208
+
2209
+ # Returns the exponent of the magnitude of the most significant digit.
2210
+ #
2211
+ # The result is the integer which is the exponent of the magnitude
2212
+ # of the most significant digit of the number (as though it were truncated
2213
+ # to a single digit while maintaining the value of that digit and
2214
+ # without limiting the resulting exponent).
2215
+ def logb(context=nil)
2216
+ context = define_context(context)
2217
+ ans = _check_nans(context)
2218
+ return ans if ans
2219
+ return num_class.infinity if infinite?
2220
+ return context.exception(DivisionByZero,'logb(0)',-1) if zero?
2221
+ Num(adjusted_exponent)
2222
+ end
2223
+
2224
+ # Adds a value to the exponent.
2225
+ def scaleb(other, context=nil)
2226
+
2227
+ context = define_context(context)
2228
+ other = _convert(other)
2229
+ ans = _check_nans(context, other)
2230
+ return ans if ans
2231
+ return context.exception(InvalidOperation) if other.infinite? || other.exponent != 0
2232
+ unless context.exact?
2233
+ liminf = -2 * (context.emax + context.precision)
2234
+ limsup = 2 * (context.emax + context.precision)
2235
+ i = other.to_i
2236
+ return context.exception(InvalidOperation) if !((liminf <= i) && (i <= limsup))
2237
+ end
2238
+ return Num(self) if infinite?
2239
+ return Num(@sign, @coeff, @exp+i)._fix(context)
2240
+
2241
+ end
2242
+
2243
+ # Convert to other numerical type.
2244
+ def convert_to(type, context=nil)
2245
+ context = define_context(context)
2246
+ context.convert_to(type, self)
2247
+ end
2248
+
2249
+ # Ruby-style to integer conversion.
2250
+ def to_i
2251
+ if special?
2252
+ if nan?
2253
+ #return context.exception(InvalidContext)
2254
+ num_class.context.exception InvalidContext
2255
+ return nil
2256
+ end
2257
+ raise Error, "Cannot convert infinity to Integer"
2258
+ end
2259
+ if @exp >= 0
2260
+ return @sign*num_class.int_mult_radix_power(@coeff,@exp)
2261
+ else
2262
+ return @sign*num_class.int_div_radix_power(@coeff,-@exp)
2263
+ end
2264
+ end
2265
+
2266
+ # Conversion to Rational.
2267
+ # Conversion of special values will raise an exception under Ruby 1.9
2268
+ def to_r
2269
+ if special?
2270
+ num = (@exp == :inf) ? @sign : 0
2271
+ Rational.respond_to?(:new!) ? Rational.new!(num,0) : Rational(num,0)
2272
+ else
2273
+ if @exp < 0
2274
+ Rational(@sign*@coeff, num_class.int_radix_power(-@exp))
2275
+ else
2276
+ Rational(num_class.int_mult_radix_power(@sign*@coeff,@exp), 1)
2277
+ end
2278
+ end
2279
+ end
2280
+
2281
+ # Conversion to Float
2282
+ def to_f
2283
+ if special?
2284
+ if @exp==:inf
2285
+ @sign/0.0
2286
+ else
2287
+ 0.0/0.0
2288
+ end
2289
+ else
2290
+ # to_rational.to_f
2291
+ # to_s.to_f
2292
+ (@sign*@coeff*(num_class.radix.to_f**@exp)).to_f
2293
+ end
2294
+ end
2295
+
2296
+ # ulp (unit in the last place) according to the definition proposed by J.M. Muller in
2297
+ # "On the definition of ulp(x)" INRIA No. 5504
2298
+ # If the mode parameter has the value :high the Golberg ulp is computed instead; which is
2299
+ # different on the powers of the radix (which are the borders between areas of different
2300
+ # ulp-magnitude)
2301
+ def ulp(context = nil, mode=:low)
2302
+ context = define_context(context)
2303
+
2304
+ return context.exception(InvalidOperation, "ulp in exact context") if context.exact?
2305
+
2306
+ if self.nan?
2307
+ return Num(self)
2308
+ elsif self.infinite?
2309
+ # The ulp here is context.maximum_finite - context.maximum_finite.next_minus
2310
+ return Num(+1, 1, context.etop)
2311
+ elsif self.zero? || self.adjusted_exponent <= context.emin
2312
+ # This is the ulp value for self.abs <= context.minimum_normal*DecNum.context
2313
+ # Here we use it for self.abs < context.minimum_normal*DecNum.context;
2314
+ # because of the simple exponent check; the remaining cases are handled below.
2315
+ return context.minimum_nonzero
2316
+ else
2317
+ # The next can compute the ulp value for the values that
2318
+ # self.abs > context.minimum_normal && self.abs <= context.maximum_finite
2319
+ # The cases self.abs < context.minimum_normal*DecNum.context have been handled above.
2320
+
2321
+ # assert self.normal? && self.abs>context.minimum_nonzero
2322
+ norm = self.normalize
2323
+ exp = norm.integral_exponent
2324
+ sig = norm.integral_significand
2325
+
2326
+ # Powers of the radix, r**n, are between areas with different ulp values: r**(n-p-1) and r**(n-p)
2327
+ # (p is context.precision).
2328
+ # This method and the ulp definitions by Muller, Kahan and Harrison assign the smaller ulp value
2329
+ # to r**n; the definition by Goldberg assigns it to the larger ulp (so ulp varies with adjusted_exponent).
2330
+ # The next line selects the smaller ulp for powers of the radix:
2331
+ exp -= 1 if sig == num_class.int_radix_power(context.precision-1) if mode == :low
2332
+
2333
+ return Num(+1, 1, exp)
2334
+ end
2335
+ end
2336
+
2337
+ def inspect
2338
+ class_name = num_class.to_s.split('::').last
2339
+ if $DEBUG
2340
+ "#{class_name}('#{self}') [coeff:#{@coeff.inspect} exp:#{@exp.inspect} s:#{@sign.inspect} radix:#{num_class.radix}]"
2341
+ else
2342
+ "#{class_name}('#{self}')"
2343
+ end
2344
+ end
2345
+
2346
+ # Internal comparison operator: returns -1 if the first number is less than the second,
2347
+ # 0 if both are equal or +1 if the first is greater than the secong.
2348
+ def <=>(other)
2349
+ case other
2350
+ when *num_class.context.coercible_types_or_num
2351
+ other = Num(other)
2352
+ if self.special? || other.special?
2353
+ if self.nan? || other.nan?
2354
+ 1
2355
+ else
2356
+ self_v = self.finite? ? 0 : self.sign
2357
+ other_v = other.finite? ? 0 : other.sign
2358
+ self_v <=> other_v
2359
+ end
2360
+ else
2361
+ if self.zero?
2362
+ if other.zero?
2363
+ 0
2364
+ else
2365
+ -other.sign
2366
+ end
2367
+ elsif other.zero?
2368
+ self.sign
2369
+ elsif other.sign < self.sign
2370
+ +1
2371
+ elsif self.sign < other.sign
2372
+ -1
2373
+ else
2374
+ self_adjusted = self.adjusted_exponent
2375
+ other_adjusted = other.adjusted_exponent
2376
+ if self_adjusted == other_adjusted
2377
+ self_padded,other_padded = self.coefficient,other.coefficient
2378
+ d = self.exponent - other.exponent
2379
+ if d>0
2380
+ self_padded *= num_class.int_radix_power(d)
2381
+ else
2382
+ other_padded *= num_class.int_radix_power(-d)
2383
+ end
2384
+ (self_padded <=> other_padded)*self.sign
2385
+ elsif self_adjusted > other_adjusted
2386
+ self.sign
2387
+ else
2388
+ -self.sign
2389
+ end
2390
+ end
2391
+ end
2392
+ else
2393
+ if !self.nan? && defined? other.coerce
2394
+ x, y = other.coerce(self)
2395
+ x <=> y
2396
+ else
2397
+ nil
2398
+ end
2399
+ end
2400
+ end
2401
+ def ==(other)
2402
+ (self<=>other) == 0
2403
+ end
2404
+ include Comparable
2405
+
2406
+ def hash
2407
+ ([num_class]+reduce.split).hash # TODO: optimize
2408
+ end
2409
+
2410
+ def eql?(other)
2411
+ return false unless other.is_a?(num_class)
2412
+ reduce.split == other.reduce.split
2413
+ end
2414
+
2415
+ # Compares like <=> but returns a DecNum value.
2416
+ def compare(other, context=nil)
2417
+
2418
+ other = _convert(other)
2419
+
2420
+ if self.special? || other.special?
2421
+ ans = _check_nans(context, other)
2422
+ return ans if ans
2423
+ end
2424
+
2425
+ return Num(self <=> other)
2426
+
2427
+ end
2428
+
2429
+ # Exponent of the magnitude of the most significant digit of the operand
2430
+ def adjusted_exponent
2431
+ if special?
2432
+ 0
2433
+ else
2434
+ @exp + number_of_digits - 1
2435
+ end
2436
+ end
2437
+
2438
+ # Synonym for DecNum#adjusted_exponent()
2439
+ def scientific_exponent
2440
+ adjusted_exponent
2441
+ end
2442
+
2443
+ # Exponent as though the significand were a fraction (the decimal point before its first digit)
2444
+ def fractional_exponent
2445
+ scientific_exponent + 1
2446
+ end
2447
+
2448
+ # Number of digits in the significand
2449
+ def number_of_digits
2450
+ # digits.size
2451
+ @coeff.is_a?(Integer) ? @coeff.to_s(num_class.radix).size : 0
2452
+ end
2453
+
2454
+ # Digits of the significand as an array of integers
2455
+ def digits
2456
+ @coeff.to_s(num_class.radix).split('').map{|d| d.to_i} # TODO: optimize in derivided classes
2457
+ end
2458
+
2459
+ # Significand as an integer, unsigned. Synonym of coefficient
2460
+ def integral_significand
2461
+ @coeff
2462
+ end
2463
+
2464
+ # Exponent of the significand as an integer. Synonym of exponent
2465
+ def integral_exponent
2466
+ # fractional_exponent - number_of_digits
2467
+ @exp
2468
+ end
2469
+
2470
+ # Sign of the number: +1 for plus / -1 for minus.
2471
+ def sign
2472
+ @sign
2473
+ end
2474
+
2475
+ # Significand as an integer, unsigned
2476
+ def coefficient
2477
+ @coeff
2478
+ end
2479
+
2480
+ # Exponent of the significand as an integer.
2481
+ def exponent
2482
+ @exp
2483
+ end
2484
+
2485
+ # Return the value of the number as an signed integer and a scale.
2486
+ def to_int_scale
2487
+ if special?
2488
+ nil
2489
+ else
2490
+ [@sign*integral_significand, integral_exponent]
2491
+ end
2492
+ end
2493
+
2494
+ # Returns a copy of with the sign set to +
2495
+ def copy_abs
2496
+ Num(+1,@coeff,@exp)
2497
+ end
2498
+
2499
+ # Returns a copy of with the sign inverted
2500
+ def copy_negate
2501
+ Num(-@sign,@coeff,@exp)
2502
+ end
2503
+
2504
+ # Returns a copy of with the sign of other
2505
+ def copy_sign(other)
2506
+ sign = other.respond_to?(:sign) ? other.sign : ((other < 0) ? -1 : +1)
2507
+ Num(sign, @coeff, @exp)
2508
+ end
2509
+
2510
+ # Returns true if the value is an integer
2511
+ def integral?
2512
+ if finite?
2513
+ if @exp>=0 || @coeff==0
2514
+ true
2515
+ else
2516
+ if @exp <= -number_of_digits
2517
+ false
2518
+ else
2519
+ m = num_class.int_radix_power(-@exp)
2520
+ (@coeff % m) == 0
2521
+ end
2522
+ end
2523
+ else
2524
+ false
2525
+ end
2526
+ end
2527
+
2528
+ # returns true if is an even integer
2529
+ def even?
2530
+ # integral? && ((to_i%2)==0)
2531
+ if finite?
2532
+ if @exp>0 || @coeff==0
2533
+ true
2534
+ else
2535
+ if @exp <= -number_of_digits
2536
+ false
2537
+ else
2538
+ m = num_class.int_radix_power(-@exp)
2539
+ if (@coeff % m) == 0
2540
+ # ((@coeff / m) % 2) == 0
2541
+ ((@coeff / m) & 1) == 0
2542
+ else
2543
+ false
2544
+ end
2545
+ end
2546
+ end
2547
+ else
2548
+ false
2549
+ end
2550
+ end
2551
+
2552
+ # returns true if is an odd integer
2553
+ def odd?
2554
+ # integral? && ((to_i%2)==1)
2555
+ # integral? && !even?
2556
+ if finite?
2557
+ if @exp>0 || @coeff==0
2558
+ false
2559
+ else
2560
+ if @exp <= -number_of_digits
2561
+ false
2562
+ else
2563
+ m = num_class.int_radix_power(-@exp)
2564
+ if (@coeff % m) == 0
2565
+ # ((@coeff / m) % 2) == 1
2566
+ ((@coeff / m) & 1) == 1
2567
+ else
2568
+ false
2569
+ end
2570
+ end
2571
+ end
2572
+ else
2573
+ false
2574
+ end
2575
+ end
2576
+
2577
+ # Rescale so that the exponent is exp, either by padding with zeros
2578
+ # or by truncating digits.
2579
+ def rescale(exp, context=nil, watch_exp=true)
2580
+ context = define_context(context)
2581
+ exp = _convert(exp)
2582
+ if self.special? || exp.special?
2583
+ ans = _check_nans(context, exp)
2584
+ return ans if ans
2585
+ if exp.infinite? || self.infinite?
2586
+ return Num(self) if exp.infinite? && self.infinite?
2587
+ return context.exception(InvalidOperation, 'rescale with one INF')
2588
+ end
2589
+ end
2590
+ return context.exception(InvalidOperation,"exponent of rescale is not integral") unless exp.integral?
2591
+ exp = exp.to_i
2592
+ _watched_rescale(exp, context, watch_exp)
2593
+ end
2594
+
2595
+ # Quantize so its exponent is the same as that of y.
2596
+ def quantize(exp, context=nil, watch_exp=true)
2597
+ exp = _convert(exp)
2598
+ context = define_context(context)
2599
+ if self.special? || exp.special?
2600
+ ans = _check_nans(context, exp)
2601
+ return ans if ans
2602
+ if exp.infinite? || self.infinite?
2603
+ return Num(self) if exp.infinite? && self.infinite?
2604
+ return context.exception(InvalidOperation, 'quantize with one INF')
2605
+ end
2606
+ end
2607
+ exp = exp.exponent
2608
+ _watched_rescale(exp, context, watch_exp)
2609
+ end
2610
+
2611
+ # Return true if has the same exponent as other.
2612
+ #
2613
+ # If either operand is a special value, the following rules are used:
2614
+ # * return true if both operands are infinities
2615
+ # * return true if both operands are NaNs
2616
+ # * otherwise, return false.
2617
+ def same_quantum?(other)
2618
+ other = _convert(other)
2619
+ if self.special? || other.special?
2620
+ return (self.nan? && other.nan?) || (self.infinite? && other.infinite?)
2621
+ end
2622
+ return self.exponent == other.exponent
2623
+ end
2624
+
2625
+ # Rounds to a nearby integer. May raise Inexact or Rounded.
2626
+ def to_integral_exact(context=nil)
2627
+ context = define_context(context)
2628
+ if special?
2629
+ ans = _check_nans(context)
2630
+ return ans if ans
2631
+ return Num(self)
2632
+ end
2633
+ return Num(self) if @exp >= 0
2634
+ return Num(@sign, 0, 0) if zero?
2635
+ context.exception Rounded
2636
+ ans = _rescale(0, context.rounding)
2637
+ context.exception Inexact if ans != self
2638
+ return ans
2639
+ end
2640
+
2641
+ # Rounds to a nearby integer. Doesn't raise Inexact or Rounded.
2642
+ def to_integral_value(context=nil)
2643
+ context = define_context(context)
2644
+ if special?
2645
+ ans = _check_nans(context)
2646
+ return ans if ans
2647
+ return Num(self)
2648
+ end
2649
+ return Num(self) if @exp >= 0
2650
+ return _rescale(0, context.rounding)
2651
+ end
2652
+
2653
+ # General rounding.
2654
+ #
2655
+ # With an integer argument this acts like Float#round: the parameter specifies the number
2656
+ # of fractional digits (or digits to the left of the decimal point if negative).
2657
+ #
2658
+ # Options can be passed as a Hash instead; valid options are:
2659
+ # * :rounding method for rounding (see Context#new())
2660
+ # The precision can be specified as:
2661
+ # * :places number of fractional digits as above.
2662
+ # * :exponent specifies the exponent corresponding to the
2663
+ # digit to be rounded (exponent == -places)
2664
+ # * :precision or :significan_digits is the number of digits
2665
+ # * :power 10^exponent, value of the digit to be rounded,
2666
+ # should be passed as a type convertible to DecNum.
2667
+ # * :index 0-based index of the digit to be rounded
2668
+ # * :rindex right 0-based index of the digit to be rounded
2669
+ #
2670
+ # The default is :places=>0 (round to integer).
2671
+ #
2672
+ # Example: ways of specifiying the rounding position
2673
+ # number: 1 2 3 4 . 5 6 7 8
2674
+ # :places -3 -2 -1 0 1 2 3 4
2675
+ # :exponent 3 2 1 0 -1 -2 -3 -4
2676
+ # :precision 1 2 3 4 5 6 7 8
2677
+ # :power 1E3 1E2 10 1 0.1 1E-2 1E-3 1E-4
2678
+ # :index 0 1 2 3 4 5 6 7
2679
+ # :index 7 6 5 4 3 2 1 0
2680
+ def round(opt={})
2681
+ opt = { :places=>opt } if opt.kind_of?(Integer)
2682
+ r = opt[:rounding] || :half_up
2683
+ as_int = false
2684
+ if v=(opt[:precision] || opt[:significant_digits])
2685
+ prec = v
2686
+ elsif v=(opt[:places])
2687
+ prec = adjusted_exponent + 1 + v
2688
+ elsif v=(opt[:exponent])
2689
+ prec = adjusted_exponent + 1 - v
2690
+ elsif v=(opt[:power])
2691
+ prec = adjusted_exponent + 1 - DecNum(v).adjusted_exponent
2692
+ elsif v=(opt[:index])
2693
+ prec = i+1
2694
+ elsif v=(opt[:rindex])
2695
+ prec = number_of_digits - v
2696
+ else
2697
+ prec = adjusted_exponent + 1
2698
+ as_int = true
2699
+ end
2700
+ dg = number_of_digits-prec
2701
+ changed = _round(r, dg)
2702
+ coeff = num_class.int_div_radix_power(@coeff, dg)
2703
+ exp = @exp + dg
2704
+ coeff += 1 if changed==1
2705
+ result = Num(@sign, coeff, exp)
2706
+ return as_int ? result.to_i : result
2707
+ end
2708
+
2709
+ # General ceiling operation (as for Float) with same options for precision
2710
+ # as Flt::Num#round()
2711
+ def ceil(opt={})
2712
+ opt[:rounding] = :ceiling
2713
+ round opt
2714
+ end
2715
+
2716
+ # General floor operation (as for Float) with same options for precision
2717
+ # as Flt::Num#round()
2718
+ def floor(opt={})
2719
+ opt[:rounding] = :floor
2720
+ round opt
2721
+ end
2722
+
2723
+ # General truncate operation (as for Float) with same options for precision
2724
+ # as Flt::Num#round()
2725
+ def truncate(opt={})
2726
+ opt[:rounding] = :down
2727
+ round opt
2728
+ end
2729
+
2730
+ # Fused multiply-add.
2731
+ #
2732
+ # Computes (self*other+third) with no rounding of the intermediate product self*other.
2733
+ def fma(other, third, context=nil)
2734
+ context =define_context(context)
2735
+ other = _convert(other)
2736
+ third = _convert(third)
2737
+ if self.special? || other.special?
2738
+ return context.exception(InvalidOperation, 'sNaN', self) if self.snan?
2739
+ return context.exception(InvalidOperation, 'sNaN', other) if other.snan?
2740
+ if self.nan?
2741
+ product = self
2742
+ elsif other.nan?
2743
+ product = other
2744
+ elsif self.infinite?
2745
+ return context.exception(InvalidOperation, 'INF * 0 in fma') if other.zero?
2746
+ product = num_class.infinity(self.sign*other.sign)
2747
+ elsif other.infinite?
2748
+ return context.exception(InvalidOperation, '0 * INF in fma') if self.zero?
2749
+ product = num_class.infinity(self.sign*other.sign)
2750
+ end
2751
+ else
2752
+ product = Num(self.sign*other.sign,self.coefficient*other.coefficient, self.exponent+other.exponent)
2753
+ end
2754
+ return product.add(third, context)
2755
+ end
2756
+
2757
+ # Convert to a text literal in the specified base (10 by default).
2758
+ #
2759
+ # If the output base is the floating-point radix, the rendered value is the exact value of the number,
2760
+ # showing trailing zeros up to the stored precision.
2761
+ #
2762
+ # With bases different from the radix, the floating-point number is treated
2763
+ # as an approximation with a precision of number_of_digits, representing any value
2764
+ # within its rounding range. In that case, this method always renders
2765
+ # that aproximated value in other base without introducing additional precision.
2766
+ #
2767
+ # The resulting text numeral is such that it has as few digits as possible while
2768
+ # preserving the original while if converted back to the same type of floating-point value with
2769
+ # the same context precision that the original number had (number_of_digits).
2770
+ #
2771
+ # To render the exact value of a Num x in a different base b this can be used
2772
+ # Flt::Num.convert_exact(x, b).to_s(:base=>b)
2773
+ # Or, to represent a BinNum x in decimal:
2774
+ # x.to_decimal_exact(:exact=>true).to_s
2775
+ #
2776
+ # Options:
2777
+ # :base output base, 10 by default
2778
+ #
2779
+ # :rounding is used to override the context rounding, but it's main use is specify :nearest
2780
+ # as the rounding-mode, which means that the text literal will have enough digits to be
2781
+ # converted back to self in any round-to_nearest rounding mode. Otherwise only enough
2782
+ # digits for conversion in a specific rounding mode are produced.
2783
+ #
2784
+ # :all_digits if true all significant digits are shown. A digit
2785
+ # is considered as significant here if when used on input, cannot
2786
+ # arbitrarily change its value and preserve the parsed value of the
2787
+ # floating point number.
2788
+ # Using all_digits will show trailing zeros up to the precision of the floating-point, so
2789
+ # the output will preserve the input precision. With all_digits and the :down rounding-mod
2790
+ # (truncation), the result will be the exact value floating-point value in the output base
2791
+ # (if it is conmensurable with the floating-point base).
2792
+ def to_s(*args)
2793
+ eng=false
2794
+ context=nil
2795
+
2796
+ # admit legacy arguments eng, context in that order
2797
+ if [true,false].include?(args.first)
2798
+ eng = args.shift
2799
+ end
2800
+ if args.first.is_a?(Num::ContextBase)
2801
+ context = args.shift
2802
+ end
2803
+ # admit also :eng to specify the eng mode
2804
+ if args.first == :eng
2805
+ eng = true
2806
+ args.shift
2807
+ end
2808
+ raise TypeError, "Invalid arguments to #{num_class}#to_s" if args.size>1 || (args.size==1 && !args.first.is_a?(Hash))
2809
+ # an admit arguments through a final parameters Hash
2810
+ options = args.first || {}
2811
+ context = options.delete(:context) if options.has_key?(:context)
2812
+ eng = options.delete(:eng) if options.has_key?(:eng)
2813
+
2814
+ format(context, options.merge(:eng=>eng))
2815
+ end
2816
+
2817
+ # Raises to the power of x.
2818
+ #
2819
+ # If self is negative then other
2820
+ # must be integral. The result will be inexact unless other is
2821
+ # integral and the result is finite and can be expressed exactly
2822
+ # in 'precision' digits.
2823
+ def power(other, context=nil)
2824
+
2825
+ context = num_class.define_context(context)
2826
+ other = _convert(other)
2827
+
2828
+ ans = _check_nans(context, other)
2829
+ return ans if ans
2830
+
2831
+ # 0**0 = NaN (!), x**0 = 1 for nonzero x (including +/-Infinity)
2832
+ if other.zero?
2833
+ if self.zero?
2834
+ return context.exception(InvalidOperation, '0 ** 0')
2835
+ else
2836
+ return Num(1)
2837
+ end
2838
+ end
2839
+
2840
+ # result has sign -1 iff self.sign is -1 and other is an odd integer
2841
+ result_sign = +1
2842
+ _self = self
2843
+ if _self.sign == -1
2844
+ if other.integral?
2845
+ result_sign = -1 if !other.even?
2846
+ else
2847
+ # -ve**noninteger = NaN
2848
+ # (-0)**noninteger = 0**noninteger
2849
+ unless self.zero?
2850
+ return context.exception(InvalidOperation, 'x ** y with x negative and y not an integer')
2851
+ end
2852
+ end
2853
+ # negate self, without doing any unwanted rounding
2854
+ _self = self.copy_negate
2855
+ end
2856
+
2857
+ # 0**(+ve or Inf)= 0; 0**(-ve or -Inf) = Infinity
2858
+ if _self.zero?
2859
+ return (other.sign == +1) ? Num(result_sign, 0, 0) : num_class.infinity(result_sign)
2860
+ end
2861
+
2862
+ # Inf**(+ve or Inf) = Inf; Inf**(-ve or -Inf) = 0
2863
+ if _self.infinite?
2864
+ return (other.sign == +1) ? num_class.infinity(result_sign) : Num(result_sign, 0, 0)
2865
+ end
2866
+
2867
+ # 1**other = 1, but the choice of exponent and the flags
2868
+ # depend on the exponent of self, and on whether other is a
2869
+ # positive integer, a negative integer, or neither
2870
+ if _self == Num(1)
2871
+ return _self if context.exact?
2872
+ if other.integral?
2873
+ # exp = max(self._exp*max(int(other), 0),
2874
+ # 1-context.prec) but evaluating int(other) directly
2875
+ # is dangerous until we know other is small (other
2876
+ # could be 1e999999999)
2877
+ if other.sign == -1
2878
+ multiplier = 0
2879
+ elsif other > context.precision
2880
+ multiplier = context.precision
2881
+ else
2882
+ multiplier = other.to_i
2883
+ end
2884
+
2885
+ exp = _self.exponent * multiplier
2886
+ if exp < 1-context.precision
2887
+ exp = 1-context.precision
2888
+ context.exception Rounded
2889
+ end
2890
+ else
2891
+ context.exception Rounded
2892
+ context.exception Inexact
2893
+ exp = 1-context.precision
2894
+ end
2895
+
2896
+ return Num(result_sign, num_class.int_radix_power(-exp), exp)
2897
+ end
2898
+
2899
+ # compute adjusted exponent of self
2900
+ self_adj = _self.adjusted_exponent
2901
+
2902
+ # self ** infinity is infinity if self > 1, 0 if self < 1
2903
+ # self ** -infinity is infinity if self < 1, 0 if self > 1
2904
+ if other.infinite?
2905
+ if (other.sign == +1) == (self_adj < 0)
2906
+ return Num(result_sign, 0, 0)
2907
+ else
2908
+ return num_class.infinity(result_sign)
2909
+ end
2910
+ end
2911
+
2912
+ # from here on, the result always goes through the call
2913
+ # to _fix at the end of this function.
2914
+ ans = nil
2915
+
2916
+ # crude test to catch cases of extreme overflow/underflow. If
2917
+ # log_radix(self)*other >= radix**bound and bound >= len(str(Emax))
2918
+ # then radixs**bound >= radix**len(str(Emax)) >= Emax+1 and hence
2919
+ # self**other >= radix**(Emax+1), so overflow occurs. The test
2920
+ # for underflow is similar.
2921
+ bound = _self._log_radix_exp_bound + other.adjusted_exponent
2922
+ if (self_adj >= 0) == (other.sign == +1)
2923
+ # self > 1 and other +ve, or self < 1 and other -ve
2924
+ # possibility of overflow
2925
+ if bound >= _number_of_digits(context.emax)
2926
+ ans = Num(result_sign, 1, context.emax+1)
2927
+ end
2928
+ else
2929
+ # self > 1 and other -ve, or self < 1 and other +ve
2930
+ # possibility of underflow to 0
2931
+ etiny = context.etiny
2932
+ if bound >= _number_of_digits(-etiny)
2933
+ ans = Num(result_sign, 1, etiny-1)
2934
+ end
2935
+ end
2936
+
2937
+ # try for an exact result with precision +1
2938
+ if ans.nil?
2939
+ if context.exact?
2940
+ if other.adjusted_exponent < 100 # ???? 4 ? ...
2941
+ test_precision = _self.number_of_digits*other.to_i+1
2942
+ else
2943
+ test_precision = _self.number_of_digits+1
2944
+ end
2945
+ else
2946
+ test_precision = context.precision + 1
2947
+ end
2948
+ ans = _self._power_exact(other, test_precision)
2949
+ if !ans.nil? && (result_sign == -1)
2950
+ ans = Num(-1, ans.coefficient, ans.exponent)
2951
+ end
2952
+ end
2953
+
2954
+ # usual case: inexact result, x**y computed directly as exp(y*log(x))
2955
+ if !ans.nil?
2956
+ return ans if context.exact?
2957
+ else
2958
+ return context.exception(Inexact, "Inexact power") if context.exact?
2959
+
2960
+ p = context.precision
2961
+ xc = _self.coefficient
2962
+ xe = _self.exponent
2963
+ yc = other.coefficient
2964
+ ye = other.exponent
2965
+ yc = -yc if other.sign == -1
2966
+
2967
+ # compute correctly rounded result: start with precision +3,
2968
+ # then increase precision until result is unambiguously roundable
2969
+ extra = 3
2970
+ coeff, exp = nil, nil
2971
+ loop do
2972
+ coeff, exp = _power(xc, xe, yc, ye, p+extra)
2973
+ break if (coeff % (num_class.int_radix_power(_number_of_digits(coeff)-p)/2)) != 0 # base 2: (coeff % (10**(_number_of_digits(coeff)-p-1))) != 0
2974
+ extra += 3
2975
+ end
2976
+ ans = Num(result_sign, coeff, exp)
2977
+ end
2978
+
2979
+ # the specification says that for non-integer other we need to
2980
+ # raise Inexact, even when the result is actually exact. In
2981
+ # the same way, we need to raise Underflow here if the result
2982
+ # is subnormal. (The call to _fix will take care of raising
2983
+ # Rounded and Subnormal, as usual.)
2984
+ if !other.integral?
2985
+ context.exception Inexact
2986
+ # pad with zeros up to length context.precision+1 if necessary
2987
+ if ans.number_of_digits <= context.precision
2988
+ expdiff = context.precision+1 - ans.number_of_digits
2989
+ ans = Num(ans.sign, num_class.int_mult_radix_power(ans.coefficient, expdiff), ans.exponent-expdiff)
2990
+ end
2991
+ context.exception Underflow if ans.adjusted_exponent < context.emin
2992
+ end
2993
+ # unlike exp, ln and log10, the power function respects the
2994
+ # rounding mode; no need to use ROUND_HALF_EVEN here
2995
+ ans._fix(context)
2996
+ end
2997
+
2998
+ # Check if the number or other is NaN, signal if sNaN or return NaN;
2999
+ # return nil if none is NaN.
3000
+ def _check_nans(context=nil, other=nil)
3001
+ #self_is_nan = self.nan?
3002
+ #other_is_nan = other.nil? ? false : other.nan?
3003
+ if self.nan? || (other && other.nan?)
3004
+ context = define_context(context)
3005
+ return context.exception(InvalidOperation, 'sNaN', self) if self.snan?
3006
+ return context.exception(InvalidOperation, 'sNaN', other) if other && other.snan?
3007
+ return self._fix_nan(context) if self.nan?
3008
+ return other._fix_nan(context)
3009
+ else
3010
+ return nil
3011
+ end
3012
+ end
3013
+
3014
+ # Rescale so that the exponent is exp, either by padding with zeros
3015
+ # or by truncating digits, using the given rounding mode.
3016
+ #
3017
+ # Specials are returned without change. This operation is
3018
+ # quiet: it raises no flags, and uses no information from the
3019
+ # context.
3020
+ #
3021
+ # exp = exp to scale to (an integer)
3022
+ # rounding = rounding mode
3023
+ def _rescale(exp, rounding)
3024
+
3025
+ return Num(self) if special?
3026
+ return Num(sign, 0, exp) if zero?
3027
+ return Num(sign, @coeff*num_class.int_radix_power(self.exponent - exp), exp) if self.exponent > exp
3028
+ #nd = number_of_digits + self.exponent - exp
3029
+ nd = exp - self.exponent
3030
+ if number_of_digits < nd
3031
+ slf = Num(sign, 1, exp-1)
3032
+ nd = number_of_digits
3033
+ else
3034
+ slf = num_class.new(self)
3035
+ end
3036
+
3037
+ changed = slf._round(rounding, nd)
3038
+ coeff = num_class.int_div_radix_power(@coeff, nd)
3039
+ coeff += 1 if changed==1
3040
+ Num(slf.sign, coeff, exp)
3041
+
3042
+ end
3043
+
3044
+ def _watched_rescale(exp, context, watch_exp)
3045
+ if !watch_exp
3046
+ ans = _rescale(exp, context.rounding)
3047
+ context.exception(Rounded) if ans.exponent > self.exponent
3048
+ context.exception(Inexact) if ans != self
3049
+ return ans
3050
+ end
3051
+
3052
+ if exp < context.etiny || exp > context.emax
3053
+ return context.exception(InvalidOperation, "target operation out of bounds in quantize/rescale")
3054
+ end
3055
+
3056
+ return Num(@sign, 0, exp)._fix(context) if zero?
3057
+
3058
+ self_adjusted = adjusted_exponent
3059
+ return context.exception(InvalidOperation,"exponent of quantize/rescale result too large for current context") if self_adjusted > context.emax
3060
+ return context.exception(InvalidOperation,"quantize/rescale has too many digits for current context") if (self_adjusted - exp + 1 > context.precision) && !context.exact?
3061
+
3062
+ ans = _rescale(exp, context.rounding)
3063
+ return context.exception(InvalidOperation,"exponent of rescale result too large for current context") if ans.adjusted_exponent > context.emax
3064
+ return context.exception(InvalidOperation,"rescale result has too many digits for current context") if (ans.number_of_digits > context.precision) && !context.exact?
3065
+ if ans.exponent > self.exponent
3066
+ context.exception(Rounded)
3067
+ context.exception(Inexact) if ans!=self
3068
+ end
3069
+ context.exception(Subnormal) if !ans.zero? && (ans.adjusted_exponent < context.emin)
3070
+ return ans._fix(context)
3071
+ end
3072
+
3073
+ # Returns copy with sign inverted
3074
+ def _neg(context=nil)
3075
+ if special?
3076
+ ans = _check_nans(context)
3077
+ return ans if ans
3078
+ end
3079
+ if zero?
3080
+ ans = copy_abs
3081
+ else
3082
+ ans = copy_negate
3083
+ end
3084
+ context = define_context(context)
3085
+ ans._fix(context)
3086
+ end
3087
+
3088
+ # Returns a copy with precision adjusted
3089
+ def _pos(context=nil)
3090
+ if special?
3091
+ ans = _check_nans(context)
3092
+ return ans if ans
3093
+ end
3094
+ if zero?
3095
+ ans = copy_abs
3096
+ else
3097
+ ans = Num(self)
3098
+ end
3099
+ context = define_context(context)
3100
+ ans._fix(context)
3101
+ end
3102
+
3103
+ # Returns a copy with positive sign
3104
+ def _abs(round=true, context=nil)
3105
+ return copy_abs if not round
3106
+
3107
+ if special?
3108
+ ans = _check_nans(context)
3109
+ return ans if ans
3110
+ end
3111
+ if sign>0
3112
+ ans = _neg(context)
3113
+ else
3114
+ ans = _pos(context)
3115
+ end
3116
+ ans
3117
+ end
3118
+
3119
+ # Round if it is necessary to keep within precision.
3120
+ def _fix(context)
3121
+ return self if context.exact?
3122
+
3123
+ if special?
3124
+ if nan?
3125
+ return _fix_nan(context)
3126
+ else
3127
+ return Num(self)
3128
+ end
3129
+ end
3130
+
3131
+ etiny = context.etiny
3132
+ etop = context.etop
3133
+ if zero?
3134
+ exp_max = context.clamp? ? etop : context.emax
3135
+ new_exp = [[@exp, etiny].max, exp_max].min
3136
+ if new_exp!=@exp
3137
+ context.exception Clamped
3138
+ return Num(sign,0,new_exp)
3139
+ else
3140
+ return Num(self)
3141
+ end
3142
+ end
3143
+
3144
+ nd = number_of_digits
3145
+ exp_min = nd + @exp - context.precision
3146
+ if exp_min > etop
3147
+ context.exception Inexact
3148
+ context.exception Rounded
3149
+ return context.exception(Overflow, 'above Emax', sign)
3150
+ end
3151
+
3152
+ self_is_subnormal = exp_min < etiny
3153
+
3154
+ if self_is_subnormal
3155
+ context.exception Subnormal
3156
+ exp_min = etiny
3157
+ end
3158
+
3159
+ if @exp < exp_min
3160
+ context.exception Rounded
3161
+ # dig is the digits number from 0 (MS) to number_of_digits-1 (LS)
3162
+ # dg = numberof_digits-dig is from 1 (LS) to number_of_digits (MS)
3163
+ dg = exp_min - @exp # dig = number_of_digits + exp - exp_min
3164
+ if dg > number_of_digits # dig<0
3165
+ d = Num(sign,1,exp_min-1)
3166
+ dg = number_of_digits # dig = 0
3167
+ else
3168
+ d = Num(self)
3169
+ end
3170
+ changed = d._round(context.rounding, dg)
3171
+ coeff = num_class.int_div_radix_power(d.coefficient, dg)
3172
+ coeff += 1 if changed==1
3173
+ ans = Num(sign, coeff, exp_min)
3174
+ if changed!=0
3175
+ context.exception Inexact
3176
+ if self_is_subnormal
3177
+ context.exception Underflow
3178
+ if ans.zero?
3179
+ context.exception Clamped
3180
+ end
3181
+ elsif ans.number_of_digits == context.precision+1
3182
+ if ans.exponent< etop
3183
+ ans = Num(ans.sign, num_class.int_div_radix_power(ans.coefficient,1), ans.exponent+1)
3184
+ else
3185
+ ans = context.exception(Overflow, 'above Emax', d.sign)
3186
+ end
3187
+ end
3188
+ end
3189
+ return ans
3190
+ end
3191
+
3192
+ if context.clamp? && @exp>etop
3193
+ context.exception Clamped
3194
+ self_padded = num_class.int_mult_radix_power(@coeff, @exp-etop)
3195
+ return Num(sign,self_padded,etop)
3196
+ end
3197
+
3198
+ return Num(self)
3199
+
3200
+ end
3201
+
3202
+ # adjust payload of a NaN to the context
3203
+ def _fix_nan(context)
3204
+ if !context.exact?
3205
+ payload = @coeff
3206
+ payload = nil if payload==0
3207
+
3208
+ max_payload_len = context.maximum_nan_diagnostic_digits
3209
+
3210
+ if number_of_digits > max_payload_len
3211
+ payload = payload.to_s[-max_payload_len..-1].to_i
3212
+ return DecNum([@sign, payload, @exp])
3213
+ end
3214
+ end
3215
+ Num(self)
3216
+ end
3217
+
3218
+ protected
3219
+
3220
+ def _divide_truncate(other, context)
3221
+ context = define_context(context)
3222
+ sign = self.sign * other.sign
3223
+ if other.infinite?
3224
+ ideal_exp = self.exponent
3225
+ else
3226
+ ideal_exp = [self.exponent, other.exponent].min
3227
+ end
3228
+
3229
+ expdiff = self.adjusted_exponent - other.adjusted_exponent
3230
+ if self.zero? || other.infinite? || (expdiff <= -2)
3231
+ return [Num(sign, 0, 0), _rescale(ideal_exp, context.rounding)]
3232
+ end
3233
+ if (expdiff <= context.precision) || context.exact?
3234
+ self_coeff = self.coefficient
3235
+ other_coeff = other.coefficient
3236
+ de = self.exponent - other.exponent
3237
+ if de >= 0
3238
+ self_coeff = num_class.int_mult_radix_power(self_coeff, de)
3239
+ else
3240
+ other_coeff = num_class.int_mult_radix_power(other_coeff, -de)
3241
+ end
3242
+ q, r = self_coeff.divmod(other_coeff)
3243
+ if (q < num_class.int_radix_power(context.precision)) || context.exact?
3244
+ return [Num(sign, q, 0),Num(self.sign, r, ideal_exp)]
3245
+ end
3246
+ end
3247
+ # Here the quotient is too large to be representable
3248
+ ans = context.exception(DivisionImpossible, 'quotient too large in //, % or divmod')
3249
+ return [ans, ans]
3250
+
3251
+ end
3252
+
3253
+ def _divide_floor(other, context)
3254
+ context = define_context(context)
3255
+ sign = self.sign * other.sign
3256
+ if other.infinite?
3257
+ ideal_exp = self.exponent
3258
+ else
3259
+ ideal_exp = [self.exponent, other.exponent].min
3260
+ end
3261
+
3262
+ expdiff = self.adjusted_exponent - other.adjusted_exponent
3263
+ if self.zero? || other.infinite? || (expdiff <= -2)
3264
+ return [Num(sign, 0, 0), _rescale(ideal_exp, context.rounding)]
3265
+ end
3266
+ if (expdiff <= context.precision) || context.exact?
3267
+ self_coeff = self.coefficient*self.sign
3268
+ other_coeff = other.coefficient*other.sign
3269
+ de = self.exponent - other.exponent
3270
+ if de >= 0
3271
+ self_coeff = num_class.int_mult_radix_power(self_coeff, de)
3272
+ else
3273
+ other_coeff = num_class.int_mult_radix_power(other_coeff, -de)
3274
+ end
3275
+ q, r = self_coeff.divmod(other_coeff)
3276
+ if r<0
3277
+ r = -r
3278
+ rs = -1
3279
+ else
3280
+ rs = +1
3281
+ end
3282
+ if q<0
3283
+ q = -q
3284
+ qs = -1
3285
+ else
3286
+ qs = +1
3287
+ end
3288
+ if (q < num_class.int_radix_power(context.precision)) || context.exact?
3289
+ return [Num(qs, q, 0),Num(rs, r, ideal_exp)]
3290
+ end
3291
+ end
3292
+ # Here the quotient is too large to be representable
3293
+ ans = context.exception(DivisionImpossible, 'quotient too large in //, % or divmod')
3294
+ return [ans, ans]
3295
+
3296
+ end
3297
+
3298
+ # Convert to a text literal in the specified base. If the result is
3299
+ # converted to BinNum with the specified context rounding and the
3300
+ # same precision that self has (self.number_of_digits), the same
3301
+ # number will be produced.
3302
+ #
3303
+ # Options:
3304
+ # :base output base, 10 by default
3305
+ #
3306
+ # :rounding is used to override the context rounding, but it's main use is specify :nearest
3307
+ # as the rounding-mode, which means that the text literal will have enough digits to be
3308
+ # converted back to self in any round-to_nearest rounding mode. Otherwise only enough
3309
+ # digits for conversion in a specific rounding mode are produced.
3310
+ #
3311
+ # :all_digits if true all significant digits are shown. A digit
3312
+ # is considere as significant here if when used on input, cannot
3313
+ # arbitrarily change its value and preserve the parsed value of the
3314
+ # floating point number.
3315
+ #
3316
+ # :output_rounding implies :all_digits; it defines the rounding mode for the output,
3317
+ # that will show all significant digits rounded.
3318
+ # If it is not passed and :all_digits is true, then :rounding or the context rounding mode
3319
+ # will be used.
3320
+ #
3321
+ # Note that when :base=>10 (the default) we're regarding the binary number x
3322
+ # as an approximation with x.number_of_digits precision and showing that
3323
+ # inexact value in decimal without introducing additional precision.
3324
+ # If the exact value of the number expressed in decimal is desired (we consider
3325
+ # the Flt an exact number), this can be done with Num.convert_exact.
3326
+ def format(num_context, options={})
3327
+ # TODO: support options (base, all_digits, any_rounding, eng) and context options in the same hash
3328
+ output_radix = options[:base] || 10
3329
+ rounding = options[:rounding]
3330
+ all_digits = options[:all_digits]
3331
+ eng = options[:eng]
3332
+ output_rounding = options[:output_rounding]
3333
+ all_digits ||= output_rounding
3334
+
3335
+ sgn = @sign<0 ? '-' : ''
3336
+ if special?
3337
+ if @exp==:inf
3338
+ return "#{sgn}Infinity"
3339
+ elsif @exp==:nan
3340
+ return "#{sgn}NaN#{@coeff}"
3341
+ else # exp==:snan
3342
+ return "#{sgn}sNaN#{@coeff}"
3343
+ end
3344
+ end
3345
+
3346
+ context = define_context(num_context)
3347
+ inexact = true
3348
+ rounding ||= context.rounding
3349
+ output_rounding ||= rounding
3350
+
3351
+ if output_radix == num_class.radix && !all_digits
3352
+ # show exactly inner representation and precision
3353
+ ds = @coeff.to_s(output_radix)
3354
+ n_ds = ds.size
3355
+ exp = integral_exponent
3356
+ leftdigits = exp + n_ds
3357
+ else
3358
+ p = self.number_of_digits # context.precision
3359
+ formatter = Flt::Support::Formatter.new(num_class.radix, context.etiny, output_radix)
3360
+ formatter.format(self, @coeff, @exp, rounding, p, all_digits)
3361
+ dec_pos,digits = formatter.adjusted_digits(output_rounding)
3362
+
3363
+ ds = digits.map{|d| d.to_s(output_radix)}.join
3364
+ n_ds = ds.size
3365
+ exp = dec_pos - n_ds
3366
+ leftdigits = dec_pos
3367
+ end
3368
+
3369
+ # TODO: DRY (this code is duplicated in DecNum#format)
3370
+ if exp<=0 && leftdigits>-6
3371
+ dotplace = leftdigits
3372
+ elsif !eng
3373
+ dotplace = 1
3374
+ elsif @coeff==0
3375
+ dotplace = (leftdigits+1)%3 - 1
3376
+ else
3377
+ dotplace = (leftdigits-1)%3 + 1
3378
+ end
3379
+
3380
+ if dotplace <=0
3381
+ intpart = '0'
3382
+ fracpart = '.' + '0'*(-dotplace) + ds
3383
+ elsif dotplace >= n_ds
3384
+ intpart = ds + '0'*(dotplace - n_ds)
3385
+ fracpart = ''
3386
+ else
3387
+ intpart = ds[0...dotplace]
3388
+ fracpart = '.' + ds[dotplace..-1]
3389
+ end
3390
+
3391
+ if leftdigits == dotplace
3392
+ e = ''
3393
+ else
3394
+ e = (context.capitals ? 'E' : 'e') + "%+d"%(leftdigits-dotplace)
3395
+ end
3396
+
3397
+ sgn + intpart + fracpart + e
3398
+
3399
+ end
3400
+
3401
+ # Auxiliar Methods
3402
+
3403
+ # Round to i digits using the specified method
3404
+ def _round(rounding, i)
3405
+ send("_round_#{rounding}", i)
3406
+ end
3407
+
3408
+ # Round down (toward 0, truncate) to i digits
3409
+ def _round_down(i)
3410
+ (@coeff % num_class.int_radix_power(i))==0 ? 0 : -1
3411
+ end
3412
+
3413
+ # Round up (away from 0) to i digits
3414
+ def _round_up(i)
3415
+ -_round_down(i)
3416
+ end
3417
+
3418
+ # Round to closest i-digit number with ties down (rounds 5 toward 0)
3419
+ def _round_half_down(i)
3420
+ m = num_class.int_radix_power(i)
3421
+ if (m>1) && ((@coeff%m) == m/2)
3422
+ -1
3423
+ else
3424
+ _round_half_up(i)
3425
+ end
3426
+ end
3427
+
3428
+ # Round to closest i-digit number with ties up (rounds 5 away from 0)
3429
+ def _round_half_up(i)
3430
+ m = num_class.int_radix_power(i)
3431
+ if (m>1) && ((@coeff % m) >= m/2)
3432
+ 1
3433
+ else
3434
+ (@coeff % m)==0 ? 0 : -1
3435
+ end
3436
+ end
3437
+
3438
+ # Round to closest i-digit number with ties (5) to an even digit
3439
+ def _round_half_even(i)
3440
+ m = num_class.int_radix_power(i)
3441
+ if (m>1) && ((@coeff%m) == m/2 && ((@coeff/m)%2)==0)
3442
+ -1
3443
+ else
3444
+ _round_half_up(i)
3445
+ end
3446
+ end
3447
+
3448
+ # Round up (not away from 0 if negative) to i digits
3449
+ def _round_ceiling(i)
3450
+ sign<0 ? _round_down(i) : -_round_down(i)
3451
+ end
3452
+
3453
+ # Round down (not toward 0 if negative) to i digits
3454
+ def _round_floor(i)
3455
+ sign>0 ? _round_down(i) : -_round_down(i)
3456
+ end
3457
+
3458
+ # Round down unless digit i-1 is 0 or 5
3459
+ def _round_up05(i)
3460
+ if ((@coeff/num_class.int_radix_power(i))%(num_class.radix/2))==0
3461
+ -_round_down(i)
3462
+ else
3463
+ _round_down(i)
3464
+ end
3465
+ end
3466
+
3467
+ # Compute a lower bound for the adjusted exponent of self.log10()
3468
+ # In other words, find r such that self.log10() >= 10**r.
3469
+ # Assumes that self is finite and positive and that self != 1.
3470
+ def _log_radix_exp_bound
3471
+ # For x >= radix or x < 1/radix we only need a bound on the integer
3472
+ # part of log_radix(self), and this comes directly from the
3473
+ # exponent of x. For 1/radix <= x <= radix we use the inequalities
3474
+ # 1-1/x <= log(x) <= x-1. If x > 1 we have |log_radix(x)| >
3475
+ # (1-1/x)/k > 0. If x < 1 then |log_radix(x)| > (1-x)/k > 0
3476
+ # with k = floor(log(radix)*radix**m)/radix**m (m = 3 for radix=10)
3477
+ #
3478
+ # The original Python cod used lexical order (having converted to strings) for (num < den) and (num < 231)
3479
+ # so the results would be different e.g. for num = 9; Can this happen? What is the correct way?
3480
+
3481
+ adj = self.exponent + number_of_digits - 1
3482
+ return _number_of_digits(adj) - 1 if adj >= 1 # self >= radix
3483
+ return _number_of_digits(-1-adj)-1 if adj <= -2 # self < 1/radix
3484
+
3485
+ k, m = {
3486
+ 10 => [231, 3],
3487
+ 2 => [89, 7]
3488
+ }[num_class.radix]
3489
+ raise InvalidOperation, "Base #{num_class.radix} not supported for _log_radix_exp_bound" if k.nil?
3490
+
3491
+ c = self.coefficient
3492
+ e = self.exponent
3493
+ if adj == 0
3494
+ # 1 < self < 10
3495
+ num = (c - num_class.int_radix_power(-e))
3496
+ den = (k*c)
3497
+ return _number_of_digits(num) - _number_of_digits(den) - ((num < den) ? 1 : 0) + (m-1)
3498
+ end
3499
+ # adj == -1, 0.1 <= self < 1
3500
+ num = (num_class.int_radix_power(-e)-c)
3501
+ return _number_of_digits(num.to_i) + e - ((num < k) ? 1 : 0) - (m-2)
3502
+ end
3503
+
3504
+ # Attempt to compute self**other exactly
3505
+ # Given Decimals self and other and an integer p, attempt to
3506
+ # compute an exact result for the power self**other, with p
3507
+ # digits of precision. Return nil if self**other is not
3508
+ # exactly representable in p digits.
3509
+ #
3510
+ # Assumes that elimination of special cases has already been
3511
+ # performed: self and other must both be nonspecial; self must
3512
+ # be positive and not numerically equal to 1; other must be
3513
+ # nonzero. For efficiency, other.exponent should not be too large,
3514
+ # so that 10**other.exponent.abs is a feasible calculation.
3515
+ def _power_exact(other, p)
3516
+
3517
+ # In the comments below, we write x for the value of self and
3518
+ # y for the value of other. Write x = xc*10**xe and y =
3519
+ # yc*10**ye.
3520
+
3521
+ # The main purpose of this method is to identify the *failure*
3522
+ # of x**y to be exactly representable with as little effort as
3523
+ # possible. So we look for cheap and easy tests that
3524
+ # eliminate the possibility of x**y being exact. Only if all
3525
+ # these tests are passed do we go on to actually compute x**y.
3526
+
3527
+ # Here's the main idea. First normalize both x and y. We
3528
+ # express y as a rational m/n, with m and n relatively prime
3529
+ # and n>0. Then for x**y to be exactly representable (at
3530
+ # *any* precision), xc must be the nth power of a positive
3531
+ # integer and xe must be divisible by n. If m is negative
3532
+ # then additionally xc must be a power of either 2 or 5, hence
3533
+ # a power of 2**n or 5**n.
3534
+ #
3535
+ # There's a limit to how small |y| can be: if y=m/n as above
3536
+ # then:
3537
+ #
3538
+ # (1) if xc != 1 then for the result to be representable we
3539
+ # need xc**(1/n) >= 2, and hence also xc**|y| >= 2. So
3540
+ # if |y| <= 1/nbits(xc) then xc < 2**nbits(xc) <=
3541
+ # 2**(1/|y|), hence xc**|y| < 2 and the result is not
3542
+ # representable.
3543
+ #
3544
+ # (2) if xe != 0, |xe|*(1/n) >= 1, so |xe|*|y| >= 1. Hence if
3545
+ # |y| < 1/|xe| then the result is not representable.
3546
+ #
3547
+ # Note that since x is not equal to 1, at least one of (1) and
3548
+ # (2) must apply. Now |y| < 1/nbits(xc) iff |yc|*nbits(xc) <
3549
+ # 10**-ye iff len(str(|yc|*nbits(xc)) <= -ye.
3550
+ #
3551
+ # There's also a limit to how large y can be, at least if it's
3552
+ # positive: the normalized result will have coefficient xc**y,
3553
+ # so if it's representable then xc**y < 10**p, and y <
3554
+ # p/log10(xc). Hence if y*log10(xc) >= p then the result is
3555
+ # not exactly representable.
3556
+
3557
+ # if len(str(abs(yc*xe)) <= -ye then abs(yc*xe) < 10**-ye,
3558
+ # so |y| < 1/xe and the result is not representable.
3559
+ # Similarly, len(str(abs(yc)*xc_bits)) <= -ye implies |y|
3560
+ # < 1/nbits(xc).
3561
+
3562
+ xc = self.coefficient
3563
+ xe = self.exponent
3564
+ while (xc % num_class.radix) == 0
3565
+ xc /= num_class.radix
3566
+ xe += 1
3567
+ end
3568
+
3569
+ yc = other.coefficient
3570
+ ye = other.exponent
3571
+ while (yc % num_class.radix) == 0
3572
+ yc /= num_class.radix
3573
+ ye += 1
3574
+ end
3575
+
3576
+ # case where xc == 1: result is 10**(xe*y), with xe*y
3577
+ # required to be an integer
3578
+ if xc == 1
3579
+ if ye >= 0
3580
+ exponent = xe*yc*num_class.int_radix_power(ye)
3581
+ else
3582
+ exponent, remainder = (xe*yc).divmod(num_class.int_radix_power(-ye))
3583
+ return nil if remainder!=0
3584
+ end
3585
+ exponent = -exponent if other.sign == -1
3586
+ # if other is a nonnegative integer, use ideal exponent
3587
+ if other.integral? and (other.sign == +1)
3588
+ ideal_exponent = self.exponent*other.to_i
3589
+ zeros = [exponent-ideal_exponent, p-1].min
3590
+ else
3591
+ zeros = 0
3592
+ end
3593
+ return Num(+1, num_class.int_radix_power(zeros), exponent-zeros)
3594
+ end
3595
+
3596
+ # case where y is negative: xc must be either a power
3597
+ # of 2 or a power of 5.
3598
+ if other.sign == -1
3599
+ # TODO: detect powers of 2 or 5
3600
+ return nil
3601
+ end
3602
+
3603
+ # now y is positive; find m and n such that y = m/n
3604
+ if ye >= 0
3605
+ m, n = num_class.int_mult_radix_power(yc,ye), 1
3606
+ else
3607
+ return nil if (xe != 0) and (_number_of_digits((yc*xe).abs) <= -ye)
3608
+ xc_bits = _nbits(xc)
3609
+ return nil if (xc != 1) and (_number_of_digits(yc.abs*xc_bits) <= -ye)
3610
+ m, n = yc, num_class.int_radix_power(-ye)
3611
+ while ((m % 2) == 0) && ((n % 2) == 0)
3612
+ m /= 2
3613
+ n /= 2
3614
+ end
3615
+ while ((m % 5) == 0) && ((n % 5) == 0)
3616
+ m /= 5
3617
+ n /= 5
3618
+ end
3619
+ end
3620
+
3621
+ # compute nth root of xc*radix**xe
3622
+ if n > 1
3623
+ # if 1 < xc < 2**n then xc isn't an nth power
3624
+ return nil if xc != 1 and xc_bits <= n
3625
+
3626
+ xe, rem = xe.divmod(n)
3627
+ return nil if rem != 0
3628
+
3629
+ # compute nth root of xc using Newton's method
3630
+ a = 1 << -(-_nbits(xc)/n) # initial estimate
3631
+ q = r = nil
3632
+ loop do
3633
+ q, r = xc.divmod(a**(n-1))
3634
+ break if a <= q
3635
+ a = (a*(n-1) + q)/n
3636
+ end
3637
+ return nil if !((a == q) and (r == 0))
3638
+ xc = a
3639
+ end
3640
+
3641
+ # now xc*radix**xe is the nth root of the original xc*radix**xe
3642
+ # compute mth power of xc*radix**xe
3643
+
3644
+ # if m > p*_log_radix_mult/_log_radix_lb(xc) then m > p/log_radix(xc),
3645
+ # hence xc**m > radix**p and the result is not representable.
3646
+ #return nil if (xc > 1) and (m > p*100/_log10_lb(xc))
3647
+ return nil if (xc > 1) and (m > p*_log_radix_mult/_log_radix_lb(xc))
3648
+ xc = xc**m
3649
+ xe *= m
3650
+ return nil if xc > num_class.int_radix_power(p)
3651
+
3652
+ # by this point the result *is* exactly representable
3653
+ # adjust the exponent to get as close as possible to the ideal
3654
+ # exponent, if necessary
3655
+ if other.integral? && other.sign == +1
3656
+ ideal_exponent = self.exponent*other.to_i
3657
+ zeros = [xe-ideal_exponent, p-_number_of_digits(xc)].min
3658
+ else
3659
+ zeros = 0
3660
+ end
3661
+ return Num(+1, num_class.int_mult_radix_power(xc, zeros), xe-zeros)
3662
+ end
3663
+
3664
+ module AuxiliarFunctions
3665
+
3666
+ module_function
3667
+
3668
+ # Convert a numeric value to decimal (internal use)
3669
+ def _convert(x, error=true)
3670
+ case x
3671
+ when num_class
3672
+ x
3673
+ when *num_class.context.coercible_types
3674
+ num_class.new(x)
3675
+ else
3676
+ raise TypeError, "Unable to convert #{x.class} to #{num_class}" if error
3677
+ nil
3678
+ end
3679
+ end
3680
+
3681
+ # Parse numeric text literals (internal use)
3682
+ def _parser(txt)
3683
+ md = /^\s*([-+])?(?:(?:(\d+)(?:\.(\d*))?|\.(\d+))(?:[eE]([-+]?\d+))?|Inf(?:inity)?|(s)?NaN(\d*))\s*$/i.match(txt)
3684
+ if md
3685
+ OpenStruct.new :sign=>md[1], :int=>md[2], :frac=>md[3], :onlyfrac=>md[4], :exp=>md[5],
3686
+ :signal=>md[6], :diag=>md[7]
3687
+ end
3688
+ end
3689
+
3690
+ # Normalizes op1, op2 to have the same exp and length of coefficient. Used for addition.
3691
+ def _normalize(op1, op2, prec=0)
3692
+ if op1.exponent < op2.exponent
3693
+ swap = true
3694
+ tmp,other = op2,op1
3695
+ else
3696
+ swap = false
3697
+ tmp,other = op1,op2
3698
+ end
3699
+ tmp_len = tmp.number_of_digits
3700
+ other_len = other.number_of_digits
3701
+ exp = tmp.exponent + [-1, tmp_len - prec - 2].min
3702
+ if (other_len+other.exponent-1 < exp) && prec>0
3703
+ other = num_class.new([other.sign, 1, exp])
3704
+ end
3705
+ tmp = Num(tmp.sign,
3706
+ num_class.int_mult_radix_power(tmp.coefficient, tmp.exponent-other.exponent),
3707
+ other.exponent)
3708
+ return swap ? [other, tmp] : [tmp, other]
3709
+ end
3710
+
3711
+ # Given integers xc, xe, yc and ye representing Num x = xc*radix**xe and
3712
+ # y = yc*radix**ye, compute x**y. Returns a pair of integers (c, e) such that:
3713
+ #
3714
+ # radix**(p-1) <= c <= radix**p, and
3715
+ # (c-1)*radix**e < x**y < (c+1)*radix**e
3716
+ #
3717
+ # in other words, c*radix**e is an approximation to x**y with p digits
3718
+ # of precision, and with an error in c of at most 1. (This is
3719
+ # almost, but not quite, the same as the error being < 1ulp: when c
3720
+ # == radix**(p-1) we can only guarantee error < radix ulp.)
3721
+ #
3722
+ # We assume that: x is positive and not equal to 1, and y is nonzero.
3723
+ def _power(xc, xe, yc, ye, p)
3724
+ # Find b such that radix**(b-1) <= |y| <= radix**b
3725
+ b = _number_of_digits(yc.abs) + ye
3726
+
3727
+ # log(x) = lxc*radix**(-p-b-1), to p+b+1 places after the decimal point
3728
+ lxc = _log(xc, xe, p+b+1)
3729
+
3730
+ # compute product y*log(x) = yc*lxc*radix**(-p-b-1+ye) = pc*radix**(-p-1)
3731
+ shift = ye-b
3732
+ if shift >= 0
3733
+ pc = lxc*yc*num_class.int_radix_power(shift)
3734
+ else
3735
+ pc = _div_nearest(lxc*yc, num_class.int_radix_power(-shift))
3736
+ end
3737
+
3738
+ if pc == 0
3739
+ # we prefer a result that isn't exactly 1; this makes it
3740
+ # easier to compute a correctly rounded result in __pow__
3741
+ if (_number_of_digits(xc) + xe >= 1) == (yc > 0) # if x**y > 1:
3742
+ coeff, exp = num_class.int_radix_power(p-1)+1, 1-p
3743
+ else
3744
+ coeff, exp = num_class.int_radix_power(p)-1, -p
3745
+ end
3746
+ else
3747
+ coeff, exp = _exp(pc, -(p+1), p+1)
3748
+ coeff = _div_nearest(coeff, num_class.radix)
3749
+ exp += 1
3750
+ end
3751
+
3752
+ return coeff, exp
3753
+ end
3754
+
3755
+ EXP_INC = 4
3756
+ # Compute an approximation to exp(c*radix**e), with p decimal places of precision.
3757
+ # Returns integers d, f such that:
3758
+ #
3759
+ # radix**(p-1) <= d <= radix**p, and
3760
+ # (d-1)*radix**f < exp(c*radix**e) < (d+1)*radix**f
3761
+ #
3762
+ # In other words, d*radix**f is an approximation to exp(c*radix**e) with p
3763
+ # digits of precision, and with an error in d of at most 1. This is
3764
+ # almost, but not quite, the same as the error being < 1ulp: when d
3765
+ # = radix**(p-1) the error could be up to radix ulp.
3766
+ def _exp(c, e, p)
3767
+ # we'll call iexp with M = radix**(p+2), giving p+3 digits of precision
3768
+ p += EXP_INC
3769
+
3770
+ # compute log(radix) with extra precision = adjusted exponent of c*radix**e
3771
+ # TODO: without the .abs tests fail because c is negative: c should not be negative!!
3772
+ extra = [0, e + _number_of_digits(c.abs) - 1].max
3773
+ q = p + extra
3774
+
3775
+ # compute quotient c*radix**e/(log(radix)) = c*radix**(e+q)/(log(radix)*radix**q),
3776
+ # rounding down
3777
+ shift = e+q
3778
+ if shift >= 0
3779
+ cshift = c*num_class.int_radix_power(shift)
3780
+ else
3781
+ cshift = c/num_class.int_radix_power(-shift)
3782
+ end
3783
+ quot, rem = cshift.divmod(_log_radix_digits(q))
3784
+
3785
+ # reduce remainder back to original precision
3786
+ rem = _div_nearest(rem, num_class.int_radix_power(extra))
3787
+
3788
+ # for radix=10: error in result of _iexp < 120; error after division < 0.62
3789
+ r = _div_nearest(_iexp(rem, num_class.int_radix_power(p)), num_class.int_radix_power(EXP_INC+1)), quot - p + (EXP_INC+1)
3790
+ return r
3791
+ end
3792
+
3793
+ LOG_PREC_INC = 4
3794
+ # Given integers c, e and p with c > 0, compute an integer
3795
+ # approximation to radix**p * log(c*radix**e), with an absolute error of
3796
+ # at most 1. Assumes that c*radix**e is not exactly 1.
3797
+ def _log(c, e, p)
3798
+ # Increase precision by 2. The precision increase is compensated
3799
+ # for at the end with a division
3800
+ p += LOG_PREC_INC
3801
+
3802
+ # rewrite c*radix**e as d*radix**f with either f >= 0 and 1 <= d <= radix,
3803
+ # or f <= 0 and 1/radix <= d <= 1. Then we can compute radix**p * log(c*radix**e)
3804
+ # as radix**p * log(d) + radix**p*f * log(radix).
3805
+ l = _number_of_digits(c)
3806
+ f = e+l - ((e+l >= 1) ? 1 : 0)
3807
+
3808
+ # compute approximation to radix**p*log(d), with error < 27 for radix=10
3809
+ if p > 0
3810
+ k = e+p-f
3811
+ if k >= 0
3812
+ c *= num_class.int_radix_power(k)
3813
+ else
3814
+ c = _div_nearest(c, num_class.int_radix_power(-k)) # error of <= 0.5 in c for radix=10
3815
+ end
3816
+
3817
+ # _ilog magnifies existing error in c by a factor of at most radix
3818
+ log_d = _ilog(c, num_class.int_radix_power(p)) # error < 5 + 22 = 27 for radix=10
3819
+ else
3820
+ # p <= 0: just approximate the whole thing by 0; error < 2.31 for radix=10
3821
+ log_d = 0
3822
+ end
3823
+
3824
+ # compute approximation to f*radix**p*log(radix), with error < 11 for radix=10.
3825
+ if f
3826
+ extra = _number_of_digits(f.abs) - 1
3827
+ if p + extra >= 0
3828
+ # for radix=10:
3829
+ # error in f * _log10_digits(p+extra) < |f| * 1 = |f|
3830
+ # after division, error < |f|/10**extra + 0.5 < 10 + 0.5 < 11
3831
+ f_log_r = _div_nearest(f*_log_radix_digits(p+extra), num_class.int_radix_power(extra))
3832
+ else
3833
+ f_log_r = 0
3834
+ end
3835
+ else
3836
+ f_log_r = 0
3837
+ end
3838
+
3839
+ # error in sum < 11+27 = 38; error after division < 0.38 + 0.5 < 1 for radix=10
3840
+ return _div_nearest(f_log_r + log_d, num_class.int_radix_power(LOG_PREC_INC)) # extra radix factor for base 2 ???
3841
+ end
3842
+
3843
+ # Given integers x and M, M > 0, such that x/M is small in absolute
3844
+ # value, compute an integer approximation to M*exp(x/M).
3845
+ # For redix=10, and 0 <= x/M <= 2.4, the absolute error in the result is bounded by 60 (and
3846
+ # is usually much smaller).
3847
+ def _iexp(x, m, l=8)
3848
+
3849
+ # Algorithm: to compute exp(z) for a real number z, first divide z
3850
+ # by a suitable power R of 2 so that |z/2**R| < 2**-L. Then
3851
+ # compute expm1(z/2**R) = exp(z/2**R) - 1 using the usual Taylor
3852
+ # series
3853
+ #
3854
+ # expm1(x) = x + x**2/2! + x**3/3! + ...
3855
+ #
3856
+ # Now use the identity
3857
+ #
3858
+ # expm1(2x) = expm1(x)*(expm1(x)+2)
3859
+ #
3860
+ # R times to compute the sequence expm1(z/2**R),
3861
+ # expm1(z/2**(R-1)), ... , exp(z/2), exp(z).
3862
+
3863
+ # Find R such that x/2**R/M <= 2**-L
3864
+ r = _nbits((x<<l)/m)
3865
+
3866
+ # Taylor series. (2**L)**T > M
3867
+ t = -(-num_class.radix*_number_of_digits(m)/(3*l)).to_i
3868
+ y = _div_nearest(x, t)
3869
+ mshift = m<<r
3870
+ (1...t).to_a.reverse.each do |i|
3871
+ y = _div_nearest(x*(mshift + y), mshift * i)
3872
+ end
3873
+
3874
+ # Expansion
3875
+ (0...r).to_a.reverse.each do |k|
3876
+ mshift = m<<(k+2)
3877
+ y = _div_nearest(y*(y+mshift), mshift)
3878
+ end
3879
+
3880
+ return m+y
3881
+ end
3882
+
3883
+ # Integer approximation to M*log(x/M), with absolute error boundable
3884
+ # in terms only of x/M.
3885
+ #
3886
+ # Given positive integers x and M, return an integer approximation to
3887
+ # M * log(x/M). For radix=10, L = 8 and 0.1 <= x/M <= 10 the difference
3888
+ # between the approximation and the exact result is at most 22. For
3889
+ # L = 8 and 1.0 <= x/M <= 10.0 the difference is at most 15. In
3890
+ # both cases these are upper bounds on the error; it will usually be
3891
+ # much smaller.
3892
+ def _ilog(x, m, l = 8)
3893
+ # The basic algorithm is the following: let log1p be the function
3894
+ # log1p(x) = log(1+x). Then log(x/M) = log1p((x-M)/M). We use
3895
+ # the reduction
3896
+ #
3897
+ # log1p(y) = 2*log1p(y/(1+sqrt(1+y)))
3898
+ #
3899
+ # repeatedly until the argument to log1p is small (< 2**-L in
3900
+ # absolute value). For small y we can use the Taylor series
3901
+ # expansion
3902
+ #
3903
+ # log1p(y) ~ y - y**2/2 + y**3/3 - ... - (-y)**T/T
3904
+ #
3905
+ # truncating at T such that y**T is small enough. The whole
3906
+ # computation is carried out in a form of fixed-point arithmetic,
3907
+ # with a real number z being represented by an integer
3908
+ # approximation to z*M. To avoid loss of precision, the y below
3909
+ # is actually an integer approximation to 2**R*y*M, where R is the
3910
+ # number of reductions performed so far.
3911
+
3912
+ y = x-m
3913
+ # argument reduction; R = number of reductions performed
3914
+ r = 0
3915
+ # while (r <= l && y.abs << l-r >= m ||
3916
+ # r > l and y.abs>> r-l >= m)
3917
+ while (((r <= l) && ((y.abs << (l-r)) >= m)) ||
3918
+ ((r > l) && ((y.abs>>(r-l)) >= m)))
3919
+ y = _div_nearest((m*y) << 1,
3920
+ m + _sqrt_nearest(m*(m+_rshift_nearest(y, r)), m))
3921
+ r += 1
3922
+ end
3923
+
3924
+ # Taylor series with T terms
3925
+ t = -(-10*_number_of_digits(m)/(3*l)).to_i
3926
+ yshift = _rshift_nearest(y, r)
3927
+ w = _div_nearest(m, t)
3928
+ # (1...t).reverse_each do |k| # Ruby 1.9
3929
+ (1...t).to_a.reverse.each do |k|
3930
+ w = _div_nearest(m, k) - _div_nearest(yshift*w, m)
3931
+ end
3932
+
3933
+ return _div_nearest(w*y, m)
3934
+ end
3935
+
3936
+ # Closest integer to the square root of the positive integer n. a is
3937
+ # an initial approximation to the square root. Any positive integer
3938
+ # will do for a, but the closer a is to the square root of n the
3939
+ # faster convergence will be.
3940
+ def _sqrt_nearest(n, a)
3941
+
3942
+ if n <= 0 or a <= 0
3943
+ raise ArgumentError, "Both arguments to _sqrt_nearest should be positive."
3944
+ end
3945
+
3946
+ b=0
3947
+ while a != b
3948
+ b, a = a, a--n/a>>1 # ??
3949
+ end
3950
+ return a
3951
+ end
3952
+
3953
+ # Given an integer x and a nonnegative integer shift, return closest
3954
+ # integer to x / 2**shift; use round-to-even in case of a tie.
3955
+ def _rshift_nearest(x, shift)
3956
+ b, q = (1 << shift), (x >> shift)
3957
+ return q + (((2*(x & (b-1)) + (q&1)) > b) ? 1 : 0)
3958
+ #return q + (2*(x & (b-1)) + (((q&1) > b) ? 1 : 0))
3959
+ end
3960
+
3961
+ # Closest integer to a/b, a and b positive integers; rounds to even
3962
+ # in the case of a tie.
3963
+ def _div_nearest(a, b)
3964
+ q, r = a.divmod(b)
3965
+ q + (((2*r + (q&1)) > b) ? 1 : 0)
3966
+ end
3967
+
3968
+ # We'll memoize the digits of log(10):
3969
+ @log_radix_digits = {
3970
+ # 10=>"23025850929940456840179914546843642076011014886",
3971
+ 2=>""
3972
+ }
3973
+ class <<self
3974
+ attr_reader :log_radix_digits
3975
+ end
3976
+ LOG_RADIX_INC = 2
3977
+ LOG_RADIX_EXTRA = 3
3978
+
3979
+ # Given an integer p >= 0, return floor(radix**p)*log(radix).
3980
+ def _log_radix_digits(p)
3981
+ # digits are stored as a string, for quick conversion to
3982
+ # integer in the case that we've already computed enough
3983
+ # digits; the stored digits should always bge correct
3984
+ # (truncated, not rounded to nearest).
3985
+ raise ArgumentError, "p should be nonnegative" if p<0
3986
+ stored_digits = (AuxiliarFunctions.log_radix_digits[num_class.radix] || "")
3987
+ if p >= stored_digits.length
3988
+ digits = nil
3989
+ # compute p+3, p+6, p+9, ... digits; continue until at
3990
+ # least one of the extra digits is nonzero
3991
+ extra = LOG_RADIX_EXTRA
3992
+ loop do
3993
+ # compute p+extra digits, correct to within 1ulp
3994
+ m = num_class.int_radix_power(p+extra+LOG_RADIX_INC)
3995
+ digits = _div_nearest(_ilog(num_class.radix*m, m), num_class.int_radix_power(LOG_RADIX_INC)).to_s(num_class.radix)
3996
+ break if digits[-extra..-1] != '0'*extra
3997
+ extra += LOG_RADIX_EXTRA
3998
+ end
3999
+ # if the radix < e (i.e. only for radix==2), we must prefix with a 0 because log(radix)<1
4000
+ # BUT THIS REDUCES PRECISION BY ONE? : may be avoid prefix and adjust scaling in the caller
4001
+ prefix = num_class.radix==2 ? '0' : ''
4002
+ # keep all reliable digits so far; remove trailing zeros
4003
+ # and next nonzero digit
4004
+ AuxiliarFunctions.log_radix_digits[num_class.radix] = prefix + digits.sub(/0*$/,'')[0...-1]
4005
+ end
4006
+ return (AuxiliarFunctions.log_radix_digits[num_class.radix][0..p]).to_i(num_class.radix)
4007
+ end
4008
+
4009
+ LOG2_MULT = 100 # TODO: K=100? K=64? ...
4010
+ LOG2_LB_CORRECTION = [ # (1..15).map{|i| (LOG2_MULT*Math.log(16.0/i)/Math.log(2)).ceil}
4011
+ 400, 300, 242, 200, 168, 142, 120, 100, 84, 68, 55, 42, 30, 20, 10
4012
+ # for LOG2_MULT=64: 256, 192, 155, 128, 108, 91, 77, 64, 54, 44, 35, 27, 20, 13, 6
4013
+ ]
4014
+ # Compute a lower bound for LOG2_MULT*log10(c) for a positive integer c.
4015
+ def log2_lb(c)
4016
+ raise ArgumentError, "The argument to _log2_lb should be nonnegative." if c <= 0
4017
+ str_c = c.to_s(16)
4018
+ return LOG2_MULT*4*str_c.length - LOG2_LB_CORRECTION[str_c[0,1].to_i(16)]
4019
+ end
4020
+
4021
+ LOG10_MULT = 100
4022
+ LOG10_LB_CORRECTION = { # (1..9).map_hash{|i| LOG10_MULT - (LOG10_MULT*Math.log10(i)).floor}
4023
+ '1'=> 100, '2'=> 70, '3'=> 53, '4'=> 40, '5'=> 31,
4024
+ '6'=> 23, '7'=> 16, '8'=> 10, '9'=> 5
4025
+ }
4026
+ # Compute a lower bound for LOG10_MULT*log10(c) for a positive integer c.
4027
+ def log10_lb(c)
4028
+ raise ArgumentError, "The argument to _log10_lb should be nonnegative." if c <= 0
4029
+ str_c = c.to_s
4030
+ return LOG10_MULT*str_c.length - LOG10_LB_CORRECTION[str_c[0,1]]
4031
+ end
4032
+
4033
+ def _log_radix_mult
4034
+ case num_class.radix
4035
+ when 10
4036
+ LOG10_MULT
4037
+ when 2
4038
+ LOG2_MULT
4039
+ else
4040
+ raise ArgumentError, "_log_radix_mult not implemented for base #{num_class.radix}"
4041
+ end
4042
+ end
4043
+
4044
+ def _log_radix_lb(c)
4045
+ case num_class.radix
4046
+ when 10
4047
+ log10_lb(c)
4048
+ when 2
4049
+ log2_lb(c)
4050
+ else
4051
+ raise ArgumentError, "_log_radix_lb not implemented for base #{num_class.radix}"
4052
+ end
4053
+ end
4054
+
4055
+ def _number_of_digits(v)
4056
+ _ndigits(v, num_class.radix)
4057
+ end
4058
+
4059
+ end # AuxiliarFunctions
4060
+
4061
+ include AuxiliarFunctions
4062
+ extend AuxiliarFunctions
4063
+
4064
+ class <<self
4065
+ # Num[base] can be use to obtain a floating-point numeric class with radix base, so that, for example,
4066
+ # Num[2] is equivalent to BinNum and Num[10] to DecNum.
4067
+ #
4068
+ # If the base does not correspond to one of the predefined classes (DecNum, BinNum), a new class
4069
+ # is dynamically generated.
4070
+ def [](base)
4071
+ case base
4072
+ when 10
4073
+ DecNum
4074
+ when 2
4075
+ BinNum
4076
+ else
4077
+ class_name = "Base#{base}Num"
4078
+ unless Flt.const_defined?(class_name)
4079
+ cls = Flt.const_set class_name, Class.new(Num) {
4080
+ def initialize(*args)
4081
+ super(*args)
4082
+ end
4083
+ }
4084
+ meta_cls = class <<cls;self;end
4085
+ meta_cls.send :define_method, :radix do
4086
+ base
4087
+ end
4088
+
4089
+ cls.const_set :Context, Class.new(Num::ContextBase)
4090
+ cls::Context.send :define_method, :initialize do |*options|
4091
+ super(cls, *options)
4092
+ end
4093
+
4094
+ default_digits = 10
4095
+ default_elimit = 100
4096
+
4097
+ cls.const_set :DefaultContext, cls::Context.new(
4098
+ :exact=>false, :precision=>default_digits, :rounding=>:half_even,
4099
+ :elimit=>default_elimit,
4100
+ :flags=>[],
4101
+ :traps=>[DivisionByZero, Overflow, InvalidOperation],
4102
+ :ignored_flags=>[],
4103
+ :capitals=>true,
4104
+ :clamp=>true
4105
+ )
4106
+
4107
+ end
4108
+ Flt.const_get class_name
4109
+
4110
+ end
4111
+ end
4112
+ end
4113
+
4114
+ # Exact base conversion: preserve x value.
4115
+ #
4116
+ # Convert x to a Flt::Num of the specified base or class
4117
+ # If the dest_context is exact, this may raise the Inexact flag (and return NaN), for some cases
4118
+ # (e.g. converting DecNum('0.1') to BinNum)
4119
+ #
4120
+ # The current destination context (overriden by dest_context) determines the valid range and the precision
4121
+ # (if its is not :exact the result will be rounded)
4122
+ def self.convert_exact(x, dest_base_or_class, dest_context=nil)
4123
+ num_class = dest_base_or_class.is_a?(Integer) ? Num[dest_base_or_class] : dest_base_or_class
4124
+ if x.special?
4125
+ if x.nan?
4126
+ num_class.nan
4127
+ else # x.infinite?
4128
+ num_class.infinity(x.sign)
4129
+ end
4130
+ elsif x.zero?
4131
+ num_class.zero(x.sign)
4132
+ else
4133
+ if dest_base_or_class == Float
4134
+ float = true
4135
+ num_class = BinNum
4136
+ dest_context = BinNum::FloatContext
4137
+ end
4138
+ y = num_class.context(dest_context) do
4139
+ sign, coeff, exp = x.split
4140
+ y = num_class.Num(sign*coeff)
4141
+ if exp < 0
4142
+ y /= x.num_class.int_radix_power(-exp)
4143
+ else
4144
+ y *= x.num_class.int_radix_power(exp)
4145
+ end
4146
+ # y.reduce
4147
+ end
4148
+ y = y.to_f if float
4149
+ y
4150
+ end
4151
+ end
4152
+
4153
+ # Approximate base conversion.
4154
+ #
4155
+ # Convert x to another Flt::Num class, so that if the result is converted to back to
4156
+ # the original class with the same precision and rounding mode, the value is preserved,
4157
+ # but use as few decimal digits as possible.
4158
+ #
4159
+ # Optional parameters: a context and/or an options hash can be passed.
4160
+ #
4161
+ # The context should be a context for the type of x, and is used to specified the precision and rounding mode
4162
+ # requiered to restore the original value from the converted value.
4163
+ #
4164
+ # The options are:
4165
+ # * :rounding used to specify the rounding required for back conversion with precedence over the context;
4166
+ # the value :nearest means any round-to-nearest.
4167
+ # * :all_digits to preserve the input precision by using all significant digits in the output, not
4168
+ # just the minimum required
4169
+ # * :minimum_precision to specify a minimum for the precision
4170
+ #
4171
+ # To increment the result number of digits x can be normalized or its precision (quantum) changed,
4172
+ # or use the :minimum_precision option.
4173
+ def self.convert(x, dest_base_or_class, *args)
4174
+ origin_context = args.shift if args.first.is_a?(ContextBase)
4175
+ raise ArgumentError,"Invalid parameters for Num.convert" unless args.size<=1 && (args.empty? || args.first.is_a?(Hash))
4176
+ options = args.first || {}
4177
+
4178
+ rounding = options[:rounding]
4179
+ all_digits = options[:all_digits] # :all_digits ? :shortest/:significative
4180
+ minimum_precision = options[:minimum_precision]
4181
+
4182
+ num_class = dest_base_or_class.is_a?(Integer) ? Num[dest_base_or_class] : dest_base_or_class
4183
+ if x.special?
4184
+ if x.nan?
4185
+ num_class.nan
4186
+ else # x.infinite?
4187
+ num_class.infinite(x.sign)
4188
+ end
4189
+ elsif x.zero?
4190
+ num_class.zero(x.sign)
4191
+ else
4192
+ context = x.num_class.define_context(origin_context)
4193
+
4194
+ p = x.number_of_digits
4195
+ p = minimum_precision if minimum_precision && p<minimum_precision
4196
+ s,f,e = x.split
4197
+ rounding ||= context.rounding unless
4198
+ formatter = Flt::Support::Formatter.new(x.num_class.radix, num_class.context.etiny, num_class.radix)
4199
+ formatter.format(x, f, e, rounding, p, all_digits)
4200
+ dec_pos,digits = formatter.adjusted_digits(rounding)
4201
+
4202
+ # f = digits.map{|d| d.to_s(num_class.radix)}.join.to_i(num_class.radix)
4203
+ f = digits.inject(0){|a,b| a*num_class.radix + b}
4204
+ e = dec_pos - digits.size
4205
+ num_class.Num(s, f, e)
4206
+ end
4207
+ end
4208
+
4209
+ end # Num
4210
+
4211
+ end # Flt