xref: /freebsd/contrib/bc/manuals/algorithms.md (revision 5f757f3f)
1# Algorithms
2
3This `bc` uses the math algorithms below:
4
5### Addition
6
7This `bc` uses brute force addition, which is linear (`O(n)`) in the number of
8digits.
9
10### Subtraction
11
12This `bc` uses brute force subtraction, which is linear (`O(n)`) in the number
13of digits.
14
15### Multiplication
16
17This `bc` uses two algorithms: [Karatsuba][1] and brute force.
18
19Karatsuba is used for "large" numbers. ("Large" numbers are defined as any
20number with `BC_NUM_KARATSUBA_LEN` digits or larger. `BC_NUM_KARATSUBA_LEN` has
21a sane default, but may be configured by the user.) Karatsuba, as implemented in
22this `bc`, is superlinear but subpolynomial (bounded by `O(n^log_2(3))`).
23
24Brute force multiplication is used below `BC_NUM_KARATSUBA_LEN` digits. It is
25polynomial (`O(n^2)`), but since Karatsuba requires both more intermediate
26values (which translate to memory allocations) and a few more additions, there
27is a "break even" point in the number of digits where brute force multiplication
28is faster than Karatsuba. There is a script (`$ROOT/scripts/karatsuba.py`) that
29will find the break even point on a particular machine.
30
31***WARNING: The Karatsuba script requires Python 3.***
32
33### Division
34
35This `bc` uses Algorithm D ([long division][2]). Long division is polynomial
36(`O(n^2)`), but unlike Karatsuba, any division "divide and conquer" algorithm
37reaches its "break even" point with significantly larger numbers. "Fast"
38algorithms become less attractive with division as this operation typically
39reduces the problem size.
40
41While the implementation of long division may appear to use the subtractive
42chunking method, it only uses subtraction to find a quotient digit. It avoids
43unnecessary work by aligning digits prior to performing subtraction and finding
44a starting guess for the quotient.
45
46Subtraction was used instead of multiplication for two reasons:
47
481.	Division and subtraction can share code (one of the less important goals of
49	this `bc` is small code).
502.	It minimizes algorithmic complexity.
51
52Using multiplication would make division have the even worse algorithmic
53complexity of `O(n^(2*log_2(3)))` (best case) and `O(n^3)` (worst case).
54
55### Power
56
57This `bc` implements [Exponentiation by Squaring][3], which (via Karatsuba) has
58a complexity of `O((n*log(n))^log_2(3))` which is favorable to the
59`O((n*log(n))^2)` without Karatsuba.
60
61### Square Root
62
63This `bc` implements the fast algorithm [Newton's Method][4] (also known as the
64Newton-Raphson Method, or the [Babylonian Method][5]) to perform the square root
65operation.
66
67Its complexity is `O(log(n)*n^2)` as it requires one division per iteration, and
68it doubles the amount of correct digits per iteration.
69
70### Sine and Cosine (`bc` Math Library Only)
71
72This `bc` uses the series
73
74```
75x - x^3/3! + x^5/5! - x^7/7! + ...
76```
77
78to calculate `sin(x)` and `cos(x)`. It also uses the relation
79
80```
81cos(x) = sin(x + pi/2)
82```
83
84to calculate `cos(x)`. It has a complexity of `O(n^3)`.
85
86**Note**: this series has a tendency to *occasionally* produce an error of 1
87[ULP][6]. (It is an unfortunate side effect of the algorithm, and there isn't
88any way around it; [this article][7] explains why calculating sine and cosine,
89and the other transcendental functions below, within less than 1 ULP is nearly
90impossible and unnecessary.) Therefore, I recommend that users do their
91calculations with the precision (`scale`) set to at least 1 greater than is
92needed.
93
94### Exponentiation (`bc` Math Library Only)
95
96This `bc` uses the series
97
98```
991 + x + x^2/2! + x^3/3! + ...
100```
101
102to calculate `e^x`. Since this only works when `x` is small, it uses
103
104```
105e^x = (e^(x/2))^2
106```
107
108to reduce `x`.
109
110It has a complexity of `O(n^3)`.
111
112**Note**: this series can also produce errors of 1 ULP, so I recommend users do
113their calculations with the precision (`scale`) set to at least 1 greater than
114is needed.
115
116### Natural Logarithm (`bc` Math Library Only)
117
118This `bc` uses the series
119
120```
121a + a^3/3 + a^5/5 + ...
122```
123
124(where `a` is equal to `(x - 1)/(x + 1)`) to calculate `ln(x)` when `x` is small
125and uses the relation
126
127```
128ln(x^2) = 2 * ln(x)
129```
130
131to sufficiently reduce `x`.
132
133It has a complexity of `O(n^3)`.
134
135**Note**: this series can also produce errors of 1 ULP, so I recommend users do
136their calculations with the precision (`scale`) set to at least 1 greater than
137is needed.
138
139### Arctangent (`bc` Math Library Only)
140
141This `bc` uses the series
142
143```
144x - x^3/3 + x^5/5 - x^7/7 + ...
145```
146
147to calculate `atan(x)` for small `x` and the relation
148
149```
150atan(x) = atan(c) + atan((x - c)/(1 + x * c))
151```
152
153to reduce `x` to small enough. It has a complexity of `O(n^3)`.
154
155**Note**: this series can also produce errors of 1 ULP, so I recommend users do
156their calculations with the precision (`scale`) set to at least 1 greater than
157is needed.
158
159### Bessel (`bc` Math Library Only)
160
161This `bc` uses the series
162
163```
164x^n/(2^n * n!) * (1 - x^2 * 2 * 1! * (n + 1)) + x^4/(2^4 * 2! * (n + 1) * (n + 2)) - ...
165```
166
167to calculate the bessel function (integer order only).
168
169It also uses the relation
170
171```
172j(-n,x) = (-1)^n * j(n,x)
173```
174
175to calculate the bessel when `x < 0`, It has a complexity of `O(n^3)`.
176
177**Note**: this series can also produce errors of 1 ULP, so I recommend users do
178their calculations with the precision (`scale`) set to at least 1 greater than
179is needed.
180
181### Modular Exponentiation
182
183This `dc` uses the [Memory-efficient method][8] to compute modular
184exponentiation. The complexity is `O(e*n^2)`, which may initially seem
185inefficient, but `n` is kept small by maintaining small numbers. In practice, it
186is extremely fast.
187
188### Non-Integer Exponentiation (`bc` Math Library 2 Only)
189
190This is implemented in the function `p(x,y)`.
191
192The algorithm used is to use the formula `e(y*l(x))`.
193
194It has a complexity of `O(n^3)` because both `e()` and `l()` do.
195
196However, there are details to this algorithm, described by the author,
197TediusTimmy, in GitHub issue [#69][12].
198
199First, check if the exponent is 0. If it is, return 1 at the appropriate
200`scale`.
201
202Next, check if the number is 0. If so, check if the exponent is greater than
203zero; if it is, return 0. If the exponent is less than 0, error (with a divide
204by 0) because that is undefined.
205
206Next, check if the exponent is actually an integer, and if it is, use the
207exponentiation operator.
208
209At the `z=0` line is the start of the meat of the new code.
210
211`z` is set to zero as a flag and as a value. What I mean by that will be clear
212later.
213
214Then we check if the number is less than 0. If it is, we negate the exponent
215(and the integer version of the exponent, which we calculated earlier to check
216if it was an integer). We also save the number in `z`; being non-zero is a flag
217for later and a value to be used. Then we store the reciprocal of the number in
218itself.
219
220All of the above paragraph will not make sense unless you remember the
221relationship `l(x) == -l(1/x)`; we negated the exponent, which is equivalent to
222the negative sign in that relationship, and we took the reciprocal of the
223number, which is equivalent to the reciprocal in the relationship.
224
225But what if the number is negative? We ignore that for now because we eventually
226call `l(x)`, which will raise an error if `x` is negative.
227
228Now, we can keep going.
229
230If at this point, the exponent is negative, we need to use the original formula
231(`e(y * l(x))`) and return that result because the result will go to zero
232anyway.
233
234But if we did *not* return, we know the exponent is *not* negative, so we can
235get clever.
236
237We then compute the integral portion of the power by computing the number to
238power of the integral portion of the exponent.
239
240Then we have the most clever trick: we add the length of that integer power (and
241a little extra) to the `scale`. Why? Because this will ensure that the next part
242is calculated to at least as many digits as should be in the integer *plus* any
243extra `scale` that was wanted.
244
245Then we check `z`, which, if it is not zero, is the original value of the
246number. If it is not zero, we need to take the take the reciprocal *again*
247because now we have the correct `scale`. And we *also* have to calculate the
248integer portion of the power again.
249
250Then we need to calculate the fractional portion of the number. We do this by
251using the original formula, but we instead of calculating `e(y * l(x))`, we
252calculate `e((y - a) * l(x))`, where `a` is the integer portion of `y`. It's
253easy to see that `y - a` will be just the fractional portion of `y` (the
254exponent), so this makes sense.
255
256But then we *multiply* it into the integer portion of the power. Why? Because
257remember: we're dealing with an exponent and a power; the relationship is
258`x^(y+z) == (x^y)*(x^z)`.
259
260So we multiply it into the integer portion of the power.
261
262Finally, we set the result to the `scale`.
263
264### Rounding (`bc` Math Library 2 Only)
265
266This is implemented in the function `r(x,p)`.
267
268The algorithm is a simple method to check if rounding away from zero is
269necessary, and if so, adds `1e10^p`.
270
271It has a complexity of `O(n)` because of add.
272
273### Ceiling (`bc` Math Library 2 Only)
274
275This is implemented in the function `ceil(x,p)`.
276
277The algorithm is a simple add of one less decimal place than `p`.
278
279It has a complexity of `O(n)` because of add.
280
281### Factorial (`bc` Math Library 2 Only)
282
283This is implemented in the function `f(n)`.
284
285The algorithm is a simple multiplication loop.
286
287It has a complexity of `O(n^3)` because of linear amount of `O(n^2)`
288multiplications.
289
290### Permutations (`bc` Math Library 2 Only)
291
292This is implemented in the function `perm(n,k)`.
293
294The algorithm is to use the formula `n!/(n-k)!`.
295
296It has a complexity of `O(n^3)` because of the division and factorials.
297
298### Combinations (`bc` Math Library 2 Only)
299
300This is implemented in the function `comb(n,r)`.
301
302The algorithm is to use the formula `n!/r!*(n-r)!`.
303
304It has a complexity of `O(n^3)` because of the division and factorials.
305
306### Logarithm of Any Base (`bc` Math Library 2 Only)
307
308This is implemented in the function `log(x,b)`.
309
310The algorithm is to use the formula `l(x)/l(b)` with double the `scale` because
311there is no good way of knowing how many digits of precision are needed when
312switching bases.
313
314It has a complexity of `O(n^3)` because of the division and `l()`.
315
316### Logarithm of Base 2 (`bc` Math Library 2 Only)
317
318This is implemented in the function `l2(x)`.
319
320This is a convenience wrapper around `log(x,2)`.
321
322### Logarithm of Base 10 (`bc` Math Library 2 Only)
323
324This is implemented in the function `l10(x)`.
325
326This is a convenience wrapper around `log(x,10)`.
327
328### Root (`bc` Math Library 2 Only)
329
330This is implemented in the function `root(x,n)`.
331
332The algorithm is [Newton's method][9]. The initial guess is calculated as
333`10^ceil(length(x)/n)`.
334
335Like square root, its complexity is `O(log(n)*n^2)` as it requires one division
336per iteration, and it doubles the amount of correct digits per iteration.
337
338### Cube Root (`bc` Math Library 2 Only)
339
340This is implemented in the function `cbrt(x)`.
341
342This is a convenience wrapper around `root(x,3)`.
343
344### Greatest Common Divisor (`bc` Math Library 2 Only)
345
346This is implemented in the function `gcd(a,b)`.
347
348The algorithm is an iterative version of the [Euclidean Algorithm][10].
349
350It has a complexity of `O(n^4)` because it has a linear number of divisions.
351
352This function ensures that `a` is always bigger than `b` before starting the
353algorithm.
354
355### Least Common Multiple (`bc` Math Library 2 Only)
356
357This is implemented in the function `lcm(a,b)`.
358
359The algorithm uses the formula `a*b/gcd(a,b)`.
360
361It has a complexity of `O(n^4)` because of `gcd()`.
362
363### Pi (`bc` Math Library 2 Only)
364
365This is implemented in the function `pi(s)`.
366
367The algorithm uses the formula `4*a(1)`.
368
369It has a complexity of `O(n^3)` because of arctangent.
370
371### Tangent (`bc` Math Library 2 Only)
372
373This is implemented in the function `t(x)`.
374
375The algorithm uses the formula `s(x)/c(x)`.
376
377It has a complexity of `O(n^3)` because of sine, cosine, and division.
378
379### Atan2 (`bc` Math Library 2 Only)
380
381This is implemented in the function `a2(y,x)`.
382
383The algorithm uses the [standard formulas][11].
384
385It has a complexity of `O(n^3)` because of arctangent.
386
387[1]: https://en.wikipedia.org/wiki/Karatsuba_algorithm
388[2]: https://en.wikipedia.org/wiki/Long_division
389[3]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
390[4]: https://en.wikipedia.org/wiki/Newton%27s_method#Square_root_of_a_number
391[5]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
392[6]: https://en.wikipedia.org/wiki/Unit_in_the_last_place
393[7]: https://people.eecs.berkeley.edu/~wkahan/LOG10HAF.TXT
394[8]: https://en.wikipedia.org/wiki/Modular_exponentiation#Memory-efficient_method
395[9]: https://en.wikipedia.org/wiki/Root-finding_algorithms#Newton's_method_(and_similar_derivative-based_methods)
396[10]: https://en.wikipedia.org/wiki/Euclidean_algorithm
397[11]: https://en.wikipedia.org/wiki/Atan2#Definition_and_computation
398[12]: https://github.com/gavinhoward/bc/issues/69
399