Module: BigDecimal::Internal
| Relationships & Source Files | |
| Defined in: | lib/bigdecimal.rb |
Constant Summary
-
EXTRA_PREC =
# File 'lib/bigdecimal.rb', line 17
Default extra precision for intermediate calculations This value is currently the same as BigDecimal.double_fig, but defined separately for future changes.
16
Class Method Summary
-
.coerce_to_bigdecimal(x, prec, method_name)
Coerce x to
::BigDecimalwith the specified precision. - .coerce_validate_prec(prec, method_name, accept_zero: false)
-
.float_log(x)
Calculates
Math.log(x.to_f) considering large or small exponent. - .infinity_computation_result
- .nan_computation_result
-
.newton_loop(prec, initial_precision: BigDecimal.double_fig / 2, safe_margin: 2)
Iteration for Newton's method with increasing precision.
-
.taylor_sum_binary_splitting(x, ds, prec)
Calculating Taylor series sum using binary splitting method Calculates f(x) = (x/d0)(1+(x/d1)(1+(x/d2)(1+(x/d3)(1+...)))) x.n_significant_digits or ds.size must be small to be performant.
- .underflow_computation_result
Class Method Details
.coerce_to_bigdecimal(x, prec, method_name)
Coerce x to ::BigDecimal with the specified precision.
TODO: some methods (example: BigMath.exp) require more precision than specified to coerce.
# File 'lib/bigdecimal.rb', line 21
def self.coerce_to_bigdecimal(x, prec, method_name) # :nodoc: case x when BigDecimal return x when Integer, Float return BigDecimal(x, 0) when Rational return BigDecimal(x, [prec, 2 * BigDecimal.double_fig].max) end raise ArgumentError, "#{x.inspect} can't be coerced into BigDecimal" end
.coerce_validate_prec(prec, method_name, accept_zero: false)
[ GitHub ]# File 'lib/bigdecimal.rb', line 33
def self.coerce_validate_prec(prec, method_name, accept_zero: false) # :nodoc: unless Integer === prec original = prec # Emulate Integer.try_convert for ruby < 3.1 if prec.respond_to?(:to_int) prec = prec.to_int else raise TypeError, "no implicit conversion of #{original.class} into Integer" end raise TypeError, "can't convert #{original.class} to Integer" unless Integer === prec end if accept_zero raise ArgumentError, "Negative precision for #{method_name}" if prec < 0 else raise ArgumentError, "Zero or negative precision for #{method_name}" if prec <= 0 end prec end
.float_log(x)
Calculates Math.log(x.to_f) considering large or small exponent
# File 'lib/bigdecimal.rb', line 87
def self.float_log(x) # :nodoc: Math.log(x._decimal_shift(-x.exponent).to_f) + x.exponent * Math.log(10) end
.infinity_computation_result
[ GitHub ]# File 'lib/bigdecimal.rb', line 53
def self.infinity_computation_result # :nodoc: if BigDecimal.mode(BigDecimal::EXCEPTION_ALL).anybits?(BigDecimal::EXCEPTION_INFINITY) raise FloatDomainError, "Computation results in 'Infinity'" end BigDecimal::INFINITY end
.nan_computation_result
[ GitHub ]# File 'lib/bigdecimal.rb', line 67
def self.nan_computation_result # :nodoc: if BigDecimal.mode(BigDecimal::EXCEPTION_ALL).anybits?(BigDecimal::EXCEPTION_NaN) raise FloatDomainError, "Computation results to 'NaN'" end BigDecimal::NAN end
.newton_loop(prec, initial_precision: BigDecimal.double_fig / 2, safe_margin: 2)
Iteration for Newton's method with increasing precision
# File 'lib/bigdecimal.rb', line 75
def self.newton_loop(prec, initial_precision: BigDecimal.double_fig / 2, safe_margin: 2) # :nodoc: precs = [] while prec > initial_precision precs << prec prec = (precs.last + 1) / 2 + safe_margin end precs.reverse_each do |p| yield p end end
.taylor_sum_binary_splitting(x, ds, prec)
Calculating Taylor series sum using binary splitting method Calculates f(x) = (x/d0)(1+(x/d1)(1+(x/d2)(1+(x/d3)(1+...)))) x.n_significant_digits or ds.size must be small to be performant.
# File 'lib/bigdecimal.rb', line 94
def self.taylor_sum_binary_splitting(x, ds, prec) # :nodoc: fs = ds.map {|d| [0, BigDecimal(d)] } # fs = [[a0, a1], [b0, b1], [c0, c1], ...] # f(x) = a0/a1(x/a1)*(1b0/b1(x/b1)*(1c0/c1(x/c1)*(1d0/d1(x/d1)*(1...)))) while fs.size > 1 # Merge two adjacent fractions # from: (1 + a0/a1 + x/a1 * (1 + b0/b1 + x/b1 * rest)) # to: (1 + (a0*b1x*(b0b1))/(a1*b1) + (x*x)/(a1*b1) * rest) xn = xn ? xn.mult(xn, prec) : x fs = fs.each_slice(2).map do |(a, b)| b ||= [0, BigDecimal(1)._decimal_shift([xn.exponent, 0].max + 2)] [ (a[0] * b[1]).add(xn * (b[0] + b[1]), prec), a[1].mult(b[1], prec) ] end end BigDecimal(fs[0][0]).div(fs[0][1], prec) end
.underflow_computation_result
[ GitHub ]# File 'lib/bigdecimal.rb', line 60
def self.underflow_computation_result # :nodoc: if BigDecimal.mode(BigDecimal::EXCEPTION_ALL).anybits?(BigDecimal::EXCEPTION_UNDERFLOW) raise FloatDomainError, 'Exponent underflow' end BigDecimal(0) end