Skip to content

Releases: eobermuhlner/big-math

Release 2.3.2

13 Nov 13:51
Compare
Choose a tag to compare

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

06 Nov 15:38
Compare
Choose a tag to compare

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

06 Nov 15:45
Compare
Choose a tag to compare

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 statement
  • DefaultBigDecimalMath.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

09 Oct 07:07
Compare
Choose a tag to compare

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
NullPointerExceptions 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.

Selected functions performance over releases

Release 2.2.0

15 Aug 11:23
Compare
Choose a tag to compare

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 number
  • POSITIVE_INFINITY to represent positive infinite values
  • NEGATIVE_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:

Performance improvements MathContext optimization

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

29 Mar 13:02
Compare
Choose a tag to compare

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 a RoundingMode 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 argument
  • BigDecimalMath.gamma(BigDecimal, MathContext) with integer argument
  • BigDecimalMath.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 argument
  • BigDecimalMath.gamma(BigDecimal, MathContext) with non-integer argument
  • BigDecimalMath.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

14 Jun 19:57
Compare
Choose a tag to compare

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

30 Mar 15:22
Compare
Choose a tag to compare

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

16 Sep 12:06
Compare
Choose a tag to compare

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 positive
  • BigFloat.isNegative() returns whether the value is negative
  • BigFloat.isZero() returns whether the value is zero
  • BigFloat.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

14 Jul 21:19
Compare
Choose a tag to compare

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.