vendor/bc: upgrade to version 6.7.2

This update improves the implementation of the power function p() and
adds 3 new functions to the extended math library: min(), max(), and
i2rand().

(cherry picked from commit 0b4a06ab29a0da80f6cb5c99189054cb8e2f756c)
This commit is contained in:
Stefan Eßer 2023-10-30 10:10:24 +01:00
parent 1fa4ddcc6d
commit aa339f1d5d
31 changed files with 1390 additions and 82 deletions

View File

@ -554,7 +554,7 @@ clean_config: clean clean_benchmarks
clean_coverage:
@printf 'Cleaning coverage files...\n'
@$(RM) -f *.gcov
@$(RM) -f *.html
@$(RM) -f *.html *.css
@$(RM) -f *.gcda *.gcno
@$(RM) -f *.profraw
@$(RM) -f $(GCDA) $(GCNO)

View File

@ -1,5 +1,27 @@
# News
## 6.7.2
This is a production release to remove some debugging code that I accidentally
committed.
## 6.7.1
This is a production release with a bug fix for `SIGINT` only being handled
once.
## 6.7.0
This is a production release with three new functions in the [extended math
library][16]: `min()`, `max()`, and `i2rand()`.
## 6.6.1
This is a production release with an improved `p()` function in the [extended
math library][16].
Users who don't care do not need to upgrade.
## 6.6.0
This is a production release with two bug fixes and one change.

View File

@ -1364,13 +1364,7 @@ if [ "$debug" -eq 1 ]; then
CFLAGS="-O0"
fi
ccbase=$(basename "$CC")
if [ "$ccbase" = "clang" ]; then
CFLAGS="-gdwarf-4 $CFLAGS"
else
CFLAGS="-g $CFLAGS"
fi
CFLAGS="-g $CFLAGS"
else

View File

@ -34,10 +34,34 @@
*/
define p(x,y){
auto a
auto a,i,s,z
if(y==0)return 1@scale
if(x==0){
if(y>0)return 0
return 1/0
}
a=y$
if(y==a)return(x^a)@scale
return e(y*l(x))
z=0
if(x<1){
y=-y
a=-a
z=x
x=1/x
}
if(y<0){
return e(y*l(x))
}
i=x^a
s=scale
scale+=length(i)+5
if(z){
x=1/z
i=x^a
}
i*=e((y-a)*l(x))
scale=s
return i@scale
}
define r(x,p){
auto t,n
@ -66,6 +90,14 @@ define f(n){
for(r=1;n>1;--n)r*=n
return r
}
define max(a,b){
if(a>b)return a
return b
}
define min(a,b){
if(a<b)return a
return b
}
define perm(n,k){
auto f,g,s
if(k>n)return 0
@ -242,6 +274,15 @@ define frand(p){
return irand(A^p)>>p
}
define ifrand(i,p){return irand(abs(i)$)+frand(p)}
define i2rand(a,b){
auto n,x
a=a$
b=b$
if(a==b)return a
n=min(a,b)
x=max(a,b)
return irand(x-n+1)+n
}
define srand(x){
if(irand(2))return -x
return x

View File

@ -36,9 +36,6 @@
#ifndef BC_BCL_H
#define BC_BCL_H
// TODO: Add a generation index when building with Valgrind to check for
// use-after-free's or double frees.
#include <stdbool.h>
#include <stdlib.h>
#include <limits.h>

View File

@ -37,6 +37,6 @@
#define BC_VERSION_H
/// The current version.
#define VERSION 6.6.0
#define VERSION 6.7.2
#endif // BC_VERSION_H

View File

@ -193,6 +193,74 @@ The algorithm used is to use the formula `e(y*l(x))`.
It has a complexity of `O(n^3)` because both `e()` and `l()` do.
However, there are details to this algorithm, described by the author,
TediusTimmy, in GitHub issue [#69][12].
First, check if the exponent is 0. If it is, return 1 at the appropriate
`scale`.
Next, check if the number is 0. If so, check if the exponent is greater than
zero; if it is, return 0. If the exponent is less than 0, error (with a divide
by 0) because that is undefined.
Next, check if the exponent is actually an integer, and if it is, use the
exponentiation operator.
At the `z=0` line is the start of the meat of the new code.
`z` is set to zero as a flag and as a value. What I mean by that will be clear
later.
Then we check if the number is less than 0. If it is, we negate the exponent
(and the integer version of the exponent, which we calculated earlier to check
if it was an integer). We also save the number in `z`; being non-zero is a flag
for later and a value to be used. Then we store the reciprocal of the number in
itself.
All of the above paragraph will not make sense unless you remember the
relationship `l(x) == -l(1/x)`; we negated the exponent, which is equivalent to
the negative sign in that relationship, and we took the reciprocal of the
number, which is equivalent to the reciprocal in the relationship.
But what if the number is negative? We ignore that for now because we eventually
call `l(x)`, which will raise an error if `x` is negative.
Now, we can keep going.
If at this point, the exponent is negative, we need to use the original formula
(`e(y * l(x))`) and return that result because the result will go to zero
anyway.
But if we did *not* return, we know the exponent is *not* negative, so we can
get clever.
We then compute the integral portion of the power by computing the number to
power of the integral portion of the exponent.
Then we have the most clever trick: we add the length of that integer power (and
a little extra) to the `scale`. Why? Because this will ensure that the next part
is calculated to at least as many digits as should be in the integer *plus* any
extra `scale` that was wanted.
Then we check `z`, which, if it is not zero, is the original value of the
number. If it is not zero, we need to take the take the reciprocal *again*
because now we have the correct `scale`. And we *also* have to calculate the
integer portion of the power again.
Then we need to calculate the fractional portion of the number. We do this by
using the original formula, but we instead of calculating `e(y * l(x))`, we
calculate `e((y - a) * l(x))`, where `a` is the integer portion of `y`. It's
easy to see that `y - a` will be just the fractional portion of `y` (the
exponent), so this makes sense.
But then we *multiply* it into the integer portion of the power. Why? Because
remember: we're dealing with an exponent and a power; the relationship is
`x^(y+z) == (x^y)*(x^z)`.
So we multiply it into the integer portion of the power.
Finally, we set the result to the `scale`.
### Rounding (`bc` Math Library 2 Only)
This is implemented in the function `r(x,p)`.
@ -327,3 +395,4 @@ It has a complexity of `O(n^3)` because of arctangent.
[9]: https://en.wikipedia.org/wiki/Root-finding_algorithms#Newton's_method_(and_similar_derivative-based_methods)
[10]: https://en.wikipedia.org/wiki/Euclidean_algorithm
[11]: https://en.wikipedia.org/wiki/Atan2#Definition_and_computation
[12]: https://github.com/gavinhoward/bc/issues/69

View File

@ -1357,8 +1357,7 @@ Any non-string expression in a print statement shall be assigned to
\f[B]last\f[R], like any other expression that is printed.
.SS Stream Statement
.PP
The \[lq]expressions in a \f[B]stream\f[R] statement may also be
strings.
The expressions in a \f[B]stream\f[R] statement may also be strings.
.PP
If a \f[B]stream\f[R] statement is given a string, it prints the string
as though the string had appeared as its own statement.
@ -1579,6 +1578,14 @@ the rounding mode round away from \f[B]0\f[R]
\f[B]f(x)\f[R]
Returns the factorial of the truncated absolute value of \f[B]x\f[R].
.TP
\f[B]max(a, b)\f[R]
Returns \f[B]a\f[R] if \f[B]a\f[R] is greater than \f[B]b\f[R];
otherwise, returns \f[B]b\f[R].
.TP
\f[B]min(a, b)\f[R]
Returns \f[B]a\f[R] if \f[B]a\f[R] is less than \f[B]b\f[R]; otherwise,
returns \f[B]b\f[R].
.TP
\f[B]perm(n, k)\f[R]
Returns the permutation of the truncated absolute value of \f[B]n\f[R]
of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R].
@ -1589,6 +1596,10 @@ Returns the combination of the truncated absolute value of \f[B]n\f[R]
of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R].
If not, it returns \f[B]0\f[R].
.TP
\f[B]fib(n)\f[R]
Returns the Fibonacci number of the truncated absolute value of
\f[B]n\f[R].
.TP
\f[B]l2(x)\f[R]
Returns the logarithm base \f[B]2\f[R] of \f[B]x\f[R].
.RS
@ -1759,7 +1770,7 @@ Functions\f[R] subsection below).
.RE
.TP
\f[B]frand(p)\f[R]
Generates a pseudo-random number between \f[B]0\f[R] (inclusive) and
Generates a pseudo-random integer between \f[B]0\f[R] (inclusive) and
\f[B]1\f[R] (exclusive) with the number of decimal digits after the
decimal point equal to the truncated absolute value of \f[B]p\f[R].
If \f[B]p\f[R] is not \f[B]0\f[R], then calling this function will
@ -1768,14 +1779,22 @@ If \f[B]p\f[R] is \f[B]0\f[R], then \f[B]0\f[R] is returned, and
\f[B]seed\f[R] is \f[I]not\f[R] changed.
.TP
\f[B]ifrand(i, p)\f[R]
Generates a pseudo-random number that is between \f[B]0\f[R] (inclusive)
and the truncated absolute value of \f[B]i\f[R] (exclusive) with the
number of decimal digits after the decimal point equal to the truncated
absolute value of \f[B]p\f[R].
Generates a pseudo-random integer that is between \f[B]0\f[R]
(inclusive) and the truncated absolute value of \f[B]i\f[R] (exclusive)
with the number of decimal digits after the decimal point equal to the
truncated absolute value of \f[B]p\f[R].
If the absolute value of \f[B]i\f[R] is greater than or equal to
\f[B]2\f[R], and \f[B]p\f[R] is not \f[B]0\f[R], then calling this
function will change the value of \f[B]seed\f[R]; otherwise, \f[B]0\f[R]
is returned and \f[B]seed\f[R] is not changed.
is returned, and \f[B]seed\f[R] is not changed.
.TP
\f[B]i2rand(a, b)\f[R]
Takes the truncated value of \f[B]a\f[R] and \f[B]b\f[R] and uses them
as inclusive bounds to enerate a pseudo-random integer.
If the difference of the truncated values of \f[B]a\f[R] and \f[B]b\f[R]
is \f[B]0\f[R], then the truncated value is returned, and \f[B]seed\f[R]
is \f[I]not\f[R] changed.
Otherwise, this function will change the value of \f[B]seed\f[R].
.TP
\f[B]srand(x)\f[R]
Returns \f[B]x\f[R] with its sign flipped with probability

View File

@ -1068,7 +1068,7 @@ like any other expression that is printed.
## Stream Statement
The "expressions in a **stream** statement may also be strings.
The expressions in a **stream** statement may also be strings.
If a **stream** statement is given a string, it prints the string as though the
string had appeared as its own statement. In other words, the **stream**
@ -1259,6 +1259,14 @@ The extended library is a **non-portable extension**.
: Returns the factorial of the truncated absolute value of **x**.
**max(a, b)**
: Returns **a** if **a** is greater than **b**; otherwise, returns **b**.
**min(a, b)**
: Returns **a** if **a** is less than **b**; otherwise, returns **b**.
**perm(n, k)**
: Returns the permutation of the truncated absolute value of **n** of the
@ -1269,6 +1277,10 @@ The extended library is a **non-portable extension**.
: Returns the combination of the truncated absolute value of **n** of the
truncated absolute value of **k**, if **k \<= n**. If not, it returns **0**.
**fib(n)**
: Returns the Fibonacci number of the truncated absolute value of **n**.
**l2(x)**
: Returns the logarithm base **2** of **x**.
@ -1418,7 +1430,7 @@ The extended library is a **non-portable extension**.
**frand(p)**
: Generates a pseudo-random number between **0** (inclusive) and **1**
: Generates a pseudo-random integer between **0** (inclusive) and **1**
(exclusive) with the number of decimal digits after the decimal point equal
to the truncated absolute value of **p**. If **p** is not **0**, then
calling this function will change the value of **seed**. If **p** is **0**,
@ -1426,12 +1438,20 @@ The extended library is a **non-portable extension**.
**ifrand(i, p)**
: Generates a pseudo-random number that is between **0** (inclusive) and the
: Generates a pseudo-random integer that is between **0** (inclusive) and the
truncated absolute value of **i** (exclusive) with the number of decimal
digits after the decimal point equal to the truncated absolute value of
**p**. If the absolute value of **i** is greater than or equal to **2**, and
**p** is not **0**, then calling this function will change the value of
**seed**; otherwise, **0** is returned and **seed** is not changed.
**seed**; otherwise, **0** is returned, and **seed** is not changed.
**i2rand(a, b)**
: Takes the truncated value of **a** and **b** and uses them as inclusive
bounds to enerate a pseudo-random integer. If the difference of the
truncated values of **a** and **b** is **0**, then the truncated value is
returned, and **seed** is *not* changed. Otherwise, this function will
change the value of **seed**.
**srand(x)**

View File

@ -1122,8 +1122,7 @@ Any non-string expression in a print statement shall be assigned to
\f[B]last\f[R], like any other expression that is printed.
.SS Stream Statement
.PP
The \[lq]expressions in a \f[B]stream\f[R] statement may also be
strings.
The expressions in a \f[B]stream\f[R] statement may also be strings.
.PP
If a \f[B]stream\f[R] statement is given a string, it prints the string
as though the string had appeared as its own statement.

View File

@ -892,7 +892,7 @@ like any other expression that is printed.
## Stream Statement
The "expressions in a **stream** statement may also be strings.
The expressions in a **stream** statement may also be strings.
If a **stream** statement is given a string, it prints the string as though the
string had appeared as its own statement. In other words, the **stream**

View File

@ -1122,8 +1122,7 @@ Any non-string expression in a print statement shall be assigned to
\f[B]last\f[R], like any other expression that is printed.
.SS Stream Statement
.PP
The \[lq]expressions in a \f[B]stream\f[R] statement may also be
strings.
The expressions in a \f[B]stream\f[R] statement may also be strings.
.PP
If a \f[B]stream\f[R] statement is given a string, it prints the string
as though the string had appeared as its own statement.

View File

@ -892,7 +892,7 @@ like any other expression that is printed.
## Stream Statement
The "expressions in a **stream** statement may also be strings.
The expressions in a **stream** statement may also be strings.
If a **stream** statement is given a string, it prints the string as though the
string had appeared as its own statement. In other words, the **stream**

View File

@ -1122,8 +1122,7 @@ Any non-string expression in a print statement shall be assigned to
\f[B]last\f[R], like any other expression that is printed.
.SS Stream Statement
.PP
The \[lq]expressions in a \f[B]stream\f[R] statement may also be
strings.
The expressions in a \f[B]stream\f[R] statement may also be strings.
.PP
If a \f[B]stream\f[R] statement is given a string, it prints the string
as though the string had appeared as its own statement.

View File

@ -892,7 +892,7 @@ like any other expression that is printed.
## Stream Statement
The "expressions in a **stream** statement may also be strings.
The expressions in a **stream** statement may also be strings.
If a **stream** statement is given a string, it prints the string as though the
string had appeared as its own statement. In other words, the **stream**

View File

@ -1122,8 +1122,7 @@ Any non-string expression in a print statement shall be assigned to
\f[B]last\f[R], like any other expression that is printed.
.SS Stream Statement
.PP
The \[lq]expressions in a \f[B]stream\f[R] statement may also be
strings.
The expressions in a \f[B]stream\f[R] statement may also be strings.
.PP
If a \f[B]stream\f[R] statement is given a string, it prints the string
as though the string had appeared as its own statement.

View File

@ -892,7 +892,7 @@ like any other expression that is printed.
## Stream Statement
The "expressions in a **stream** statement may also be strings.
The expressions in a **stream** statement may also be strings.
If a **stream** statement is given a string, it prints the string as though the
string had appeared as its own statement. In other words, the **stream**

View File

@ -1357,8 +1357,7 @@ Any non-string expression in a print statement shall be assigned to
\f[B]last\f[R], like any other expression that is printed.
.SS Stream Statement
.PP
The \[lq]expressions in a \f[B]stream\f[R] statement may also be
strings.
The expressions in a \f[B]stream\f[R] statement may also be strings.
.PP
If a \f[B]stream\f[R] statement is given a string, it prints the string
as though the string had appeared as its own statement.
@ -1579,6 +1578,14 @@ the rounding mode round away from \f[B]0\f[R]
\f[B]f(x)\f[R]
Returns the factorial of the truncated absolute value of \f[B]x\f[R].
.TP
\f[B]max(a, b)\f[R]
Returns \f[B]a\f[R] if \f[B]a\f[R] is greater than \f[B]b\f[R];
otherwise, returns \f[B]b\f[R].
.TP
\f[B]min(a, b)\f[R]
Returns \f[B]a\f[R] if \f[B]a\f[R] is less than \f[B]b\f[R]; otherwise,
returns \f[B]b\f[R].
.TP
\f[B]perm(n, k)\f[R]
Returns the permutation of the truncated absolute value of \f[B]n\f[R]
of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R].
@ -1589,6 +1596,10 @@ Returns the combination of the truncated absolute value of \f[B]n\f[R]
of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R].
If not, it returns \f[B]0\f[R].
.TP
\f[B]fib(n)\f[R]
Returns the Fibonacci number of the truncated absolute value of
\f[B]n\f[R].
.TP
\f[B]l2(x)\f[R]
Returns the logarithm base \f[B]2\f[R] of \f[B]x\f[R].
.RS
@ -1759,7 +1770,7 @@ Functions\f[R] subsection below).
.RE
.TP
\f[B]frand(p)\f[R]
Generates a pseudo-random number between \f[B]0\f[R] (inclusive) and
Generates a pseudo-random integer between \f[B]0\f[R] (inclusive) and
\f[B]1\f[R] (exclusive) with the number of decimal digits after the
decimal point equal to the truncated absolute value of \f[B]p\f[R].
If \f[B]p\f[R] is not \f[B]0\f[R], then calling this function will
@ -1768,14 +1779,22 @@ If \f[B]p\f[R] is \f[B]0\f[R], then \f[B]0\f[R] is returned, and
\f[B]seed\f[R] is \f[I]not\f[R] changed.
.TP
\f[B]ifrand(i, p)\f[R]
Generates a pseudo-random number that is between \f[B]0\f[R] (inclusive)
and the truncated absolute value of \f[B]i\f[R] (exclusive) with the
number of decimal digits after the decimal point equal to the truncated
absolute value of \f[B]p\f[R].
Generates a pseudo-random integer that is between \f[B]0\f[R]
(inclusive) and the truncated absolute value of \f[B]i\f[R] (exclusive)
with the number of decimal digits after the decimal point equal to the
truncated absolute value of \f[B]p\f[R].
If the absolute value of \f[B]i\f[R] is greater than or equal to
\f[B]2\f[R], and \f[B]p\f[R] is not \f[B]0\f[R], then calling this
function will change the value of \f[B]seed\f[R]; otherwise, \f[B]0\f[R]
is returned and \f[B]seed\f[R] is not changed.
is returned, and \f[B]seed\f[R] is not changed.
.TP
\f[B]i2rand(a, b)\f[R]
Takes the truncated value of \f[B]a\f[R] and \f[B]b\f[R] and uses them
as inclusive bounds to enerate a pseudo-random integer.
If the difference of the truncated values of \f[B]a\f[R] and \f[B]b\f[R]
is \f[B]0\f[R], then the truncated value is returned, and \f[B]seed\f[R]
is \f[I]not\f[R] changed.
Otherwise, this function will change the value of \f[B]seed\f[R].
.TP
\f[B]srand(x)\f[R]
Returns \f[B]x\f[R] with its sign flipped with probability

View File

@ -1068,7 +1068,7 @@ like any other expression that is printed.
## Stream Statement
The "expressions in a **stream** statement may also be strings.
The expressions in a **stream** statement may also be strings.
If a **stream** statement is given a string, it prints the string as though the
string had appeared as its own statement. In other words, the **stream**
@ -1259,6 +1259,14 @@ The extended library is a **non-portable extension**.
: Returns the factorial of the truncated absolute value of **x**.
**max(a, b)**
: Returns **a** if **a** is greater than **b**; otherwise, returns **b**.
**min(a, b)**
: Returns **a** if **a** is less than **b**; otherwise, returns **b**.
**perm(n, k)**
: Returns the permutation of the truncated absolute value of **n** of the
@ -1269,6 +1277,10 @@ The extended library is a **non-portable extension**.
: Returns the combination of the truncated absolute value of **n** of the
truncated absolute value of **k**, if **k \<= n**. If not, it returns **0**.
**fib(n)**
: Returns the Fibonacci number of the truncated absolute value of **n**.
**l2(x)**
: Returns the logarithm base **2** of **x**.
@ -1418,7 +1430,7 @@ The extended library is a **non-portable extension**.
**frand(p)**
: Generates a pseudo-random number between **0** (inclusive) and **1**
: Generates a pseudo-random integer between **0** (inclusive) and **1**
(exclusive) with the number of decimal digits after the decimal point equal
to the truncated absolute value of **p**. If **p** is not **0**, then
calling this function will change the value of **seed**. If **p** is **0**,
@ -1426,12 +1438,20 @@ The extended library is a **non-portable extension**.
**ifrand(i, p)**
: Generates a pseudo-random number that is between **0** (inclusive) and the
: Generates a pseudo-random integer that is between **0** (inclusive) and the
truncated absolute value of **i** (exclusive) with the number of decimal
digits after the decimal point equal to the truncated absolute value of
**p**. If the absolute value of **i** is greater than or equal to **2**, and
**p** is not **0**, then calling this function will change the value of
**seed**; otherwise, **0** is returned and **seed** is not changed.
**seed**; otherwise, **0** is returned, and **seed** is not changed.
**i2rand(a, b)**
: Takes the truncated value of **a** and **b** and uses them as inclusive
bounds to enerate a pseudo-random integer. If the difference of the
truncated values of **a** and **b** is **0**, then the truncated value is
returned, and **seed** is *not* changed. Otherwise, this function will
change the value of **seed**.
**srand(x)**

View File

@ -1357,8 +1357,7 @@ Any non-string expression in a print statement shall be assigned to
\f[B]last\f[R], like any other expression that is printed.
.SS Stream Statement
.PP
The \[lq]expressions in a \f[B]stream\f[R] statement may also be
strings.
The expressions in a \f[B]stream\f[R] statement may also be strings.
.PP
If a \f[B]stream\f[R] statement is given a string, it prints the string
as though the string had appeared as its own statement.
@ -1579,6 +1578,14 @@ the rounding mode round away from \f[B]0\f[R]
\f[B]f(x)\f[R]
Returns the factorial of the truncated absolute value of \f[B]x\f[R].
.TP
\f[B]max(a, b)\f[R]
Returns \f[B]a\f[R] if \f[B]a\f[R] is greater than \f[B]b\f[R];
otherwise, returns \f[B]b\f[R].
.TP
\f[B]min(a, b)\f[R]
Returns \f[B]a\f[R] if \f[B]a\f[R] is less than \f[B]b\f[R]; otherwise,
returns \f[B]b\f[R].
.TP
\f[B]perm(n, k)\f[R]
Returns the permutation of the truncated absolute value of \f[B]n\f[R]
of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R].
@ -1589,6 +1596,10 @@ Returns the combination of the truncated absolute value of \f[B]n\f[R]
of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R].
If not, it returns \f[B]0\f[R].
.TP
\f[B]fib(n)\f[R]
Returns the Fibonacci number of the truncated absolute value of
\f[B]n\f[R].
.TP
\f[B]l2(x)\f[R]
Returns the logarithm base \f[B]2\f[R] of \f[B]x\f[R].
.RS
@ -1759,7 +1770,7 @@ Functions\f[R] subsection below).
.RE
.TP
\f[B]frand(p)\f[R]
Generates a pseudo-random number between \f[B]0\f[R] (inclusive) and
Generates a pseudo-random integer between \f[B]0\f[R] (inclusive) and
\f[B]1\f[R] (exclusive) with the number of decimal digits after the
decimal point equal to the truncated absolute value of \f[B]p\f[R].
If \f[B]p\f[R] is not \f[B]0\f[R], then calling this function will
@ -1768,14 +1779,22 @@ If \f[B]p\f[R] is \f[B]0\f[R], then \f[B]0\f[R] is returned, and
\f[B]seed\f[R] is \f[I]not\f[R] changed.
.TP
\f[B]ifrand(i, p)\f[R]
Generates a pseudo-random number that is between \f[B]0\f[R] (inclusive)
and the truncated absolute value of \f[B]i\f[R] (exclusive) with the
number of decimal digits after the decimal point equal to the truncated
absolute value of \f[B]p\f[R].
Generates a pseudo-random integer that is between \f[B]0\f[R]
(inclusive) and the truncated absolute value of \f[B]i\f[R] (exclusive)
with the number of decimal digits after the decimal point equal to the
truncated absolute value of \f[B]p\f[R].
If the absolute value of \f[B]i\f[R] is greater than or equal to
\f[B]2\f[R], and \f[B]p\f[R] is not \f[B]0\f[R], then calling this
function will change the value of \f[B]seed\f[R]; otherwise, \f[B]0\f[R]
is returned and \f[B]seed\f[R] is not changed.
is returned, and \f[B]seed\f[R] is not changed.
.TP
\f[B]i2rand(a, b)\f[R]
Takes the truncated value of \f[B]a\f[R] and \f[B]b\f[R] and uses them
as inclusive bounds to enerate a pseudo-random integer.
If the difference of the truncated values of \f[B]a\f[R] and \f[B]b\f[R]
is \f[B]0\f[R], then the truncated value is returned, and \f[B]seed\f[R]
is \f[I]not\f[R] changed.
Otherwise, this function will change the value of \f[B]seed\f[R].
.TP
\f[B]srand(x)\f[R]
Returns \f[B]x\f[R] with its sign flipped with probability

View File

@ -1068,7 +1068,7 @@ like any other expression that is printed.
## Stream Statement
The "expressions in a **stream** statement may also be strings.
The expressions in a **stream** statement may also be strings.
If a **stream** statement is given a string, it prints the string as though the
string had appeared as its own statement. In other words, the **stream**
@ -1259,6 +1259,14 @@ The extended library is a **non-portable extension**.
: Returns the factorial of the truncated absolute value of **x**.
**max(a, b)**
: Returns **a** if **a** is greater than **b**; otherwise, returns **b**.
**min(a, b)**
: Returns **a** if **a** is less than **b**; otherwise, returns **b**.
**perm(n, k)**
: Returns the permutation of the truncated absolute value of **n** of the
@ -1269,6 +1277,10 @@ The extended library is a **non-portable extension**.
: Returns the combination of the truncated absolute value of **n** of the
truncated absolute value of **k**, if **k \<= n**. If not, it returns **0**.
**fib(n)**
: Returns the Fibonacci number of the truncated absolute value of **n**.
**l2(x)**
: Returns the logarithm base **2** of **x**.
@ -1418,7 +1430,7 @@ The extended library is a **non-portable extension**.
**frand(p)**
: Generates a pseudo-random number between **0** (inclusive) and **1**
: Generates a pseudo-random integer between **0** (inclusive) and **1**
(exclusive) with the number of decimal digits after the decimal point equal
to the truncated absolute value of **p**. If **p** is not **0**, then
calling this function will change the value of **seed**. If **p** is **0**,
@ -1426,12 +1438,20 @@ The extended library is a **non-portable extension**.
**ifrand(i, p)**
: Generates a pseudo-random number that is between **0** (inclusive) and the
: Generates a pseudo-random integer that is between **0** (inclusive) and the
truncated absolute value of **i** (exclusive) with the number of decimal
digits after the decimal point equal to the truncated absolute value of
**p**. If the absolute value of **i** is greater than or equal to **2**, and
**p** is not **0**, then calling this function will change the value of
**seed**; otherwise, **0** is returned and **seed** is not changed.
**seed**; otherwise, **0** is returned, and **seed** is not changed.
**i2rand(a, b)**
: Takes the truncated value of **a** and **b** and uses them as inclusive
bounds to enerate a pseudo-random integer. If the difference of the
truncated values of **a** and **b** is **0**, then the truncated value is
returned, and **seed** is *not* changed. Otherwise, this function will
change the value of **seed**.
**srand(x)**

View File

@ -1357,8 +1357,7 @@ Any non-string expression in a print statement shall be assigned to
\f[B]last\f[R], like any other expression that is printed.
.SS Stream Statement
.PP
The \[lq]expressions in a \f[B]stream\f[R] statement may also be
strings.
The expressions in a \f[B]stream\f[R] statement may also be strings.
.PP
If a \f[B]stream\f[R] statement is given a string, it prints the string
as though the string had appeared as its own statement.
@ -1579,6 +1578,14 @@ the rounding mode round away from \f[B]0\f[R]
\f[B]f(x)\f[R]
Returns the factorial of the truncated absolute value of \f[B]x\f[R].
.TP
\f[B]max(a, b)\f[R]
Returns \f[B]a\f[R] if \f[B]a\f[R] is greater than \f[B]b\f[R];
otherwise, returns \f[B]b\f[R].
.TP
\f[B]min(a, b)\f[R]
Returns \f[B]a\f[R] if \f[B]a\f[R] is less than \f[B]b\f[R]; otherwise,
returns \f[B]b\f[R].
.TP
\f[B]perm(n, k)\f[R]
Returns the permutation of the truncated absolute value of \f[B]n\f[R]
of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R].
@ -1589,6 +1596,10 @@ Returns the combination of the truncated absolute value of \f[B]n\f[R]
of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R].
If not, it returns \f[B]0\f[R].
.TP
\f[B]fib(n)\f[R]
Returns the Fibonacci number of the truncated absolute value of
\f[B]n\f[R].
.TP
\f[B]l2(x)\f[R]
Returns the logarithm base \f[B]2\f[R] of \f[B]x\f[R].
.RS
@ -1759,7 +1770,7 @@ Functions\f[R] subsection below).
.RE
.TP
\f[B]frand(p)\f[R]
Generates a pseudo-random number between \f[B]0\f[R] (inclusive) and
Generates a pseudo-random integer between \f[B]0\f[R] (inclusive) and
\f[B]1\f[R] (exclusive) with the number of decimal digits after the
decimal point equal to the truncated absolute value of \f[B]p\f[R].
If \f[B]p\f[R] is not \f[B]0\f[R], then calling this function will
@ -1768,14 +1779,22 @@ If \f[B]p\f[R] is \f[B]0\f[R], then \f[B]0\f[R] is returned, and
\f[B]seed\f[R] is \f[I]not\f[R] changed.
.TP
\f[B]ifrand(i, p)\f[R]
Generates a pseudo-random number that is between \f[B]0\f[R] (inclusive)
and the truncated absolute value of \f[B]i\f[R] (exclusive) with the
number of decimal digits after the decimal point equal to the truncated
absolute value of \f[B]p\f[R].
Generates a pseudo-random integer that is between \f[B]0\f[R]
(inclusive) and the truncated absolute value of \f[B]i\f[R] (exclusive)
with the number of decimal digits after the decimal point equal to the
truncated absolute value of \f[B]p\f[R].
If the absolute value of \f[B]i\f[R] is greater than or equal to
\f[B]2\f[R], and \f[B]p\f[R] is not \f[B]0\f[R], then calling this
function will change the value of \f[B]seed\f[R]; otherwise, \f[B]0\f[R]
is returned and \f[B]seed\f[R] is not changed.
is returned, and \f[B]seed\f[R] is not changed.
.TP
\f[B]i2rand(a, b)\f[R]
Takes the truncated value of \f[B]a\f[R] and \f[B]b\f[R] and uses them
as inclusive bounds to enerate a pseudo-random integer.
If the difference of the truncated values of \f[B]a\f[R] and \f[B]b\f[R]
is \f[B]0\f[R], then the truncated value is returned, and \f[B]seed\f[R]
is \f[I]not\f[R] changed.
Otherwise, this function will change the value of \f[B]seed\f[R].
.TP
\f[B]srand(x)\f[R]
Returns \f[B]x\f[R] with its sign flipped with probability

View File

@ -1068,7 +1068,7 @@ like any other expression that is printed.
## Stream Statement
The "expressions in a **stream** statement may also be strings.
The expressions in a **stream** statement may also be strings.
If a **stream** statement is given a string, it prints the string as though the
string had appeared as its own statement. In other words, the **stream**
@ -1259,6 +1259,14 @@ The extended library is a **non-portable extension**.
: Returns the factorial of the truncated absolute value of **x**.
**max(a, b)**
: Returns **a** if **a** is greater than **b**; otherwise, returns **b**.
**min(a, b)**
: Returns **a** if **a** is less than **b**; otherwise, returns **b**.
**perm(n, k)**
: Returns the permutation of the truncated absolute value of **n** of the
@ -1269,6 +1277,10 @@ The extended library is a **non-portable extension**.
: Returns the combination of the truncated absolute value of **n** of the
truncated absolute value of **k**, if **k \<= n**. If not, it returns **0**.
**fib(n)**
: Returns the Fibonacci number of the truncated absolute value of **n**.
**l2(x)**
: Returns the logarithm base **2** of **x**.
@ -1418,7 +1430,7 @@ The extended library is a **non-portable extension**.
**frand(p)**
: Generates a pseudo-random number between **0** (inclusive) and **1**
: Generates a pseudo-random integer between **0** (inclusive) and **1**
(exclusive) with the number of decimal digits after the decimal point equal
to the truncated absolute value of **p**. If **p** is not **0**, then
calling this function will change the value of **seed**. If **p** is **0**,
@ -1426,12 +1438,20 @@ The extended library is a **non-portable extension**.
**ifrand(i, p)**
: Generates a pseudo-random number that is between **0** (inclusive) and the
: Generates a pseudo-random integer that is between **0** (inclusive) and the
truncated absolute value of **i** (exclusive) with the number of decimal
digits after the decimal point equal to the truncated absolute value of
**p**. If the absolute value of **i** is greater than or equal to **2**, and
**p** is not **0**, then calling this function will change the value of
**seed**; otherwise, **0** is returned and **seed** is not changed.
**seed**; otherwise, **0** is returned, and **seed** is not changed.
**i2rand(a, b)**
: Takes the truncated value of **a** and **b** and uses them as inclusive
bounds to enerate a pseudo-random integer. If the difference of the
truncated values of **a** and **b** is **0**, then the truncated value is
returned, and **seed** is *not* changed. Otherwise, this function will
change the value of **seed**.
**srand(x)**

View File

@ -2929,14 +2929,14 @@ bc_num_printExponent(const BcNum* restrict n, bool eng, bool newline)
#endif // BC_ENABLE_EXTRA_MATH
/**
* Converts a number from limbs with base BC_BASE_POW to base @a pow, where
* @a pow is obase^N.
* Takes a number with limbs with base BC_BASE_POW and converts the limb at the
* given index to base @a pow, where @a pow is obase^N.
* @param n The number to convert.
* @param rem BC_BASE_POW - @a pow.
* @param pow The power of obase we will convert the number to.
* @param idx The index of the number to start converting at. Doing the
* conversion is O(n^2); we have to sweep through starting at the
* least significant limb
* least significant limb.
*/
static void
bc_num_printFixup(BcNum* restrict n, BcBigDig rem, BcBigDig pow, size_t idx)
@ -2998,8 +2998,8 @@ bc_num_printFixup(BcNum* restrict n, BcBigDig rem, BcBigDig pow, size_t idx)
}
/**
* Prepares a number for printing in a base that is not a divisor of
* BC_BASE_POW. This basically converts the number from having limbs of base
* Prepares a number for printing in a base that does not have BC_BASE_POW as a
* power. This basically converts the number from having limbs of base
* BC_BASE_POW to limbs of pow, where pow is obase^N.
* @param n The number to prepare for printing.
* @param rem The remainder of BC_BASE_POW when divided by a power of the base.

View File

@ -214,7 +214,7 @@ bc_vm_sigaction(void)
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_flags = BC_ENABLE_EDITLINE ? 0 : SA_NODEFER;
// This mess is to silence a warning on Clang with regards to glibc's
// sigaction handler, which activates the warning here.

View File

@ -1,6 +1,7 @@
p(2, 8.0000)
p(2, 8.0001)
p(2, -8.0001)
p(1024,32.1)
r(0, 0)
r(0, 1)
r(0, 100)

View File

@ -1,6 +1,8 @@
256.00000000000000000000
256.01774518281640169821
256.01774518281640171326
.00390597924876622489
42719740718418201647900434123391042292054090447133055398940832156444\
39451561281100045924173873151.99999999999999999999
0
0
0

View File

@ -19,3 +19,4 @@ strings2.bc
ifs.bc
ifs2.bc
afl1.bc
i2rand.bc

View File

@ -0,0 +1,29 @@
#! /usr/bin/bc -lq
for (i = 0; i < 10; ++i)
{
if (brand()) {
a = srand(ifrand(101, scale))
}
else {
a = srand(irand(101))
}
if (brand()) {
b = srand(ifrand(101, scale))
}
else {
b = srand(irand(101))
}
min = min(a$, b$)
max = max(a$, b$)
for (j = 0; j < 100; ++j)
{
r = i2rand(a, b)
r >= min && r <= max
}
}
halt

File diff suppressed because it is too large Load Diff

View File

@ -132,7 +132,7 @@ fi
# Skip the tests that require extra math if we don't have it.
if [ "$run_extra_tests" -eq 0 ]; then
if [ "$f" = "rand.bc" ] || [ "$f" = "root.bc" ]; then
if [ "$f" = "rand.bc" ] || [ "$f" = "root.bc" ] || [ "$f" = "i2rand.bc" ]; then
printf 'Skipping %s script: %s\n' "$d" "$f"
exit 0
fi