bigdecimal 4.1.1 → 4.1.3
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 +4 -4
- data/bigdecimal.gemspec +2 -0
- data/ext/bigdecimal/bigdecimal.c +60 -18
- data/ext/bigdecimal/bigdecimal.h +5 -5
- data/ext/bigdecimal/div.h +70 -43
- data/ext/bigdecimal/missing/dtoa.c +184 -137
- data/ext/bigdecimal/ntt.h +5 -5
- data/lib/bigdecimal/math/erf.rb +291 -0
- data/lib/bigdecimal/math/gamma.rb +513 -0
- data/lib/bigdecimal/math.rb +10 -221
- data/lib/bigdecimal.rb +20 -12
- data/sig/big_decimal.rbs +3 -1
- metadata +3 -1
data/ext/bigdecimal/ntt.h
CHANGED
|
@@ -68,7 +68,7 @@ ntt(int size_bits, uint32_t *input, uint32_t *output, uint32_t *tmp, int r_base,
|
|
|
68
68
|
|
|
69
69
|
// rmax**(1 << shift) % prime == 1
|
|
70
70
|
// r**size % prime == 1
|
|
71
|
-
uint32_t rmax = mod_pow(r_base, base, prime);
|
|
71
|
+
uint32_t rmax = mod_pow((uint32_t)r_base, (uint32_t)base, prime);
|
|
72
72
|
uint32_t r = mod_pow(rmax, (uint32_t)1 << (shift - size_bits), prime);
|
|
73
73
|
|
|
74
74
|
if (dir < 0) r = mod_pow(r, prime - 2, prime);
|
|
@@ -123,7 +123,7 @@ ntt_multiply(size_t a_size, size_t b_size, uint32_t *a, uint32_t *b, uint32_t *c
|
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
int ntt_size_bits = bit_length(b_size - 1) + 1;
|
|
126
|
+
int ntt_size_bits = (int)bit_length(b_size - 1) + 1;
|
|
127
127
|
if (ntt_size_bits > MAX_NTT32_BITS) {
|
|
128
128
|
rb_raise(rb_eArgError, "Multiply size too large");
|
|
129
129
|
}
|
|
@@ -133,7 +133,7 @@ ntt_multiply(size_t a_size, size_t b_size, uint32_t *a, uint32_t *b, uint32_t *c
|
|
|
133
133
|
uint32_t batch_size = ntt_size - (uint32_t)b_size;
|
|
134
134
|
uint32_t batch_count = (uint32_t)((a_size + batch_size - 1) / batch_size);
|
|
135
135
|
|
|
136
|
-
uint32_t *mem = ruby_xcalloc(
|
|
136
|
+
uint32_t *mem = ruby_xcalloc(ntt_size * 9, sizeof(uint32_t));
|
|
137
137
|
uint32_t *ntt1 = mem;
|
|
138
138
|
uint32_t *ntt2 = mem + ntt_size;
|
|
139
139
|
uint32_t *ntt3 = mem + ntt_size * 2;
|
|
@@ -177,12 +177,12 @@ ntt_multiply(size_t a_size, size_t b_size, uint32_t *a, uint32_t *b, uint32_t *c
|
|
|
177
177
|
// so this sum doesn't overflow uint32_t.
|
|
178
178
|
for (int j = 0; j < 3; j++) {
|
|
179
179
|
// Index check: if dig[j] is non-zero, assign index is within valid range.
|
|
180
|
-
if (dig[j]) c[idx * batch_size + i + 1 - j] += dig[j];
|
|
180
|
+
if (dig[j]) c[idx * batch_size + i + 1 - (uint32_t)j] += dig[j];
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
uint32_t carry = 0;
|
|
185
|
-
for (int32_t i = (
|
|
185
|
+
for (int32_t i = (int32_t)(a_size + b_size - 1); i >= 0; i--) {
|
|
186
186
|
uint32_t v = c[i] + carry;
|
|
187
187
|
c[i] = v % NTT_DECDIG_BASE;
|
|
188
188
|
carry = v / NTT_DECDIG_BASE;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BigMath
|
|
4
|
+
# Bit-burst implementation of BigMath.erf and BigMath.erfc.
|
|
5
|
+
#
|
|
6
|
+
# Both functions share the same incremental update: given erf(x0+...+xk) (or erfc),
|
|
7
|
+
# extend to erf(x0+...+xk+x_{k+1}) by adding (or, for erfc, subtracting) the Taylor
|
|
8
|
+
# expansion of the difference function
|
|
9
|
+
# g(t) := (erf(t + a) - erf(a)) * exp(a**2) * sqrt(pi) / 2 with a = x0+...+xk
|
|
10
|
+
# which satisfies the homogeneous ODE g''(t) + 2*(t+a)*g'(t) = 0.
|
|
11
|
+
# Each step uses binary splitting on the 3-term recurrence of g's Taylor coefficients;
|
|
12
|
+
# split widths x1, x2, ... double in digits, giving quasi-linear total cost.
|
|
13
|
+
#
|
|
14
|
+
# Only the bit-burst seed differs between the two:
|
|
15
|
+
# erf : seed = erf(x0) via Taylor expansion at 0
|
|
16
|
+
# erfc : seed = erfc(x0) via asymptotic expansion (requires x0 large enough;
|
|
17
|
+
# returns nil if asymptotic cannot reach the requested precision, in which
|
|
18
|
+
# case erfc(x) is recovered from 1 - erf(x) with extra digits to absorb
|
|
19
|
+
# cancellation)
|
|
20
|
+
#
|
|
21
|
+
# Edge cases (after symmetry erf(-x) = -erf(x)):
|
|
22
|
+
# x == 0 : erf = 0
|
|
23
|
+
# x > 5e9 : erf = 1, erfc underflows
|
|
24
|
+
# x < 0.5 (erfc only) : compute via 1 - erf to avoid unnecessary work
|
|
25
|
+
module Erf # :nodoc:
|
|
26
|
+
|
|
27
|
+
# Calculates erf with given precision.
|
|
28
|
+
def self.erf(x, prec)
|
|
29
|
+
prec = BigDecimal::Internal.coerce_validate_prec(prec, :erf)
|
|
30
|
+
x = BigDecimal::Internal.coerce_to_bigdecimal(x, prec, :erf)
|
|
31
|
+
return BigDecimal::Internal.nan_computation_result if x.nan?
|
|
32
|
+
return BigDecimal(x.infinite?) if x.infinite?
|
|
33
|
+
return BigDecimal(0) if x == 0
|
|
34
|
+
return -erf(-x, prec) if x < 0
|
|
35
|
+
return BigDecimal(1) if x > 5000000000 # erf(5000000000) > 1 - 1e-10000000000000000000
|
|
36
|
+
if x > 8
|
|
37
|
+
xf = x.to_f
|
|
38
|
+
log10_erfc = -xf ** 2 / Math.log(10) - Math.log10(xf * Math::PI ** 0.5)
|
|
39
|
+
erfc_prec = [prec + log10_erfc.ceil, 1].max
|
|
40
|
+
erfc = erfc_bit_burst(x, erfc_prec + BigDecimal::Internal::EXTRA_PREC)
|
|
41
|
+
return BigDecimal(1).sub(erfc, prec) if erfc
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
erf_bit_burst(x, prec + BigDecimal::Internal::EXTRA_PREC).mult(1, prec)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Calculates erfc with given precision.
|
|
48
|
+
def self.erfc(x, prec)
|
|
49
|
+
prec = BigDecimal::Internal.coerce_validate_prec(prec, :erfc)
|
|
50
|
+
x = BigDecimal::Internal.coerce_to_bigdecimal(x, prec, :erfc)
|
|
51
|
+
return BigDecimal::Internal.nan_computation_result if x.nan?
|
|
52
|
+
return BigDecimal(1 - x.infinite?) if x.infinite?
|
|
53
|
+
return BigDecimal(1).sub(erf(x, prec + BigDecimal::Internal::EXTRA_PREC), prec) if x < 0.5
|
|
54
|
+
return BigDecimal::Internal.underflow_computation_result if x > 5000000000 # erfc(5000000000) < 1e-10000000000000000000 (underflow)
|
|
55
|
+
|
|
56
|
+
if x > 8
|
|
57
|
+
y = erfc_bit_burst(x, prec + BigDecimal::Internal::EXTRA_PREC)
|
|
58
|
+
return y.mult(1, prec) if y
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# erfc(x) = 1 - erf(x) < exp(-x**2)/x/sqrt(pi)
|
|
62
|
+
# Precision of erf(x) needs about log10(exp(-x**2)/x/sqrt(pi)) extra digits
|
|
63
|
+
log10 = 2.302585092994046
|
|
64
|
+
xf = x.to_f
|
|
65
|
+
high_prec = prec + BigDecimal::Internal::EXTRA_PREC + ((xf**2 + Math.log(xf) + Math.log(Math::PI)/2) / log10).ceil
|
|
66
|
+
BigDecimal(1).sub(erf_bit_burst(x, high_prec), prec)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Matrix multiplication. m1 and m2 are size*size length array that represents size*size matrix
|
|
70
|
+
def self.matrix_mult(m1, m2, size, prec)
|
|
71
|
+
(size * size).times.map do |i|
|
|
72
|
+
size.times.map do |k|
|
|
73
|
+
m1[i / size * size + k].mult(m2[size * k + i % size], prec)
|
|
74
|
+
end.reduce {|a, b| a.add(b, prec) }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Returns (erf(x + a) - erf(a)) * exp(a**2) * sqrt(pi) / 2 calculated with binary splitting method.
|
|
79
|
+
def self.erf_binary_splitting_diff(x, a, prec)
|
|
80
|
+
# Let f(x) = (erf(x + a) - erf(a)) * exp(a**2) * sqrt(pi) / 2
|
|
81
|
+
# f(x) satisfies the following differential equation:
|
|
82
|
+
# 2*(x+a)*f'(x) + f''(x) = 0
|
|
83
|
+
# We can derive the following recurrence for the Taylor coefficients of f:
|
|
84
|
+
# f(x) = x * (c0 + c1*x + c2*x**2 + c3*x**3 + ...)
|
|
85
|
+
# c(0) = 1
|
|
86
|
+
# c(1) = -a
|
|
87
|
+
# c(i) = -2 * (a * c(i - 1) + c(i - 2) * (i - 1) / i) / (i + 1)
|
|
88
|
+
|
|
89
|
+
# Estimate required number of terms by calculating c(i) with low precision
|
|
90
|
+
low_prec = 10
|
|
91
|
+
a_low = a.mult(1, low_prec)
|
|
92
|
+
x_low = x.mult(1, low_prec)
|
|
93
|
+
coefs = [BigDecimal(1), -a_low]
|
|
94
|
+
xn = BigDecimal(1)
|
|
95
|
+
threshold = BigDecimal(1)._decimal_shift(-prec)
|
|
96
|
+
steps = (2..).find do |n|
|
|
97
|
+
prevprev, prev = coefs
|
|
98
|
+
xn = xn.mult(x_low, low_prec)
|
|
99
|
+
coefs = prev, (a_low * prev + (prevprev * (n - 1)).div(n, low_prec)).mult(-2, low_prec).div(n + 1, low_prec)
|
|
100
|
+
coefs[0].mult(xn, low_prec).abs < threshold && coefs[1].mult(xn * x_low, low_prec).abs < threshold
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Let M(i) be a 2x2 matrix that generates the next coefficients vector (c(i-1), c(i))
|
|
104
|
+
# from the previous two coefficients (c(i-2), c(i-1)).
|
|
105
|
+
# M(i) = | 0, 1 |
|
|
106
|
+
# | -2*(i-1)/i/(i+1), -2*a/(i+1) |
|
|
107
|
+
#
|
|
108
|
+
# Then, we can calculate (c(steps-1), c(steps)) as M(steps)*M(steps-1)*...*M(2)*Vector(c0, c1).
|
|
109
|
+
#
|
|
110
|
+
# Calculate a matrix that represents the sum of the Taylor series:
|
|
111
|
+
# SumMatrix = ((((...+I)x*M4+I)*x*M3+I)*M2*x+I)
|
|
112
|
+
# Actual sum can be calculated as:
|
|
113
|
+
# SumMatrix * Vector(c0, c1) = Vector(c0+c1*x+c2*x**2+c3*x**3+..., _)
|
|
114
|
+
# In this binary splitting method, adjacent two operations are combined into one repeatedly.
|
|
115
|
+
# ((...) * x * A + B) / C is the form of each operation. A and B are 2x2 matrices, C is a scalar.
|
|
116
|
+
|
|
117
|
+
zero = BigDecimal(0)
|
|
118
|
+
operations = (2..steps + 2).map do |i|
|
|
119
|
+
d = BigDecimal(i * (i + 1))
|
|
120
|
+
[[zero, d, BigDecimal(-2 * (i - 1)), a * (-2 * i)], [d, zero, zero, d], d]
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
while operations.size > 1
|
|
124
|
+
xpow = xpow ? xpow.mult(xpow, prec) : x.mult(1, prec)
|
|
125
|
+
operations = operations.each_slice(2).map do |op1, op2|
|
|
126
|
+
# Combine two operations into one:
|
|
127
|
+
# (((Remaining * x * A2 + B2) / C2) * x * A1 + B1) / C1
|
|
128
|
+
# ((Remaining * (x*x) * (A2*A1) + (x*B2*A1+B1*C2)) / (C1*C2)
|
|
129
|
+
# Therefore, combined operation can be represented as:
|
|
130
|
+
# Anext = A2 * A1
|
|
131
|
+
# Bnext = x * B2 * A1 + B1 * C2
|
|
132
|
+
# Cnext = C1 * C2
|
|
133
|
+
# xnext = x * x
|
|
134
|
+
a1, b1, c1 = op1
|
|
135
|
+
a2, b2, c2 = op2 || [[zero] * 4, [zero] * 4, BigDecimal(1)]
|
|
136
|
+
[
|
|
137
|
+
matrix_mult(a2, a1, 2, prec),
|
|
138
|
+
array_weighted_sum(matrix_mult(b2, a1, 2, prec), xpow, b1, c2, prec),
|
|
139
|
+
c1.mult(c2, prec),
|
|
140
|
+
]
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
_, sum_matrix, denominator = operations.first
|
|
144
|
+
sum = (sum_matrix[0] - a * sum_matrix[1]).div(denominator, prec)
|
|
145
|
+
x.mult(sum, prec)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Calculates erfc(x) using bit-burst algorithm.
|
|
149
|
+
# Returns nil if the asymptotic expansion does not reach the requested precision.
|
|
150
|
+
def self.erfc_bit_burst(x, prec)
|
|
151
|
+
# By bounding the relative error via |d(erfc)/erfc| <= 2*x*|dx| (erfc(x) decays as exp(-x**2)/x),
|
|
152
|
+
# truncate x to the minimum digits sufficient for prec-digit accuracy of the result.
|
|
153
|
+
x = x.mult(1, prec + Math.log10(2 * x.to_f**2).ceil)
|
|
154
|
+
erf_erfc_bit_burst(x, prec, start_digits: 40, mode: :erfc)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Calculates erf(x) using bit-burst algorithm.
|
|
158
|
+
def self.erf_bit_burst(x, prec)
|
|
159
|
+
# By bounding the error via erf'(x) = (2/sqrt(pi)) * exp(-x**2),
|
|
160
|
+
# truncate x to the minimum digits sufficient for prec-digit accuracy of the result.
|
|
161
|
+
x = x.mult(1, [(prec - x.floor**2 / Math.log(10) + Math.log10(x.ceil)).ceil, 10].max)
|
|
162
|
+
erf_erfc_bit_burst(x, prec, start_digits: 8, mode: :erf)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Calculates erf or erfc using bit-burst algorithm.
|
|
166
|
+
# Returns nil if erfc mode cannot reach the requested precision.
|
|
167
|
+
def self.erf_erfc_bit_burst(x, prec, start_digits:, mode:)
|
|
168
|
+
digits = [-x.exponent * 2, start_digits].max
|
|
169
|
+
partial = x.truncate(digits)
|
|
170
|
+
case mode
|
|
171
|
+
when :erf
|
|
172
|
+
f = erf_exp2_binary_splitting(partial, prec)
|
|
173
|
+
when :erfc
|
|
174
|
+
f = erfc_exp2_asymptotic_binary_splitting(partial, prec)
|
|
175
|
+
return unless f
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
exp_scale = BigMath.exp(-partial * partial, prec)
|
|
179
|
+
f = f.mult(exp_scale, prec)
|
|
180
|
+
|
|
181
|
+
calculated_x = partial
|
|
182
|
+
x -= partial
|
|
183
|
+
|
|
184
|
+
until x.zero?
|
|
185
|
+
digits *= 2
|
|
186
|
+
partial = x.truncate(digits)
|
|
187
|
+
next if partial.zero?
|
|
188
|
+
|
|
189
|
+
diff_prec = [prec - f.exponent + exp_scale.exponent + partial.exponent, 1].max
|
|
190
|
+
diff = erf_binary_splitting_diff(partial, calculated_x, diff_prec)
|
|
191
|
+
case mode
|
|
192
|
+
when :erf
|
|
193
|
+
f = f.add(diff.mult(exp_scale, prec), prec)
|
|
194
|
+
when :erfc
|
|
195
|
+
f = f.sub(diff.mult(exp_scale, prec), prec)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
calculated_x += partial
|
|
199
|
+
x -= partial
|
|
200
|
+
exp_scale = exp_scale.mult(BigMath.exp(partial * (partial - 2 * calculated_x), diff_prec), diff_prec) unless x.zero?
|
|
201
|
+
end
|
|
202
|
+
f.mult(BigDecimal(2).div(BigMath::PI(prec).sqrt(prec), prec), prec)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Matrix/Vector weighted sum
|
|
206
|
+
def self.array_weighted_sum(m1, w1, m2, w2, prec)
|
|
207
|
+
m1.zip(m2).map {|v1, v2| (v1 * w1).add(v2 * w2, prec) }
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Calculates Taylor expansion of erf(x)*exp(x**2)*sqrt(pi)/2 with binary splitting method.
|
|
211
|
+
def self.erf_exp2_binary_splitting(x, prec)
|
|
212
|
+
# Let f(x) = erf(x)*exp(x**2)*sqrt(pi)/2
|
|
213
|
+
# = c0 + c1*x + c2*x**2 + c3*x**3 + c4*x**4 + ...
|
|
214
|
+
# f(x) is designed to make all coefficients positive so that we don't need to consider cancellation error.
|
|
215
|
+
#
|
|
216
|
+
# f(x) satisfies the following differential equation:
|
|
217
|
+
# f'(x) = 1 + 2 * x * f(x)
|
|
218
|
+
# f'(x) = c1 + 2*c2*x + 3*c3*x**2 + 4*c4*x**3 + 5*c5*x**4 + ...
|
|
219
|
+
# = 1+2*x*(c0 + c1*x + c2*x**2 + c3*x**3 + c4*x**4 + ...)
|
|
220
|
+
# therefore,
|
|
221
|
+
# c0 = 0
|
|
222
|
+
# c1 = 1
|
|
223
|
+
# c2 = 2 * (c0 + c1) / 2
|
|
224
|
+
# c3 = 2 * (c1 + c2) / 3
|
|
225
|
+
# c4 = 2 * (c2 + c3) / 4
|
|
226
|
+
|
|
227
|
+
# Find the smallest n where the n-th Taylor term |c_n * x^n| falls below the precision
|
|
228
|
+
# threshold, using a Stirling-based upper bound on |c_n|.
|
|
229
|
+
log10f = Math.log(10)
|
|
230
|
+
cexponent = Math.log10(Math.sqrt(2)) + BigDecimal::Internal.float_log(x.abs) / log10f
|
|
231
|
+
|
|
232
|
+
x_to_f = x < 1e-300 ? 1e-300 : x.to_f # x.to_f may underflow when x is very small (e.g. 1e-400)
|
|
233
|
+
steps = (2..).bsearch do |n|
|
|
234
|
+
x_to_f ** 2 < n && n * cexponent + Math.lgamma(n / 2)[0] / log10f + n * Math.log10(2) - Math.lgamma(n - 1)[0] / log10f < -prec + x_to_f**2 / log10f
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
denominators = (steps / 2).times.map {|i| 2 * i + 3 }
|
|
238
|
+
x.mult(1 + BigDecimal::Internal.taylor_sum_binary_splitting(2 * x * x, denominators, prec), prec)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Calculates asymptotic expansion of erfc(x)*exp(x**2)*sqrt(pi)/2 with binary splitting method
|
|
242
|
+
def self.erfc_exp2_asymptotic_binary_splitting(x, prec)
|
|
243
|
+
# Let f(x) = erfc(x)*sqrt(pi)*exp(x**2)/2
|
|
244
|
+
# f(x) satisfies the following differential equation:
|
|
245
|
+
# 2*x*f(x) = f'(x) + 1
|
|
246
|
+
# From the above equation, we can derive the following asymptotic expansion:
|
|
247
|
+
# f(x) = (0..kmax).sum { (-1)**k * (2*k)! / 4**k / k! / x**(2*k) } / x / 2
|
|
248
|
+
|
|
249
|
+
# This asymptotic expansion does not converge.
|
|
250
|
+
# But if there is a k that satisfies (2*k)! / 4**k / k! / x**(2*k) < 10**(-prec),
|
|
251
|
+
# It is enough to calculate erfc within the given precision.
|
|
252
|
+
# Using Stirling's approximation, we can simplify this condition to:
|
|
253
|
+
# log(2)/2 + k*log(k) - k - 2*k*log(x) < -prec*log(10)
|
|
254
|
+
# and the left side is minimized when k = x**2.
|
|
255
|
+
xf = x.to_f
|
|
256
|
+
kmax = (1..(xf ** 2).floor).bsearch do |k|
|
|
257
|
+
Math.log(2) / 2 + k * Math.log(k) - k - 2 * k * Math.log(xf) < -prec * Math.log(10)
|
|
258
|
+
end
|
|
259
|
+
return unless kmax
|
|
260
|
+
|
|
261
|
+
# Convert asymptotic expansion to nested form:
|
|
262
|
+
# 1 + a/x + a*b/x/x + a*b*c/x/x/x + a*b*c/x/x/x*rest
|
|
263
|
+
# = 1 + (a/x) * (1 + (b/x) * (1 + (c/x) * (1 + rest)))
|
|
264
|
+
#
|
|
265
|
+
# And calculate it with binary splitting:
|
|
266
|
+
# (a1/d + b1/d * (a2/d + b2/d * (rest)))
|
|
267
|
+
# = ((a1*d+b1*a2)/(d*d) + b1*b2/(d*denominator) * (rest)))
|
|
268
|
+
denominator = x.mult(x, prec).mult(2, prec)
|
|
269
|
+
fractions = (1..kmax).map do |k|
|
|
270
|
+
[denominator, BigDecimal(1 - 2 * k)]
|
|
271
|
+
end
|
|
272
|
+
while fractions.size > 1
|
|
273
|
+
fractions = fractions.each_slice(2).map do |fraction1, fraction2|
|
|
274
|
+
a1, b1 = fraction1
|
|
275
|
+
a2, b2 = fraction2 || [BigDecimal(0), denominator]
|
|
276
|
+
[
|
|
277
|
+
a1.mult(denominator, prec).add(b1.mult(a2, prec), prec),
|
|
278
|
+
b1.mult(b2, prec),
|
|
279
|
+
]
|
|
280
|
+
end
|
|
281
|
+
denominator = denominator.mult(denominator, prec)
|
|
282
|
+
end
|
|
283
|
+
# Plug rest = 1 into the merged form: the innermost "(1 + rest)" of the nested expansion
|
|
284
|
+
# evaluates to 1 at truncation (rest = 0).
|
|
285
|
+
sum = fractions[0][0].add(fractions[0][1], prec).div(denominator, prec)
|
|
286
|
+
sum.div(x, prec) / 2
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
private_constant :Erf
|
|
291
|
+
end
|