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

Low-level betterC utilities for big integer arithmetic libraries.

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

enum WordEndian: int;
little
big
enum WordEndian TargetEndian;
struct BigUIntView(W, WordEndian endian = TargetEndian) if (__traits(isUnsigned, W));
Arbitrary length unsigned integer view.
Examples:
import std.traits;
alias AliasSeq(T...) = T;

foreach (T; AliasSeq!(ubyte, ushort, uint, ulong))
foreach (endian; AliasSeq!(WordEndian.little, WordEndian.big))
{
    static if (endian == WordEndian.little)
    {
        T[3] lhsData = [1, T.max-1, 0];
        T[3] rhsData = [T.max, T.max, 0];
    }
    else
    {
        T[3] lhsData = [0, T.max-1, 1];
        T[3] rhsData = [0, T.max, T.max];
    }

    auto lhs = BigUIntView!(T, endian)(lhsData).normalized;

    /// bool overflow = bigUInt op= scalar
    assert(lhs.leastSignificantFirst == [1, T.max-1]);
    assert(lhs.mostSignificantFirst == [T.max-1, 1]);
    static if (T.sizeof >= 4)
    {
        assert((lhs += T.max) == false);
        assert(lhs.leastSignificantFirst == [0, T.max]);
        assert((lhs += T.max) == false);
        assert((lhs += T.max) == true); // overflow bit
        assert(lhs.leastSignificantFirst == [T.max-1, 0]);
        assert((lhs -= T(1)) == false);
        assert(lhs.leastSignificantFirst == [T.max-2, 0]);
        assert((lhs -= T.max) == true); // underflow bit
        assert(lhs.leastSignificantFirst == [T.max-1, T.max]);
        assert((lhs -= Signed!T(-4)) == true); // overflow bit
        assert(lhs.leastSignificantFirst == [2, 0]);
        assert((lhs += Signed!T.max) == false); // overflow bit
        assert(lhs.leastSignificantFirst == [Signed!T.max + 2, 0]);

        ///  bool overflow = bigUInt op= bigUInt/bigInt
        lhs = BigUIntView!(T, endian)(lhsData);
        auto rhs = BigUIntView!(T, endian)(rhsData).normalized;
        assert(lhs.leastSignificantFirst == [Signed!T.max + 2, 0, 0]);
        assert(rhs.leastSignificantFirst == [T.max, T.max]);
        assert((lhs += rhs) == false);
        assert(lhs.leastSignificantFirst == [Signed!T.max + 1, 0, 1]);
        assert((lhs -= rhs) == false);
        assert(lhs.leastSignificantFirst == [Signed!T.max + 2, 0, 0]);
        assert((lhs += -rhs) == true);
        assert(lhs.leastSignificantFirst == [Signed!T.max + 3, 0, T.max]);
        assert((lhs += -(-rhs)) == true);
        assert(lhs.leastSignificantFirst == [Signed!T.max + 2, 0, 0]);

        /// W overflow = bigUInt *= scalar
        assert((lhs *= T.max) == 0);
        assert((lhs += T(Signed!T.max + 2)) == false);
        assert(lhs.leastSignificantFirst == [0, Signed!T.max + 2, 0]);
        lhs = lhs.normalized;
        lhs.leastSignificantFirst[1] = T.max / 2 + 3;
        assert(lhs.leastSignificantFirst == [0, T.max / 2 + 3]);
        assert((lhs *= 8u) == 4);
        assert(lhs.leastSignificantFirst == [0, 16]);
    }
}
W[] coefficients;
A group of coefficients for a radix W.max + 1.
The order corresponds to endianness.
pure nothrow @nogc @property @safe BigIntView!(W, endian) signed()();

Retrurns signed integer view using the same data payload

const T opCast(T, bool wordNormalized = false, bool nonZero = false)()
if (isFloatingPoint!T && isMutable!T);
Examples:
auto a = cast(double) BigUIntView!size_t.fromHexString("afbbfae3cd0aff2714a1de7022b0029d");
assert(a == 0xa.fbbfae3cd0bp+124);
assert(cast(double) BigUIntView!size_t.init == 0);
assert(cast(double) BigUIntView!size_t([0]) == 0);
const @safe T opCast(T : Fp!coefficientSize, size_t internalRoundLastBits = 0, bool wordNormalized = false, bool nonZero = false, size_t coefficientSize)()
if (internalRoundLastBits < size_t.sizeof * 8 && (size_t.sizeof >= W.sizeof || endian == TargetEndian));
Examples:
import mir.bignum.fp: Fp;
import mir.bignum.fixed: UInt;

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

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

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

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

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

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

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

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

fp = cast(Fp!128) BigUIntView!size_t.fromHexString("fffffffffffffffffffffffffffffffe8000000000000001");
assert(fp.exponent == 64);
assert(fp.coefficient == UInt!128.fromHexString("ffffffffffffffffffffffffffffffff"));
pure nothrow @nogc @trusted BigUIntView!V opCast(T : BigUIntView!V, V)()
if (V.sizeof <= W.sizeof);
const pure nothrow @nogc @property @safe BigUIntView!(const(W), endian) lightConst()();
const pure nothrow @nogc @safe sizediff_t opCmp(BigUIntView!(const(W), endian) rhs);
const pure nothrow @nogc @safe bool opEquals(BigUIntView!(const(W), endian) rhs);
inout @property ref inout(W) mostSignificant();
inout @property ref inout(W) leastSignificant();
void popMostSignificant();
void popLeastSignificant();
BigUIntView topMostSignificantPart(size_t length);
BigUIntView topLeastSignificantPart(size_t length);
void smallLeftShiftInPlace()(uint shift);
Shifts left using at most size_t.sizeof * 8 - 1 bits
Examples:
auto a = BigUIntView!size_t.fromHexString("afbbfae3cd0aff2714a1de7022b0029d");
a.smallLeftShiftInPlace(4);
assert(a == BigUIntView!size_t.fromHexString("fbbfae3cd0aff2714a1de7022b0029d0"));
a.smallLeftShiftInPlace(0);
assert(a == BigUIntView!size_t.fromHexString("fbbfae3cd0aff2714a1de7022b0029d0"));
void smallRightShiftInPlace()(uint shift);
Shifts right using at most size_t.sizeof * 8 - 1 bits
Examples:
auto a = BigUIntView!size_t.fromHexString("afbbfae3cd0aff2714a1de7022b0029d");
a.smallRightShiftInPlace(4);
assert(a == BigUIntView!size_t.fromHexString("afbbfae3cd0aff2714a1de7022b0029"));
static pure @trusted BigUIntView fromHexString(scope const(char)[] str);
pure @nogc @safe void fromHexStringImpl(scope const(char)[] str);
pure nothrow @nogc @safe bool opOpAssign(string op)(BigUIntView!(const(W), endian) rhs, bool overflow = false)
if (op == "+" || op == "-");

pure nothrow @nogc @safe bool opOpAssign(string op)(BigIntView!(const(W), endian) rhs, bool overflow = false)
if (op == "+" || op == "-");
Performs bool overflow = big +(-)= big operatrion.
Parameters:
BigUIntView!(const(W), endian) rhs value to add with non-empty coefficients
bool overflow (overflow) initial iteration overflow

Precondition non-empty coefficients length of greater or equal to the rhs coefficients length.

Returns:
true in case of unsigned overflow
pure nothrow @nogc @safe bool opOpAssign(string op, T)(const T rhs)
if ((op == "+" || op == "-") && is(T == W));

pure nothrow @nogc @safe bool opOpAssign(string op, T)(const T rhs)
if ((op == "+" || op == "-") && is(T == Signed!W));
Performs bool Overflow = big +(-)= scalar operatrion.

Precondition non-empty coefficients

Parameters:
T rhs value to add
Returns:
true in case of unsigned overflow
pure nothrow @nogc @safe W opOpAssign(string op : "*")(W rhs, W overflow = 0u);
Performs W overflow = (big += overflow) *= scalar operatrion.

Precondition non-empty coefficients

Parameters:
W rhs unsigned value to multiply by
W overflow initial overflow
Returns:
unsigned overflow value
pure nothrow @nogc @safe UInt!size opOpAssign(string op : "*", size_t size)(UInt!size rhs, UInt!size overflow = 0);
Performs W overflow = (big += overflow) *= scalar operatrion.

Precondition non-empty coefficients

Parameters:
UInt!size rhs unsigned fixed-length integer to multiply by
UInt!size overflow initial overflow
Returns:
unsigned fixed-length integer overflow value
BigIntView!(W, endian) opUnary(string op : "-")();
Returns:
the same intger view with inversed sign
void bitwiseNotInPlace();
bool twoComplementInPlace();
Performs number=-number operatrion.

Precondition non-empty coefficients

Returns:
true if 'number=-number=0' and false otherwise
pure nothrow @nogc @property @safe auto leastSignificantFirst();
Returns:
a slice of coefficients starting from the least significant.
const pure nothrow @nogc @property @safe auto leastSignificantFirst();
pure nothrow @nogc @property @safe auto mostSignificantFirst();
Returns:
a slice of coefficients starting from the most significant.
const pure nothrow @nogc @property @safe auto mostSignificantFirst();
BigUIntView normalized();

const BigUIntView!(const(W), endian) normalized();
Strips most significant zero coefficients.
bool bt()(size_t position);
const pure nothrow @nogc @property @safe size_t ctlz()();
const pure nothrow @nogc @property @safe size_t cttz()();
BigIntView!(W, endian) withSign()(bool sign);
const pure nothrow @nogc @safe bool get(U)(out scope U value)
if (isUnsigned!U);
Parameters:
U value (out) unsigned integer
Returns:
const pure nothrow @nogc @safe bool opEquals(ulong rhs);
Returns:
true if the integer and equals to rhs.
struct BigIntView(W, WordEndian endian = TargetEndian) if (is(Unqual!W == ubyte) || is(Unqual!W == ushort) || is(Unqual!W == uint) || is(Unqual!W == ulong));
Arbitrary length signed integer view.
Examples:
import std.traits;
alias AliasSeq(T...) = T;

foreach (T; AliasSeq!(ubyte, ushort, uint, ulong))
foreach (endian; AliasSeq!(WordEndian.little, WordEndian.big))
{
    static if (endian == WordEndian.little)
    {
        T[3] lhsData = [1, T.max-1, 0];
        T[3] rhsData = [T.max, T.max, 0];
    }
    else
    {
        T[3] lhsData = [0, T.max-1, 1];
        T[3] rhsData = [0, T.max, T.max];
    }

    auto lhs = BigIntView!(T, endian)(lhsData).normalized;

    ///  bool overflow = bigUInt op= scalar
    assert(lhs.leastSignificantFirst == [1, T.max-1]);
    assert(lhs.mostSignificantFirst == [T.max-1, 1]);

    static if (T.sizeof >= 4)
    {

        assert((lhs += T.max) == false);
        assert(lhs.leastSignificantFirst == [0, T.max]);
        assert((lhs += T.max) == false);
        assert((lhs += T.max) == true); // overflow bit
        assert(lhs.leastSignificantFirst == [T.max-1, 0]);
        assert((lhs -= T(1)) == false);
        assert(lhs.leastSignificantFirst == [T.max-2, 0]);
        assert((lhs -= T.max) == false);
        assert(lhs.leastSignificantFirst == [2, 0]);
        assert(lhs.sign);
        assert((lhs -= Signed!T(-4)) == false);
        assert(lhs.leastSignificantFirst == [2, 0]);
        assert(lhs.sign == false);
        assert((lhs += Signed!T.max) == false);
        assert(lhs.leastSignificantFirst == [Signed!T.max + 2, 0]);

        ///  bool overflow = bigUInt op= bigUInt/bigInt
        lhs = BigIntView!(T, endian)(lhsData);
        auto rhs = BigUIntView!(T, endian)(rhsData).normalized;
        assert(lhs.leastSignificantFirst == [Signed!T.max + 2, 0, 0]);
        assert(rhs.leastSignificantFirst == [T.max, T.max]);
        assert((lhs += rhs) == false);
        assert(lhs.leastSignificantFirst == [Signed!T.max + 1, 0, 1]);
        assert((lhs -= rhs) == false);
        assert(lhs.leastSignificantFirst == [Signed!T.max + 2, 0, 0]);
        assert((lhs += -rhs) == false);
        assert(lhs.sign);
        assert(lhs.leastSignificantFirst == [T.max - (Signed!T.max + 2), T.max, 0]);
        assert(lhs.sign);
        assert((lhs -= -rhs) == false);
        assert(lhs.leastSignificantFirst == [Signed!T.max + 2, 0, 0]);
        assert(lhs.sign == false);
    }
}
BigUIntView!(W, endian) unsigned;
Self-assigned to unsigned integer view BigUIntView..
Sign is stored in the most significant bit.
The number is encoded as pair of unsigned and sign.
bool sign;
Sign bit
inout @property inout(W)[] coefficients();
this(W[] coefficients, bool sign = false);
this(BigUIntView!(W, endian) unsigned, bool sign = false);
const T opCast(T, bool wordNormalized = false, bool nonZero = false)()
if (isFloatingPoint!T);
Examples:
auto a = cast(double) -BigUIntView!size_t.fromHexString("afbbfae3cd0aff2714a1de7022b0029d");
assert(a == -0xa.fbbfae3cd0bp+124);
const T opCast(T : Fp!coefficientSize, size_t internalRoundLastBits = 0, bool wordNormalized = false, bool nonZero = false, size_t coefficientSize)()
if (internalRoundLastBits < size_t.sizeof * 8 && (size_t.sizeof >= W.sizeof || endian == TargetEndian));
Examples:
import mir.bignum.fixed: UInt;
import mir.bignum.fp: Fp;

auto fp = cast(Fp!128) -BigUIntView!size_t.fromHexString("afbbfae3cd0aff2714a1de7022b0029d");
assert(fp.sign);
assert(fp.exponent == 0);
assert(fp.coefficient == UInt!128.fromHexString("afbbfae3cd0aff2714a1de7022b0029d"));
BigIntView!V opCast(T : BigIntView!V, V)()
if (V.sizeof <= W.sizeof);
const pure nothrow @nogc @property @safe BigIntView!(const(W), endian) lightConst()();
const pure nothrow @nogc @safe sizediff_t opCmp(BigIntView!(const(W), endian) rhs);
const pure nothrow @nogc @safe bool opEquals(BigIntView!(const(W), endian) rhs);
BigIntView topMostSignificantPart(size_t length);
BigIntView topLeastSignificantPart(size_t length);
pure nothrow @nogc @safe bool opOpAssign(string op)(BigIntView!(const(W), endian) rhs, bool overflow = false)
if (op == "+" || op == "-");

pure nothrow @nogc @safe bool opOpAssign(string op)(BigUIntView!(const(W), endian) rhs, bool overflow = false)
if (op == "+" || op == "-");
Performs bool overflow = big +(-)= big operatrion.
Parameters:
BigIntView!(const(W), endian) rhs value to add with non-empty coefficients
bool overflow (overflow) initial iteration overflow

Precondition non-empty coefficients length of greater or equal to the rhs coefficients length.

Returns:
true in case of unsigned overflow
pure nothrow @nogc @safe bool opOpAssign(string op, T)(const T rhs)
if ((op == "+" || op == "-") && is(T == Signed!W));

pure nothrow @nogc @safe bool opOpAssign(string op, T)(const T rhs)
if ((op == "+" || op == "-") && is(T == W));
Performs bool overflow = big +(-)= scalar operatrion.

Precondition non-empty coefficients

Parameters:
T rhs value to add
Returns:
true in case of unsigned overflow
pure nothrow @nogc @safe W opOpAssign(string op : "*")(W rhs, W overflow = 0u);
Performs W overflow = (big += overflow) *= scalar operatrion.

Precondition non-empty coefficients

Parameters:
W rhs unsigned value to multiply by
W overflow initial overflow
Returns:
unsigned overflow value
BigIntView opUnary(string op : "-")();
Returns:
the same intger view with inversed sign
pure nothrow @nogc @property @safe auto leastSignificantFirst();
Returns:
a slice of coefficients starting from the least significant.
pure nothrow @nogc @property @safe auto mostSignificantFirst();
Returns:
a slice of coefficients starting from the most significant.
BigIntView normalized();

const BigIntView!(const(W), endian) normalized();
Strips zero most significant coefficients. Strips most significant zero coefficients. Sets sign to zero if no coefficients were left.
struct BigUIntAccumulator(W, WordEndian endian = TargetEndian) if (is(Unqual!W == uint) || is(Unqual!W == ulong));
An utility type to wrap a local buffer to accumulate unsigned numbers.
Examples:
import std.traits;
alias AliasSeq(T...) = T;

foreach (T; AliasSeq!(uint, ulong))
foreach (endian; AliasSeq!(WordEndian.little, WordEndian.big))
{
    T[16 / T.sizeof] buffer;
    auto accumulator = BigUIntAccumulator!(T, endian)(buffer);
    assert(accumulator.length == 0);
    assert(accumulator.coefficients.length == buffer.length);
    assert(accumulator.view.coefficients.length == 0);
    // needs to put a number before any operations on `.view`
    accumulator.put(1);
    // compute N factorial
    auto N = 30;
    foreach(i; 1 .. N + 1)
    {
        if (auto overflow = accumulator.view *= i)
        {
            if (!accumulator.canPut)
                throw new Exception("Factorial buffer overflow");
            accumulator.put(overflow);
        }
    }
    assert(accumulator.view == BigUIntView!(T, endian).fromHexString("D13F6370F96865DF5DD54000000"));
}
Examples:
import mir.bignum.fixed: UInt;
import mir.bignum.low_level_view: BigUIntView;
auto bigView = BigUIntView!size_t.fromHexString("55a325ad18b2a77120d870d987d5237473790532acab45da44bc07c92c92babf0b5e2e2c7771cd472ae5d7acdb159a56fbf74f851a058ae341f69d1eb750d7e3");
auto fixed = UInt!256.fromHexString("55e5669576d31726f4a9b58a90159de5923adc6c762ebd3c4ba518d495229072");
auto overflow = bigView *= fixed;
assert(overflow == UInt!256.fromHexString("1cbbe8c42dc21f936e4ce5b2f52ac404439857f174084012fcd1b71fdec2a398"));
assert(bigView == BigUIntView!size_t.fromHexString("c73fd2b26f2514c103c324943b6c90a05d2732118d5f0099c36a69a8051bb0573adc825b5c9295896c70280faa4c4d369df8e92f82bfffafe078b52ae695d316"));
Examples:
Computes 13 * 10^^60
uint[7] buffer;
auto accumulator = BigUIntAccumulator!uint(buffer);
accumulator.put(13); // initial value
assert(accumulator.approxCanMulPow5(60));
accumulator.mulPow5(60);
assert(accumulator.canMulPow2(60));
accumulator.mulPow2(60);
assert(accumulator.view == BigUIntView!uint.fromHexString("81704fcef32d3bd8117effd5c4389285b05d000000000000000"));
W[] coefficients;
A group of coefficients for a DecimalRadix.!W.
The order corresponds to endianness.
The unused part can be uninitialized.
size_t length;
Current length of initialized coefficients.
The initialization order corresponds to endianness.
The view method may return a view with empty coefficients, which isn't usable. Put 0 or another number first to make the accumulator maintain a non-empty view.
pure nothrow @nogc @property @safe BigUIntView!(W, endian) view();
Returns:
Current unsigned integer view.

Note The method may return a view with empty coefficients, which isn't usable. Put 0 or another number first to make the accumulator maintain a non-empty view.

@property bool canPut();
Returns:
True if the accumulator can accept next most significant coefficient
void put(W coeffecient);
Places coefficient to the next most significant position.
void normalize();
Strips most significant zero coefficients from the current view.

Note The view method may return a view with empty coefficients, which isn't usable. Put 0 or another number first to make the accumulator maintain a non-empty view.

bool canPutN(size_t n);
bool approxCanMulPow5(size_t degree);
bool canMulPow2(size_t degree);
void mulPow5(size_t degree);
void mulPow2(size_t degree);
struct DecimalView(W, WordEndian endian = TargetEndian, Exp = int) if (isUnsigned!W);
Examples:
alias AliasSeq(T...) = T;

foreach (T; AliasSeq!(float, double, real))
{{
    T value = 3.518437208883201171875E+013;
    
}}

foreach(E; AliasSeq!(WordEndian.little, WordEndian.big))
foreach(W; AliasSeq!(ulong, uint, ushort, ubyte))
static if (!(E != TargetEndian && (W.sizeof > size_t.sizeof || W.sizeof == 1)))
{{
    alias Args = AliasSeq!(W, E);

    auto view = DecimalView!Args(false, -8, BigUIntView!Args.fromHexString("BEBC2000000011E1A3"));

    assert (cast(float)view == 3.518437208883201171875E+013f);
    assert (cast(double)view == 3.518437208883201171875E+013);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 3.518437208883201171875E+013L);

    view = DecimalView!Args(true, -169, BigUIntView!Args.fromHexString("5A174AEDA65CC"));
    assert (cast(float)view == -0);
    assert (cast(double)view == -0x1.1p-511);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == -0x8.80000000000019fp-514L);

    view = DecimalView!Args(true, 293, BigUIntView!Args.fromHexString("36496F6C4ED38"));
    assert (cast(float)view == -float.infinity);
    assert (cast(double)view == -9.55024478104888e+307);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == -9.55024478104888e+307L);

    view = DecimalView!Args(false, 0, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 1);
    assert (cast(double)view == 1);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 1L);

    view = DecimalView!Args(false, -5, BigUIntView!Args.fromHexString("3"));
    assert (cast(float)view == 3e-5f);
    assert (cast(double)view == 3e-5);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 3e-5L);

    view = DecimalView!Args(false, -1, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0.1f);
    assert (cast(double)view == 0.1);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0.1L);

    view = DecimalView!Args(false, 0, BigUIntView!Args.fromHexString("3039"));
    assert (cast(float)view == 12345.0f);
    assert (cast(double)view == 12345.0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 12345.0L);

    view = DecimalView!Args(false, -7, BigUIntView!Args.fromHexString("98967F"));
    assert (cast(float)view == 0.9999999f);
    assert (cast(double)view == 0.9999999);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0.9999999L);

    view = DecimalView!Args(false, -324, BigUIntView!Args.fromHexString("4F0CEDC95A718E"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 2.2250738585072014e-308);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 2.2250738585072014e-308L);

    view = DecimalView!Args(false, 0, BigUIntView!Args.fromHexString("1FFFFFFFFFFFFFFFD"));
    assert (cast(float)view == 36893488147419103229f);
    assert (cast(double)view == 36893488147419103229.0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x1FFFFFFFFFFFFFFFDp0L);

    view = DecimalView!Args(false, -33, BigUIntView!Args.fromHexString("65"));
    assert (cast(float)view == 101e-33f);
    assert (cast(double)view == 101e-33);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 101e-33L);

    view = DecimalView!Args(false, 23, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 1e23f);
    assert (cast(double)view == 1e23);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 1e23L);

    view = DecimalView!Args(false, 23, BigUIntView!Args.fromHexString("81B"));
    assert (cast(float)view == 2075e23f);
    assert (cast(double)view == 0xaba3d58a1f1a98p+32);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xaba3d58a1f1a9cp+32L);

    view = DecimalView!Args(false, -23, BigUIntView!Args.fromHexString("2209"));
    assert (cast(float)view == 8713e-23f);
    assert (cast(double)view == 0x1.9b75b4e7de2b9p-64);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xc.dbada73ef15c401p-67L);

    view = DecimalView!Args(false, 300, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == float.infinity);
    assert (cast(double)view == 0x1.7e43c8800759cp+996);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xb.f21e44003acdd2dp+993L);

    view = DecimalView!Args(false, 245, BigUIntView!Args.fromHexString("B3A73CEB227"));
    assert (cast(float)view == float.infinity);
    assert (cast(double)view == 0x1.48e3735333cb6p+857);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xa.471b9a999e5b01ep+854L);

    view = DecimalView!Args(false, 0, BigUIntView!Args.fromHexString("88BF4748507FB9900ADB624CCFF8D78897DC900FB0460327D4D86D327219"));
    assert (cast(float)view == float.infinity);
    assert (cast(double)view == 0x1.117e8e90a0ff7p+239);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.8bf4748507fb99p+236L);

    view = DecimalView!Args(false, -324, BigUIntView!Args.fromHexString("5"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0x0.0000000000001p-1022);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.18995ce7aa0e1b2p-1077L);

    view = DecimalView!Args(false, -324, BigUIntView!Args.fromHexString("5B"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0x0.0000000000012p-1022);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x9.3594d9adeb09a55p-1073L);

    view = DecimalView!Args(false, -322, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0x0.0000000000014p-1022);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xa.1ebfb4219491a1fp-1073L);

    view = DecimalView!Args(false, -320, BigUIntView!Args.fromHexString("CA1CCB"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0x0.000063df832d9p-1022);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xc.7bf065b215888c7p-1043L);

    view = DecimalView!Args(false, -319, BigUIntView!Args.fromHexString("33CE7943FB"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0x1.000000000162p-1022);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.000000000b103b6p-1025L);

    view = DecimalView!Args(false, -309, BigUIntView!Args.fromHexString("15"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0x0.f19c2629ccf53p-1022);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xf.19c2629ccf52fc4p-1026L);

    view = DecimalView!Args(false, -340, BigUIntView!Args.fromHexString("AF87023B9BF0EE"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0x0.0000000000001p-1022);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xf.fffffffffffff64p-1078L);

    view = DecimalView!Args(false, 400, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == float.infinity);
    assert (cast(double)view == double.infinity);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xd.a763fc8cb9ff9e6p+1325L);

    view = DecimalView!Args(false, 309, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == float.infinity);
    assert (cast(double)view == double.infinity);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xb.201833b35d63f73p+1023L);

    view = DecimalView!Args(false, 308, BigUIntView!Args.fromHexString("2"));
    assert (cast(float)view == float.infinity);
    assert (cast(double)view == double.infinity);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.e679c2f5e44ff8fp+1021L);

    view = DecimalView!Args(false, 308, BigUIntView!Args.fromHexString("2"));
    assert (cast(float)view == float.infinity);
    assert (cast(double)view == double.infinity);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.e679c2f5e44ff8fp+1021L);

    view = DecimalView!Args(false, 295, BigUIntView!Args.fromHexString("1059949B7090"));
    assert (cast(float)view == float.infinity);
    assert (cast(double)view == double.infinity);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.00000000006955ap+1021L);

    view = DecimalView!Args(false, 0, BigUIntView!Args.fromHexString("0"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0L);

    view = DecimalView!Args(false, 0, BigUIntView!Args.init);
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0L);

    view = DecimalView!Args(false, -325, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xa.5ced43b7e3e9188p-1083L);

    view = DecimalView!Args(false, -326, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.4a57695fe98746dp-1086L);

    view = DecimalView!Args(false, -500, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.33ada2003db9a8p-1664L);

    view = DecimalView!Args(false, -1000, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.68a9188a89e1467p-3325L);

    view = DecimalView!Args(false, -4999, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0L);

    view = DecimalView!Args(false, -10000, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0L);

    view = DecimalView!Args(false, -4969, BigUIntView!Args.fromHexString("329659A941466C6B"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == real.min_normal * real.epsilon);

    view = DecimalView!Args(false, -15, BigUIntView!Args.fromHexString("525DB0200FFAB"));
    assert (cast(float)view == 1.448997445238699f);
    assert (cast(double)view == 0x1.72f17f1f49aadp+0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xb.978bf8fa4d56cp-3L);

    view = DecimalView!Args(false, -15, BigUIntView!Args.fromHexString("525DB0200FFAB"));
    assert (cast(float)view == 1.448997445238699f);
    assert (cast(double)view == 0x1.72f17f1f49aadp+0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xb.978bf8fa4d56cp-3L);

    view = DecimalView!Args(false, -325, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xa.5ced43b7e3e9188p-1083L);

    view = DecimalView!Args(false, -326, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0);
    assert (cast(double)view == 0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8.4a57695fe98746dp-1086L);

    view = DecimalView!Args(false, 0, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 1);
    assert (cast(double)view == 0x1p+0);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0x8p-3L);

    view = DecimalView!Args(false, -5, BigUIntView!Args.fromHexString("3"));
    assert (cast(float)view == 3e-5f);
    assert (cast(double)view == 0x1.f75104d551d69p-16);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xf.ba8826aa8eb4635p-19L);

    view = DecimalView!Args(false, -1, BigUIntView!Args.fromHexString("1"));
    assert (cast(float)view == 0.1f);
    assert (cast(double)view == 0x1.999999999999ap-4);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xc.ccccccccccccccdp-7L);

    view = DecimalView!Args(false, -7, BigUIntView!Args.fromHexString("98967F"));
    assert (cast(float)view == 0.9999999f);
    assert (cast(double)view == 0x1.fffffca501acbp-1);
    static if (real.mant_dig >= 64)
        assert (cast(real)view == 0xf.ffffe5280d65435p-4L);
}}
bool sign;
Exp exponent;
BigUIntView!(W, endian) coefficient;
const pure nothrow @nogc @property @safe DecimalView!(const(W), endian, Exp) lightConst()();
BigIntView!(W, endian) signedCoefficient();
const T opCast(T, bool wordNormalized = false, bool nonZero = false)()
if (isFloatingPoint!T && isMutable!T);
Mir parsing supports up-to quadruple precision. The conversion error is 0 ULP for normal numbers. Subnormal numbers with an exponent greater than or equal to -512 have upper error bound equal to 1 ULP.
struct BinaryView(W, WordEndian endian = TargetEndian, Exp = int);
bool sign;
Exp exponent;
BigUIntView!(W, endian) coefficient;
const pure nothrow @nogc @property @safe DecimalView!(const(W), endian, Exp) lightConst()();
BigIntView!(W, endian) signedCoefficient();