ruby-decimal 0.2.2 → 1.0.0

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