5
5
end
6
6
7
7
class BigDecimal
8
+ module Internal # :nodoc:
9
+
10
+ # Coerce x to BigDecimal with the specified precision.
11
+ # TODO: some methods (example: BigMath.exp) require more precision than specified to coerce.
12
+ def self . coerce_to_bigdecimal ( x , prec , method_name ) # :nodoc:
13
+ case x
14
+ when BigDecimal
15
+ return x
16
+ when Integer , Float
17
+ return BigDecimal ( x )
18
+ when Rational
19
+ return BigDecimal ( x , [ prec , 2 * BigDecimal . double_fig ] . max )
20
+ end
21
+ raise ArgumentError , "#{ x . inspect } can't be coerced into BigDecimal"
22
+ end
23
+
24
+ def self . validate_prec ( prec , method_name ) # :nodoc:
25
+ raise ArgumentError , 'precision must be an Integer' unless Integer === prec
26
+ raise ArgumentError , "Zero or negative precision for #{ method_name } " if prec <= 0
27
+ end
28
+
29
+ def self . infinity_computation_result # :nodoc:
30
+ if BigDecimal . mode ( BigDecimal ::EXCEPTION_ALL ) . anybits? ( BigDecimal ::EXCEPTION_INFINITY )
31
+ raise FloatDomainError , "Computation results in 'Infinity'"
32
+ end
33
+ BigDecimal ::INFINITY
34
+ end
35
+
36
+ def self . nan_computation_result # :nodoc:
37
+ if BigDecimal . mode ( BigDecimal ::EXCEPTION_ALL ) . anybits? ( BigDecimal ::EXCEPTION_NaN )
38
+ raise FloatDomainError , "Computation results to 'NaN'"
39
+ end
40
+ BigDecimal ::NAN
41
+ end
42
+ end
8
43
9
44
# call-seq:
10
45
# self ** other -> bigdecimal
@@ -39,11 +74,11 @@ def **(y)
39
74
# Also available as the operator **.
40
75
#
41
76
def power ( y , prec = nil )
42
- BigMath . _validate_prec ( prec , :power ) if prec
77
+ Internal . validate_prec ( prec , :power ) if prec
43
78
x = self
44
- y = BigMath . _coerce_to_bigdecimal ( y , prec || n_significant_digits , :power )
79
+ y = Internal . coerce_to_bigdecimal ( y , prec || n_significant_digits , :power )
45
80
46
- return BigMath . _nan_computation_result if x . nan? || y . nan?
81
+ return Internal . nan_computation_result if x . nan? || y . nan?
47
82
return BigDecimal ( 1 ) if y . zero?
48
83
49
84
if y . infinite?
@@ -52,11 +87,11 @@ def power(y, prec = nil)
52
87
return BigDecimal ( 0 ) if x > -1 && y . positive?
53
88
raise Math ::DomainError , 'Result undefined for negative base raised to infinite power'
54
89
elsif x < 1
55
- return y . positive? ? BigDecimal ( 0 ) : BigMath . _infinity_computation_result
90
+ return y . positive? ? BigDecimal ( 0 ) : BigDecimal :: Internal . infinity_computation_result
56
91
elsif x == 1
57
92
return BigDecimal ( 1 )
58
93
else
59
- return y . positive? ? BigMath . _infinity_computation_result : BigDecimal ( 0 )
94
+ return y . positive? ? BigDecimal :: Internal . infinity_computation_result : BigDecimal ( 0 )
60
95
end
61
96
end
62
97
@@ -70,9 +105,9 @@ def power(y, prec = nil)
70
105
return BigDecimal ( 1 ) if y . zero?
71
106
return BigDecimal ( 0 ) if y > 0
72
107
if y . frac . zero? && y % 2 == 1 && x . sign == -1
73
- return -BigMath . _infinity_computation_result
108
+ return -BigDecimal :: Internal . infinity_computation_result
74
109
else
75
- return BigMath . _infinity_computation_result
110
+ return BigDecimal :: Internal . infinity_computation_result
76
111
end
77
112
elsif x < 0
78
113
if y . frac . zero?
@@ -105,7 +140,7 @@ def power(y, prec = nil)
105
140
xn *= xn
106
141
# Detect overflow/underflow before consuming infinite memory
107
142
if ( xn . exponent . abs - 1 ) * int_part / n >= 0x7FFFFFFFFFFFFFFF
108
- return ( ( xn . exponent > 0 ) ^ neg ? BigMath . _infinity_computation_result : BigDecimal ( 0 ) ) * ( int_part . even? || x > 0 ? 1 : -1 )
143
+ return ( ( xn . exponent > 0 ) ^ neg ? BigDecimal :: Internal . infinity_computation_result : BigDecimal ( 0 ) ) * ( int_part . even? || x > 0 ? 1 : -1 )
109
144
end
110
145
end
111
146
return neg ? BigDecimal ( 1 ) / ans : ans
@@ -116,7 +151,7 @@ def power(y, prec = nil)
116
151
if y < 0
117
152
inv = x . power ( -y , prec )
118
153
return BigDecimal ( 0 ) if inv . infinite?
119
- return BigMath . _infinity_computation_result if inv . zero?
154
+ return BigDecimal :: Internal . infinity_computation_result if inv . zero?
120
155
return BigDecimal ( 1 ) . div ( inv , prec )
121
156
end
122
157
@@ -143,43 +178,6 @@ def power(y, prec = nil)
143
178
# Other methods (sin, cos, atan) are defined in 'bigdecimal/math.rb'.
144
179
module BigMath
145
180
146
- # Coerce x to BigDecimal with the specified precision.
147
- # TODO: some methods (example: BigMath.exp) require more precision than specified to coerce.
148
- def self . _coerce_to_bigdecimal ( x , prec , method_name , complex_domain_error = false ) # :nodoc:
149
- case x
150
- when BigDecimal
151
- return x
152
- when Integer , Float
153
- return BigDecimal ( x )
154
- when Rational
155
- return BigDecimal ( x , [ prec , 2 * BigDecimal . double_fig ] . max )
156
- when Complex
157
- if complex_domain_error
158
- raise Math ::DomainError , "Complex argument for BigMath.#{ method_name } "
159
- end
160
- end
161
- raise ArgumentError , "#{ x . inspect } can't be coerced into BigDecimal"
162
- end
163
-
164
- def self . _validate_prec ( prec , method_name ) # :nodoc:
165
- raise ArgumentError , 'precision must be an Integer' unless Integer === prec
166
- raise ArgumentError , "Zero or negative precision for #{ method_name } " if prec <= 0
167
- end
168
-
169
- def self . _infinity_computation_result # :nodoc:
170
- if BigDecimal . mode ( BigDecimal ::EXCEPTION_ALL ) . anybits? ( BigDecimal ::EXCEPTION_INFINITY )
171
- raise FloatDomainError , "Computation results in 'Infinity'"
172
- end
173
- BigDecimal ::INFINITY
174
- end
175
-
176
- def self . _nan_computation_result # :nodoc:
177
- if BigDecimal . mode ( BigDecimal ::EXCEPTION_ALL ) . anybits? ( BigDecimal ::EXCEPTION_NaN )
178
- raise FloatDomainError , "Computation results to 'NaN'"
179
- end
180
- BigDecimal ::NAN
181
- end
182
-
183
181
# call-seq:
184
182
# BigMath.log(decimal, numeric) -> BigDecimal
185
183
#
@@ -193,11 +191,13 @@ def self._nan_computation_result # :nodoc:
193
191
# If +decimal+ is NaN, returns NaN.
194
192
#
195
193
def self . log ( x , prec )
196
- _validate_prec ( prec , :log )
197
- x = _coerce_to_bigdecimal ( x , prec , :log , true )
198
- return _nan_computation_result if x . nan?
194
+ BigDecimal ::Internal . validate_prec ( prec , :log )
195
+ raise Math ::DomainError , 'Complex argument for BigMath.log' if Complex === x
196
+
197
+ x = BigDecimal ::Internal . coerce_to_bigdecimal ( x , prec , :log )
198
+ return BigDecimal ::Internal . nan_computation_result if x . nan?
199
199
raise Math ::DomainError , 'Zero or negative argument for log' if x <= 0
200
- return _infinity_computation_result if x . infinite?
200
+ return BigDecimal :: Internal . infinity_computation_result if x . infinite?
201
201
return BigDecimal ( 0 ) if x == 1
202
202
203
203
if x > 10 || x < 0.1
@@ -259,10 +259,10 @@ def self.log(x, prec)
259
259
# If +decimal+ is NaN, returns NaN.
260
260
#
261
261
def self . exp ( x , prec )
262
- _validate_prec ( prec , :exp )
263
- x = _coerce_to_bigdecimal ( x , prec , :exp )
264
- return _nan_computation_result if x . nan?
265
- return x . positive? ? _infinity_computation_result : BigDecimal ( 0 ) if x . infinite?
262
+ BigDecimal :: Internal . validate_prec ( prec , :exp )
263
+ x = BigDecimal :: Internal . coerce_to_bigdecimal ( x , prec , :exp )
264
+ return BigDecimal :: Internal . nan_computation_result if x . nan?
265
+ return x . positive? ? BigDecimal :: Internal . infinity_computation_result : BigDecimal ( 0 ) if x . infinite?
266
266
return BigDecimal ( 1 ) if x . zero?
267
267
return BigDecimal ( 1 ) . div ( exp ( -x , prec ) , prec ) if x < 0
268
268
0 commit comments