Releases: eobermuhlner/big-math
Release 2.3.2
API changes
BigRational
implements now Serializable
The BigRational
class implements now the Serializable
interface and can be serialized
with the standard Java approach using ObjectInputStream
and deserialized using ObjectOutputStream
.
BigRational
extends now Number
The BigRational
class extends now from Number
and provides the following standard methods:
int intValue()
long longValue()
float floatValue()
double doubleValue()
Bugfixes
BigRational.toFloat()
and BigRational.toDouble()
with large nominators/denominators
The methods BigRational.toFloat()
and BigRational.toDouble()
failed to convert large nominators/denominators
into valid float
, respectively double
numbers.
For example:
BigRational x = BigRational.valueOf("8.804462619980757911125181749462772084351");
System.out.println("rational : " + x.toRationalString());
System.out.println("float : " + x.toFloat());
would print:
rational : 8804462619980757911125181749462772084351/1000000000000000000000000000000000000000
float : NaN
After the fix this example prints:
rational : 8804462619980757911125181749462772084351/1000000000000000000000000000000000000000
float : 8.804462
BigRational.toIntegerRationalString()
with small negative numbers
Negative rational numbers smaller than 1 where printed without -
sign.
For example:
BigRational v = valueOf(-1, 2);
System.out.println("small negative rational toString(): " + v);
System.out.println("small negative rational toIntegerRationalString(): " + v);
would print:
small negative rational toString(): -0.5
small negative rational toIntegerRationalString(): 1/2
After the fix this example prints:
small negative rational toString(): -0.5
small negative rational toIntegerRationalString(): -1/2
BigDecimalMath.root(x, n)
faster with large n
The BigDecimalMath.root(BigDecimal, BigDecimal, MathContext)
function converged very slowly for larger values of n.
This was due to a bad initial value for the Newton-Raphson approximation.
Now the initial value for the Newton-Raphson approximation is calculated using double precision.
If the initial value cannot be calculated using double precision the function pow(x, 1/n) is used to calculate the root.
Enhancements
No enhancements.
Examples
Note: The example code is available on github, but not part of the big-math library.
No changes in the examples.
Release 2.3.1
IMPORTANT
The big-math
release 2.3.1 published on maven central (https://search.maven.org/) was accidentally built with uncommitted experimental changes.
DO NOT USE RELEASE 2.3.1 AND USE 2.3.2 instead.
API changes
BigRational
implements now Serializable
The BigRational
class implements now the Serializable
interface and can be serialized
with the standard Java approach using ObjectInputStream
and deserialized using ObjectOutputStream
.
BigRational
extends now Number
The BigRational
class extends now from Number
and provides the following standard methods:
int intValue()
long longValue()
float floatValue()
double doubleValue()
Bugfixes
BigRational.toFloat()
and BigRational.toDouble()
with large nominators/denominators
The methods BigRational.toFloat()
and BigRational.toDouble()
failed to convert large nominators/denominators
into valid float
, respectively double
numbers.
For example:
BigRational x = BigRational.valueOf("8.804462619980757911125181749462772084351");
System.out.println("rational : " + x.toRationalString());
System.out.println("float : " + x.toFloat());
would print:
rational : 8804462619980757911125181749462772084351/1000000000000000000000000000000000000000
float : NaN
After the fix this example prints:
rational : 8804462619980757911125181749462772084351/1000000000000000000000000000000000000000
float : 8.804462
BigRational.toIntegerRationalString()
with small negative numbers
Negative rational numbers smaller than 1 where printed without -
sign.
For example:
BigRational v = valueOf(-1, 2);
System.out.println("small negative rational toString(): " + v);
System.out.println("small negative rational toIntegerRationalString(): " + v);
would print:
small negative rational toString(): -0.5
small negative rational toIntegerRationalString(): 1/2
After the fix this example prints:
small negative rational toString(): -0.5
small negative rational toIntegerRationalString(): -1/2
BigDecimalMath.root(x, n)
faster with large n
The BigDecimalMath.root(BigDecimal, BigDecimal, MathContext)
function converged very slowly for larger values of n.
This was due to a bad initial value for the Newton-Raphson approximation.
Now the initial value for the Newton-Raphson approximation is calculated using double precision.
If the initial value cannot be calculated using double precision the function pow(x, 1/n) is used to calculate the root.
Enhancements
No enhancements.
Examples
Note: The example code is available on github, but not part of the big-math library.
No changes in the examples.
Release 2.3.0
API changes
No API changes.
Bugfixes
No Bugfix changes.
Enhancements
Added DefaultBigDecimalMath.createLocalMathContext()
and withLocalMathContext()
The class DefaultBigDecimalMath
is a wrapper around BigDecimalMath
that passes always the current MathContext
to the
functions that need a MathContext
argument.
The initial default MathContext
is equivalent to MathContext.DECIMAL128
but this can be overridden by setting the following system properties:
ch.obermuhlner.math.big.default.precision
to a positive integer precision (default=34)ch.obermuhlner.math.big.default.rounding
to a RoundingMode name (default=HALF_UP)
It is also possible to programmatically set the default MathContext
using setDefaultMathContext(MathContext)
.
It is recommended to set the desired precision in the MathContext
very early in the startup of the application and to not change it afterwards.
Important: Avoid the pitfall of setting the precision temporarily using setDefaultMathContext(MathContext)
for a calculation.
This can lead to race conditions and calculations with the wrong precision if other threads in your application do the same thing.
To set a temporary MathContext
you have to choice to use either:
DefaultBigDecimalMath.createLocalMathContext()
in a try-with-resources statementDefaultBigDecimalMath.withLocalMathContext()
with a lambda function
Example code using DefaultBigDecimalMath.createLocalMathContext()
:
System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
try (DefaultBigDecimalMath.LocalMathContext context = DefaultBigDecimalMath.createLocalMathContext(5)) {
System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
try (DefaultBigDecimalMath.LocalMathContext context2 = DefaultBigDecimalMath.createLocalMathContext(10)) {
System.out.println("Pi[10]: " + DefaultBigDecimalMath.pi());
};
System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
};
System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
Example code using DefaultBigDecimalMath.withLocalMathContext()
:
System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
DefaultBigDecimalMath.withLocalMathContext(5, () -> {
System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
DefaultBigDecimalMath.withLocalMathContext(10, () -> {
System.out.println("Pi[10]: " + DefaultBigDecimalMath.pi());
});
System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
});
System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
Both snippets will give the following output:
Pi[default]: 3.141592653589793238462643383279503
Pi[5]: 3.1416
Pi[10]: 3.141592654
Pi[5]: 3.1416
Pi[default]: 3.141592653589793238462643383279503
The temporary MathContext
are stored in ThreadLocal
variables
and will therefore not conflict with each other when used in multi-threaded use case.
Important: Due to the ThreadLocal
variables the temporary MathContext
will
not be available in other threads.
This includes streams using parallel()
, thread pools and manually started threads.
If you need temporary MathContext
for calculations then you must
set the local MathContext
inside every separate thread.
try (DefaultBigDecimalMath.LocalMathContext context = DefaultBigDecimalMath.createLocalMathContext(5)) {
BigDecimalStream.range(0.0, 1.0, 0.01, DefaultBigDecimalMath.currentMathContext())
.map(b -> DefaultBigDecimalMath.cos(b))
.map(b -> "sequential " + Thread.currentThread().getName() + " [5]: " + b)
.forEach(System.out::println);
BigDecimalStream.range(0.0, 1.0, 0.01, DefaultBigDecimalMath.currentMathContext())
.parallel()
.map(b -> {
try (DefaultBigDecimalMath.LocalMathContext context2 = DefaultBigDecimalMath.createLocalMathContext(5)) {
return DefaultBigDecimalMath.cos(b);
}
})
.map(b -> "parallel " + Thread.currentThread().getName() + " [5]: " + b)
.forEach(System.out::println);
}
Examples
Note: The example code is available on github, but not part of the big-math library.
Examples for createLocalMathContext()
and withLocalMathContext()
Example code was added to the class DefaultBigDecimalMathExample
to demonstrate the usage of DefaultBigDecimalMath.createLocalMathContext()
and DefaultBigDecimalMath.withLocalMathContext()
.
Release 2.2.1
API changes
No API changes.
Bugfixes
Concurrency bug in Taylor series based calculations
The code that calculates Taylor series caches the intermediate results
to improve the performance of future calculations of the same Taylor series.
This cache had a bug that would lead to
NullPointerException
s or wrong calculation when used in a multi-threaded scenario.
The bug was fixed by synchronizing the access to the cache and other changes to mutable state.
Special thanks to modestukasai for reporting and anlyzing the bug.
Enhancements
No enhancements.
Examples
Note: The example code is available on github, but not part of the big-math library.
Improved performance regression measurements
The PerformanceRegressionBigDecimalMath
example class was improved and wrapped in
several gradle projects to allow reproducable performance regression measurements
over all releases of big-math
.
Release 2.2.0
API changes
Support for NaN
, POSITIVE_INFINITY
, NEGATIVE_INFINITY
in BigFloat
The BigFloat
class supports now the same special values as double
:
NaN
for values that cannot be represented a numberPOSITIVE_INFINITY
to represent positive infinite valuesNEGATIVE_INFINITY
to represent negative infinite values
Bugfixes
No Bugfix changes.
Enhancements
Performance optimizations
Performance analysis of the basic operations on BigDecimal
has shown
that the add()
and subtract()
operation are faster without
specifying a MathContext
argument. The multiply()
operation has a
more complex performance behaviour. A single multiplication tends to be
faster without MathContext
argument but the following operations are
at risk to be slower since it accumulates precision.
Many operations where manually fine tuned to find the optimum
performance.
The following chart shows performance improvements for the involved
operations:
Examples
Note: The example code is available on github, but not part of the big-math library.
No changes in the examples.
Release 2.1.0
API changes
Use DefaultBigDecimalMath
to avoid passing MathContext
Due to popular demand a convenience class DefaultBigDecimalMath
was added that provides mathematical functions
where the MathContext
must not be passed every time.
The class DefaultBigDecimalMath
is a wrapper around BigDecimalMath
that passes always the same default MathContext
to the
functions that need a MathContext
argument.
This class is designed for applications that will always need the same precision in all calculations.
The initial default MathContext
is equivalent to MathContext.DECIMAL128
but this can be overridden by setting the following system properties:
ch.obermuhlner.math.big.default.precision
to a positive integer precision (default=34)ch.obermuhlner.math.big.default.rounding
to aRoundingMode
name (default=HALF_UP)
It is also possible to set the default MathContext
using DefaultBigDecimalMath.setDefaultMathContext(MathContext)
.
It is recommended to set the desired precision in the MathContext
early in the startup of the application.
Important: Avoid the pitfall of setting the precision temporarily for a calculation.
This can lead to race conditions and calculations with the wrong precision
if other threads in your application do the same thing.
Improved rounding with BigDecimalMath.roundWithTrailingZeroes()
The new function BigDecimalMath.roundWithTrailingZeroes()
rounds the specified BigDecimal
to the precision of the specified MathContext
including trailing zeroes.
Example:
MathContext mc = new MathContext(5);
System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("1.234567"), mc)); // 1.2346
System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("123.4567"), mc)); // 123.46
System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("0.001234567"), mc)); // 0.0012346
System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("1.23"), mc)); // 1.2300
System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("1.230000"), mc)); // 1.2300
System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("0.00123"), mc)); // 0.0012300
System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("0"), mc)); // 0.0000
System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("0.00000000"), mc)); // 0.0000
For consistency the normal BigDecimal.round()
function has also been provided in BigDecimalMath
.
Bugfixes
Performance improvement in log()
In release 2.0.0 the calculation precision was improved at the cost of calculation performance.
The calculation performance has now again been improved by up to factor 5 and is practically back to pre-2.0.0 levels,
while the calculations are still correct to the specified precision.
Fix sqrt()
sometimes wrong in last digit with low precision.
Calculation of square root with low precision (16 digits and less) could sometimes
calculate the last digit wrong.
For example:
BigDecimalMath.sqrt(new BigDecimal("43.79427225801566", new MathContext(16)));
returns 6.617724099568950
instead of 6.617724099568949
This has been fixed.
Fix BigDecimalMath
functions with MathContext.UNLIMITED
The behaviour of the BigDecimalMath
functions when being used with the MathContext.UNLIMITED
was badly defined.
In many cases the calculation was done with a low precision like 10.
The functions that calculate the result with an algorithm using well defined and obvious operations
may throw the same ArithmeticException
as the underlying BigDecimal
operations
if the specified MathContext
has a precision of 0 (for example MathContext.UNLIMITED
):
BigDecimalMath.reciprocal(BigDecimal)
BigDecimalMath.bernoulli(int, MathContext)
BigDecimalMath.factorial(BigDecimal, MathContext)
with integer argumentBigDecimalMath.gamma(BigDecimal, MathContext)
with integer argumentBigDecimalMath.pow(BigDecimal, long, MathContext)
All other functions that use approximations to calculate the result will throw a UnsupportedOperationException
if the specified MathContext
has a precision of 0 (for example MathContext.UNLIMITED
):
BigDecimalMath.factorial(BigDecimal, MathContext)
with non-integer argumentBigDecimalMath.gamma(BigDecimal, MathContext)
with non-integer argumentBigDecimalMath.pow(BigDecimal, BigDecimal, MathContext)
BigDecimalMath.sqrt(BigDecimal, MathContext)
BigDecimalMath.root(BigDecimal, BigDecimal, MathContext)
BigDecimalMath.log(BigDecimal, MathContext)
BigDecimalMath.log2(BigDecimal, MathContext)
BigDecimalMath.log10(BigDecimal, MathContext)
BigDecimalMath.pi(MathContext)
BigDecimalMath.e(MathContext)
BigDecimalMath.exp(BigDecimal, MathContext)
BigDecimalMath.sin(BigDecimal, MathContext)
BigDecimalMath.asin(BigDecimal, MathContext)
BigDecimalMath.cos(BigDecimal, MathContext)
BigDecimalMath.acos(BigDecimal, MathContext)
BigDecimalMath.tan(BigDecimal, MathContext)
BigDecimalMath.atan(BigDecimal, MathContext)
BigDecimalMath.atan2(BigDecimal, BigDecimal MathContext)
BigDecimalMath.cot(BigDecimal, MathContext)
BigDecimalMath.acot(BigDecimal, MathContext)
BigDecimalMath.sinh(BigDecimal, MathContext)
BigDecimalMath.cosh(BigDecimal, MathContext)
BigDecimalMath.tanh(BigDecimal, MathContext)
BigDecimalMath.coth(BigDecimal, MathContext)
BigDecimalMath.asinh(BigDecimal, MathContext)
BigDecimalMath.acosh(BigDecimal, MathContext)
BigDecimalMath.atanh(BigDecimal, MathContext)
BigDecimalMath.acoth(BigDecimal, MathContext)
Enhancements
Added BigDecimalMath.reciprocal()
The convenience method BigDecimalMath.reciprocal(BigDecimal, MathContext)
was added.
Added BigComplexMath.factorial()
The method BigComplexMath.factorial(BigComplex x, MathContext mathContext)
was added.
It calculates the factorial in the complex domain and is equivalent to BigDecimalMath.factorial(BigDecimal x, MathContext mathContext)
.
Added BigComplexMath.gamma()
The method BigComplexMath.gamma(BigComplex x, MathContext mathContext)
was added.
It calculates the gamma function in the complex domain and is equivalent to BigDecimalMath.gamma(BigDecimal x, MathContext mathContext)
.
Added BigDecimalMath.toBigDecimal(String)
The BigDecimal(String)
constructor as provided by Java gets increasingly slower if you pass longer strings to it.
The implementation in Java 11 and before is O(n^2).
If you want to convert very long strings (10000 characters or longer) then this slow constructor may become an issue.
BigDecimalMath.toBigDecimal(String)
is a drop in replacement with the same functionality
(converting a string representation into a BigDecimal
) but it is using a faster recursive implementation.
Improved performance of BigDecimalMath.factorial(int)
The factorial functions for integer values has been heavily optimized based on the beautiful implementation written by
Andriy Plokhotnyuk.
Thanks Andriy for giving permission to use it.
Examples
Note: The example code is available on github, but not part of the big-math library.
No changes in the examples.
Release 2.0.1
API changes
Module name for Java 9
Not really an API change but rather an API specification.
The deployed big-math Jar file contains now a module name for the Java 9 JigSaw module system.
This allows it to be used as automatic module with a well defined module name instead
of deriving the name magically from the Jar file name.
The module name follows the reverse domain convention and is: ch.obermuhlner.math.big
OSGi support
The big-math Jar file is now OSGi compatible.
The MANIFEST.MF
contains all the necessary headers and exports the public packages
ch.obermuhlner.math.big
ch.obermuhlner.math.big.stream
Bugfixes
Fixed BigDecimalMath.log(BigDecimal, MathContext)
argument x
very close to 0
BigDecimalMath.log(BigDecimal, MathContext)
failed with arguments very close to 0 due to
BigDecimal.doubleValue()
rounding down to 0.
Fixed BigDecimalMath.atan2(BigDecimal, BigDecimal, MathContext)
with positive x
A stupid typo in a division would give results with wrong precision results with positive x
arguments.
Examples
Note: The example code is available on github, but not part of the big-math library.
No changes in the examples.
Release 2.0.0
API changes
Added BigComplex
and BigComplexMath
Class BigComplex
The class BigComplex
represents complex numbers in the form (a + bi)
.
It follows the design of BigDecimal
with some convenience improvements like overloaded operator methods.
A big difference to BigDecimal
is that BigComplex.equals()
implements the mathematical equality
and not the strict technical equality.
This was a difficult decision because it means that BigComplex
behaves slightly different than BigDecimal
but considering that the strange equality of BigDecimal
is a major source of bugs we
decided it was worth the slight inconsistency.
If you need the strict equality use BigComplex.strictEquals()
.
-
re
-
im
-
add(BigComplex)
-
add(BigComplex, MathContext)
-
add(BigDecimal)
-
add(BigDecimal, MathContext)
-
add(double)
-
subtract(BigComplex)
-
subtract(BigComplex, MathContext)
-
subtract(BigDecimal)
-
subtract(BigDecimal, MathContext)
-
subtract(double)
-
multiply(BigComplex)
-
multiply(BigComplex, MathContext)
-
multiply(BigDecimal)
-
multiply(BigDecimal, MathContext)
-
multiply(double)
-
divide(BigComplex)
-
divide(BigComplex, MathContext)
-
divide(BigDecimal)
-
divide(BigDecimal, MathContext)
-
divide(double)
-
reciprocal(MathContext)
-
conjugate()
-
negate()
-
abs(MathContext)
-
angle(MathContext)
-
absSquare(MathContext)
-
isReal()
-
re()
-
im()
-
round(MathContext)
-
hashCode()
-
equals(Object)
-
strictEquals(Object)
-
toString()
-
valueOf(BigDecimal)
-
valueOf(double)
-
valueOf(BigDecimal, BigDecimal)
-
valueOf(double, double)
-
valueOfPolar(BigDecimal, BigDecimal, MathContext)
-
valueOfPolar(double, double, MathContext)
Class BigComplexMath
The class BigComplexMath
is the equivalent of BigDecimalMath
and contains mathematical functions in the complex domain.
sin(BigComplex, MathContext)
cos(BigComplex, MathContext)
tan(BigComplex, MathContext)
asin(BigComplex, MathContext)
acos(BigComplex, MathContext)
atan(BigComplex, MathContext)
acot(BigComplex, MathContext)
exp(BigComplex, MathContext)
log(BigComplex, MathContext)
pow(BigComplex, long, MathContext)
pow(BigComplex, BigDecimal, MathContext)
pow(BigComplex, BigComplex, MathContext)
sqrt(BigComplex, MathContext)
root(BigComplex, BigDecimal, MathContext)
root(BigComplex, BigComplex, MathContext)
Changed pow(BigDecimal, int)
to pow(BigDecimal, long)
The signature of BigDecimalMath.pow(BigDecimal, int)
to BigDecimalMath.pow(BigDecimal, long)
in order to improve the possible range of the y
argument.
Bugfixes
Fix pow(BigDecimal, int)
with large integer y
argument
The BigDecimalMath.pow(BigDecimal, int)
would give wrong results for large y
values, because
internally BigDecimal.intValue()
was used instead of BigDecimal.intValueExact()
.
This has been fixed and improved so that calculations with very large y
values are still possible.
Precision improvements in log()
, sqrt()
Strict unit testing has shown that the log()
function would not calculate
with the maximum precision, especially if the x
argument was transformed into
another value range (for example if x > 10
).
This has been fixed by calculating the internal transformation calculations with a higher precision.
Examples
Note: The example code is available on github, but not part of the big-math library.
Added example HighPrecisionMath
The example class HighPrecisionMath
was added to the examples.
The same class is also used in the FAQ section of the README.md on github.
Release 1.3.0
API changes
No API changes.
Bugfixes
No Bugfix changes.
Enhancements
Factory methods for BigDecimal
and BigFloat
streams
The classes BigDecimalStream
and BigFloatStream
provide factory methods for streams of BigDecimal
respectively BigFloat
elements.
Overloaded variants of range(start, end, step)
provide sequential elements equivalent to IntStream.range(start, end)
but with configurable step.
Similar methods for the rangeClosed()
(inclusive end) are available.
The streams are well behaved when used in parallel mode.
The following code snippet:
System.out.println("Range [0, 10) step 1 (using BigDecimal as input parameters)");
BigDecimalStream.range(BigDecimal.valueOf(0), BigDecimal.valueOf(10), BigDecimal.ONE, mathContext)
.forEach(System.out::println);
System.out.println("Range [0, 10) step 3 (using long as input parameters)");
BigDecimalStream.range(0, 10, 3, mathContext)
.forEach(System.out::println);
produces this output:
Range [0, 10) step 1 (using BigDecimal as input parameters)
0
1
2
3
4
5
6
7
8
9
Range [0, 12] step 3 (using long as input parameters)
0
3
6
9
12
Added BigDecimalMath.atan2(y, x)
The atan2(y, x)
function calculates the arc tangens (inverted tangens) of y / x in the range -π to π.
This is useful to calculate the angle θ from the conversion of rectangular
coordinates (x, y) to polar coordinates (r, θ).
Added BigFloat.signum()
and convenience BigFloat.isNegative()
, BigFloat.isZero()
, BigFloat.isPositive()
The signum()
function and its convenience variants where added to the BigFloat
class:
BigFloat.signum()
returns -1, 0, or 1 as the value is negative, zero, or positiveBigFloat.isNegative()
returns whether the value is negativeBigFloat.isZero()
returns whether the value is zeroBigFloat.isPositive()
returns whether the value is positive
Examples
Note: The example code is available on github, but not part of the big-math library.
No changes in the examples.
Release 1.2.1
API changes
No API changes.
Bugfixes
BigDecimalMath.isDoubleValue()
to return true
for values abs(x) < Double.MIN_VALUE
Fixed isDoubleValue()
to return true
for values abs(x) < Double.MIN_VALUE
.
For example BigDecimalMath.isDoubleValue(new BigDecimal("1E-325"))
will return true
although this value is smaller than Double.MIN_VALUE
(and therefore outside the range of values that can be represented as double
)
because new BigDecimal("1E-325").doubleValue()
returns 0
which is a legal value with loss of precision.
Enhancements
BigFloat.equals()
tests mathematical identity, not technical
One of the most common problem for programmers using BigDecimal
is probably that BigDecimal.equals()
tests for technical identity,
not mathematical identity (the common workaround is to use compareTo()
instead).
BigFloat.equals()
tests for mathematical identity.
For example
BigFloat.context(100).valueOf(123).equals(BigFloat.context(10).valueOf(123))
returns true
.
Examples
Note: The example code is available on github, but not part of the big-math library.
No changes in the examples.