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.bignum.fp

Note The module doesn't provide full arithmetic API for now.

struct Fp(size_t coefficientSize, Exp = sizediff_t) if ((is(Exp == int) || is(Exp == long)) && (coefficientSize % (size_t.sizeof * 8) == 0) && (coefficientSize >= size_t.sizeof * 8));
Software floating point number.
Parameters:
coefficientSize coefficient size in bits

Note the implementation doesn't support NaN and Infinity values.

nothrow this(bool sign, Exp exponent, UInt!coefficientSize normalizedCoefficient);
pure nothrow @nogc @safe this(T)(const T value, bool normalize = true)
if (isFloatingPoint!T && (T.mant_dig <= coefficientSize));
Constructs Fp from hardaware floating point number.
Parameters:
T value Hardware floating point number. Special values nan and inf aren't allowed.
bool normalize flag to indicate if the normalization should be performed.
Examples:
enum h = -33.0 * 2.0 ^^ -10;
auto f = Fp!64(h);
assert(f.sign);
assert(f.exponent == -10 - (64 - 6));
assert(f.coefficient == 33UL << (64 - 6));
assert(cast(double) f == h);

// CTFE
static assert(cast(double) Fp!64(h) == h);

f = Fp!64(-0.0);
assert(f.sign);
assert(f.exponent == 0);
assert(f.coefficient == 0);

// subnormals
static assert(cast(float) Fp!64(float.min_normal / 2) == float.min_normal / 2);
static assert(cast(float) Fp!64(float.min_normal * float.epsilon) == float.min_normal * float.epsilon);
// subnormals
static assert(cast(double) Fp!64(double.min_normal / 2) == double.min_normal / 2);
static assert(cast(double) Fp!64(double.min_normal * double.epsilon) == double.min_normal * double.epsilon);
// subnormals
static assert(cast(real) Fp!64(real.min_normal / 2) == real.min_normal / 2);
static assert(cast(real) Fp!64(real.min_normal * real.epsilon) == real.min_normal * real.epsilon);

enum d = cast(float) Fp!64(float.min_normal / 2, false);

// subnormals
static assert(cast(float) Fp!64(float.min_normal / 2, false) == float.min_normal / 2, d.stringof);
static assert(cast(float) Fp!64(float.min_normal * float.epsilon, false) == float.min_normal * float.epsilon);
// subnormals
static assert(cast(double) Fp!64(double.min_normal / 2, false) == double.min_normal / 2);
static assert(cast(double) Fp!64(double.min_normal * double.epsilon, false) == double.min_normal * double.epsilon);
// subnormals
static assert(cast(real) Fp!64(real.min_normal / 2, false) == real.min_normal / 2);
static assert(cast(real) Fp!64(real.min_normal * real.epsilon, false) == real.min_normal * real.epsilon);
Examples:
Without normalization
auto f = Fp!64(-33.0 * 2.0 ^^ -10, false);
assert(f.sign);
assert(f.exponent == -10 - (double.mant_dig - 6));
assert(f.coefficient == 33UL << (double.mant_dig - 6));
nothrow this(size_t size)(UInt!size integer, bool normalizedInteger = false);
Examples:
import mir.bignum.fixed: UInt;

auto fp = Fp!128(UInt!128.fromHexString("afbbfae3cd0aff2714a1de7022b0029d"));
assert(fp.exponent == 0);
assert(fp.coefficient == UInt!128.fromHexString("afbbfae3cd0aff2714a1de7022b0029d"));

fp = Fp!128(UInt!128.fromHexString("afbbfae3cd0aff2714a1de7022b0029d"), true);
assert(fp.exponent == 0);
assert(fp.coefficient == UInt!128.fromHexString("afbbfae3cd0aff2714a1de7022b0029d"));

fp = Fp!128(UInt!128.fromHexString("ae3cd0aff2714a1de7022b0029d"));
assert(fp.exponent == -20);
assert(fp.coefficient == UInt!128.fromHexString("ae3cd0aff2714a1de7022b0029d00000"));

fp = Fp!128(UInt!128.fromHexString("e7022b0029d"));
assert(fp.exponent == -84);
assert(fp.coefficient == UInt!128.fromHexString("e7022b0029d000000000000000000000"));

fp = Fp!128(UInt!64.fromHexString("e7022b0029d"));
assert(fp.exponent == -84);
assert(fp.coefficient == UInt!128.fromHexString("e7022b0029d000000000000000000000"));

fp = Fp!128(UInt!64.fromHexString("e7022b0029dd0aff"), true);
assert(fp.exponent == -64);
assert(fp.coefficient == UInt!128.fromHexString("e7022b0029dd0aff0000000000000000"));

fp = Fp!128(UInt!64.fromHexString("e7022b0029d"));
assert(fp.exponent == -84);
assert(fp.coefficient == UInt!128.fromHexString("e7022b0029d000000000000000000000"));

fp = Fp!128(UInt!192.fromHexString("ffffffffffffffffffffffffffffffff1000000000000000"));
assert(fp.exponent == 64);
assert(fp.coefficient == UInt!128.fromHexString("ffffffffffffffffffffffffffffffff"));

fp = Fp!128(UInt!192.fromHexString("ffffffffffffffffffffffffffffffff8000000000000000"));
assert(fp.exponent == 65);
assert(fp.coefficient == UInt!128.fromHexString("80000000000000000000000000000000"));

fp = Fp!128(UInt!192.fromHexString("fffffffffffffffffffffffffffffffe8000000000000000"));
assert(fp.exponent == 64);
assert(fp.coefficient == UInt!128.fromHexString("fffffffffffffffffffffffffffffffe"));

fp = Fp!128(UInt!192.fromHexString("fffffffffffffffffffffffffffffffe8000000000000001"));
assert(fp.exponent == 64);
assert(fp.coefficient == UInt!128.fromHexString("ffffffffffffffffffffffffffffffff"));
nothrow ref Fp opOpAssign(string op : "*")(Fp rhs) return;
const nothrow Fp opBinary(string op : "*")(Fp rhs);
Examples:
import mir.bignum.fixed: UInt;

auto a = Fp!128(0, -13, UInt!128.fromHexString("dfbbfae3cd0aff2714a1de7022b0029d"));
auto b = Fp!128(1, 100, UInt!128.fromHexString("e3251bacb112c88b71ad3f85a970a314"));
auto fp = a * b;
assert(fp.sign);
assert(fp.exponent == 100 - 13 + 128);
assert(fp.coefficient == UInt!128.fromHexString("c6841dd302415d785373ab6d93712988"));
const nothrow T opCast(T)()
if (is(Unqual!T == bool));
const nothrow T opCast(T, bool noHalf = false)()
if (isFloatingPoint!T);
Examples:
import mir.bignum.fixed: UInt;
auto fp = Fp!128(1, 100, UInt!128.fromHexString("e3251bacb112cb8b71ad3f85a970a314"));
assert(cast(double)fp == -0xE3251BACB112C8p+172);
Examples:
import mir.bignum.fixed: UInt;
auto fp = Fp!128(1, 100, UInt!128.fromHexString("e3251bacb112cb8b71ad3f85a970a314"));
static if (real.mant_dig == 64)
    assert(cast(real)fp == -0xe3251bacb112cb8bp+164L);
Examples:
import mir.bignum.fixed: UInt;
auto fp = Fp!64(1, 100, UInt!64(0xe3251bacb112cb8b));
version (DigitalMars)
{
    // https://issues.dlang.org/show_bug.cgi?id=20963
    assert(cast(double)fp == -0xE3251BACB112C8p+108
        || cast(double)fp == -0xE3251BACB112D0p+108);
}
else
{
    assert(cast(double)fp == -0xE3251BACB112C8p+108);
}
Examples:
import mir.bignum.fixed: UInt;
auto fp = Fp!64(1, 100, UInt!64(0xe3251bacb112cb8b));
static if (real.mant_dig == 64)
    assert(cast(real)fp == -0xe3251bacb112cb8bp+100L);
const nothrow T opCast(T : Fp!newCoefficientSize, size_t newCoefficientSize)();
Examples:
import mir.bignum.fixed: UInt;
auto fp = cast(Fp!64) Fp!128(UInt!128.fromHexString("afbbfae3cd0aff2784a1de7022b0029d"));
assert(fp.exponent == 64);
assert(fp.coefficient == UInt!64.fromHexString("afbbfae3cd0aff28"));
pure nothrow @nogc @safe Fp!(coefficientizeA + coefficientizeB) extendedMul(size_t coefficientizeA, size_t coefficientizeB)(Fp!coefficientizeA a, Fp!coefficientizeB b);