ruby-decimal 0.2.2 → 1.0.0

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