flt 1.0.0

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