ruby-decimal 0.2.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +28 -0
- data/Gemfile +3 -0
- data/History.txt +4 -0
- data/{README.txt → README.rdoc} +9 -0
- data/Rakefile +16 -30
- data/expand.rb +177 -0
- data/lib/decimal.rb +7 -3
- data/lib/decimal/shortcut.rb +1 -6
- data/lib/decimal/version.rb +2 -8
- data/test/helper.rb +2 -2
- data/test/test_basic.rb +1 -1
- data/test/test_coercion.rb +1 -1
- data/test/test_comparisons.rb +1 -1
- data/test/test_dectest.rb +1 -1
- data/test/test_define_conversions.rb +2 -9
- data/test/test_epsilon.rb +1 -1
- data/test/test_exact.rb +1 -2
- data/test/test_flags.rb +8 -9
- data/test/test_flt_wrapping.rb +12 -0
- data/test/test_multithreading.rb +1 -3
- data/test/test_odd_even.rb +1 -1
- data/test/test_round.rb +1 -2
- data/test/test_shortcut.rb +11 -0
- data/test/test_to_int.rb +1 -1
- data/test/test_to_rf.rb +1 -1
- data/test/test_ulp.rb +1 -1
- metadata +80 -73
- data/lib/decimal/decimal.rb +0 -4171
- data/lib/decimal/support.rb +0 -337
- data/setup.rb +0 -1585
- data/tasks/ann.rake +0 -80
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -192
- data/tasks/git.rake +0 -40
- data/tasks/manifest.rake +0 -48
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -39
- data/tasks/rdoc.rake +0 -50
- data/tasks/rubyforge.rake +0 -55
- data/tasks/setup.rb +0 -279
- data/tasks/spec.rake +0 -54
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -40
data/test/test_multithreading.rb
CHANGED
data/test/test_odd_even.rb
CHANGED
data/test/test_round.rb
CHANGED
data/test/test_to_int.rb
CHANGED
data/test/test_to_rf.rb
CHANGED
data/test/test_ulp.rb
CHANGED
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.
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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:
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
32
|
-
-
|
33
|
-
-
|
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.
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
92
|
+
homepage: https://github.com/jgoizueta/ruby-decimal
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata: {}
|
80
96
|
post_install_message:
|
81
|
-
rdoc_options:
|
82
|
-
|
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:
|
99
|
-
|
100
|
-
|
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:
|
105
|
-
version:
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
106
110
|
requirements: []
|
107
|
-
|
108
|
-
|
109
|
-
rubygems_version: 1.3.3
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.2.2
|
110
113
|
signing_key:
|
111
|
-
specification_version:
|
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
|
data/lib/decimal/decimal.rb
DELETED
@@ -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
|