Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

std.math.operations

This is a submodule of std.math.
It contains several functions for work with floating point numbers.
Authors:
Walter Bright, Don Clugston, Conversion of CEPHES math library to D by Iain Buclaw and David Nadlinger
pure nothrow @nogc @trusted real NaN(ulong payload);
Create a quiet NAN, storing an integer inside the payload.
For floats, the largest possible payload is 0x3F_FFFF. For doubles, it is 0x3_FFFF_FFFF_FFFF. For 80-bit or 128-bit reals, it is 0x3FFF_FFFF_FFFF_FFFF.
Examples:
import std.math.traits : isNaN;

real a = NaN(1_000_000);
assert(isNaN(a));
writeln(getNaNPayload(a)); // 1_000_000
pure nothrow @nogc @trusted ulong getNaNPayload(real x);
Extract an integral payload from a NAN.
Returns:
the integer payload as a ulong.
For floats, the largest possible payload is 0x3F_FFFF. For doubles, it is 0x3_FFFF_FFFF_FFFF. For 80-bit or 128-bit reals, it is 0x3FFF_FFFF_FFFF_FFFF.
Examples:
import std.math.traits : isNaN;

real a = NaN(1_000_000);
assert(isNaN(a));
writeln(getNaNPayload(a)); // 1_000_000
pure nothrow @nogc @trusted real nextUp(real x);

pure nothrow @nogc @trusted double nextUp(double x);

pure nothrow @nogc @trusted float nextUp(float x);
Calculate the next largest floating point value after x.
Return the least number greater than x that is representable as a real; thus, it gives the next point on the IEEE number line.
Special Values
x nextUp(x)
-∞ -real.max
±0.0 real.min_normal*real.epsilon
real.max
NAN NAN
Examples:
assert(nextUp(1.0 - 1.0e-6).feqrel(0.999999) > 16);
assert(nextUp(1.0 - real.epsilon).feqrel(1.0) > 16);
pure nothrow @nogc @safe real nextDown(real x);

pure nothrow @nogc @safe double nextDown(double x);

pure nothrow @nogc @safe float nextDown(float x);
Calculate the next smallest floating point value before x.
Return the greatest number less than x that is representable as a real; thus, it gives the previous point on the IEEE number line.
Special Values
x nextDown(x)
real.max
±0.0 -real.min_normal*real.epsilon
-real.max -∞
-∞ -∞
NAN NAN
Examples:
writeln(nextDown(1.0 + real.epsilon)); // 1.0
pure nothrow @nogc @safe T nextafter(T)(const T x, const T y);
Calculates the next representable value after x in the direction of y.
If y > x, the result will be the next largest floating-point value; if y < x, the result will be the next smallest value. If x == y, the result is y. If x or y is a NaN, the result is a NaN.

Remarks This function is not generally very useful; it's almost always better to use the faster functions nextUp() or nextDown() instead.

The FE_INEXACT and FE_OVERFLOW exceptions will be raised if x is finite and the function result is infinite. The FE_INEXACT and FE_UNDERFLOW exceptions will be raised if the function value is subnormal, and x is not equal to y.

Examples:
import std.math.traits : isNaN;

float a = 1;
assert(is(typeof(nextafter(a, a)) == float));
assert(nextafter(a, a.infinity) > a);
assert(isNaN(nextafter(a, a.nan)));
assert(isNaN(nextafter(a.nan, a)));

double b = 2;
assert(is(typeof(nextafter(b, b)) == double));
assert(nextafter(b, b.infinity) > b);
assert(isNaN(nextafter(b, b.nan)));
assert(isNaN(nextafter(b.nan, b)));

real c = 3;
assert(is(typeof(nextafter(c, c)) == real));
assert(nextafter(c, c.infinity) > c);
assert(isNaN(nextafter(c, c.nan)));
assert(isNaN(nextafter(c.nan, c)));
pure nothrow @nogc @safe real fdim(real x, real y);
Returns the positive difference between x and y.
Equivalent to fmax(x-y, 0).
Returns:
Special Values
x, y fdim(x, y)
x > y x - y
x <= y +0.0
Examples:
import std.math.traits : isNaN;

writeln(fdim(2.0, 0.0)); // 2.0
writeln(fdim(-2.0, 0.0)); // 0.0
writeln(fdim(real.infinity, 2.0)); // real.infinity
assert(isNaN(fdim(real.nan, 2.0)));
assert(isNaN(fdim(2.0, real.nan)));
assert(isNaN(fdim(real.nan, real.nan)));
pure nothrow @nogc @safe F fmax(F)(const F x, const F y)
if (__traits(isFloating, F));
Returns the larger of x and y.
If one of the arguments is a NaN, the other is returned.
See Also:
std.algorithm.comparison.max is faster because it does not perform the isNaN test.
Examples:
import std.meta : AliasSeq;
static foreach (F; AliasSeq!(float, double, real))
{
    writeln(fmax(F(0.0), F(2.0))); // 2.0
    writeln(fmax(F(-2.0), 0.0)); // F(0.0)
    writeln(fmax(F.infinity, F(2.0))); // F.infinity
    writeln(fmax(F.nan, F(2.0))); // F(2.0)
    writeln(fmax(F(2.0), F.nan)); // F(2.0)
}
pure nothrow @nogc @safe F fmin(F)(const F x, const F y)
if (__traits(isFloating, F));
Returns the smaller of x and y.
If one of the arguments is a NaN, the other is returned.
See Also:
std.algorithm.comparison.min is faster because it does not perform the isNaN test.
Examples:
import std.meta : AliasSeq;
static foreach (F; AliasSeq!(float, double, real))
{
    writeln(fmin(F(0.0), F(2.0))); // 0.0
    writeln(fmin(F(-2.0), F(0.0))); // -2.0
    writeln(fmin(F.infinity, F(2.0))); // 2.0
    writeln(fmin(F.nan, F(2.0))); // 2.0
    writeln(fmin(F(2.0), F.nan)); // 2.0
}
pure nothrow @nogc @safe real fma(real x, real y, real z);
Returns (x * y) + z, rounding only once according to the current rounding mode.
Bugs:
Not currently implemented - rounds twice.
Examples:
writeln(fma(0.0, 2.0, 2.0)); // 2.0
writeln(fma(2.0, 2.0, 2.0)); // 6.0
writeln(fma(real.infinity, 2.0, 2.0)); // real.infinity
assert(fma(real.nan, 2.0, 2.0) is real.nan);
assert(fma(2.0, 2.0, real.nan) is real.nan);
pure nothrow @nogc @trusted int feqrel(X)(const X x, const X y)
if (isFloatingPoint!X);
To what precision is x equal to y?
Returns:
the number of mantissa bits which are equal in x and y. eg, 0x1.F8p+60 and 0x1.F1p+60 are equal to 5 bits of precision.
Special Values
x y feqrel(x, y)
x x real.mant_dig
x >= 2*x 0
x <= x/2 0
NAN any 0
any NAN 0
Examples:
writeln(feqrel(2.0, 2.0)); // 53
writeln(feqrel(2.0f, 2.0f)); // 24
writeln(feqrel(2.0, double.nan)); // 0

// Test that numbers are within n digits of each
// other by testing if feqrel > n * log2(10)

// five digits
assert(feqrel(2.0, 2.00001) > 16);
// ten digits
assert(feqrel(2.0, 2.00000000001) > 33);
bool approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 0.01, V maxAbsDiff = 1e-05);
Computes whether a values is approximately equal to a reference value, admitting a maximum relative difference, and a maximum absolute difference.

Warning This template is considered out-dated. It will be removed from Phobos in 2.106.0. Please use isClose instead. To achieve a similar behaviour to approxEqual(a, b) use isClose(a, b, 1e-2, 1e-5). In case of comparing to 0.0, isClose(a, b, 0.0, eps) should be used, where eps represents the accepted deviation from 0.0."

Parameters:
T value Value to compare.
U reference Reference value.
V maxRelDiff Maximum allowable difference relative to reference. Setting to 0.0 disables this check. Defaults to 1e-2.
V maxAbsDiff Maximum absolute difference. This is mainly usefull for comparing values to zero. Setting to 0.0 disables this check. Defaults to 1e-5.
Returns:
true if value is approximately equal to reference under either criterium. It is sufficient, when value satisfies one of the two criteria.
If one item is a range, and the other is a single value, then the result is the logical and-ing of calling approxEqual on each element of the ranged item against the single item. If both items are ranges, then approxEqual returns true if and only if the ranges have the same number of elements and if approxEqual evaluates to true for each pair of elements.
See Also:
Use feqrel to get the number of equal bits in the mantissa.
bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T, FloatingPointBaseType!U))(T lhs, U rhs, V maxRelDiff = CommonDefaultFor!(T, U), V maxAbsDiff = 0.0);
Computes whether two values are approximately equal, admitting a maximum relative difference, and a maximum absolute difference.
Parameters:
T lhs First item to compare.
U rhs Second item to compare.
V maxRelDiff Maximum allowable relative difference. Setting to 0.0 disables this check. Default depends on the type of lhs and rhs: It is approximately half the number of decimal digits of precision of the smaller type.
V maxAbsDiff Maximum absolute difference. This is mainly usefull for comparing values to zero. Setting to 0.0 disables this check. Defaults to 0.0.
Returns:
true if the two items are approximately equal under either criterium. It is sufficient, when value satisfies one of the two criteria.
If one item is a range, and the other is a single value, then the result is the logical and-ing of calling isClose on each element of the ranged item against the single item. If both items are ranges, then isClose returns true if and only if the ranges have the same number of elements and if isClose evaluates to true for each pair of elements.
See Also:
Use feqrel to get the number of equal bits in the mantissa.
Examples:
assert(isClose(1.0,0.999_999_999));
assert(isClose(0.001, 0.000_999_999_999));
assert(isClose(1_000_000_000.0,999_999_999.0));

assert(isClose(17.123_456_789, 17.123_456_78));
assert(!isClose(17.123_456_789, 17.123_45));

// use explicit 3rd parameter for less (or more) accuracy
assert(isClose(17.123_456_789, 17.123_45, 1e-6));
assert(!isClose(17.123_456_789, 17.123_45, 1e-7));

// use 4th parameter when comparing close to zero
assert(!isClose(1e-100, 0.0));
assert(isClose(1e-100, 0.0, 0.0, 1e-90));
assert(!isClose(1e-10, -1e-10));
assert(isClose(1e-10, -1e-10, 0.0, 1e-9));
assert(!isClose(1e-300, 1e-298));
assert(isClose(1e-300, 1e-298, 0.0, 1e-200));

// different default limits for different floating point types
assert(isClose(1.0f, 0.999_99f));
assert(!isClose(1.0, 0.999_99));
static if (real.sizeof > double.sizeof)
    assert(!isClose(1.0L, 0.999_999_999L));
Examples:
assert(isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001, 3.0]));
assert(!isClose([1.0, 2.0], [0.999_999_999, 2.000_000_001, 3.0]));
assert(!isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001]));

assert(isClose([2.0, 1.999_999_999, 2.000_000_001], 2.0));
assert(isClose(2.0, [2.0, 1.999_999_999, 2.000_000_001]));
pure nothrow @nogc @trusted int cmp(T)(const(T) x, const(T) y)
if (isFloatingPoint!T);
Defines a total order on all floating-point numbers.
The order is defined as follows:
  • All numbers in [-∞, +∞] are ordered the same way as by built-in comparison, with the exception of -0.0, which is less than +0.0;
  • If the sign bit is set (that is, it's 'negative'), NAN is less than any number; if the sign bit is not set (it is 'positive'), NAN is greater than any number;
  • NANs of the same sign are ordered by the payload ('negative' ones - in reverse order).
Returns:
negative value if x precedes y in the order specified above; 0 if x and y are identical, and positive value otherwise.
See Also:
Standards:
Conforms to IEEE 754-2008
Examples:
Most numbers are ordered naturally.
assert(cmp(-double.infinity, -double.max) < 0);
assert(cmp(-double.max, -100.0) < 0);
assert(cmp(-100.0, -0.5) < 0);
assert(cmp(-0.5, 0.0) < 0);
assert(cmp(0.0, 0.5) < 0);
assert(cmp(0.5, 100.0) < 0);
assert(cmp(100.0, double.max) < 0);
assert(cmp(double.max, double.infinity) < 0);

writeln(cmp(1.0, 1.0)); // 0
Examples:
Positive and negative zeroes are distinct.
assert(cmp(-0.0, +0.0) < 0);
assert(cmp(+0.0, -0.0) > 0);
Examples:
Depending on the sign, NANs go to either end of the spectrum.
assert(cmp(-double.nan, -double.infinity) < 0);
assert(cmp(double.infinity, double.nan) < 0);
assert(cmp(-double.nan, double.nan) < 0);
Examples:
NANs of the same sign are ordered by the payload.
assert(cmp(NaN(10), NaN(20)) < 0);
assert(cmp(-NaN(20), -NaN(10)) < 0);