Report a bug
If you spot a problem with this page, click here to create a GitHub 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.

mir.math.ieee

Base floating point routines.
Authors:
Walter Bright, Don Clugston, Ilya Yaroshenko
pure nothrow @nogc @trusted int signbit(T)(const T x);
Return 1 if sign bit of e is set, 0 if not.
Examples:
assert(!signbit(float.nan));
assert(signbit(-float.nan));
assert(!signbit(168.1234f));
assert(signbit(-168.1234f));
assert(!signbit(0.0f));
assert(signbit(-0.0f));
assert(signbit(-float.max));
assert(!signbit(float.max));

assert(!signbit(double.nan));
assert(signbit(-double.nan));
assert(!signbit(168.1234));
assert(signbit(-168.1234));
assert(!signbit(0.0));
assert(signbit(-0.0));
assert(signbit(-double.max));
assert(!signbit(double.max));

assert(!signbit(real.nan));
assert(signbit(-real.nan));
assert(!signbit(168.1234L));
assert(signbit(-168.1234L));
assert(!signbit(0.0L));
assert(signbit(-0.0L));
assert(signbit(-real.max));
assert(!signbit(real.max));
pure nothrow @nogc @trusted int feqrel(T)(const T x, const T y)
if (isFloatingPoint!T);
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:
assert(feqrel(2.0, 2.0) == 53);
assert(feqrel(2.0f, 2.0f) == 24);
assert(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);
enum RealFormat: int;
ieeeHalf
ieeeSingle
ieeeDouble
ieeeExtended
x87 80-bit real
ieeeExtended53
x87 real rounded to precision of double.
ibmExtended
IBM 128-bit extended
ieeeQuadruple
pure nothrow @nogc @trusted T nextUp(T)(const T x)
if (isFloatingPoint!T);
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 T nextDown(T)(const T 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:
assert( nextDown(1.0 + real.epsilon) == 1.0);
pure nothrow @nogc @trusted T ieeeMean(T)(const T xx, const T yy);
Return the value that lies halfway between x and y on the IEEE number line.
Formally, the result is the arithmetic mean of the binary significands of x and y, multiplied by the geometric mean of the binary exponents of x and y. x and y must not be NaN.

Note this function is useful for ensuring O(log n) behaviour in algorithms involving a 'binary chop'.

Parameters:
T xx x value
T yy y value
Special cases: If x and y not null and have opposite sign bits, then copysign(T(0), y) is returned. If x and y are within a factor of 2 and have the same sign, (ie, feqrel(x, y) > 0), the return value is the arithmetic mean (x + y) / 2. If x and y are even powers of 2 and have the same sign, the return value is the geometric mean, ieeeMean(x, y) = sgn(x) * sqrt(fabs(x * y)).
pure nothrow @nogc @trusted T frexp(T)(const T value, ref int exp)
if (isFloatingPoint!T);
Separate floating point value into significand and exponent.
Returns:
Calculate and return x and exp such that value =x*2exp and .5 <= |x| < 1.0
x has same sign as value.
Special Values
value returns exp
±0.0 ±0.0 0
+∞ +∞ int.max
-∞ -∞ int.min
±NAN ±NAN int.min
Examples:
import mir.math.common: pow, approxEqual;
alias isNaN = x => x != x;
int exp;
real mantissa = frexp(123.456L, exp);

assert(approxEqual(mantissa * pow(2.0L, cast(real) exp), 123.456L));

exp = 1234; // random number
assert(isNaN(frexp(-real.nan, exp)) && exp == 1234);
assert(isNaN(frexp(real.nan, exp)) && exp == 1234);
assert(frexp(-real.infinity, exp) == -real.infinity && exp == 1234);
assert(frexp(real.infinity, exp) == real.infinity && exp == 1234);

assert(frexp(-0.0, exp) == -0.0 && exp == 0);
assert(frexp(0.0, exp) == 0.0 && exp == 0);
pure nothrow @nogc @trusted T ldexp(T)(const T n, int exp)
if (isFloatingPoint!T);
Returns:
n * 2exp
See Also:
Examples:
import std.meta : AliasSeq;
static foreach (T; AliasSeq!(float, double, real))
{{
    T r = ldexp(cast(T) 3.0, cast(int) 3);
    assert(r == 24);

    T n = 3.0;
    int exp = 3;
    r = ldexp(n, exp);
    assert(r == 24);
}}