diff --git a/README.md b/README.md index 948d924f..c3fa6255 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,9 @@ void main() row[3] = 6; assert(matrix[2, 3] == 6); // D & C index order - import std.stdio; - matrix.writeln; // [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 6]] + import mir.stdio; + matrix.writeln; + // prints [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 6.0]] } ``` diff --git a/bigint_benchmark/source/app.d b/bigint_benchmark/source/app.d index ed60869b..d113422f 100644 --- a/bigint_benchmark/source/app.d +++ b/bigint_benchmark/source/app.d @@ -1,45 +1,26 @@ -import mir.bignum.integer: BigInt; import mir.stdio; -import std.bigint: StdBigInt = BigInt; -import gmp.z : GmpBigInt = MpZ, powmod; import std.datetime.stopwatch; immutable ps = "E5B5B1EDC8DF0F307C2220151CFCBE31F69B15659A5D6FBA1E50F55A08B341218312D707CFC16ED86A1765F5AEAFA7E6A11C4431038914C76F0F398FE6BE031E289B220D13D9E02226C691D15BC6E1186EA18222D93F52A393BE1DA1A42853512419B5E6E304FD02E962A4C2D0ECDDB8F44AC094FACA8333AE94110A5B10DA539C24A96F08530E7699E3F705165CF14B7F90A2F32ED28D21615F91D7C808AC566D6EEEF6773450AB53542CDAC337C3124530CB16319752267C3422149D41543D8742586BAB578F4E06360745AE0BD8F0E800D1920DC1F3661287367A78967458383A82465C5D966E7299EFCF58BD860185F96655E1F8D300F6B096DFE883CF15"; immutable qs = "D9757338E9A6B363F227F3104EDEF6240C0CAF53B7D509F48870553C4A821F460469AE5616301B9CC30FBF4598A176B84284AF3A41D697A34CDC2C8D88A4C4BE82AE8DB5347511FE5B4DD915CA6A728CCFD0444CE38FC7190824059D86A9083C273581EA5AD1D5E3A8D8EC6858F291A5EADA98B0F5FD7C8E8CA6226657B8B7955796B22899B087714E293A86C78D42A7021754A6220F1D0A9588C280DD9AEC376E421D539F30A3053D95C7D70F24B471D14ECF282FA3E0B1CED2C405BA22404F3B75CD961A46097D7C098324FC47281D298734DA0DFCD8AF82E685657C926672727296147867EAEDFDEF89A79DE81FF104CF7D9157EF65A1BC333C98A7FED685"; immutable es = ps ~ qs; -void stdPowMod(ref StdBigInt base, StdBigInt exponent, StdBigInt modulus) -{ - StdBigInt result = 1; - - while (exponent != 0) - { - base %= modulus; - if (exponent & 1) - { - result *= base; - result %= modulus; - } - exponent >>= 1; - base *= base; - } - base = result; -} - void testStd() { - StdBigInt p = "0x" ~ ps; - StdBigInt q = "0x" ~ qs; - StdBigInt m = p; + import std.bigint; + BigInt p = "0x" ~ ps; + BigInt q = "0x" ~ qs; + BigInt m = p; m *= q; - StdBigInt e = "0x" ~ es; - StdBigInt b = e; - b.stdPowMod(e, m); + BigInt e = "0x" ~ es; + BigInt b = e; + b = powmod(b, e, m); debug dout << b << endl; } void testMir() { + import mir.bignum.integer; auto p = BigInt!64.fromHexString(ps); auto q = BigInt!64.fromHexString(qs); BigInt!64 m = p; @@ -52,14 +33,15 @@ void testMir() void testGmp() { + import gmp.z : BigInt = MpZ, powmod; import std.algorithm.mutation : move; - auto p = GmpBigInt.fromHexString(ps); - auto q = GmpBigInt.fromHexString(qs); - GmpBigInt m = p.move(); + auto p = BigInt.fromHexString(ps); + auto q = BigInt.fromHexString(qs); + BigInt m = p.move(); m *= q; - auto e = GmpBigInt.fromHexString(es); - GmpBigInt b = e.dup; - b.powmod(e, m); + auto e = BigInt.fromHexString(es); + BigInt b = e.dup; + b = b.powmod(e, m); debug dout << b << endl; } @@ -76,27 +58,17 @@ void main() { import std.system: os; const res = 10.benchmark!(testStd, testMir, testGmp); - { - const mirRatio = double(res[0].total!"usecs") / res[1].total!"usecs"; - dout + const mirRatio = double(res[0].total!"usecs") / res[1].total!"usecs"; + const gmpRatio = double(res[0].total!"usecs") / res[2].total!"usecs"; + dout << "--------------------------------------------" << endl + << "gmp speedup = " << cast(int)((gmpRatio - 1) * 100_0) / 10.0 << "%" << endl << "mir speedup = " << cast(int)((mirRatio - 1) * 100_0) / 10.0 << "%" << endl << "std = " << res[0] << endl << "mir = " << res[1] << endl - << " ............... " << size_t.sizeof * 8 << "bit " << os << " ............... " << endl - << "--------------------------------------------" - << endl; - } - { - const gmpRatio = double(res[0].total!"usecs") / res[2].total!"usecs"; - dout - << "--------------------------------------------" << endl - << "gmp speedup = " << cast(int)((gmpRatio - 1) * 100_0) / 10.0 << "%" << endl - << "std = " << res[0] << endl << "gmp = " << res[2] << endl << " ............... " << size_t.sizeof * 8 << "bit " << os << " ............... " << endl << "--------------------------------------------" << endl; - } } } diff --git a/dub.sdl b/dub.sdl index bbee2c1f..c53be93f 100644 --- a/dub.sdl +++ b/dub.sdl @@ -6,11 +6,12 @@ copyright "2020 Ilya Yaroshenko, Kaleidic Associates Advisory Limited, Symmetry license "Apache-2.0" dependency "mir-core" version=">=1.1.106" -// dependency "silly" version="~>1.1.1" + +// versions "TeslAlgoM" buildType "unittest" { buildOptions "unittests" "debugMode" "debugInfo" - versions "mir_bignum_test" "mir_bignum_test_llv" "mir_ndslice_test" "mir_test" + versions "mir_bignum_test" "mir_bignum_test_llv" // "mir_ndslice_test" "mir_test" dflags "-lowmem" } buildType "unittest-dip1008" { @@ -54,7 +55,7 @@ configuration "dips" { } configuration "ci-bignum-test" { - versions "mir_bignum_test" + versions "mir_bignum_test" "mir_bignum_test_llv" } configuration "ci-core-test" { diff --git a/source/mir/appender.d b/source/mir/appender.d index 9c54182e..f1b6b8d5 100644 --- a/source/mir/appender.d +++ b/source/mir/appender.d @@ -38,7 +38,8 @@ struct ScopedBuffer(T, size_t bytes = 4096) return *cast(inout(T[_bufferLength])*)&_scopeBufferPayload; } - private T[] prepare(size_t n) @trusted scope + /// + T[] prepare(size_t n) @trusted scope { import mir.internal.memory: realloc, malloc; _currentLength += n; diff --git a/source/mir/bignum/decimal.d b/source/mir/bignum/decimal.d index 48896ab0..c9a43f2c 100644 --- a/source/mir/bignum/decimal.d +++ b/source/mir/bignum/decimal.d @@ -18,11 +18,11 @@ private static immutable C[9] zerosImpl(C) = "0.00000.0"; /++ Stack-allocated decimal type. Params: - maxSize64 = count of 64bit words in coefficient + size64 = count of 64bit words in coefficient +/ @serdeScoped @serdeProxy!(const(char)[]) -struct Decimal(uint maxSize64) - if (maxSize64 && maxSize64 <= ushort.max) +struct Decimal(uint size64) + if (size64 && size64 <= ushort.max) { import mir.format: NumericSpec; import mir.bignum.integer; @@ -32,7 +32,7 @@ struct Decimal(uint maxSize64) /// long exponent; /// - BigInt!maxSize64 coefficient; + BigInt!size64 coefficient; /// DecimalView!size_t view() @@ -56,11 +56,11 @@ struct Decimal(uint maxSize64) static if (__traits(compiles, () @nogc { throw new Exception("Can't parse Decimal."); })) { import mir.exception: MirException; - throw new MirException("Can't parse Decimal!" ~ maxSize64.stringof ~ " from string `", str , "`"); + throw new MirException("Can't parse Decimal!" ~ size64.stringof ~ " from string `", str , "`"); } else { - static immutable exception = new Exception("Can't parse Decimal!" ~ maxSize64.stringof ~ "."); + static immutable exception = new Exception("Can't parse Decimal!" ~ size64.stringof ~ "."); throw exception; } } @@ -71,7 +71,7 @@ struct Decimal(uint maxSize64) The number is the shortest decimal representation that being converted back would result the same floating-point number. +/ this(T)(const T x) - if (isFloatingPoint!T && maxSize64 >= 1 + (T.mant_dig >= 64)) + if (isFloatingPoint!T && size64 >= 1 + (T.mant_dig >= 64)) { import mir.bignum.internal.ryu.generic_128: genericBinaryToDecimal; this = genericBinaryToDecimal(x); @@ -79,7 +79,7 @@ struct Decimal(uint maxSize64) /// ref opAssign(uint rhsMaxSize64)(auto ref scope const Decimal!rhsMaxSize64 rhs) return - if (rhsMaxSize64 < maxSize64) + if (rhsMaxSize64 < size64) { this.exponent = rhs.exponent; this.coefficient = rhs.coefficient; @@ -180,7 +180,7 @@ struct Decimal(uint maxSize64) scope @trusted pure @nogc nothrow if (isSomeChar!C) { - enum optimize = size_t.sizeof == 8 && maxSize64 == 1; + enum optimize = size_t.sizeof == 8 && size64 == 1; version(LDC) { static if (optimize || (allowSpecialValues && allowDExponent && allowStartingPlus && checkEmpty) == false) @@ -333,7 +333,7 @@ struct Decimal(uint maxSize64) v = mulu(v, multplier, overflow); if (overflow) return false; - v = addu(v, value, overflow);; + v = addu(v, value, overflow); if (overflow) return false; } @@ -351,7 +351,7 @@ struct Decimal(uint maxSize64) v = mulu(v, cast(uint)10, overflow); if (overflow) return false; - v = addu(v, d, overflow);; + v = addu(v, d, overflow); if (overflow) return false; } @@ -503,13 +503,13 @@ struct Decimal(uint maxSize64) } else { - BigInt!maxSize64 work = coefficient; + BigInt!size64 work = coefficient; coefficientLength = work.view.unsigned.toStringImpl(buffer); } } else { - BigInt!maxSize64 work = coefficient; + BigInt!size64 work = coefficient; coefficientLength = work.view.unsigned.toStringImpl(buffer); } @@ -675,7 +675,7 @@ struct Decimal(uint maxSize64) if (op == "+" || op == "-") { import mir.utility: max; - BigInt!(max(rhsMaxSize64, maxSize64, 256u)) rhsCopy = void; + BigInt!(max(rhsMaxSize64, size64, 256u)) rhsCopy = void; BigIntView!(const size_t) rhsView; auto expDiff = cast(sizediff_t) (exponent - rhs.exponent); if (expDiff >= 0) @@ -702,13 +702,14 @@ version(mir_bignum_test) @safe pure nothrow @nogc unittest { + import mir.test: should; import mir.conv: to; Decimal!256 decimal = void; DecimalExponentKey key; assert(decimal.fromStringImpl("3.141592653589793378e-10", key)); - assert(cast(double) decimal == 0x1.596bf8ce7631ep-32); - assert(key == DecimalExponentKey.e); + decimal.to!double.should == 0x1.596bf8ce7631ep-32; + key.should == DecimalExponentKey.e; } /// @@ -808,6 +809,8 @@ version(mir_bignum_test) @safe pure nothrow @nogc unittest { + import mir.test: should; + import mir.conv: to; Decimal!3 decimal; DecimalExponentKey key; @@ -865,7 +868,7 @@ unittest assert(decimal.coefficient.length == 0); assert(decimal.exponent == decimal.exponent.max); assert(key == DecimalExponentKey.infinity); - assert(cast(double) decimal == -double.infinity); + should(cast(double) decimal) == -double.infinity; assert(!decimal.fromStringImpl("3.3.4", key)); assert(!decimal.fromStringImpl("3.4.", key)); diff --git a/source/mir/bignum/fp.d b/source/mir/bignum/fp.d index 61338fdc..8d5cbf49 100644 --- a/source/mir/bignum/fp.d +++ b/source/mir/bignum/fp.d @@ -378,7 +378,7 @@ struct Fp(uint size) /// Fp!(max(size, rhsSize)) opBinary(string op : "*", uint rhsSize)(Fp!rhsSize rhs) nothrow const { - return cast(Fp) .extendedMul!(size, rhsSize)(cast()this, rhs); + return cast(Fp) .extendedMul(cast()this, rhs); } static if (size == 128) @@ -418,16 +418,19 @@ struct Fp(uint size) } /// - T opCast(T, bool noHalf = false)() nothrow const + T opCast(T, bool noSpecial = false, bool noHalf = false)() nothrow const if (is(T == float) || is(T == double) || is(T == real)) { import mir.math.ieee: ldexp; - if (_expect(this.isSpecial, false)) + static if (!noSpecial) { - T ret = this.coefficient ? T.nan : T.infinity; - if (this.sign) - ret = -ret; - return ret; + if (_expect(this.isSpecial, false)) + { + T ret = this.coefficient ? T.nan : T.infinity; + if (this.sign) + ret = -ret; + return ret; + } } auto exp = cast()this.exponent; static if (size == 32) @@ -544,30 +547,37 @@ struct Fp(uint size) } /// - T opCast(T : Fp!newSize, size_t newSize)() nothrow const + T opCast(T : Fp!newSize, bool noSpecial = false, size_t newSize)() nothrow const if (newSize != size) { Fp!newSize ret; ret.sign = this.sign; - if (_expect(this.isSpecial, false)) - { - ret.exponent = ret.exponent.max; - ret.coefficient = !!this.coefficient; - return ret; - } - if (!this) + + static if (!noSpecial) { - return ret; + if (_expect(this.isSpecial, false)) + { + ret.exponent = ret.exponent.max; + ret.coefficient = !!this.coefficient; + return ret; + } + if (!this) + { + return ret; + } } UInt!size coefficient = this.coefficient; int shift; // subnormal - if (this.exponent == this.exponent.min) + static if (!noSpecial) { - shift = cast(int)coefficient.ctlz; - coefficient <<= shift; + if (this.exponent == this.exponent.min) + { + shift = cast(int)coefficient.ctlz; + coefficient <<= shift; + } } ret = Fp!newSize(coefficient, true); @@ -576,23 +586,31 @@ struct Fp(uint size) import mir.checkedint: adds; /// overflow - bool overflow; - ret.exponent = adds(ret.exponent, this.exponent, overflow); - if (_expect(overflow, false)) + + static if (!noSpecial) { - // overflow - if (this.exponent > 0) + bool overflow; + ret.exponent = adds(ret.exponent, this.exponent, overflow); + if (_expect(overflow, false)) { - ret.exponent = ret.exponent.max; - ret.coefficient = 0u; - } - // underflow - else - { - ret.coefficient >>= cast(uint)(ret.exponent - exponent.min); - ret.exponent = ret.coefficient ? ret.exponent.min : 0; + // overflow + if (this.exponent > 0) + { + ret.exponent = ret.exponent.max; + ret.coefficient = 0u; + } + // underflow + else + { + ret.coefficient >>= cast(uint)(ret.exponent - exponent.min); + ret.exponent = ret.coefficient ? ret.exponent.min : 0; + } } } + else + { + ret.exponent += this.exponent; + } return ret; } @@ -612,52 +630,64 @@ struct Fp(uint size) } /// -Fp!(coefficientizeA + coefficientizeB) extendedMul(uint coefficientizeA, uint coefficientizeB)(Fp!coefficientizeA a, Fp!coefficientizeB b) +Fp!(coefficientizeA + coefficientizeB) extendedMul(bool noSpecial = false, uint coefficientizeA, uint coefficientizeB)(Fp!coefficientizeA a, Fp!coefficientizeB b) @safe pure nothrow @nogc { import mir.bignum.fixed: extendedMul; import mir.checkedint: adds; typeof(return) ret = void; - // nan * any -> nan - // inf * fin -> inf ret.coefficient = extendedMul(a.coefficient, b.coefficient); - if (_expect(a.isSpecial | b.isSpecial, false)) - { // set nan - ret.exponent = ret.exponent.max; - // nan inf case - if (a.isSpecial & b.isSpecial) - ret.coefficient = a.coefficient | b.coefficient; + static if (noSpecial) + { + ret.exponent = a.exponent + b.exponent; + if (!ret.coefficient.signBit) + { + ret.exponent -= 1; // check overflow + ret.coefficient = ret.coefficient.smallLeftShift(1); + } } else { - bool overflow; - ret.exponent = adds(a.exponent, b.exponent, overflow); - // exponent underflow -> 0 or subnormal - // overflow -> inf - if (_expect(overflow, false)) + // nan * any -> nan + // inf * fin -> inf + if (_expect(a.isSpecial | b.isSpecial, false)) + { // set nan + ret.exponent = ret.exponent.max; + // nan inf case + if (a.isSpecial & b.isSpecial) + ret.coefficient = a.coefficient | b.coefficient; + } + else { - // overflow - if (a.exponent > 0) // && b.exponent > 0 is always true + bool overflow; + ret.exponent = adds(a.exponent, b.exponent, overflow); + // exponent underflow -> 0 or subnormal + // overflow -> inf + if (_expect(overflow, false)) { - ret.exponent = ret.exponent.max; - ret.coefficient = 0; + // overflow + if (a.exponent > 0) // && b.exponent > 0 is always true + { + ret.exponent = ret.exponent.max; + ret.coefficient = 0; + } + // underflow + else // a.exponent < 0 and b.exponent < 0 + { + // TODO: subnormal + ret.exponent = 0; + ret.coefficient = 0; + } } - // underflow - else // a.exponent < 0 and b.exponent < 0 + else + if (!ret.coefficient.signBit) { - // TODO: subnormal - ret.exponent = 0; - ret.coefficient = 0; + auto normal = ret.exponent != ret.exponent.min; + ret.exponent -= normal; // check overflow + ret.coefficient = ret.coefficient.smallLeftShift(normal); } } - else - if (!ret.coefficient.signBit) - { - auto normal = ret.exponent != ret.exponent.min; - ret.exponent -= normal; // check overflow - ret.coefficient = ret.coefficient.smallLeftShift(normal); - } } ret.sign = a.sign ^ b.sign; return ret; diff --git a/source/mir/bignum/integer.d b/source/mir/bignum/integer.d index 2d70bf8c..a1ac4609 100644 --- a/source/mir/bignum/integer.d +++ b/source/mir/bignum/integer.d @@ -12,11 +12,11 @@ import std.traits; /++ Stack-allocated big signed integer. Params: - maxSize64 = count of 64bit words in coefficient + size64 = count of 64bit words in coefficient +/ @serdeScoped @serdeProxy!(const(char)[]) -struct BigInt(uint maxSize64) - if (maxSize64 && maxSize64 <= ushort.max) +struct BigInt(uint size64) + if (size64 && size64 <= ushort.max) { import mir.bignum.low_level_view; import mir.bignum.fixed; @@ -26,7 +26,7 @@ struct BigInt(uint maxSize64) /// uint length; /// - size_t[ulong.sizeof / size_t.sizeof * maxSize64] data;// = void; + size_t[ulong.sizeof / size_t.sizeof * size64] data;// = void; /// this(uint size)(UInt!size fixedInt) @@ -108,11 +108,11 @@ struct BigInt(uint maxSize64) static if (__traits(compiles, () @nogc { throw new Exception("Can't parse BigInt."); })) { import mir.exception: MirException; - throw new MirException("Can't parse BigInt!" ~ maxSize64.stringof ~ " from string `", str , "`."); + throw new MirException("Can't parse BigInt!" ~ size64.stringof ~ " from string `", str , "`."); } else { - static immutable exception = new Exception("Can't parse BigInt!" ~ maxSize64.stringof ~ "."); + static immutable exception = new Exception("Can't parse BigInt!" ~ size64.stringof ~ "."); throw exception; } } @@ -158,7 +158,7 @@ struct BigInt(uint maxSize64) return this; } - static if (maxSize64 == 3) + static if (size64 == 3) /// version(mir_bignum_test) @safe pure @nogc unittest { @@ -174,7 +174,7 @@ struct BigInt(uint maxSize64) @trusted pure nothrow @nogc in (rhs.length <= this.data.length) { - static if (maxSize64 == rhsSize64) + static if (size64 == rhsSize64) { if (&this is &rhs) return this; @@ -226,7 +226,7 @@ struct BigInt(uint maxSize64) { if (rhs == 0 && this.length == 0 || this.length == 1 && this.sign == rhsSign && this.data[0] == rhs) return true; - static if (is(size_t == ulong) || maxSize64 == 1) + static if (is(size_t == ulong) || size64 == 1) return false; else return this.length == 2 && this.data[0] == cast(uint) rhs && this.data[1] == cast(uint) (rhs >> 32); @@ -433,9 +433,9 @@ struct BigInt(uint maxSize64) return this; } - BigInt!(maxSize64 * 2) bas = void; + BigInt!(size64 * 2) bas = void; bas = this; - BigInt!(maxSize64 * 2) res = void; + BigInt!(size64 * 2) res = void; res = 1u; foreach (b; exponent.coefficients.bitwise[0 .. $ - exponent.ctlz]) @@ -454,7 +454,7 @@ struct BigInt(uint maxSize64) } /// - static if (maxSize64 == 3) + static if (size64 == 3) version (mir_bignum_test) unittest { @@ -467,7 +467,7 @@ struct BigInt(uint maxSize64) } /// - static if (maxSize64 == 3) + static if (size64 == 3) version (mir_bignum_test) unittest { @@ -487,7 +487,7 @@ struct BigInt(uint maxSize64) scope ref const BigInt!bSize64 b, ) @safe pure nothrow @nogc scope return - if (maxSize64 >= aSize64 + bSize64) + if (size64 >= aSize64 + bSize64) { import mir.utility: max; import mir.bignum.internal.kernel : multiply, karatsubaRequiredBuffSize; @@ -498,12 +498,26 @@ struct BigInt(uint maxSize64) return this; } - ref divMod(uint divisorSize64, uint remainderSize = maxSize64) + /// + ref divMod(uint divisorSize64, uint remainderSize = size64) ( scope ref const BigInt!divisorSize64 divisor, + scope ref BigInt!size64 quotient, + scope ref BigInt!remainderSize remainder, + ) + const @trusted pure nothrow @nogc scope return + if (remainderSize >= divisorSize64) + { + return this.divMod(divisor, quotient, &remainder); + } + + private ref divMod(uint divisorSize64, uint remainderSize = size64) + ( + scope ref const BigInt!divisorSize64 divisor, + scope ref BigInt!size64 quotient, scope BigInt!remainderSize* remainder = null, ) - @trusted pure nothrow @nogc scope return + const @trusted pure nothrow @nogc scope return if (remainderSize >= divisorSize64) { import mir.bignum.internal.kernel : divMod, divisionRequiredBuffSize; @@ -523,28 +537,30 @@ struct BigInt(uint maxSize64) *remainder = this; remainder.sign = 0; } - if (&this !is remainder) - { - this.sign = 0; - this.length = 0; - } + + static if (size64 == remainderSize) + if ("ient is remainder) + return this; + + quotient.sign = 0; + quotient.length = 0; return this; } enum sizeM = ulong.sizeof / size_t.sizeof; - enum vlen = min(divisorSize64, maxSize64); - size_t[divisionRequiredBuffSize(maxSize64 * sizeM, vlen * sizeM)] buffer = void; + enum vlen = min(divisorSize64, size64); + size_t[divisionRequiredBuffSize(size64 * sizeM, vlen * sizeM)] buffer = void; - this.length = cast(uint) divMod( - this.coefficients, + quotient.length = cast(uint) divMod( + quotient.data, remainder !is null ? remainder.data[] : null, this.coefficients, divisor.coefficients, buffer, ); - this.sign = (this.sign ^ divisor.sign) && this.length; + quotient.sign = (this.sign ^ divisor.sign) && quotient.length; if (remainder !is null) { @@ -568,7 +584,7 @@ struct BigInt(uint maxSize64) if (op == "/" || op == "%") { enum isRem = op == "%"; - return this.divMod(rhs, isRem ? &this : null); + return this.divMod(rhs, this, isRem ? &this : null); } /++ @@ -581,14 +597,14 @@ struct BigInt(uint maxSize64) ref opOpAssign(string op : "*", size_t rhsSize64)(scope const ref BigInt!rhsSize64 rhs) @safe pure nothrow @nogc return { - BigInt!(maxSize64 + rhsSize64) c = void; + BigInt!(size64 + rhsSize64) c = void; c.multiply(this, rhs); this = c; return this; } /// - static if (maxSize64 == 3) + static if (size64 == 3) version (mir_bignum_test) unittest { @@ -726,7 +742,7 @@ struct BigInt(uint maxSize64) assert(0, binaryStringErrorMsg); } - static if (maxSize64 == 3) + static if (size64 == 3) /// version(mir_bignum_test) @safe pure @nogc unittest { @@ -751,7 +767,24 @@ struct BigInt(uint maxSize64) } /// - bool mulPow5(size_t degree) + ref pow()(ulong degree) + { + BigInt!size64 bas = void; + bas = this; + this = 1u; + + while (degree) + { + if (degree & 1) + this *= bas; + bas *= bas; + degree >>= 1; + } + return this; + } + + /// + bool mulPow5()(ulong degree) { import mir.bignum.internal.dec2float: MaxWordPow5; // assert(approxCanMulPow5(degree)); @@ -760,7 +793,8 @@ struct BigInt(uint maxSize64) enum n = MaxWordPow5!size_t; enum wordInit = size_t(5) ^^ n; size_t word = wordInit; - bool of; + size_t overflow; + while(degree) { if (degree >= n) @@ -773,14 +807,9 @@ struct BigInt(uint maxSize64) do word *= 5; while(--degree); } - if (auto overflow = view *= word) - { - of = length >= data.length; - if (!of) - putCoefficient(overflow); - } + overflow |= this *= word; } - return of; + return overflow != 0; } /// @@ -925,7 +954,7 @@ struct BigInt(uint maxSize64) return buffer[$ - len .. $].idup; } - static if (maxSize64 == 3) + static if (size64 == 3) /// version(mir_bignum_test) @safe pure unittest { @@ -949,17 +978,28 @@ struct BigInt(uint maxSize64) w.put(buffer[$ - len .. $]); } - static if (maxSize64 == 3) - /// Check @nogc toString impl - version(mir_bignum_test) @safe pure @nogc unittest + /// + size_t bitLength()() const @property { - import mir.format; - auto str = "-34010447314490204552169750449563978034784726557588085989975288830070948234680"; - auto integer = BigInt!4(str); - auto buffer = stringBuf; - buffer << integer; - assert(buffer.data == str); + return length == 0 ? 0 : length * size_t.sizeof * 8 - data[length - 1].ctlz; } + + /// + size_t ctlz()() const @property + { + return data.sizeof * 8 - bitLength; + } +} + +/// Check @nogc toString impl +version(mir_bignum_test) @safe pure @nogc unittest +{ + import mir.format; + auto str = "-34010447314490204552169750449563978034784726557588085989975288830070948234680"; + auto integer = BigInt!4(str); + auto buffer = stringBuf; + buffer << integer; + assert(buffer.data == str); } /// @@ -974,9 +1014,11 @@ unittest auto b = UInt!128.fromHexString("f79a222050aaeaaa417fa25a2ac93291"); // ca3d7e25aebe687b 168dcef32d0bb2f0 - assert((a /= b) == BigInt!4.fromHexString("ca3d7e25aebe687b7cc1b250b44690fb")); - a = BigInt!4.fromHexString("c39b18a9f06fd8e962d99935cea0707f79a222050aaeaaaed17feb7aa76999d7"); + import mir.format; assert((a %= b) == BigInt!4.fromHexString("bf4c87424431d21563f23b1fc00d75ac")); + a = BigInt!4.fromHexString("c39b18a9f06fd8e962d99935cea0707f79a222050aaeaaaed17feb7aa76999d7"); + a /= b; + assert(a == BigInt!4.fromHexString("ca3d7e25aebe687b7cc1b250b44690fb"), a.data.text); } { diff --git a/source/mir/bignum/internal/dec2float.d b/source/mir/bignum/internal/dec2float.d index 02c7460d..02449299 100644 --- a/source/mir/bignum/internal/dec2float.d +++ b/source/mir/bignum/internal/dec2float.d @@ -1,6 +1,6 @@ module mir.bignum.internal.dec2float; -version(LDC) import ldc.attributes: optStrategy; +version (LDC) import ldc.attributes: optStrategy; else struct optStrategy { string opt; } template MaxWordPow5(T) @@ -43,316 +43,340 @@ alias decimalTo(T : float) = decimalToFloat32; alias decimalTo(T : double) = decimalToFloat64; alias decimalTo(T : real) = decimalToReal; -private float decimalToFloat32(scope const size_t[] coefficients, long exponent) +alias binaryTo(T : float) = binaryToFloat32; +alias binaryTo(T : double) = binaryToFloat64; +alias binaryTo(T : real) = binaryToReal; + +private float binaryToFloat32(scope const size_t[] coefficients, long exponent = 0) { pragma(inline, false); - return decimalToFloatImpl!float(coefficients, exponent); + return binaryToFloatImpl!float(coefficients, exponent); } -private double decimalToFloat64(scope const size_t[] coefficients, long exponent) +private double binaryToFloat64(scope const size_t[] coefficients, long exponent = 0) { pragma(inline, false); - return decimalToFloatImpl!double(coefficients, exponent); + return binaryToFloatImpl!double(coefficients, exponent); } -private real decimalToReal(scope const size_t[] coefficients, long exponent) +private real binaryToReal(scope const size_t[] coefficients, long exponent = 0) { pragma(inline, real.mant_dig == double.mant_dig); static if (real.mant_dig == double.mant_dig) - return decimalToFloat64(coefficients, exponent); + return binaryToFloat64(coefficients, exponent); else - return decimalToFloatImpl!real(coefficients, exponent); + return binaryToFloatImpl!real(coefficients, exponent); } -private float decimalToFloat32(scope const size_t[] coefficients) +private float decimalToFloat32(scope const ulong coefficient, long exponent) { pragma(inline, false); - return decimalToFloatImpl!float(coefficients); + return decimalToFloatImpl!float(coefficient, exponent); } -private double decimalToFloat64(scope const size_t[] coefficients) +private double decimalToFloat64(scope const ulong coefficient, long exponent) { pragma(inline, false); - return decimalToFloatImpl!double(coefficients); + return decimalToFloatImpl!double(coefficient, exponent); } -private real decimalToReal(scope const size_t[] coefficients) +private real decimalToReal(scope const ulong coefficient, long exponent) { pragma(inline, real.mant_dig == double.mant_dig); static if (real.mant_dig == double.mant_dig) - return decimalToFloat64(coefficients); + return decimalToFloat64(coefficient, exponent); else - return decimalToFloatImpl!real(coefficients); + return decimalToFloatImpl!real(coefficient, exponent); } -T decimalToFloat(T)(ulong coefficient, long exponent) - if (is(T == real)) +private float decimalToFloat32(scope const size_t[] coefficients, long exponent) { - version(LDC) - pragma(inline, true); - static if (T.mant_dig < 64) - { - return decimalToFloat!double(coefficient, exponent); - } + pragma(inline, false); + return decimalToFloatImpl!float(coefficients, exponent); +} + +private double decimalToFloat64(scope const size_t[] coefficients, long exponent) +{ + pragma(inline, false); + return decimalToFloatImpl!double(coefficients, exponent); +} + +private real decimalToReal(scope const size_t[] coefficients, long exponent) +{ + pragma(inline, real.mant_dig == double.mant_dig); + static if (real.mant_dig == double.mant_dig) + return decimalToFloat64(coefficients, exponent); else - { - auto coefficients = cast(size_t[ulong.sizeof / size_t.sizeof]) cast(ulong[1])[coefficient]; - static if (coefficients.length == 1) - return decimalTo!real(approx, coefficients[0 .. !!coefficient], exponent); - else - return decimalTo!real(approx, coefficients[0 .. !!coefficient + (coefficient > uint.max)], exponent); - } + return decimalToFloatImpl!real(coefficients, exponent); } -T decimalToFloat(T)(ulong coefficient, long exponent) - if (is(T == float) || is(T == double)) +T decimalToFloatImpl(T)(ulong coefficient, long exponent) + if (is(T == float) || is(T == double) || is(T == real)) { + version (LDC) + pragma(inline, true); + import mir.bignum.fixed: UInt; import mir.bignum.fp: Fp, extendedMul; import mir.utility: _expect; - version(LDC) - pragma(inline, true); - - enum ulong mask = (1UL << (64 - T.mant_dig)) - 1; - enum ulong half = (1UL << (64 - T.mant_dig - 1)); - enum ulong bound = ulong(1) << T.mant_dig; + enum wordBits = T.mant_dig < 64 ? 64 : 128; + enum ulong half = (1UL << (wordBits - T.mant_dig - 1)); + static if (T.mant_dig > 64) + enum ulong mask = (1UL << (128 - T.mant_dig)) - 1; + else + static if (T.mant_dig == 64) + enum ulong mask = ulong.max; + else + enum ulong mask = (1UL << (64 - T.mant_dig)) - 1; + + if (coefficient == 0) + return 0; - auto expSign = exponent < 0; - if (_expect((expSign ? -exponent : exponent) >>> dec_S == 0, true)) + version (TeslAlgoM) {} else + if (_expect(-ExponentM <= exponent && exponent <= ExponentM, true)) { - auto c = Fp!64(UInt!64(coefficient)); - auto z = c.extendedMul(load64(exponent)); - auto approx = cast(T) z; - long bitsDiff = (cast(ulong) z.opCast!(Fp!64).coefficient & mask) - half; - if (_expect((bitsDiff < 0 ? -bitsDiff : bitsDiff) > 3 * expSign, true)) - return approx; - assert(coefficient); - if (!expSign && exponent <= MaxWordPow5!ulong || exponent == 0) + auto c = coefficient.Fp!64; + auto z = c.extendedMul!true(_load!T(exponent)); + auto approx = z.opCast!(T, true); + long bitsDiff = (cast(ulong) z.opCast!(Fp!wordBits).coefficient & mask) - half; + int slop = 3 * (exponent < 0); + if (_expect(approx > T.min_normal && (bitsDiff < 0 ? -bitsDiff : bitsDiff) > slop, true)) return approx; - if (expSign && MaxFpPow5!T >= -exponent && cast(ulong)c.coefficient < bound) + + if (0 <= exponent) { - auto e = load64(-exponent); - return c.opCast!(T, true) / cast(T) (cast(ulong)e.coefficient >> e.exponent); + if (exponent <= MaxWordPow5!ulong) + return approx; } - auto coefficients = cast(size_t[ulong.sizeof / size_t.sizeof]) cast(ulong[1])[coefficient]; - static if (coefficients.length == 1) - return decimalToFloatFallback(approx, coefficients, cast(int) exponent); else - return decimalToFloatFallback(approx, coefficients[0 .. 1 + (coefficient > uint.max)], cast(int) exponent); + { + if (-exponent <= MaxFpPow5!T) + { + auto e = _load!T(-exponent); + return coefficient / e.opCast!(T, true); + } + } } - return expSign ? 0 : exponent != exponent.max ? T.infinity : coefficient ? T.nan : T.infinity; + size_t[ulong.sizeof / size_t.sizeof] coefficients; + coefficients[0] = cast(size_t) coefficient; + static if (coefficients.length == 2) + coefficients[1] = cast(size_t) (coefficient >> 32); + static if (coefficients.length == 1) + return algorithmM!T(coefficients, exponent); + else + return algorithmM!T(coefficients[0 .. 1 + (coefficient > uint.max)], exponent); } -private T decimalToFloatImpl(T)(scope const size_t[] coefficients) +private T decimalToFloatImpl(T)(scope const size_t[] coefficients, long exponent) @safe if ((is(T == float) || is(T == double) || is(T == real))) in (coefficients.length == 0 || coefficients[$ - 1]) { - version(LDC) + version (LDC) pragma(inline, true); - enum md = T.mant_dig; - enum b = size_t.sizeof * 8; - enum n = md / b + (md % b != 0); - enum s = n * b; + import mir.bignum.fixed: UInt; + import mir.bignum.fp: Fp, extendedMul; + import mir.utility: _expect; + + enum wordBits = T.mant_dig < 64 ? 64 : 128; + enum ulong half = (1UL << (wordBits - T.mant_dig - 1)); + static if (T.mant_dig > 64) + enum ulong mask = (1UL << (128 - T.mant_dig)) - 1; + else + static if (T.mant_dig == 64) + enum ulong mask = ulong.max; + else + enum ulong mask = (1UL << (64 - T.mant_dig)) - 1; - return coefficients.length ? coefficients.decimalToFp!(s, s - md).opCast!(T, true) : 0; + if (coefficients.length < 1) + return 0; + + if (coefficients.length == 1) + return decimalTo!T(coefficients[0], exponent); + + static if (size_t.sizeof == uint.sizeof) + { + if (coefficients.length == 2) + return decimalTo!T(coefficients[0] | (ulong(coefficients[1]) << 32), exponent); + } + + version (TeslAlgoM) {} else + if (_expect(-ExponentM <= exponent && exponent <= ExponentM, true)) + { + auto c = coefficients.binaryToFp!wordBits; + auto z = c.extendedMul!true(_load!T(exponent)); + auto approx = z.opCast!(T, true); + auto slop = 1 + 3 * (exponent < 0); + long bitsDiff = (cast(ulong) z.opCast!(Fp!wordBits).coefficient & mask) - half; + + if (_expect(approx > T.min_normal && (bitsDiff < 0 ? -bitsDiff : bitsDiff) > slop, true)) + return approx; + } + return algorithmM!T(coefficients, exponent); } -private T decimalToFloatImpl(T)(scope const size_t[] coefficients, long exponent) - @safe +private enum LOG2_10 = 0x3.5269e12f346e2bf924afdbfd36bf6p0; + +private template bigSize(T) if ((is(T == float) || is(T == double) || is(T == real))) - in (coefficients.length == 0 || coefficients[$ - 1]) { - import mir.bignum.fixed: UInt; - import mir.bignum.fp: Fp, extendedMul; - import mir.math.common: floor; - import mir.utility: _expect; - static if (T.mant_dig < 64) { - enum ulong mask = (1UL << (64 - T.mant_dig)) - 1; - enum ulong half = (1UL << (64 - T.mant_dig - 1)); - enum ulong bound = ulong(1) << T.mant_dig; - - if (coefficients.length == 1) - return decimalToFloat!T(coefficients[0], exponent); - if (coefficients.length < 1) - return exponent == exponent.max ? T.infinity : 0; - auto expSign = exponent < 0; - if (_expect((expSign ? -exponent : exponent) >>> dec_S == 0, true)) - { - auto c = coefficients.decimalToFp!64; - auto z = c.extendedMul(load64(exponent)); - auto approx = cast(T) z; - auto slop = (coefficients.length > (ulong.sizeof / size_t.sizeof)) + 3 * expSign; - long bitsDiff = (cast(ulong) z.opCast!(Fp!64).coefficient & mask) - half; - if (_expect((bitsDiff < 0 ? -bitsDiff : bitsDiff) > slop, true)) - return approx; - if (slop == 0 && exponent <= MaxWordPow5!ulong || exponent == 0) - return approx; - if (slop == 3 && MaxFpPow5!T >= -exponent && cast(ulong)c.coefficient < bound) - { - auto e = load64(-exponent); - approx = c.opCast!(T, true) / cast(T) (cast(ulong)e.coefficient >> e.exponent); - return approx; - } - return decimalToFloatFallback(approx, coefficients, cast(int) exponent); - } - return expSign ? 0 : exponent != exponent.max ? T.infinity : T.nan; + enum size_t bigSize = 83; } else { - if (exponent == 0) - return decimalTo!T(coefficients); - - if (coefficients.length == 0) - return exponent == exponent.max ? T.infinity : 0; - - auto expSign = exponent < 0; - ulong exp = exponent; - exp = expSign ? -exp : exp; - if (exp >= 5000) - { - return expSign ? 0 : exponent != exponent.max ? T.infinity : T.nan; - } - long index = exp & 0x1FF; - bool gotoAlgoR; - auto c = load128(expSign ? -index : index); - { - exp >>= dec_S; - gotoAlgoR = exp != 0; - if (_expect(gotoAlgoR, false)) - { - auto v = load128(expSign ? -dec_P : dec_P); - do - { - if (exp & 1) - c *= v; - exp >>>= 1; - if (exp == 0) - break; - v *= v; - } - while(true); - } - } - auto z = coefficients.decimalToFp!128.extendedMul(c); - auto ret = cast(T) z; - if (!gotoAlgoR) - { - static if (T.mant_dig > 64) - enum ulong mask = (1UL << (128 - T.mant_dig)) - 1; - else - enum ulong mask = ulong.max; - enum ulong half = (1UL << (128 - T.mant_dig - 1)); - enum UInt!128 bound = UInt!128(1) << T.mant_dig; - - auto slop = (coefficients.length > (ulong.sizeof * 2 / size_t.sizeof)) + 3 * expSign; - long bitsDiff = (cast(ulong) z.opCast!(Fp!128).coefficient & mask) - half; - if (_expect((bitsDiff < 0 ? -bitsDiff : bitsDiff) > slop, true)) - return ret; - if (slop == 0 && exponent <= 55 || exponent == 0) - return ret; - if (slop == 3 && MaxFpPow5!T >= -exponent && c.coefficient < bound) - { - auto e = load128(-exponent); - return c.opCast!(T, true) / cast(T) e; - } - } - return decimalToFloatFallback(ret, coefficients, cast(int) exponent); + enum size_t bits = T.max_exp - T.min_exp + T.mant_dig; + enum size_t bigSize = bits / 64 + bits % 64 + 1; + pragma(msg, "bigSize = ", bigSize); } } @optStrategy("minsize") -private T decimalToFloatFallback(T)(T ret, scope const size_t[] coeff, int exponent) +private T algorithmM(T)(scope const size_t[] coefficients, long exponent) if ((is(T == float) || is(T == double) || is(T == real))) - in (0 <= ret && ret <= T.infinity) + in (coefficients.length) { pragma(inline, false); - import mir.bignum.fixed: UInt; + + import mir.bitop: ctlz; + import mir.bignum.fp: Fp; import mir.bignum.integer: BigInt; - import mir.math.common: floor; - import mir.math.ieee: ldexp, frexp, nextDown, nextUp; - import mir.utility: _expect; + import mir.math.common: log2, ceil; + import mir.math.ieee: ldexp, nextUp; - BigInt!256 x = void, y = void; // max value is 2^(2^14)-1 + BigInt!(bigSize!T) u = void; + BigInt!(bigSize!T) v = void; + BigInt!(bigSize!T) q = void; + BigInt!(bigSize!T) r = void; - if (exponent == 0) - return decimalTo!T(coeff); + if (coefficients.length == 0) + return 0; // if no overflow - if (exponent > 0 && !x.copyFrom(coeff) && !x.mulPow5(exponent)) - return x.coefficients.decimalTo!T.ldexp(exponent); + if (exponent >= 0) + { + if (3 * exponent + coefficients.length * size_t.sizeof * 8 - ctlz(coefficients[$ - 1]) - 1 > T.max_exp) + return T.infinity; + if (exponent == 0) + return coefficients.binaryTo!T; + u.copyFrom(coefficients); + u.mulPow5(exponent); + return u.coefficients.binaryTo!T(exponent); + } + + auto log2_u = coefficients.binaryTo!T.log2; + auto log2_v = cast(T)(-LOG2_10) * exponent; + sizediff_t k = cast(sizediff_t) ceil(log2_u - log2_v); - do + k -= T.mant_dig; + + if (k < T.min_exp - T.mant_dig) { - if (ret < ret.min_normal) + if (k + T.mant_dig + 1 < T.min_exp - T.mant_dig) + return 0; + k = T.min_exp - T.mant_dig; + } + else + if (k > T.max_exp) + { + if (k - 2 > T.max_exp) + return T.infinity; + k = T.max_exp; + } + + if(u.copyFrom(coefficients)) + return T.nan; + if (k < 0) + { + if (u.ctlz < -k) + return T.nan; + u <<= -k; + } + + if (log2_v >= bigSize!T * 64) + return T.nan; + + v = 1; + v.mulPow5(-exponent); + v <<= cast(int)-exponent + (k > 0 ? k : 0); + + sizediff_t s; + for(;;) + { + u.divMod(v, q, r); + + s = cast(int) q.bitLength - T.mant_dig; + assert(k >= T.min_exp - T.mant_dig); + if (s == 0) break; - int k; - auto m0 = frexp(ret, k); - k -= T.mant_dig; - static if (T.mant_dig <= 64) + + if (s < 0) { - enum p2 = T(2) ^^ T.mant_dig; - auto m = UInt!64(cast(ulong) (m0 * p2)); + if (k == T.min_exp - T.mant_dig) + break; + k--; } else { - enum p2h = T(2) ^^ (T.mant_dig - 64); - enum p2l = T(2) ^^ 64; - m0 *= p2h; - auto mhf = floor(m0); - auto mh = cast(ulong) mhf; - m0 -= mhf; - m0 *= p2l; - auto ml = cast(ulong) m0; - auto m = UInt!128(mh); - m <<= 64; - m |= UInt!128(ml); - } - auto mtz = m.cttz; - if (mtz != m.sizeof * 8) - { - m >>= mtz; - k += mtz; + if (k == T.max_exp) + return T.infinity; + k++; } - if (x.copyFrom(coeff)) // if overflow - break; - y = m; - y.mulPow5(-exponent); - auto shift = k - exponent; - (shift >= 0 ? y : x) <<= shift >= 0 ? shift : -shift; - x -= y; - if (x.length == 0) - break; - x <<= 1; - x *= m; - auto cond = mtz == T.mant_dig - 1 && x.sign; - auto cmp = x.view.unsigned.opCmp(y.view.unsigned); - if (cmp < 0) - { - if (!cond) - break; - x <<= 1; - if (x.view.unsigned <= y.view.unsigned) - break; - } - else - if (!cmp && !cond && !mtz) - break; - ret = x.sign ? nextDown(ret) : nextUp(ret); - if (ret == 0) - break; + if ((s < 0 ? u : v).ctlz == 0) + return T.nan; + (s < 0 ? u : v) <<= 1; } - while (T.mant_dig >= 64 && exponent < -512); - return ret; + + sizediff_t cmp; + if (s <= 0) + { + u = v; + u -= r; + cmp = r.opCmp(u); + } + else + { + cmp = s - 1 - q.view.unsigned.cttz; + if (cmp == 0) // half + cmp += r != 0; + q >>= s; + k += s; + } + auto z = q.coefficients.binaryTo!T.ldexp(cast(int)k); + return cmp < 0 || cmp == 0 && !q.view.unsigned.bt(0) ? z : nextUp(z); } -auto decimalToFp(uint coefficientSize, uint internalRoundLastBits = 0) +private T binaryToFloatImpl(T)(scope const size_t[] coefficients, long exponent) + @safe + if ((is(T == float) || is(T == double) || is(T == real))) + in (coefficients.length == 0 || coefficients[$ - 1]) +{ + version (LDC) + pragma(inline, true); + + enum md = T.mant_dig; + enum b = size_t.sizeof * 8; + enum n = md / b + (md % b != 0); + enum s = n * b; + + if (coefficients.length == 0) + return 0; + + if (exponent > T.max_exp) + return T.infinity; + + auto fp = coefficients.binaryToFp!(s, s - md); + fp.exponent += exponent; + return fp.opCast!(T, true, true); +} + + +package(mir.bignum) auto binaryToFp(uint coefficientSize, uint internalRoundLastBits = 0) (scope const(size_t)[] coefficients) if (internalRoundLastBits < size_t.sizeof * 8) in (coefficients.length) @@ -364,11 +388,10 @@ auto decimalToFp(uint coefficientSize, uint internalRoundLastBits = 0) import mir.utility: _expect; version (LDC) - pragma(inline, internalRoundLastBits != 0); + pragma(inline, true); Fp!coefficientSize ret; - assert(coefficients.length); enum N = ret.coefficient.data.length; sizediff_t size = coefficients.length * (size_t.sizeof * 8); sizediff_t expShift = size - coefficientSize; @@ -416,7 +439,7 @@ auto decimalToFp(uint coefficientSize, uint internalRoundLastBits = 0) coefficients = coefficients[1 .. $]; assert(coefficients.length); } - return coefficients.length > (N + 1); + return coefficients.length > N + 1; } static if (internalRoundLastBits) @@ -454,40 +477,57 @@ auto decimalToFp(uint coefficientSize, uint internalRoundLastBits = 0) return ret; } -private enum dec_S = 9; -private enum dec_P = 1 << dec_S; +private enum ExponentM = 512; -private auto load64()(long e) +private auto _load(T)(long e) @trusted + if (T.mant_dig < 64) + in (-ExponentM < e && e < ExponentM) { - version(LDC) + version (LDC) pragma(inline, true); import mir.bignum.fixed: UInt; import mir.bignum.fp: Fp; import mir.bignum.internal.dec2float_table; - auto p10coeff = p10_coefficients[cast(sizediff_t)e - min_p10_e][0]; - auto p10exp = p10_exponents[cast(sizediff_t)e - min_p10_e]; + auto idx = cast(sizediff_t)e - min_p10_e; + auto p10coeff = p10_coefficients_h[idx]; + auto p10exp = p10_exponents[idx]; return Fp!64(false, p10exp, UInt!64(p10coeff)); } -private auto load128()(long e) +private auto _load(T)(long e) @trusted + if (T.mant_dig >= 64) + in (-ExponentM < e && e < ExponentM) { - version(LDC) + version (LDC) pragma(inline, true); import mir.bignum.fixed: UInt; import mir.bignum.fp: Fp; import mir.bignum.internal.dec2float_table; - static assert(min_p10_e <= -dec_P); - static assert(max_p10_e >= dec_P); + static assert(min_p10_e <= -ExponentM); + static assert(max_p10_e >= ExponentM); auto idx = cast(sizediff_t)e - min_p10_e; - ulong h = p10_coefficients[idx][0]; - ulong l = p10_coefficients[idx][1]; + ulong h = p10_coefficients_h[idx]; + ulong l = p10_coefficients_l[idx]; if (l >= cast(ulong)long.min) h--; auto p10coeff = UInt!128(cast(ulong[2])[l, h]); auto p10exp = p10_exponents[idx] - 64; return Fp!128(false, p10exp, p10coeff); } + +unittest +{ + import mir.bignum.fp; + import mir.bignum.fixed; + import mir.test; + ulong[2] data = [ulong.max - 2, 1]; + auto coefficients = cast(size_t[])data[]; + if (coefficients[$ - 1] == 0) + coefficients = coefficients[0 .. $ - 1]; + coefficients.binaryToFp!64.should == Fp!64(false, 1, UInt!64(0xFFFFFFFFFFFFFFFE)); + coefficients.binaryToFp!128.should == Fp!128(false, -63, UInt!128([0x8000000000000000, 0xFFFFFFFFFFFFFFFE])); +} diff --git a/source/mir/bignum/internal/dec2float_table.d b/source/mir/bignum/internal/dec2float_table.d index 73691085..96200a23 100644 --- a/source/mir/bignum/internal/dec2float_table.d +++ b/source/mir/bignum/internal/dec2float_table.d @@ -7,1036 +7,6 @@ module mir.bignum.internal.dec2float_table; enum min_p10_e = -512; enum max_p10_e = 512; -// -static immutable align(16) ulong[2][1025] p10_coefficients = [ - [0x9049EE32DB23D21C, 0x7132D332E3F204D5], - [0xB45C69BF91ECC6A4, 0x8D7F87FF9CEE860A], - [0xE173842F7667F84C, 0x70DF69FF842A278D], - [0x8CE8329DAA00FB30, 0xC68BA23FB29A58B8], - [0xB0223F45148139FC, 0xB82E8ACF9F40EEE6], - [0xDC2ACF1659A1887B, 0xA63A2D8387112A9F], - [0x899AC16DF804F54D, 0xA7E45C72346ABAA4], - [0xAC0171C9760632A0, 0xD1DD738EC185694D], - [0xD701CE3BD387BF48, 0xC654D07271E6C3A0], - [0x866120E56434D78D, 0xDBF5024787303A44], - [0xA7F9691EBD420D70, 0x12F242D968FC48D5], - [0xD1F7C3666C9290CC, 0x17AED38FC33B5B0A], - [0x833ADA2003DB9A80, 0x8ECD4439DA0518E6], - [0xA40990A804D2811F, 0x7280954850865F20], - [0xCD0BF4D206072167, 0x4F20BA9A64A7F6E8], - [0x8027790343C474E1, 0x917474A07EE8FA51], - [0xA031574414B59219, 0xB5D191C89EA338E5], - [0xC83DAD1519E2F69F, 0xE345F63AC64C071E], - [0xFA4D185A605BB447, 0x9C1773C977DF08E6], - [0x9C702F387C3950AC, 0x218EA85DEAEB6590], - [0xC38C3B069B47A4D7, 0x29F2527565A63EF4], - [0xF46F49C842198E0D, 0xF46EE712BF0FCEB0], - [0x98C58E1D294FF8C8, 0x18C5506BB769E12E], - [0xBEF6F1A473A3F6FA, 0x1EF6A486A544597A], - [0xEEB4AE0D908CF4B9, 0xA6B44DA84E956FD8], - [0x9530ECC87A5818F3, 0x6830B089311D65E7], - [0xBA7D27FA98EE1F30, 0x423CDCAB7D64BF61], - [0xE91C71F93F29A6FC, 0x52CC13D65CBDEF39], - [0x91B1C73BC77A085E, 0xB3BF8C65F9F6B584], - [0xB61E390AB9588A75, 0x20AF6F7F787462E5], - [0xE3A5C74D67AEAD12, 0x68DB4B5F56917B9E], - [0x8E479C9060CD2C2C, 0x81890F1B961AED43], - [0xB1D983B479007736, 0x61EB52E27BA1A893], - [0xDE4FE4A197409504, 0xFA66279B1A8A12B8], - [0x8AF1EEE4FE885D22, 0x7C7FD8C0F0964BB3], - [0xADAE6A9E3E2A746B, 0x1B9FCEF12CBBDEA0], - [0xD91A0545CDB51186, 0xE287C2AD77EAD648], - [0x87B0434BA0912AF4, 0xAD94D9AC6AF2C5ED], - [0xA99C541E88B575B1, 0x98FA101785AF7768], - [0xD40369262AE2D31D, 0xBF38941D671B5542], - [0x848221B7DACDC3F2, 0xF7835C9260711549], - [0xA5A2AA25D18134EE, 0x756433B6F88D5A9C], - [0xCF0B54AF45E1822A, 0x12BD40A4B6B0B143], - [0x816714ED8BACF15A, 0x4BB64866F22E6ECA], - [0xA1C0DA28EE982DB1, 0xDEA3DA80AEBA0A7C], - [0xCA3110B32A3E391D, 0x164CD120DA688D1B], - [0xFCBD54DFF4CDC764, 0x5BE005691102B062], - [0x9DF6550BF9009C9F, 0xB96C0361AAA1AE3D], - [0xC573EA4EF740C3C6, 0x67C7043A154A19CC], - [0xF6D0E4E2B510F4B8, 0x01B8C5489A9CA040], - [0x9A428F0DB12A98F3, 0x01137B4D60A1E428], - [0xC0D332D11D753F30, 0xC1585A20B8CA5D32], - [0xF107FF8564D28EFC, 0xB1AE70A8E6FCF47E], - [0x96A4FFB35F03995D, 0x4F0D0669905E18CF], - [0xBC4E3FA036C47FB5, 0xA2D04803F4759F02], - [0xEB61CF8844759FA2, 0xCB845A04F19306C3], - [0x931D21B52AC983C5, 0x1F32B84316FBE43A], - [0xB7E46A22757BE4B6, 0x66FF6653DCBADD48], - [0xE5DD84AB12DADDE4, 0x00BF3FE8D3E9949A], - [0x8FAA72EAEBC8CAAF, 0x807787F18471FCE1], - [0xB3950FA5A6BAFD5A, 0x209569EDE58E7C19], - [0xE07A538F1069BCB1, 0xA8BAC4695EF21B1F], - [0x8C4C74396A4215EE, 0x6974BAC1DB5750F3], - [0xAF5F9147C4D29B6A, 0x03D1E972522D2530], - [0xDB377599B6074245, 0x84C663CEE6B86E7C], - [0x8902A98011C4896B, 0xD2FBFE615033450E], - [0xAB4353E01635ABC6, 0x87BAFDF9A4401651], - [0xD61428D81BC316B7, 0xE9A9BD780D501BE5], - [0x85CC99871159EE32, 0x520A166B0852116F], - [0xA73FBFE8D5B069BF, 0xE68C9C05CA6695CB], - [0xD10FAFE30B1C842F, 0xA02FC3073D003B3E], - [0x82A9CDEDE6F1D29D, 0x241DD9E486202507], - [0xA354416960AE4744, 0x6D25505DA7A82E48], - [0xCC2951C3B8D9D916, 0x886EA475119239DA], - [0xFF33A634A7104F5B, 0xEA8A4D9255F6C851], - [0x9F8047E0E86A3199, 0xD296707B75BA3D33], - [0xC76059D92284BDFF, 0x073C0C9A5328CC7F], - [0xF938704F6B25ED7F, 0xC90B0FC0E7F2FF9F], - [0x9BC34631A2F7B46F, 0x3DA6E9D890F7DFC3], - [0xC2B417BE0BB5A18B, 0x0D10A44EB535D7B4], - [0xF3611DAD8EA309EE, 0xD054CD6262834DA1], - [0x981CB28C7925E635, 0xA235005D7D921085], - [0xBE23DF2F976F5FC2, 0xCAC24074DCF694A6], - [0xEDACD6FB7D4B37B2, 0x3D72D092143439D0], - [0x948C065D2E4F02CF, 0x6667C25B4CA0A422], - [0xB9AF07F479E2C383, 0x4001B2F21FC8CD2A], - [0xE81AC9F1985B7464, 0x10021FAEA7BB0075], - [0x9110BE36FF3928BF, 0x8A0153CD28D4E049], - [0xB554EDC4BF0772EE, 0x2C81A8C0730A185B], - [0xE2AA2935EEC94FAA, 0xB7A212F08FCC9E72], - [0x8DAA59C1B53DD1CA, 0x12C54BD659DFE307], - [0xB114F032228D463D, 0x97769ECBF057DBC9], - [0xDD5A2C3EAB3097CC, 0xBD54467EEC6DD2BB], - [0x8A585BA72AFE5EDF, 0x5654AC0F53C4A3B5], - [0xACEE7290F5BDF697, 0x2BE9D71328B5CCA2], - [0xD82A0F35332D743D, 0xF6E44CD7F2E33FCB], - [0x871A49813FFC68A6, 0x1A4EB006F7CE07DF], - [0xA8E0DBE18FFB82D0, 0xA0E25C08B5C189D7], - [0xD31912D9F3FA6384, 0x891AF30AE331EC4C], - [0x83EFABC8387C7E32, 0x35B0D7E6CDFF33B0], - [0xA4EB96BA469B9DBF, 0xC31D0DE0817F009C], - [0xCE267C68D842852E, 0x73E45158A1DEC0C2], - [0x80D80DC18729933D, 0x086EB2D7652B387A], - [0xA10E1131E8F3F80C, 0x4A8A5F8D3E760698], - [0xC951957E6330F60F, 0x5D2CF7708E13883E], - [0xFBA5FADDFBFD3393, 0x3478354CB1986A4D], - [0x9D47BCCABD7E403C, 0x00CB214FEEFF4270], - [0xC499ABFD6CDDD04B, 0x00FDE9A3EABF130C], - [0xF5C016FCC815445E, 0xC13D640CE56ED7D0], - [0x99980E5DFD0D4ABB, 0x98C65E880F6546E2], - [0xBFFE11F57C509D69, 0x3EF7F62A133E989A], - [0xEFFD9672DB64C4C4, 0x8EB5F3B4980E3EC1], - [0x95FE7E07C91EFAFA, 0x3931B850DF08E738], - [0xBB7E1D89BB66B9B9, 0xC77E266516CB2106], - [0xEA5DA4EC2A406827, 0xF95DAFFE5C7DE948], - [0x927A87139A684118, 0x5BDA8DFEF9CEB1CD], - [0xB71928D88102515E, 0x72D1317EB8425E40], - [0xE4DF730EA142E5B6, 0x0F857DDE6652F5D0], - [0x8F0BA7E924C9CF92, 0xC9B36EAAFFF3D9A2], - [0xB2CE91E36DFC4376, 0x3C204A55BFF0D00B], - [0xDF82365C497B5454, 0xCB285CEB2FED040E], - [0x8BB161F9ADED14B4, 0x5EF93A12FDF42288], - [0xAE9DBA78196859E1, 0x76B78897BD712B2B], - [0xDA4529161FC2705A, 0xD4656ABDACCD75F5], - [0x886B39ADD3D98638, 0x24BF62B68C0069B9], - [0xAA86081948CFE7C6, 0x2DEF3B642F008428], - [0xD5278A1F9B03E1B8, 0xB96B0A3D3AC0A531], - [0x8538B653C0E26D13, 0xD3E2E66644B8673F], - [0xA686E3E8B11B0858, 0x88DB9FFFD5E6810F], - [0xD0289CE2DD61CA6D, 0x6B1287FFCB602152], - [0x8219620DCA5D1E84, 0x62EB94FFDF1C14D3], - [0xA29FBA913CF46625, 0x7BA67A3FD6E31A08], - [0xCB47A9358C317FAF, 0xDA9018CFCC9BE08A], - [0xFE199382EF3DDF9B, 0x91341F03BFC2D8AD], - [0x9ECFFC31D586ABC1, 0x9AC0936257D9C76C], - [0xC683FB3E4AE856B1, 0xC170B83AEDD03947], - [0xF824FA0DDDA26C5D, 0xF1CCE649A9444799], - [0x9B171C48AA8583BA, 0x17200FEE09CAACC0], - [0xC1DCE35AD526E4A9, 0x9CE813E98C3D57EF], - [0xF2541C318A709DD3, 0xC42218E3EF4CADEB], - [0x9774919EF68662A4, 0xBA954F8E758FECB3], - [0xBD51B606B427FB4D, 0xA93AA37212F3E7E0], - [0xECA623886131FA20, 0xD3894C4E97B0E1D8], - [0x93E7D6353CBF3C54, 0xE435CFB11ECE8D27], - [0xB8E1CBC28BEF0B69, 0xDD43439D66823071], - [0xE71A3EB32EEACE43, 0x14941484C022BC8D], - [0x9070672FFD52C0EA, 0xECDC8CD2F815B5D8], - [0xB48C80FBFCA77124, 0x6813B007B61B234E], - [0xE1AFA13AFBD14D6E, 0x82189C09A3A1EC21], - [0x8D0DC4C4DD62D064, 0x714F618606453395], - [0xB05135F614BB847E, 0x8DA339E787D6807A], - [0xDC65837399EA659D, 0xF10C086169CC2099], - [0x89BF722840327F82, 0x16A7853CE21F945F], - [0xAC2F4EB2503F1F63, 0x9C51668C1AA77977], - [0xD73B225EE44EE73B, 0x4365C02F215157D5], - [0x8684F57B4EB15085, 0x0A1F981D74D2D6E5], - [0xA82632DA225DA4A6, 0x4CA77E24D2078C9E], - [0xD22FBF90AAF50DD0, 0xDFD15DAE06896FC6], - [0x835DD7BA6AD928A2, 0xEBE2DA8CC415E5DC], - [0xA4354DA9058F72CA, 0x66DB912FF51B5F53], - [0xCD42A11346F34F7D, 0x0092757BF2623727], - [0x8049A4AC0C5811AE, 0x205B896D777D6279], - [0xA05C0DD70F6E161A, 0xA8726BC8D55CBB17], - [0xC873114CD3499BA0, 0x128F06BB0AB3E9DD], - [0xFA8FD5A0081C0288, 0x1732C869CD60E454], - [0x9C99E58405118195, 0x0E7FBD42205C8EB4], - [0xC3C05EE50655E1FA, 0x521FAC92A873B261], - [0xF4B0769E47EB5A79, 0xE6A797B752909EFA], - [0x98EE4A22ECF3188C, 0x9028BED2939A635C], - [0xBF29DCABA82FDEAE, 0x7432EE873880FC33], - [0xEEF453D6923BD65A, 0x113FAA2906A13B40], - [0x9558B4661B6565F8, 0x4AC7CA59A424C508], - [0xBAAEE17FA23EBF76, 0x5D79BCF00D2DF64A], - [0xE95A99DF8ACE6F54, 0xF4D82C2C107973DC], - [0x91D8A02BB6C10594, 0x79071B9B8A4BE86A], - [0xB64EC836A47146FA, 0x9748E2826CDEE284], - [0xE3E27A444D8D98B8, 0xFD1B1B2308169B25], - [0x8E6D8C6AB0787F73, 0xFE30F0F5E50E20F7], - [0xB208EF855C969F50, 0xBDBD2D335E51A935], - [0xDE8B2B66B3BC4724, 0xAD2C788035E61382], - [0x8B16FB203055AC76, 0x4C3BCB5021AFCC31], - [0xADDCB9E83C6B1794, 0xDF4ABE242A1BBF3E], - [0xD953E8624B85DD79, 0xD71D6DAD34A2AF0D], - [0x87D4713D6F33AA6C, 0x8672648C40E5AD68], - [0xA9C98D8CCB009506, 0x680EFDAF511F18C2], - [0xD43BF0EFFDC0BA48, 0x0212BD1B2566DEF3], - [0x84A57695FE98746D, 0x014BB630F7604B58], - [0xA5CED43B7E3E9188, 0x419EA3BD35385E2E], - [0xCF42894A5DCE35EA, 0x52064CAC828675B9], - [0x818995CE7AA0E1B2, 0x7343EFEBD1940994], - [0xA1EBFB4219491A1F, 0x1014EBE6C5F90BF9], - [0xCA66FA129F9B60A7, 0xD41A26E077774EF7], - [0xFD00B897478238D1, 0x8920B098955522B5], - [0x9E20735E8CB16382, 0x55B46E5F5D5535B1], - [0xC5A890362FDDBC63, 0xEB2189F734AA831D], - [0xF712B443BBD52B7C, 0xA5E9EC7501D523E4], - [0x9A6BB0AA55653B2D, 0x47B233C92125366F], - [0xC1069CD4EABE89F9, 0x999EC0BB696E840A], - [0xF148440A256E2C77, 0xC00670EA43CA250D], - [0x96CD2A865764DBCA, 0x380406926A5E5728], - [0xBC807527ED3E12BD, 0xC605083704F5ECF2], - [0xEBA09271E88D976C, 0xF7864A44C633682F], - [0x93445B8731587EA3, 0x7AB3EE6AFBE0211D], - [0xB8157268FDAE9E4C, 0x5960EA05BAD82965], - [0xE61ACF033D1A45DF, 0x6FB92487298E33BE], - [0x8FD0C16206306BAC, 0xA5D3B6D479F8E057], - [0xB3C4F1BA87BC8697, 0x8F48A4899877186C], - [0xE0B62E2929ABA83C, 0x331ACDABFE94DE87], - [0x8C71DCD9BA0B4926, 0x9FF0C08B7F1D0B15], - [0xAF8E5410288E1B6F, 0x07ECF0AE5EE44DDA], - [0xDB71E91432B1A24B, 0xC9E82CD9F69D6150], - [0x892731AC9FAF056F, 0xBE311C083A225CD2], - [0xAB70FE17C79AC6CA, 0x6DBD630A48AAF407], - [0xD64D3D9DB981787D, 0x092CBBCCDAD5B108], - [0x85F0468293F0EB4E, 0x25BBF56008C58EA5], - [0xA76C582338ED2622, 0xAF2AF2B80AF6F24E], - [0xD1476E2C07286FAA, 0x1AF5AF660DB4AEE2], - [0x82CCA4DB847945CA, 0x50D98D9FC890ED4D], - [0xA37FCE126597973D, 0xE50FF107BAB528A1], - [0xCC5FC196FEFD7D0C, 0x1E53ED49A96272C9], - [0xFF77B1FCBEBCDC4F, 0x25E8E89C13BB0F7B], - [0x9FAACF3DF73609B1, 0x77B191618C54E9AD], - [0xC795830D75038C1E, 0xD59DF5B9EF6A2418], - [0xF97AE3D0D2446F25, 0x4B0573286B44AD1E], - [0x9BECCE62836AC577, 0x4EE367F9430AEC33], - [0xC2E801FB244576D5, 0x229C41F793CDA73F], - [0xF3A20279ED56D48A, 0x6B43527578C1110F], - [0x9845418C345644D7, 0x830A13896B78AAAA], - [0xBE5691EF416BD60C, 0x23CC986BC656D554], - [0xEDEC366B11C6CB8F, 0x2CBFBE86B7EC8AA9], - [0x94B3A202EB1C3F39, 0x7BF7D71432F3D6AA], - [0xB9E08A83A5E34F08, 0xDAF5CCD93FB0CC54], - [0xE858AD248F5C22CA, 0xD1B3400F8F9CFF69], - [0x91376C36D99995BE, 0x23100809B9C21FA2], - [0xB58547448FFFFB2E, 0xABD40A0C2832A78A], - [0xE2E69915B3FFF9F9, 0x16C90C8F323F516D], - [0x8DD01FAD907FFC3C, 0xAE3DA7D97F6792E4], - [0xB1442798F49FFB4B, 0x99CD11CFDF41779D], - [0xDD95317F31C7FA1D, 0x40405643D711D584], - [0x8A7D3EEF7F1CFC52, 0x482835EA666B2572], - [0xAD1C8EAB5EE43B67, 0xDA3243650005EECF], - [0xD863B256369D4A41, 0x90BED43E40076A83], - [0x873E4F75E2224E68, 0x5A7744A6E804A292], - [0xA90DE3535AAAE202, 0x711515D0A205CB36], - [0xD3515C2831559A83, 0x0D5A5B44CA873E04], - [0x8412D9991ED58092, 0xE858790AFE9486C2], - [0xA5178FFF668AE0B6, 0x626E974DBE39A873], - [0xCE5D73FF402D98E4, 0xFB0A3D212DC81290], - [0x80FA687F881C7F8E, 0x7CE66634BC9D0B9A], - [0xA139029F6A239F72, 0x1C1FFFC1EBC44E80], - [0xC987434744AC874F, 0xA327FFB266B56220], - [0xFBE9141915D7A922, 0x4BF1FF9F0062BAA8], - [0x9D71AC8FADA6C9B5, 0x6F773FC3603DB4A9], - [0xC4CE17B399107C23, 0xCB550FB4384D21D4], - [0xF6019DA07F549B2B, 0x7E2A53A146606A48], - [0x99C102844F94E0FB, 0x2EDA7444CBFC426D], - [0xC0314325637A193A, 0xFA911155FEFB5309], - [0xF03D93EEBC589F88, 0x793555AB7EBA27CB], - [0x96267C7535B763B5, 0x4BC1558B2F3458DF], - [0xBBB01B9283253CA3, 0x9EB1AAEDFB016F16], - [0xEA9C227723EE8BCB, 0x465E15A979C1CADC], - [0x92A1958A7675175F, 0x0BFACD89EC191ECA], - [0xB749FAED14125D37, 0xCEF980EC671F667C], - [0xE51C79A85916F485, 0x82B7E12780E7401B], - [0x8F31CC0937AE58D3, 0xD1B2ECB8B0908811], - [0xB2FE3F0B8599EF08, 0x861FA7E6DCB4AA15], - [0xDFBDCECE67006AC9, 0x67A791E093E1D49A], - [0x8BD6A141006042BE, 0xE0C8BB2C5C6D24E0], - [0xAECC49914078536D, 0x58FAE9F773886E19], - [0xDA7F5BF590966849, 0xAF39A475506A899F], - [0x888F99797A5E012D, 0x6D8406C952429603], - [0xAAB37FD7D8F58179, 0xC8E5087BA6D33B84], - [0xD5605FCDCF32E1D7, 0xFB1E4A9A90880A65], - [0x855C3BE0A17FCD26, 0x5CF2EEA09A55067F], - [0xA6B34AD8C9DFC070, 0xF42FAA48C0EA481F], - [0xD0601D8EFC57B08C, 0xF13B94DAF124DA27], - [0x823C12795DB6CE57, 0x76C53D08D6B70858], - [0xA2CB1717B52481ED, 0x54768C4B0C64CA6E], - [0xCB7DDCDDA26DA269, 0xA9942F5DCF7DFD0A], - [0xFE5D54150B090B03, 0xD3F93B35435D7C4C], - [0x9EFA548D26E5A6E2, 0xC47BC5014A1A6DB0], - [0xC6B8E9B0709F109A, 0x359AB6419CA1091B], - [0xF867241C8CC6D4C1, 0xC30163D203C94B62], - [0x9B407691D7FC44F8, 0x79E0DE63425DCF1D], - [0xC21094364DFB5637, 0x985915FC12F542E5], - [0xF294B943E17A2BC4, 0x3E6F5B7B17B2939E], - [0x979CF3CA6CEC5B5B, 0xA705992CEECF9C43], - [0xBD8430BD08277231, 0x50C6FF782A838353], - [0xECE53CEC4A314EBE, 0xA4F8BF5635246428], - [0x940F4613AE5ED137, 0x871B7795E136BE99], - [0xB913179899F68584, 0x28E2557B59846E3F], - [0xE757DD7EC07426E5, 0x331AEADA2FE589CF], - [0x9096EA6F3848984F, 0x3FF0D2C85DEF7622], - [0xB4BCA50B065ABE63, 0x0FED077A756B53AA], - [0xE1EBCE4DC7F16DFC, 0xD3E8495912C62894], - [0x8D3360F09CF6E4BD, 0x64712DD7ABBBD95D], - [0xB080392CC4349DED, 0xBD8D794D96AACFB4], - [0xDCA04777F541C568, 0xECF0D7A0FC5583A1], - [0x89E42CAAF9491B61, 0xF41686C49DB57245], - [0xAC5D37D5B79B6239, 0x311C2875C522CED6], - [0xD77485CB25823AC7, 0x7D633293366B828B], - [0x86A8D39EF77164BD, 0xAE5DFF9C02033197], - [0xA8530886B54DBDEC, 0xD9F57F830283FDFD], - [0xD267CAA862A12D67, 0xD072DF63C324FD7C], - [0x8380DEA93DA4BC60, 0x4247CB9E59F71E6D], - [0xA46116538D0DEB78, 0x52D9BE85F074E609], - [0xCD795BE870516656, 0x67902E276C921F8B], - [0x806BD9714632DFF6, 0x00BA1CD8A3DB53B7], - [0xA086CFCD97BF97F4, 0x80E8A40ECCD228A5], - [0xC8A883C0FDAF7DF0, 0x6122CD128006B2CE], - [0xFAD2A4B13D1B5D6C, 0x796B805720085F81], - [0x9CC3A6EEC6311A64, 0xCBE3303674053BB1], - [0xC3F490AA77BD60FD, 0xBEDBFC4411068A9D], - [0xF4F1B4D515ACB93C, 0xEE92FB5515482D44], - [0x991711052D8BF3C5, 0x751BDD152D4D1C4B], - [0xBF5CD54678EEF0B7, 0xD262D45A78A0635D], - [0xEF340A98172AACE5, 0x86FB897116C87C35], - [0x9580869F0E7AAC0F, 0xD45D35E6AE3D4DA1], - [0xBAE0A846D2195713, 0x8974836059CCA109], - [0xE998D258869FACD7, 0x2BD1A438703FC94B], - [0x91FF83775423CC06, 0x7B6306A34627DDCF], - [0xB67F6455292CBF08, 0x1A3BC84C17B1D543], - [0xE41F3D6A7377EECA, 0x20CABA5F1D9E4A94], - [0x8E938662882AF53E, 0x547EB47B7282EE9C], - [0xB23867FB2A35B28E, 0xE99E619A4F23AA43], - [0xDEC681F9F4C31F31, 0x6405FA00E2EC94D4], - [0x8B3C113C38F9F37F, 0xDE83BC408DD3DD05], - [0xAE0B158B4738705F, 0x9624AB50B148D446], - [0xD98DDAEE19068C76, 0x3BADD624DD9B0957], - [0x87F8A8D4CFA417CA, 0xE54CA5D70A80E5D6], - [0xA9F6D30A038D1DBC, 0x5E9FCF4CCD211F4C], - [0xD47487CC8470652B, 0x7647C3200069671F], - [0x84C8D4DFD2C63F3B, 0x29ECD9F40041E073], - [0xA5FB0A17C777CF0A, 0xF468107100525890], - [0xCF79CC9DB955C2CC, 0x7182148D4066EEB4], - [0x81AC1FE293D599C0, 0xC6F14CD848405531], - [0xA21727DB38CB0030, 0xB8ADA00E5A506A7D], - [0xCA9CF1D206FDC03C, 0xA6D90811F0E4851C], - [0xFD442E4688BD304B, 0x908F4A166D1DA663], - [0x9E4A9CEC15763E2F, 0x9A598E4E043287FE], - [0xC5DD44271AD3CDBA, 0x40EFF1E1853F29FE], - [0xF7549530E188C129, 0xD12BEE59E68EF47D], - [0x9A94DD3E8CF578BA, 0x82BB74F8301958CE], - [0xC13A148E3032D6E8, 0xE36A52363C1FAF02], - [0xF18899B1BC3F8CA2, 0xDC44E6C3CB279AC2], - [0x96F5600F15A7B7E5, 0x29AB103A5EF8C0B9], - [0xBCB2B812DB11A5DE, 0x7415D448F6B6F0E8], - [0xEBDF661791D60F56, 0x111B495B3464AD21], - [0x936B9FCEBB25C996, 0xCAB10DD900BEEC35], - [0xB84687C269EF3BFB, 0x3D5D514F40EEA742], - [0xE65829B3046B0AFA, 0x0CB4A5A3112A5113], - [0x8FF71A0FE2C2E6DC, 0x47F0E785EABA72AC], - [0xB3F4E093DB73A093, 0x59ED216765690F57], - [0xE0F218B8D25088B8, 0x306869C13EC3532C], - [0x8C974F7383725573, 0x1E414218C73A13FC], - [0xAFBD2350644EEAD0, 0xE5D1929EF90898FB], - [0xDBAC6C247D62A584, 0xDF45F746B74ABF39], - [0x894BC396CE5DA772, 0x6B8BBA8C328EB784], - [0xAB9EB47C81F5114F, 0x066EA92F3F326565], - [0xD686619BA27255A3, 0xC80A537B0EFEFEBE], - [0x8613FD0145877586, 0xBD06742CE95F5F37], - [0xA798FC4196E952E7, 0x2C48113823B73704], - [0xD17F3B51FCA3A7A1, 0xF75A15862CA504C5], - [0x82EF85133DE648C5, 0x9A984D73DBE722FB], - [0xA3AB66580D5FDAF6, 0xC13E60D0D2E0EBBA], - [0xCC963FEE10B7D1B3, 0x318DF905079926A9], - [0xFFBBCFE994E5C620, 0xFDF17746497F7053], - [0x9FD561F1FD0F9BD4, 0xFEB6EA8BEDEFA634], - [0xC7CABA6E7C5382C9, 0xFE64A52EE96B8FC1], - [0xF9BD690A1B68637B, 0x3DFDCE7AA3C673B1], - [0x9C1661A651213E2D, 0x06BEA10CA65C084F], - [0xC31BFA0FE5698DB8, 0x486E494FCFF30A62], - [0xF3E2F893DEC3F126, 0x5A89DBA3C3EFCCFB], - [0x986DDB5C6B3A76B8, 0xF89629465A75E01D], - [0xBE89523386091466, 0xF6BBB397F1135824], - [0xEE2BA6C0678B597F, 0x746AA07DED582E2D], - [0x94DB483840B717F0, 0xA8C2A44EB4571CDC], - [0xBA121A4650E4DDEC, 0x92F34D62616CE413], - [0xE896A0D7E51E1566, 0x77B020BAF9C81D18], - [0x915E2486EF32CD60, 0x0ACE1474DC1D122F], - [0xB5B5ADA8AAFF80B8, 0x0D819992132456BB], - [0xE3231912D5BF60E6, 0x10E1FFF697ED6C69], - [0x8DF5EFABC5979C90, 0xCA8D3FFA1EF463C2], - [0xB1736B96B6FD83B4, 0xBD308FF8A6B17CB2], - [0xDDD0467C64BCE4A1, 0xAC7CB3F6D05DDBDF], - [0x8AA22C0DBEF60EE4, 0x6BCDF07A423AA96B], - [0xAD4AB7112EB3929E, 0x86C16C98D2C953C6], - [0xD89D64D57A607745, 0xE871C7BF077BA8B8], - [0x87625F056C7C4A8B, 0x11471CD764AD4973], - [0xA93AF6C6C79B5D2E, 0xD598E40D3DD89BCF], - [0xD389B47879823479, 0x4AFF1D108D4EC2C3], - [0x843610CB4BF160CC, 0xCEDF722A585139BA], - [0xA54394FE1EEDB8FF, 0xC2974EB4EE658829], - [0xCE947A3DA6A9273E, 0x733D226229FEEA33], - [0x811CCC668829B887, 0x0806357D5A3F5260], - [0xA163FF802A3426A9, 0xCA07C2DCB0CF26F8], - [0xC9BCFF6034C13053, 0xFC89B393DD02F0B6], - [0xFC2C3F3841F17C68, 0xBBAC2078D443ACE3], - [0x9D9BA7832936EDC1, 0xD54B944B84AA4C0E], - [0xC5029163F384A931, 0x0A9E795E65D4DF11], - [0xF64335BCF065D37D, 0x4D4617B5FF4A16D6], - [0x99EA0196163FA42E, 0x504BCED1BF8E4E46], - [0xC06481FB9BCF8D3A, 0xE45EC2862F71E1D7], - [0xF07DA27A82C37088, 0x5D767327BB4E5A4D], - [0x964E858C91BA2655, 0x3A6A07F8D510F870], - [0xBBE226EFB628AFEB, 0x890489F70A55368C], - [0xEADAB0ABA3B2DBE5, 0x2B45AC74CCEA842F], - [0x92C8AE6B464FC96F, 0x3B0B8BC90012929D], - [0xB77ADA0617E3BBCB, 0x09CE6EBB40173745], - [0xE55990879DDCAABE, 0xCC420A6A101D0516], - [0x8F57FA54C2A9EAB7, 0x9FA946824A12232E], - [0xB32DF8E9F3546564, 0x47939822DC96ABF9], - [0xDFF9772470297EBD, 0x59787E2B93BC56F7], - [0x8BFBEA76C619EF36, 0x57EB4EDB3C55B65B], - [0xAEFAE51477A06B04, 0xEDE622920B6B23F1], - [0xDAB99E59958885C5, 0xE95FAB368E45ECED], - [0x88B402F7FD75539B, 0x11DBCB0218EBB414], - [0xAAE103B5FCD2A882, 0xD652BDC29F26A11A], - [0xD59944A37C0752A2, 0x4BE76D3346F04960], - [0x857FCAE62D8493A5, 0x6F70A4400C562DDC], - [0xA6DFBD9FB8E5B88F, 0xCB4CCD500F6BB953], - [0xD097AD07A71F26B2, 0x7E2000A41346A7A8], - [0x825ECC24C8737830, 0x8ED400668C0C28C9], - [0xA2F67F2DFA90563B, 0x728900802F0F32FB], - [0xCBB41EF979346BCA, 0x4F2B40A03AD2FFBA], - [0xFEA126B7D78186BD, 0xE2F610C84987BFA8], - [0x9F24B832E6B0F436, 0x0DD9CA7D2DF4D7C9], - [0xC6EDE63FA05D3144, 0x91503D1C79720DBB], - [0xF8A95FCF88747D94, 0x75A44C6397CE912A], - [0x9B69DBE1B548CE7D, 0xC986AFBE3EE11ABA], - [0xC24452DA229B021C, 0xFBE85BADCE996169], - [0xF2D56790AB41C2A3, 0xFAE27299423FB9C3], - [0x97C560BA6B0919A6, 0xDCCD879FC967D41A], - [0xBDB6B8E905CB600F, 0x5400E987BBC1C921], - [0xED246723473E3813, 0x290123E9AAB23B69], - [0x9436C0760C86E30C, 0xF9A0B6720AAF6521], - [0xB94470938FA89BCF, 0xF808E40E8D5B3E6A], - [0xE7958CB87392C2C3, 0xB60B1D1230B20E04], - [0x90BD77F3483BB9BA, 0xB1C6F22B5E6F48C3], - [0xB4ECD5F01A4AA828, 0x1E38AEB6360B1AF3], - [0xE2280B6C20DD5232, 0x25C6DA63C38DE1B0], - [0x8D590723948A535F, 0x579C487E5A38AD0E], - [0xB0AF48EC79ACE837, 0x2D835A9DF0C6D852], - [0xDCDB1B2798182245, 0xF8E431456CF88E66], - [0x8A08F0F8BF0F156B, 0x1B8E9ECB641B5900], - [0xAC8B2D36EED2DAC6, 0xE272467E3D222F40], - [0xD7ADF884AA879177, 0x5B0ED81DCC6ABB10], - [0x86CCBB52EA94BAEB, 0x98E947129FC2B4EA], - [0xA87FEA27A539E9A5, 0x3F2398D747B36224], - [0xD29FE4B18E88640F, 0x8EEC7F0D19A03AAD], - [0x83A3EEEEF9153E89, 0x1953CF68300424AC], - [0xA48CEAAAB75A8E2B, 0x5FA8C3423C052DD7], - [0xCDB02555653131B6, 0x3792F412CB06794D], - [0x808E17555F3EBF12, 0xE2BBD88BBEE40BD0], - [0xA0B19D2AB70E6ED6, 0x5B6ACEAEAE9D0EC4], - [0xC8DE047564D20A8C, 0xF245825A5A445275], - [0xFB158592BE068D2F, 0xEED6E2F0F0D56713], - [0x9CED737BB6C4183D, 0x55464DD69685606C], - [0xC428D05AA4751E4D, 0xAA97E14C3C26B887], - [0xF53304714D9265E0, 0xD53DD99F4B3066A8], - [0x993FE2C6D07B7FAC, 0xE546A8038EFE4029], - [0xBF8FDB78849A5F97, 0xDE98520472BDD033], - [0xEF73D256A5C0F77D, 0x963E66858F6D4440], - [0x95A8637627989AAE, 0xDDE7001379A44AA8], - [0xBB127C53B17EC159, 0x5560C018580D5D52], - [0xE9D71B689DDE71B0, 0xAAB8F01E6E10B4A7], - [0x9226712162AB070E, 0xCAB3961304CA70E8], - [0xB6B00D69BB55C8D1, 0x3D607B97C5FD0D22], - [0xE45C10C42A2B3B06, 0x8CB89A7DB77C506B], - [0x8EB98A7A9A5B04E3, 0x77F3608E92ADB243], - [0xB267ED1940F1C61C, 0x55F038B237591ED3], - [0xDF01E85F912E37A3, 0x6B6C46DEC52F6688], - [0x8B61313BBABCE2C6, 0x2323AC4B3B3DA015], - [0xAE397D8AA96C1B78, 0xABEC975E0A0D081B], - [0xD9C7DCED53C72256, 0x96E7BD358C904A21], - [0x881CEA14545C7575, 0x7E50D64177DA2E55], - [0xAA242499697392D3, 0xDDE50BD1D5D0B9EA], - [0xD4AD2DBFC3D07788, 0x955E4EC64B44E864], - [0x84EC3C97DA624AB5, 0xBD5AF13BEF0B113F], - [0xA6274BBDD0FADD62, 0xECB1AD8AEACDD58E], - [0xCFB11EAD453994BA, 0x67DE18EDA5814AF2], - [0x81CEB32C4B43FCF5, 0x80EACF948770CED7], - [0xA2425FF75E14FC32, 0xA1258379A94D028D], - [0xCAD2F7F5359A3B3E, 0x096EE45813A04330], - [0xFD87B5F28300CA0E, 0x8BCA9D6E188853FC], - [0x9E74D1B791E07E48, 0x775EA264CF55347E], - [0xC612062576589DDB, 0x95364AFE032A819D], - [0xF79687AED3EEC551, 0x3A83DDBD83F52205], - [0x9ABE14CD44753B53, 0xC4926A9672793543], - [0xC16D9A0095928A27, 0x75B7053C0F178294], - [0xF1C90080BAF72CB1, 0x5324C68B12DD6338], - [0x971DA05074DA7BEF, 0xD3F6FC16EBCA5E03], - [0xBCE5086492111AEB, 0x88F4BB1CA6BCF584], - [0xEC1E4A7DB69561A5, 0x2B31E9E3D06C32E5], - [0x9392EE8E921D5D07, 0x3AFF322E62439FCF], - [0xB877AA3236A4B449, 0x09BEFEB9FAD487C3], - [0xE69594BEC44DE15B, 0x4C2EBE687989A9B4], - [0x901D7CF73AB0ACD9, 0x0F9D37014BF60A10], - [0xB424DC35095CD80F, 0x538484C19EF38C94], - [0xE12E13424BB40E13, 0x2865A5F206B06FBA], - [0x8CBCCC096F5088CC, 0xF93F87B7442E45D4], - [0xAFEBFF0BCB24AAFF, 0xF78F69A51539D749], - [0xDBE6FECEBDEDD5BF, 0xB573440E5A884D1B], - [0x89705F4136B4A597, 0x31680A88F8953031], - [0xABCC77118461CEFD, 0xFDC20D2B36BA7C3D], - [0xD6BF94D5E57A42BC, 0x3D32907604691B4D], - [0x8637BD05AF6C69B6, 0xA63F9A49C2C1B110], - [0xA7C5AC471B478423, 0x0FCF80DC33721D54], - [0xD1B71758E219652C, 0xD3C36113404EA4A9], - [0x83126E978D4FDF3B, 0x645A1CAC083126E9], - [0xA3D70A3D70A3D70A, 0x3D70A3D70A3D70A4], - [0xCCCCCCCCCCCCCCCD, 0xCCCCCCCCCCCCCCCD], - [0x8000000000000000, 0x0000000000000000], - [0xA000000000000000, 0x0000000000000000], - [0xC800000000000000, 0x0000000000000000], - [0xFA00000000000000, 0x0000000000000000], - [0x9C40000000000000, 0x0000000000000000], - [0xC350000000000000, 0x0000000000000000], - [0xF424000000000000, 0x0000000000000000], - [0x9896800000000000, 0x0000000000000000], - [0xBEBC200000000000, 0x0000000000000000], - [0xEE6B280000000000, 0x0000000000000000], - [0x9502F90000000000, 0x0000000000000000], - [0xBA43B74000000000, 0x0000000000000000], - [0xE8D4A51000000000, 0x0000000000000000], - [0x9184E72A00000000, 0x0000000000000000], - [0xB5E620F480000000, 0x0000000000000000], - [0xE35FA931A0000000, 0x0000000000000000], - [0x8E1BC9BF04000000, 0x0000000000000000], - [0xB1A2BC2EC5000000, 0x0000000000000000], - [0xDE0B6B3A76400000, 0x0000000000000000], - [0x8AC7230489E80000, 0x0000000000000000], - [0xAD78EBC5AC620000, 0x0000000000000000], - [0xD8D726B7177A8000, 0x0000000000000000], - [0x878678326EAC9000, 0x0000000000000000], - [0xA968163F0A57B400, 0x0000000000000000], - [0xD3C21BCECCEDA100, 0x0000000000000000], - [0x84595161401484A0, 0x0000000000000000], - [0xA56FA5B99019A5C8, 0x0000000000000000], - [0xCECB8F27F4200F3A, 0x0000000000000000], - [0x813F3978F8940984, 0x4000000000000000], - [0xA18F07D736B90BE5, 0x5000000000000000], - [0xC9F2C9CD04674EDF, 0xA400000000000000], - [0xFC6F7C4045812296, 0x4D00000000000000], - [0x9DC5ADA82B70B59E, 0xF020000000000000], - [0xC5371912364CE305, 0x6C28000000000000], - [0xF684DF56C3E01BC7, 0xC732000000000000], - [0x9A130B963A6C115C, 0x3C7F400000000000], - [0xC097CE7BC90715B3, 0x4B9F100000000000], - [0xF0BDC21ABB48DB20, 0x1E86D40000000000], - [0x96769950B50D88F4, 0x1314448000000000], - [0xBC143FA4E250EB31, 0x17D955A000000000], - [0xEB194F8E1AE525FD, 0x5DCFAB0800000000], - [0x92EFD1B8D0CF37BE, 0x5AA1CAE500000000], - [0xB7ABC627050305AE, 0xF14A3D9E40000000], - [0xE596B7B0C643C719, 0x6D9CCD05D0000000], - [0x8F7E32CE7BEA5C70, 0xE4820023A2000000], - [0xB35DBF821AE4F38C, 0xDDA2802C8A800000], - [0xE0352F62A19E306F, 0xD50B2037AD200000], - [0x8C213D9DA502DE45, 0x4526F422CC340000], - [0xAF298D050E4395D7, 0x9670B12B7F410000], - [0xDAF3F04651D47B4C, 0x3C0CDD765F114000], - [0x88D8762BF324CD10, 0xA5880A69FB6AC800], - [0xAB0E93B6EFEE0054, 0x8EEA0D047A457A00], - [0xD5D238A4ABE98068, 0x72A4904598D6D880], - [0x85A36366EB71F041, 0x47A6DA2B7F864750], - [0xA70C3C40A64E6C52, 0x999090B65F67D924], - [0xD0CF4B50CFE20766, 0xFFF4B4E3F741CF6D], - [0x82818F1281ED44A0, 0xBFF8F10E7A8921A4], - [0xA321F2D7226895C8, 0xAFF72D52192B6A0D], - [0xCBEA6F8CEB02BB3A, 0x9BF4F8A69F764490], - [0xFEE50B7025C36A08, 0x02F236D04753D5B5], - [0x9F4F2726179A2245, 0x01D762422C946591], - [0xC722F0EF9D80AAD6, 0x424D3AD2B7B97EF5], - [0xF8EBAD2B84E0D58C, 0xD2E0898765A7DEB2], - [0x9B934C3B330C8577, 0x63CC55F49F88EB2F], - [0xC2781F49FFCFA6D5, 0x3CBF6B71C76B25FB], - [0xF316271C7FC3908B, 0x8BEF464E3945EF7A], - [0x97EDD871CFDA3A57, 0x97758BF0E3CBB5AC], - [0xBDE94E8E43D0C8EC, 0x3D52EEED1CBEA317], - [0xED63A231D4C4FB27, 0x4CA7AAA863EE4BDD], - [0x945E455F24FB1CF9, 0x8FE8CAA93E74EF6A], - [0xB975D6B6EE39E437, 0xB3E2FD538E122B45], - [0xE7D34C64A9C85D44, 0x60DBBCA87196B616], - [0x90E40FBEEA1D3A4B, 0xBC8955E946FE31CE], - [0xB51D13AEA4A488DD, 0x6BABAB6398BDBE41], - [0xE264589A4DCDAB15, 0xC696963C7EED2DD2], - [0x8D7EB76070A08AED, 0xFC1E1DE5CF543CA3], - [0xB0DE65388CC8ADA8, 0x3B25A55F43294BCC], - [0xDD15FE86AFFAD912, 0x49EF0EB713F39EBF], - [0x8A2DBF142DFCC7AB, 0x6E3569326C784337], - [0xACB92ED9397BF996, 0x49C2C37F07965405], - [0xD7E77A8F87DAF7FC, 0xDC33745EC97BE906], - [0x86F0AC99B4E8DAFD, 0x69A028BB3DED71A4], - [0xA8ACD7C0222311BD, 0xC40832EA0D68CE0D], - [0xD2D80DB02AABD62C, 0xF50A3FA490C30190], - [0x83C7088E1AAB65DB, 0x792667C6DA79E0FA], - [0xA4B8CAB1A1563F52, 0x577001B891185939], - [0xCDE6FD5E09ABCF27, 0xED4C0226B55E6F87], - [0x80B05E5AC60B6178, 0x544F8158315B05B4], - [0xA0DC75F1778E39D6, 0x696361AE3DB1C721], - [0xC913936DD571C84C, 0x03BC3A19CD1E38EA], - [0xFB5878494ACE3A5F, 0x04AB48A04065C724], - [0x9D174B2DCEC0E47B, 0x62EB0D64283F9C76], - [0xC45D1DF942711D9A, 0x3BA5D0BD324F8394], - [0xF5746577930D6501, 0xCA8F44EC7EE36479], - [0x9968BF6ABBE85F20, 0x7E998B13CF4E1ECC], - [0xBFC2EF456AE276E9, 0x9E3FEDD8C321A67F], - [0xEFB3AB16C59B14A3, 0xC5CFE94EF3EA101E], - [0x95D04AEE3B80ECE6, 0xBBA1F1D158724A13], - [0xBB445DA9CA61281F, 0x2A8A6E45AE8EDC98], - [0xEA1575143CF97227, 0xF52D09D71A3293BE], - [0x924D692CA61BE758, 0x593C2626705F9C56], - [0xB6E0C377CFA2E12E, 0x6F8B2FB00C77836C], - [0xE498F455C38B997A, 0x0B6DFB9C0F956447], - [0x8EDF98B59A373FEC, 0x4724BD4189BD5EAC], - [0xB2977EE300C50FE7, 0x58EDEC91EC2CB658], - [0xDF3D5E9BC0F653E1, 0x2F2967B66737E3ED], - [0x8B865B215899F46D, 0xBD79E0D20082EE74], - [0xAE67F1E9AEC07188, 0xECD8590680A3AA11], - [0xDA01EE641A708DEA, 0xE80E6F4820CC9496], - [0x884134FE908658B2, 0x3109058D147FDCDE], - [0xAA51823E34A7EEDF, 0xBD4B46F0599FD415], - [0xD4E5E2CDC1D1EA96, 0x6C9E18AC7007C91A], - [0x850FADC09923329E, 0x03E2CF6BC604DDB0], - [0xA6539930BF6BFF46, 0x84DB8346B786151D], - [0xCFE87F7CEF46FF17, 0xE612641865679A64], - [0x81F14FAE158C5F6E, 0x4FCB7E8F3F60C07E], - [0xA26DA3999AEF774A, 0xE3BE5E330F38F09E], - [0xCB090C8001AB551C, 0x5CADF5BFD3072CC5], - [0xFDCB4FA002162A63, 0x73D9732FC7C8F7F7], - [0x9E9F11C4014DDA7E, 0x2867E7FDDCDD9AFA], - [0xC646D63501A1511E, 0xB281E1FD541501B9], - [0xF7D88BC24209A565, 0x1F225A7CA91A4227], - [0x9AE757596946075F, 0x3375788DE9B06958], - [0xC1A12D2FC3978937, 0x0052D6B1641C83AE], - [0xF209787BB47D6B85, 0xC0678C5DBD23A49A], - [0x9745EB4D50CE6333, 0xF840B7BA963646E0], - [0xBD176620A501FC00, 0xB650E5A93BC3D898], - [0xEC5D3FA8CE427B00, 0xA3E51F138AB4CEBE], - [0x93BA47C980E98CE0, 0xC66F336C36B10137], - [0xB8A8D9BBE123F018, 0xB80B0047445D4185], - [0xE6D3102AD96CEC1E, 0xA60DC059157491E6], - [0x9043EA1AC7E41393, 0x87C89837AD68DB30], - [0xB454E4A179DD1877, 0x29BABE4598C311FC], - [0xE16A1DC9D8545E95, 0xF4296DD6FEF3D67B], - [0x8CE2529E2734BB1D, 0x1899E4A65F58660D], - [0xB01AE745B101E9E4, 0x5EC05DCFF72E7F90], - [0xDC21A1171D42645D, 0x76707543F4FA1F74], - [0x899504AE72497EBA, 0x6A06494A791C53A8], - [0xABFA45DA0EDBDE69, 0x0487DB9D17636892], - [0xD6F8D7509292D603, 0x45A9D2845D3C42B7], - [0x865B86925B9BC5C2, 0x0B8A2392BA45A9B2], - [0xA7F26836F282B733, 0x8E6CAC7768D7141F], - [0xD1EF0244AF2364FF, 0x3207D795430CD927], - [0x8335616AED761F1F, 0x7F44E6BD49E807B8], - [0xA402B9C5A8D3A6E7, 0x5F16206C9C6209A6], - [0xCD036837130890A1, 0x36DBA887C37A8C10], - [0x802221226BE55A65, 0xC2494954DA2C978A], - [0xA02AA96B06DEB0FE, 0xF2DB9BAA10B7BD6C], - [0xC83553C5C8965D3D, 0x6F92829494E5ACC7], - [0xFA42A8B73ABBF48D, 0xCB772339BA1F17F9], - [0x9C69A97284B578D8, 0xFF2A760414536EFC], - [0xC38413CF25E2D70E, 0xFEF5138519684ABB], - [0xF46518C2EF5B8CD1, 0x7EB258665FC25D69], - [0x98BF2F79D5993803, 0xEF2F773FFBD97A62], - [0xBEEEFB584AFF8604, 0xAAFB550FFACFD8FA], - [0xEEAABA2E5DBF6785, 0x95BA2A53F983CF39], - [0x952AB45CFA97A0B3, 0xDD945A747BF26184], - [0xBA756174393D88E0, 0x94F971119AEEF9E4], - [0xE912B9D1478CEB17, 0x7A37CD5601AAB85E], - [0x91ABB422CCB812EF, 0xAC62E055C10AB33B], - [0xB616A12B7FE617AA, 0x577B986B314D6009], - [0xE39C49765FDF9D95, 0xED5A7E85FDA0B80B], - [0x8E41ADE9FBEBC27D, 0x14588F13BE847307], - [0xB1D219647AE6B31C, 0x596EB2D8AE258FC9], - [0xDE469FBD99A05FE3, 0x6FCA5F8ED9AEF3BB], - [0x8AEC23D680043BEE, 0x25DE7BB9480D5855], - [0xADA72CCC20054AEA, 0xAF561AA79A10AE6A], - [0xD910F7FF28069DA4, 0x1B2BA1518094DA05], - [0x87AA9AFF79042287, 0x90FB44D2F05D0843], - [0xA99541BF57452B28, 0x353A1607AC744A54], - [0xD3FA922F2D1675F2, 0x42889B8997915CE9], - [0x847C9B5D7C2E09B7, 0x69956135FEBADA11], - [0xA59BC234DB398C25, 0x43FAB9837E699096], - [0xCF02B2C21207EF2F, 0x94F967E45E03F4BB], - [0x8161AFB94B44F57D, 0x1D1BE0EEBAC278F5], - [0xA1BA1BA79E1632DC, 0x6462D92A69731732], - [0xCA28A291859BBF93, 0x7D7B8F7503CFDCFF], - [0xFCB2CB35E702AF78, 0x5CDA735244C3D43F], - [0x9DEFBF01B061ADAB, 0x3A0888136AFA64A7], - [0xC56BAEC21C7A1916, 0x088AAA1845B8FDD1], - [0xF6C69A72A3989F5C, 0x8AAD549E57273D45], - [0x9A3C2087A63F6399, 0x36AC54E2F678864B], - [0xC0CB28A98FCF3C80, 0x84576A1BB416A7DE], - [0xF0FDF2D3F3C30B9F, 0x656D44A2A11C51D5], - [0x969EB7C47859E744, 0x9F644AE5A4B1B325], - [0xBC4665B596706115, 0x873D5D9F0DDE1FEF], - [0xEB57FF22FC0C795A, 0xA90CB506D155A7EA], - [0x9316FF75DD87CBD8, 0x09A7F12442D588F3], - [0xB7DCBF5354E9BECE, 0x0C11ED6D538AEB2F], - [0xE5D3EF282A242E82, 0x8F1668C8A86DA5FB], - [0x8FA475791A569D11, 0xF96E017D694487BD], - [0xB38D92D760EC4455, 0x37C981DCC395A9AC], - [0xE070F78D3927556B, 0x85BBE253F47B1417], - [0x8C469AB843B89563, 0x93956D7478CCEC8E], - [0xAF58416654A6BABB, 0x387AC8D1970027B2], - [0xDB2E51BFE9D0696A, 0x06997B05FCC0319F], - [0x88FCF317F22241E2, 0x441FECE3BDF81F03], - [0xAB3C2FDDEEAAD25B, 0xD527E81CAD7626C4], - [0xD60B3BD56A5586F2, 0x8A71E223D8D3B075], - [0x85C7056562757457, 0xF6872D5667844E49], - [0xA738C6BEBB12D16D, 0xB428F8AC016561DB], - [0xD106F86E69D785C8, 0xE13336D701BEBA52], - [0x82A45B450226B39D, 0xECC0024661173473], - [0xA34D721642B06084, 0x27F002D7F95D0190], - [0xCC20CE9BD35C78A5, 0x31EC038DF7B441F4], - [0xFF290242C83396CE, 0x7E67047175A15271], - [0x9F79A169BD203E41, 0x0F0062C6E984D387], - [0xC75809C42C684DD1, 0x52C07B78A3E60868], - [0xF92E0C3537826146, 0xA7709A56CCDF8A83], - [0x9BBCC7A142B17CCC, 0x88A66076400BB692], - [0xC2ABF989935DDBFE, 0x6ACFF893D00EA436], - [0xF356F7EBF83552FE, 0x0583F6B8C4124D43], - [0x98165AF37B2153DF, 0xC3727A337A8B704A], - [0xBE1BF1B059E9A8D6, 0x744F18C0592E4C5D], - [0xEDA2EE1C7064130C, 0x1162DEF06F79DF74], - [0x9485D4D1C63E8BE8, 0x8ADDCB5645AC2BA8], - [0xB9A74A0637CE2EE1, 0x6D953E2BD7173693], - [0xE8111C87C5C1BA9A, 0xC8FA8DB6CCDD0437], - [0x910AB1D4DB9914A0, 0x1D9C9892400A22A2], - [0xB54D5E4A127F59C8, 0x2503BEB6D00CAB4B], - [0xE2A0B5DC971F303A, 0x2E44AE64840FD61E], - [0x8DA471A9DE737E24, 0x5CEAECFED289E5D3], - [0xB10D8E1456105DAD, 0x7425A83E872C5F47], - [0xDD50F1996B947519, 0xD12F124E28F77719], - [0x8A5296FFE33CC930, 0x82BD6B70D99AAA70], - [0xACE73CBFDC0BFB7B, 0x636CC64D1001550C], - [0xD8210BEFD30EFA5A, 0x3C47F7E05401AA4F], - [0x8714A775E3E95C78, 0x65ACFAEC34810A71], - [0xA8D9D1535CE3B396, 0x7F1839A741A14D0D], - [0xD31045A8341CA07C, 0x1EDE48111209A051], - [0x83EA2B892091E44E, 0x934AED0AAB460432], - [0xA4E4B66B68B65D61, 0xF81DA84D5617853F], - [0xCE1DE40642E3F4B9, 0x36251260AB9D668F], - [0x80D2AE83E9CE78F4, 0xC1D72B7C6B426019], - [0xA1075A24E4421731, 0xB24CF65B8612F820], - [0xC94930AE1D529CFD, 0xDEE033F26797B628], - [0xFB9B7CD9A4A7443C, 0x169840EF017DA3B1], - [0x9D412E0806E88AA6, 0x8E1F289560EE864F], - [0xC491798A08A2AD4F, 0xF1A6F2BAB92A27E3], - [0xF5B5D7EC8ACB58A3, 0xAE10AF696774B1DB], - [0x9991A6F3D6BF1766, 0xACCA6DA1E0A8EF29], - [0xBFF610B0CC6EDD3F, 0x17FD090A58D32AF3], - [0xEFF394DCFF8A948F, 0xDDFC4B4CEF07F5B0], - [0x95F83D0A1FB69CD9, 0x4ABDAF101564F98E], - [0xBB764C4CA7A44410, 0x9D6D1AD41ABE37F2], - [0xEA53DF5FD18D5514, 0x84C86189216DC5EE], - [0x92746B9BE2F8552C, 0x32FD3CF5B4E49BB5], - [0xB7118682DBB66A77, 0x3FBC8C33221DC2A2], - [0xE4D5E82392A40515, 0x0FABAF3FEAA5334A], - [0x8F05B1163BA6832D, 0x29CB4D87F2A7400E], - [0xB2C71D5BCA9023F8, 0x743E20E9EF511012], - [0xDF78E4B2BD342CF7, 0x914DA9246B255417], - [0x8BAB8EEFB6409C1A, 0x1AD089B6C2F7548E], - [0xAE9672ABA3D0C321, 0xA184AC2473B529B2], - [0xDA3C0F568CC4F3E9, 0xC9E5D72D90A2741E], - [0x8865899617FB1871, 0x7E2FA67C7A658893], - [0xAA7EEBFB9DF9DE8E, 0xDDBB901B98FEEAB8], - [0xD51EA6FA85785631, 0x552A74227F3EA565], - [0x8533285C936B35DF, 0xD53A88958F87275F], - [0xA67FF273B8460357, 0x8A892ABAF368F137], - [0xD01FEF10A657842C, 0x2D2B7569B0432D85], - [0x8213F56A67F6B29C, 0x9C3B29620E29FC73], - [0xA298F2C501F45F43, 0x8349F3BA91B47B90], - [0xCB3F2F7642717713, 0x241C70A936219A74], - [0xFE0EFB53D30DD4D8, 0xED238CD383AA0111], - [0x9EC95D1463E8A507, 0xF4363804324A40AB], - [0xC67BB4597CE2CE49, 0xB143C6053EDCD0D5], - [0xF81AA16FDC1B81DB, 0xDD94B7868E94050A], - [0x9B10A4E5E9913129, 0xCA7CF2B4191C8327], - [0xC1D4CE1F63F57D73, 0xFD1C2F611F63A3F0], - [0xF24A01A73CF2DCD0, 0xBC633B39673C8CEC], - [0x976E41088617CA02, 0xD5BE0503E085D814], - [0xBD49D14AA79DBC82, 0x4B2D8644D8A74E19], - [0xEC9C459D51852BA3, 0xDDF8E7D60ED1219F], - [0x93E1AB8252F33B46, 0xCABB90E5C942B503], - [0xB8DA1662E7B00A17, 0x3D6A751F3B936244], - [0xE7109BFBA19C0C9D, 0x0CC512670A783AD5], - [0x906A617D450187E2, 0x27FB2B80668B24C5], - [0xB484F9DC9641E9DB, 0xB1F9F660802DEDF6], - [0xE1A63853BBD26451, 0x5E7873F8A0396974], - [0x8D07E33455637EB3, 0xDB0B487B6423E1E8], - [0xB049DC016ABC5E60, 0x91CE1A9A3D2CDA63], - [0xDC5C5301C56B75F7, 0x7641A140CC7810FB], - [0x89B9B3E11B6329BB, 0xA9E904C87FCB0A9D], - [0xAC2820D9623BF429, 0x546345FA9FBDCD44], - [0xD732290FBACAF134, 0xA97C177947AD4095], - [0x867F59A9D4BED6C0, 0x49ED8EABCCCC485D], - [0xA81F301449EE8C70, 0x5C68F256BFFF5A75], - [0xD226FC195C6A2F8C, 0x73832EEC6FFF3112], - [0x83585D8FD9C25DB8, 0xC831FD53C5FF7EAB], - [0xA42E74F3D032F526, 0xBA3E7CA8B77F5E56], - [0xCD3A1230C43FB26F, 0x28CE1BD2E55F35EB], - [0x80444B5E7AA7CF85, 0x7980D163CF5B81B3], - [0xA0555E361951C367, 0xD7E105BCC3326220], - [0xC86AB5C39FA63441, 0x8DD9472BF3FEFAA8], - [0xFA856334878FC151, 0xB14F98F6F0FEB952], - [0x9C935E00D4B9D8D2, 0x6ED1BF9A569F33D3], - [0xC3B8358109E84F07, 0x0A862F80EC4700C8], - [0xF4A642E14C6262C9, 0xCD27BB612758C0FA], - [0x98E7E9CCCFBD7DBE, 0x8038D51CB897789C], - [0xBF21E44003ACDD2D, 0xE0470A63E6BD56C3], - [0xEEEA5D5004981478, 0x1858CCFCE06CAC74], - [0x95527A5202DF0CCB, 0x0F37801E0C43EBC9], - [0xBAA718E68396CFFE, 0xD30560258F54E6BB], - [0xE950DF20247C83FD, 0x47C6B82EF32A2069], - [0x91D28B7416CDD27E, 0x4CDC331D57FA5442], - [0xB6472E511C81471E, 0xE0133FE4ADF8E952], - [0xE3D8F9E563A198E5, 0x58180FDDD97723A7], - [0x8E679C2F5E44FF8F, 0x570F09EAA7EA7648], - [0xB201833B35D63F73, 0x2CD2CC6551E513DA], - [0xDE81E40A034BCF50, 0xF8077F7EA65E58D1], - [0x8B112E86420F6192, 0xFB04AFAF27FAF783], - [0xADD57A27D29339F6, 0x79C5DB9AF1F9B563], - [0xD94AD8B1C7380874, 0x18375281AE7822BC], - [0x87CEC76F1C830549, 0x8F2293910D0B15B6], - [0xA9C2794AE3A3C69B, 0xB2EB3875504DDB23], - [0xD433179D9C8CB841, 0x5FA60692A46151EC], - [0x849FEEC281D7F329, 0xDBC7C41BA6BCD333], - [0xA5C7EA73224DEFF3, 0x12B9B522906C0800], - [0xCF39E50FEAE16BF0, 0xD768226B34870A00], - [0x81842F29F2CCE376, 0xE6A1158300D46640], - [0xA1E53AF46F801C53, 0x60495AE3C1097FD0], - [0xCA5E89B18B602368, 0x385BB19CB14BDFC4], - [0xFCF62C1DEE382C42, 0x46729E03DD9ED7B5], - [0x9E19DB92B4E31BA9, 0x6C07A2C26A8346D1], - [0xC5A05277621BE294, 0xC7098B7305241886], - [0xF70867153AA2DB39, 0xB8CBEE4FC66D1EA7], - [0x9A65406D44A5C903, 0x737F74F1DC043328], - [0xC0FE908895CF3B44, 0x505F522E53053FF2], - [0xF13E34AABB430A15, 0x647726B9E7C68FEF], - [0x96C6E0EAB509E64D, 0x5ECA783430DC19F5], - [0xBC789925624C5FE1, 0xB67D16413D132073], - [0xEB96BF6EBADF77D9, 0xE41C5BD18C57E88F], - [0x933E37A534CBAAE8, 0x8E91B962F7B6F15A], - [0xB80DC58E81FE95A1, 0x723627BBB5A4ADB0], - [0xE61136F2227E3B0A, 0xCEC3B1AAA30DD91C], - [0x8FCAC257558EE4E6, 0x213A4F0AA5E8A7B2], - [0xB3BD72ED2AF29E20, 0xA988E2CD4F62D19E], - [0xE0ACCFA875AF45A8, 0x93EB1B80A33B8605], - [0x8C6C01C9498D8B89, 0xBC72F130660533C3], - [0xAF87023B9BF0EE6B, 0xEB8FAD7C7F8680B4], - [0xDB68C2CA82ED2A06, 0xA67398DB9F6820E1], - [0x892179BE91D43A44, 0x88083F8943A1148D], - [0xAB69D82E364948D4, 0x6A0A4F6B948959B0], - [0xD6444E39C3DB9B0A, 0x848CE34679ABB01C], - [0x85EAB0E41A6940E6, 0xF2D80E0C0C0B4E12], - [0xA7655D1D2103911F, 0x6F8E118F0F0E2196], - [0xD13EB46469447567, 0x4B7195F2D2D1A9FB], - [0x82C730BEC1CAC961, 0x8F26FDB7C3C30A3D], - [0xA378FCEE723D7BB9, 0xB2F0BD25B4B3CCCC], - [0xCC573C2A0ECCDAA7, 0xDFACEC6F21E0C000], - [0xFF6D0B3492801151, 0x9798278AEA58EFFF], - [0x9FA42700DB900AD2, 0x5EBF18B6D2779600], - [0xC78D30C112740D87, 0xF66EDEE487157B80], - [0xF9707CF1571110E9, 0xB40A969DA8DADA5F], - [0x9BE64E16D66AAA91, 0x70869E228988C87C], - [0xC2DFE19C8C055536, 0xCCA845AB2BEAFA9B], - [0xF397DA03AF06AA83, 0x3FD25715F6E5B941], - [0x983EE8424D642A92, 0x07E3766DBA4F93C9], - [0xBE4EA252E0BD3537, 0x89DC540928E378BB], - [0xEDE24AE798EC8284, 0x2C53690B731C56EA], - [0x94AD6ED0BF93D193, 0x9BB421A727F1B652], - [0xB9D8CA84EF78C5F7, 0x42A12A10F1EE23E7], - [0xE84EFD262B56F775, 0x134974952E69ACE0], - [0x91315E37DB165AA9, 0x2C0DE8DD3D020C0C], - [0xB57DB5C5D1DBF153, 0x771163148C428F0F], - [0xE2DD23374652EDA8, 0x54D5BBD9AF5332D3], - [0x8DCA36028BF3D489, 0x350595680D93FFC4], - [0xB13CC3832EF0C9AC, 0x8246FAC210F8FFB5], - [0xDD8BF463FAACFC16, 0x62D8B97295373FA2], - [0x8A7778BE7CAC1D8E, 0xFDC773E79D4287C5], - [0xAD1556EE1BD724F1, 0x7D3950E1849329B7], - [0xD85AACA9A2CCEE2E, 0xDC87A519E5B7F424], - [0x8738ABEA05C014DD, 0xA9D4C7302F92F897], - [0xA906D6E487301A14, 0xD449F8FC3B77B6BC], - [0xD3488C9DA8FC2099, 0xC95C773B4A55A46B], - [0x840D57E2899D945F, 0x7DD9CA850E7586C3], - [0xA510ADDB2C04F977, 0x5D503D265212E874], - [0xCE54D951F70637D5, 0x34A44C6FE697A291], - [0x80F507D33A63E2E5, 0x40E6AFC5F01EC59B], - [0xA13249C808FCDB9F, 0x91205BB76C267701], - [0xC97EDC3A0B3C1286, 0x356872A5473014C1], - [0xFBDE93488E0B1728, 0xC2C28F4E98FC19F2], - [0x9D6B1C0D58C6EE79, 0xD9B999911F9D9037], - [0xC4C5E310AEF8AA17, 0x1027FFF56784F445], - [0xF5F75BD4DAB6D49D, 0xD431FFF2C1663156], - [0x99BA996508B244E2, 0x049F3FF7B8DFDED6], - [0xC0293FBE4ADED61B, 0x85C70FF5A717D68B], - [0xF0338FADDD968BA1, 0x2738D3F310DDCC2E], - [0x962039CCAA7E1745, 0xB8838477EA8A9F9D], - [0xBBA8483FD51D9D16, 0xE6A46595E52D4784], - [0xEA925A4FCA65045B, 0x604D7EFB5E789965], - [0x929B7871DE7F22B9, 0x1C306F5D1B0B5FDF], - [0xB742568E561EEB67, 0x633C8B3461CE37D7], - [0xE512EC31EBA6A641, 0x3C0BAE017A41C5CD], - [0x8F2BD39F334827E9, 0xC5874CC0EC691BA0], - [0xB2F6C887001A31E3, 0xF6E91FF127836288], - [0xDFB47AA8C020BE5C, 0xB4A367ED71643B2A], - [0x8BD0CCA9781476F9, 0x50E620F466DEA4FA], - [0xAEC4FFD3D61994B8, 0xA51FA93180964E39], - [0xDA763FC8CB9FF9E6, 0x8E67937DE0BBE1C7], - [0x8889E7DD7F43FC2F, 0x7900BC2EAC756D1C], - [0xAAAC61D4DF14FB3B, 0x5740EB3A5792C863], - [0xD5577A4A16DA3A0A, 0x2D112608ED777A7C], - [0x8556AC6E4E486446, 0x5C2AB7C5946AAC8E], - [0xA6AC5789E1DA7D58, 0xF33565B6F98557B1], - [0xD0576D6C5A511CAE, 0xF002BF24B7E6AD9D], - [0x8236A463B872B1ED, 0xB601B776F2F02C82], - [0xA2C44D7CA68F5E68, 0xE3822554AFAC37A3], - [0xCB7560DBD0333602, 0xDC62AEA9DB97458C], - [0xFE52B912C4400382, 0x537B5A54527D16EE], - [0x9EF3B3ABBAA80231, 0x742D1874B38E2E55], - [0xC6B0A096A95202BE, 0xD1385E91E071B9EA], - [0xF85CC8BC53A6836D, 0x45867636588E2865], - [0x9B39FD75B4481224, 0x4B7409E1F758D93F], - [0xC2087CD3215A16AD, 0x5E510C5A752F0F8F], - [0xF28A9C07E9B09C59, 0xB5E54F71127AD373], - [0x9796A184F20E61B7, 0x71AF51A6AB8CC428], - [0xBD7C49E62E91FA25, 0x4E1B2610566FF531], - [0xECDB5C5FBA3678AF, 0xA1A1EF946C0BF27E], - [0x940919BBD4620B6D, 0x250535BCC387778F], - [0xB90B602AC97A8E48, 0x6E46832BF4695572], - [0xE74E38357BD931DB, 0x89D823F6F183AACF], - [0x9090E3216D67BF29, 0x9627167A56F24AC1], - [0xB4B51BE9C8C1AEF3, 0xBBB0DC18ECAEDD72], - [0xE1E262E43AF21AAF, 0x6A9D131F27DA94CE], - [0x8D2D7DCEA4D750AE, 0xA2A22BF378E89D01], - [0xB078DD424E0D24D9, 0x0B4AB6F05722C441], - [0xDC971492E1906E0F, 0x4E1D64AC6CEB7551], - [0x89DE6CDBCCFA44CA, 0x90D25EEBC4132953], - [0xAC560812C038D5FC, 0xF506F6A6B517F3A7], - [0xD76B8A1770470B7B, 0xF248B450625DF091], - [0x86A3364EA62C672D, 0xD76D70B23D7AB65B], - [0xA84C03E24FB780F8, 0x0D48CCDECCD963F2], - [0xD25F04DAE3A56136, 0x109B0016800FBCEE], - [0x837B6308CE475CC2, 0xCA60E00E1009D615], - [0xA45A3BCB01D933F2, 0x3CF91811940C4B9A], - [0xCD70CABDC24F80EF, 0xCC375E15F90F5E80], - [0x80667EB69971B095, 0x3FA29ACDBBA99B10], - [0xA0801E643FCE1CBB, 0x8F8B41812A9401D4], - [0xC8A025FD4FC1A3E9, 0x336E11E175390249], - [0xFAC82F7CA3B20CE4, 0x80499659D28742DC], - [0x9CBD1DADE64F480E, 0x302DFDF8239489C9], - [0xC3EC65195FE31A12, 0xBC397D762C79AC3C], - [0xF4E77E5FB7DBE096, 0x2B47DCD3B798174B], - [0x9910AEFBD2E96C5E, 0xDB0CEA0452BF0E8F], - [0xBF54DABAC7A3C775, 0x51D02485676ED232], - [0xEF2A1169798CB953, 0xA6442DA6C14A86BF], - [0x957A4AE1EBF7F3D4, 0xA7EA9C8838CE9437], - [0xBAD8DD9A66F5F0C9, 0x91E543AA47023945], - [0xE98F150100B36CFB, 0xB65E9494D8C2C796], - [0x91F96D20A070241D, 0xB1FB1CDD0779BCBE], - [0xB677C868C88C2D24, 0xDE79E41449582BED], - [0xE415BA82FAAF386D, 0xD6185D195BAE36E9], - [0x8E8D9491DCAD8344, 0x05CF3A2FD94CE251], - [0xB230F9B653D8E415, 0x074308BBCFA01AE6], - [0xDEBD3823E8CF1D1A, 0x4913CAEAC388219F], - [0x8B36431671817230, 0x6DAC5ED2BA351504], - [0xAE03D3DC0DE1CEBD, 0x8917768768C25A44], - [0xD984C8D3115A426C, 0xAB5D542942F2F0D6], - [0x87F2FD83EAD86983, 0x4B1A5499C9D7D685], - [0xA9EFBCE4E58E83E4, 0x1DE0E9C03C4DCC27], - [0xD46BAC1E1EF224DD, 0x255924304B613F31], - [0x84C34B92D357570A, 0x3757B69E2F1CC77E], - [0xA5F41E77882D2CCD, 0xC52DA445BAE3F95E], - [0xCF7126156A387800, 0xF6790D57299CF7B5], - [0x81A6B7CD62634B00, 0xFA0BA8567A021AD1], - [0xA21065C0BAFC1DC0, 0xF88E926C1882A186], - [0xCA947F30E9BB2530, 0xF6B237071EA349E7], - [0xFD399EFD2429EE7C, 0xF45EC4C8E64C1C61], - [0x9E44035E369A350D, 0x78BB3AFD8FEF91BD], - [0xC5D50435C440C251, 0xD6EA09BCF3EB762C], - [0xF74A45433550F2E5, 0x0CA48C2C30E653B7], - [0x9A8E6B4A015297CF, 0x27E6D79B9E8FF452], - [0xC132061C81A73DC3, 0xF1E08D828633F167], - [0xF17E87A3A2110D34, 0xAE58B0E327C0EDC0], - [0x96EF14C6454AA840, 0x4CF76E8DF8D89498], - [0xBCAAD9F7D69D5250, 0x60354A31770EB9BE], - [0xEBD59075CC44A6E4, 0x78429CBDD4D2682E], - [0x93657A499FAAE84F, 0xCB29A1F6A503811D], - [0xB83ED8DC0795A262, 0x7DF40A744E446164], - [0xE64E8F13097B0AFB, 0x1D710D1161D579BD], - [0x8FF1196BE5ECE6DD, 0xF266A82ADD256C16], - [0xB3ED5FC6DF682094, 0x2F005235946EC71C], - [0xE0E8B7B8974228B9, 0x3AC066C2F98A78E2], - [0x8C9172D35E895974, 0xC4B84039DBF68B8E], - [0xAFB5CF88362BAFD1, 0xB5E6504852F42E71], - [0xDBA3436A43B69BC5, 0xE35FE45A67B13A0D], - [0x89460A226A52215B, 0x0E1BEEB880CEC448], - [0xAB978CAB04E6A9B2, 0xD1A2EA66A102755A], - [0xD67D6FD5C620541E, 0x460BA500494312B1], - [0x860E65E59BD43493, 0xEBC747202DC9EBAF], - [0xA791FF5F02C941B8, 0xA6B918E8393C669A], - [0xD1767F36C37B9226, 0x90675F22478B8041], - [0x82EA0F823A2D3B57, 0x7A409B756CB73028], - [0xA3A49362C8B88A2D, 0x58D0C252C7E4FC33], - [0xCC8DB83B7AE6ACB9, 0xAF04F2E779DE3B3F], - [0xFFB1264A59A057E7, 0xDAC62FA15855CA0F], - [0x9FCEB7EE780436F0, 0x48BBDDC4D7359E49], - [0xC7C265EA160544AC, 0x5AEAD5360D0305DC], - [0xF9B2FF649B8695D7, 0x71A58A839043C753], - [0x9C0FDF9EE1341DA7, 0xA70776923A2A5C94], - [0xC313D78699812510, 0x50C95436C8B4F3B9], - [0xF3D8CD683FE16E54, 0x64FBA9447AE230A7], - [0x9867806127ECE4F5, 0xBF1D49CACCCD5E68], - [0xBE81607971E81E32, 0xEEE49C3D8000B602], - [0xEE21B897CE6225BE, 0x6A9DC34CE000E383], - [0x94D5135EE0FD5797, 0x02A29A100C008E32], - [0xBA0A5836993CAD7D, 0xC34B40940F00B1BE], - [0xE88CEE443F8BD8DC, 0xF41E10B912C0DE2E], - [0x915814EAA7B76789, 0x7892CA73ABB88ADD], - [0xB5AE1A2551A5416C, 0xD6B77D1096A6AD94], - [0xE319A0AEA60E91C7, 0xCC655C54BC5058F9], -]; - -// static immutable short[1025] p10_exponents = [ -1764, -1761, @@ -2064,3 +1034,2060 @@ static immutable short[1025] p10_exponents = [ 1634, 1637, ]; + +static immutable align(16) ulong[1025] p10_coefficients_h = [ + 0x9049EE32DB23D21C, + 0xB45C69BF91ECC6A4, + 0xE173842F7667F84C, + 0x8CE8329DAA00FB30, + 0xB0223F45148139FC, + 0xDC2ACF1659A1887B, + 0x899AC16DF804F54D, + 0xAC0171C9760632A0, + 0xD701CE3BD387BF48, + 0x866120E56434D78D, + 0xA7F9691EBD420D70, + 0xD1F7C3666C9290CC, + 0x833ADA2003DB9A80, + 0xA40990A804D2811F, + 0xCD0BF4D206072167, + 0x8027790343C474E1, + 0xA031574414B59219, + 0xC83DAD1519E2F69F, + 0xFA4D185A605BB447, + 0x9C702F387C3950AC, + 0xC38C3B069B47A4D7, + 0xF46F49C842198E0D, + 0x98C58E1D294FF8C8, + 0xBEF6F1A473A3F6FA, + 0xEEB4AE0D908CF4B9, + 0x9530ECC87A5818F3, + 0xBA7D27FA98EE1F30, + 0xE91C71F93F29A6FC, + 0x91B1C73BC77A085E, + 0xB61E390AB9588A75, + 0xE3A5C74D67AEAD12, + 0x8E479C9060CD2C2C, + 0xB1D983B479007736, + 0xDE4FE4A197409504, + 0x8AF1EEE4FE885D22, + 0xADAE6A9E3E2A746B, + 0xD91A0545CDB51186, + 0x87B0434BA0912AF4, + 0xA99C541E88B575B1, + 0xD40369262AE2D31D, + 0x848221B7DACDC3F2, + 0xA5A2AA25D18134EE, + 0xCF0B54AF45E1822A, + 0x816714ED8BACF15A, + 0xA1C0DA28EE982DB1, + 0xCA3110B32A3E391D, + 0xFCBD54DFF4CDC764, + 0x9DF6550BF9009C9F, + 0xC573EA4EF740C3C6, + 0xF6D0E4E2B510F4B8, + 0x9A428F0DB12A98F3, + 0xC0D332D11D753F30, + 0xF107FF8564D28EFC, + 0x96A4FFB35F03995D, + 0xBC4E3FA036C47FB5, + 0xEB61CF8844759FA2, + 0x931D21B52AC983C5, + 0xB7E46A22757BE4B6, + 0xE5DD84AB12DADDE4, + 0x8FAA72EAEBC8CAAF, + 0xB3950FA5A6BAFD5A, + 0xE07A538F1069BCB1, + 0x8C4C74396A4215EE, + 0xAF5F9147C4D29B6A, + 0xDB377599B6074245, + 0x8902A98011C4896B, + 0xAB4353E01635ABC6, + 0xD61428D81BC316B7, + 0x85CC99871159EE32, + 0xA73FBFE8D5B069BF, + 0xD10FAFE30B1C842F, + 0x82A9CDEDE6F1D29D, + 0xA354416960AE4744, + 0xCC2951C3B8D9D916, + 0xFF33A634A7104F5B, + 0x9F8047E0E86A3199, + 0xC76059D92284BDFF, + 0xF938704F6B25ED7F, + 0x9BC34631A2F7B46F, + 0xC2B417BE0BB5A18B, + 0xF3611DAD8EA309EE, + 0x981CB28C7925E635, + 0xBE23DF2F976F5FC2, + 0xEDACD6FB7D4B37B2, + 0x948C065D2E4F02CF, + 0xB9AF07F479E2C383, + 0xE81AC9F1985B7464, + 0x9110BE36FF3928BF, + 0xB554EDC4BF0772EE, + 0xE2AA2935EEC94FAA, + 0x8DAA59C1B53DD1CA, + 0xB114F032228D463D, + 0xDD5A2C3EAB3097CC, + 0x8A585BA72AFE5EDF, + 0xACEE7290F5BDF697, + 0xD82A0F35332D743D, + 0x871A49813FFC68A6, + 0xA8E0DBE18FFB82D0, + 0xD31912D9F3FA6384, + 0x83EFABC8387C7E32, + 0xA4EB96BA469B9DBF, + 0xCE267C68D842852E, + 0x80D80DC18729933D, + 0xA10E1131E8F3F80C, + 0xC951957E6330F60F, + 0xFBA5FADDFBFD3393, + 0x9D47BCCABD7E403C, + 0xC499ABFD6CDDD04B, + 0xF5C016FCC815445E, + 0x99980E5DFD0D4ABB, + 0xBFFE11F57C509D69, + 0xEFFD9672DB64C4C4, + 0x95FE7E07C91EFAFA, + 0xBB7E1D89BB66B9B9, + 0xEA5DA4EC2A406827, + 0x927A87139A684118, + 0xB71928D88102515E, + 0xE4DF730EA142E5B6, + 0x8F0BA7E924C9CF92, + 0xB2CE91E36DFC4376, + 0xDF82365C497B5454, + 0x8BB161F9ADED14B4, + 0xAE9DBA78196859E1, + 0xDA4529161FC2705A, + 0x886B39ADD3D98638, + 0xAA86081948CFE7C6, + 0xD5278A1F9B03E1B8, + 0x8538B653C0E26D13, + 0xA686E3E8B11B0858, + 0xD0289CE2DD61CA6D, + 0x8219620DCA5D1E84, + 0xA29FBA913CF46625, + 0xCB47A9358C317FAF, + 0xFE199382EF3DDF9B, + 0x9ECFFC31D586ABC1, + 0xC683FB3E4AE856B1, + 0xF824FA0DDDA26C5D, + 0x9B171C48AA8583BA, + 0xC1DCE35AD526E4A9, + 0xF2541C318A709DD3, + 0x9774919EF68662A4, + 0xBD51B606B427FB4D, + 0xECA623886131FA20, + 0x93E7D6353CBF3C54, + 0xB8E1CBC28BEF0B69, + 0xE71A3EB32EEACE43, + 0x9070672FFD52C0EA, + 0xB48C80FBFCA77124, + 0xE1AFA13AFBD14D6E, + 0x8D0DC4C4DD62D064, + 0xB05135F614BB847E, + 0xDC65837399EA659D, + 0x89BF722840327F82, + 0xAC2F4EB2503F1F63, + 0xD73B225EE44EE73B, + 0x8684F57B4EB15085, + 0xA82632DA225DA4A6, + 0xD22FBF90AAF50DD0, + 0x835DD7BA6AD928A2, + 0xA4354DA9058F72CA, + 0xCD42A11346F34F7D, + 0x8049A4AC0C5811AE, + 0xA05C0DD70F6E161A, + 0xC873114CD3499BA0, + 0xFA8FD5A0081C0288, + 0x9C99E58405118195, + 0xC3C05EE50655E1FA, + 0xF4B0769E47EB5A79, + 0x98EE4A22ECF3188C, + 0xBF29DCABA82FDEAE, + 0xEEF453D6923BD65A, + 0x9558B4661B6565F8, + 0xBAAEE17FA23EBF76, + 0xE95A99DF8ACE6F54, + 0x91D8A02BB6C10594, + 0xB64EC836A47146FA, + 0xE3E27A444D8D98B8, + 0x8E6D8C6AB0787F73, + 0xB208EF855C969F50, + 0xDE8B2B66B3BC4724, + 0x8B16FB203055AC76, + 0xADDCB9E83C6B1794, + 0xD953E8624B85DD79, + 0x87D4713D6F33AA6C, + 0xA9C98D8CCB009506, + 0xD43BF0EFFDC0BA48, + 0x84A57695FE98746D, + 0xA5CED43B7E3E9188, + 0xCF42894A5DCE35EA, + 0x818995CE7AA0E1B2, + 0xA1EBFB4219491A1F, + 0xCA66FA129F9B60A7, + 0xFD00B897478238D1, + 0x9E20735E8CB16382, + 0xC5A890362FDDBC63, + 0xF712B443BBD52B7C, + 0x9A6BB0AA55653B2D, + 0xC1069CD4EABE89F9, + 0xF148440A256E2C77, + 0x96CD2A865764DBCA, + 0xBC807527ED3E12BD, + 0xEBA09271E88D976C, + 0x93445B8731587EA3, + 0xB8157268FDAE9E4C, + 0xE61ACF033D1A45DF, + 0x8FD0C16206306BAC, + 0xB3C4F1BA87BC8697, + 0xE0B62E2929ABA83C, + 0x8C71DCD9BA0B4926, + 0xAF8E5410288E1B6F, + 0xDB71E91432B1A24B, + 0x892731AC9FAF056F, + 0xAB70FE17C79AC6CA, + 0xD64D3D9DB981787D, + 0x85F0468293F0EB4E, + 0xA76C582338ED2622, + 0xD1476E2C07286FAA, + 0x82CCA4DB847945CA, + 0xA37FCE126597973D, + 0xCC5FC196FEFD7D0C, + 0xFF77B1FCBEBCDC4F, + 0x9FAACF3DF73609B1, + 0xC795830D75038C1E, + 0xF97AE3D0D2446F25, + 0x9BECCE62836AC577, + 0xC2E801FB244576D5, + 0xF3A20279ED56D48A, + 0x9845418C345644D7, + 0xBE5691EF416BD60C, + 0xEDEC366B11C6CB8F, + 0x94B3A202EB1C3F39, + 0xB9E08A83A5E34F08, + 0xE858AD248F5C22CA, + 0x91376C36D99995BE, + 0xB58547448FFFFB2E, + 0xE2E69915B3FFF9F9, + 0x8DD01FAD907FFC3C, + 0xB1442798F49FFB4B, + 0xDD95317F31C7FA1D, + 0x8A7D3EEF7F1CFC52, + 0xAD1C8EAB5EE43B67, + 0xD863B256369D4A41, + 0x873E4F75E2224E68, + 0xA90DE3535AAAE202, + 0xD3515C2831559A83, + 0x8412D9991ED58092, + 0xA5178FFF668AE0B6, + 0xCE5D73FF402D98E4, + 0x80FA687F881C7F8E, + 0xA139029F6A239F72, + 0xC987434744AC874F, + 0xFBE9141915D7A922, + 0x9D71AC8FADA6C9B5, + 0xC4CE17B399107C23, + 0xF6019DA07F549B2B, + 0x99C102844F94E0FB, + 0xC0314325637A193A, + 0xF03D93EEBC589F88, + 0x96267C7535B763B5, + 0xBBB01B9283253CA3, + 0xEA9C227723EE8BCB, + 0x92A1958A7675175F, + 0xB749FAED14125D37, + 0xE51C79A85916F485, + 0x8F31CC0937AE58D3, + 0xB2FE3F0B8599EF08, + 0xDFBDCECE67006AC9, + 0x8BD6A141006042BE, + 0xAECC49914078536D, + 0xDA7F5BF590966849, + 0x888F99797A5E012D, + 0xAAB37FD7D8F58179, + 0xD5605FCDCF32E1D7, + 0x855C3BE0A17FCD26, + 0xA6B34AD8C9DFC070, + 0xD0601D8EFC57B08C, + 0x823C12795DB6CE57, + 0xA2CB1717B52481ED, + 0xCB7DDCDDA26DA269, + 0xFE5D54150B090B03, + 0x9EFA548D26E5A6E2, + 0xC6B8E9B0709F109A, + 0xF867241C8CC6D4C1, + 0x9B407691D7FC44F8, + 0xC21094364DFB5637, + 0xF294B943E17A2BC4, + 0x979CF3CA6CEC5B5B, + 0xBD8430BD08277231, + 0xECE53CEC4A314EBE, + 0x940F4613AE5ED137, + 0xB913179899F68584, + 0xE757DD7EC07426E5, + 0x9096EA6F3848984F, + 0xB4BCA50B065ABE63, + 0xE1EBCE4DC7F16DFC, + 0x8D3360F09CF6E4BD, + 0xB080392CC4349DED, + 0xDCA04777F541C568, + 0x89E42CAAF9491B61, + 0xAC5D37D5B79B6239, + 0xD77485CB25823AC7, + 0x86A8D39EF77164BD, + 0xA8530886B54DBDEC, + 0xD267CAA862A12D67, + 0x8380DEA93DA4BC60, + 0xA46116538D0DEB78, + 0xCD795BE870516656, + 0x806BD9714632DFF6, + 0xA086CFCD97BF97F4, + 0xC8A883C0FDAF7DF0, + 0xFAD2A4B13D1B5D6C, + 0x9CC3A6EEC6311A64, + 0xC3F490AA77BD60FD, + 0xF4F1B4D515ACB93C, + 0x991711052D8BF3C5, + 0xBF5CD54678EEF0B7, + 0xEF340A98172AACE5, + 0x9580869F0E7AAC0F, + 0xBAE0A846D2195713, + 0xE998D258869FACD7, + 0x91FF83775423CC06, + 0xB67F6455292CBF08, + 0xE41F3D6A7377EECA, + 0x8E938662882AF53E, + 0xB23867FB2A35B28E, + 0xDEC681F9F4C31F31, + 0x8B3C113C38F9F37F, + 0xAE0B158B4738705F, + 0xD98DDAEE19068C76, + 0x87F8A8D4CFA417CA, + 0xA9F6D30A038D1DBC, + 0xD47487CC8470652B, + 0x84C8D4DFD2C63F3B, + 0xA5FB0A17C777CF0A, + 0xCF79CC9DB955C2CC, + 0x81AC1FE293D599C0, + 0xA21727DB38CB0030, + 0xCA9CF1D206FDC03C, + 0xFD442E4688BD304B, + 0x9E4A9CEC15763E2F, + 0xC5DD44271AD3CDBA, + 0xF7549530E188C129, + 0x9A94DD3E8CF578BA, + 0xC13A148E3032D6E8, + 0xF18899B1BC3F8CA2, + 0x96F5600F15A7B7E5, + 0xBCB2B812DB11A5DE, + 0xEBDF661791D60F56, + 0x936B9FCEBB25C996, + 0xB84687C269EF3BFB, + 0xE65829B3046B0AFA, + 0x8FF71A0FE2C2E6DC, + 0xB3F4E093DB73A093, + 0xE0F218B8D25088B8, + 0x8C974F7383725573, + 0xAFBD2350644EEAD0, + 0xDBAC6C247D62A584, + 0x894BC396CE5DA772, + 0xAB9EB47C81F5114F, + 0xD686619BA27255A3, + 0x8613FD0145877586, + 0xA798FC4196E952E7, + 0xD17F3B51FCA3A7A1, + 0x82EF85133DE648C5, + 0xA3AB66580D5FDAF6, + 0xCC963FEE10B7D1B3, + 0xFFBBCFE994E5C620, + 0x9FD561F1FD0F9BD4, + 0xC7CABA6E7C5382C9, + 0xF9BD690A1B68637B, + 0x9C1661A651213E2D, + 0xC31BFA0FE5698DB8, + 0xF3E2F893DEC3F126, + 0x986DDB5C6B3A76B8, + 0xBE89523386091466, + 0xEE2BA6C0678B597F, + 0x94DB483840B717F0, + 0xBA121A4650E4DDEC, + 0xE896A0D7E51E1566, + 0x915E2486EF32CD60, + 0xB5B5ADA8AAFF80B8, + 0xE3231912D5BF60E6, + 0x8DF5EFABC5979C90, + 0xB1736B96B6FD83B4, + 0xDDD0467C64BCE4A1, + 0x8AA22C0DBEF60EE4, + 0xAD4AB7112EB3929E, + 0xD89D64D57A607745, + 0x87625F056C7C4A8B, + 0xA93AF6C6C79B5D2E, + 0xD389B47879823479, + 0x843610CB4BF160CC, + 0xA54394FE1EEDB8FF, + 0xCE947A3DA6A9273E, + 0x811CCC668829B887, + 0xA163FF802A3426A9, + 0xC9BCFF6034C13053, + 0xFC2C3F3841F17C68, + 0x9D9BA7832936EDC1, + 0xC5029163F384A931, + 0xF64335BCF065D37D, + 0x99EA0196163FA42E, + 0xC06481FB9BCF8D3A, + 0xF07DA27A82C37088, + 0x964E858C91BA2655, + 0xBBE226EFB628AFEB, + 0xEADAB0ABA3B2DBE5, + 0x92C8AE6B464FC96F, + 0xB77ADA0617E3BBCB, + 0xE55990879DDCAABE, + 0x8F57FA54C2A9EAB7, + 0xB32DF8E9F3546564, + 0xDFF9772470297EBD, + 0x8BFBEA76C619EF36, + 0xAEFAE51477A06B04, + 0xDAB99E59958885C5, + 0x88B402F7FD75539B, + 0xAAE103B5FCD2A882, + 0xD59944A37C0752A2, + 0x857FCAE62D8493A5, + 0xA6DFBD9FB8E5B88F, + 0xD097AD07A71F26B2, + 0x825ECC24C8737830, + 0xA2F67F2DFA90563B, + 0xCBB41EF979346BCA, + 0xFEA126B7D78186BD, + 0x9F24B832E6B0F436, + 0xC6EDE63FA05D3144, + 0xF8A95FCF88747D94, + 0x9B69DBE1B548CE7D, + 0xC24452DA229B021C, + 0xF2D56790AB41C2A3, + 0x97C560BA6B0919A6, + 0xBDB6B8E905CB600F, + 0xED246723473E3813, + 0x9436C0760C86E30C, + 0xB94470938FA89BCF, + 0xE7958CB87392C2C3, + 0x90BD77F3483BB9BA, + 0xB4ECD5F01A4AA828, + 0xE2280B6C20DD5232, + 0x8D590723948A535F, + 0xB0AF48EC79ACE837, + 0xDCDB1B2798182245, + 0x8A08F0F8BF0F156B, + 0xAC8B2D36EED2DAC6, + 0xD7ADF884AA879177, + 0x86CCBB52EA94BAEB, + 0xA87FEA27A539E9A5, + 0xD29FE4B18E88640F, + 0x83A3EEEEF9153E89, + 0xA48CEAAAB75A8E2B, + 0xCDB02555653131B6, + 0x808E17555F3EBF12, + 0xA0B19D2AB70E6ED6, + 0xC8DE047564D20A8C, + 0xFB158592BE068D2F, + 0x9CED737BB6C4183D, + 0xC428D05AA4751E4D, + 0xF53304714D9265E0, + 0x993FE2C6D07B7FAC, + 0xBF8FDB78849A5F97, + 0xEF73D256A5C0F77D, + 0x95A8637627989AAE, + 0xBB127C53B17EC159, + 0xE9D71B689DDE71B0, + 0x9226712162AB070E, + 0xB6B00D69BB55C8D1, + 0xE45C10C42A2B3B06, + 0x8EB98A7A9A5B04E3, + 0xB267ED1940F1C61C, + 0xDF01E85F912E37A3, + 0x8B61313BBABCE2C6, + 0xAE397D8AA96C1B78, + 0xD9C7DCED53C72256, + 0x881CEA14545C7575, + 0xAA242499697392D3, + 0xD4AD2DBFC3D07788, + 0x84EC3C97DA624AB5, + 0xA6274BBDD0FADD62, + 0xCFB11EAD453994BA, + 0x81CEB32C4B43FCF5, + 0xA2425FF75E14FC32, + 0xCAD2F7F5359A3B3E, + 0xFD87B5F28300CA0E, + 0x9E74D1B791E07E48, + 0xC612062576589DDB, + 0xF79687AED3EEC551, + 0x9ABE14CD44753B53, + 0xC16D9A0095928A27, + 0xF1C90080BAF72CB1, + 0x971DA05074DA7BEF, + 0xBCE5086492111AEB, + 0xEC1E4A7DB69561A5, + 0x9392EE8E921D5D07, + 0xB877AA3236A4B449, + 0xE69594BEC44DE15B, + 0x901D7CF73AB0ACD9, + 0xB424DC35095CD80F, + 0xE12E13424BB40E13, + 0x8CBCCC096F5088CC, + 0xAFEBFF0BCB24AAFF, + 0xDBE6FECEBDEDD5BF, + 0x89705F4136B4A597, + 0xABCC77118461CEFD, + 0xD6BF94D5E57A42BC, + 0x8637BD05AF6C69B6, + 0xA7C5AC471B478423, + 0xD1B71758E219652C, + 0x83126E978D4FDF3B, + 0xA3D70A3D70A3D70A, + 0xCCCCCCCCCCCCCCCD, + 0x8000000000000000, + 0xA000000000000000, + 0xC800000000000000, + 0xFA00000000000000, + 0x9C40000000000000, + 0xC350000000000000, + 0xF424000000000000, + 0x9896800000000000, + 0xBEBC200000000000, + 0xEE6B280000000000, + 0x9502F90000000000, + 0xBA43B74000000000, + 0xE8D4A51000000000, + 0x9184E72A00000000, + 0xB5E620F480000000, + 0xE35FA931A0000000, + 0x8E1BC9BF04000000, + 0xB1A2BC2EC5000000, + 0xDE0B6B3A76400000, + 0x8AC7230489E80000, + 0xAD78EBC5AC620000, + 0xD8D726B7177A8000, + 0x878678326EAC9000, + 0xA968163F0A57B400, + 0xD3C21BCECCEDA100, + 0x84595161401484A0, + 0xA56FA5B99019A5C8, + 0xCECB8F27F4200F3A, + 0x813F3978F8940984, + 0xA18F07D736B90BE5, + 0xC9F2C9CD04674EDF, + 0xFC6F7C4045812296, + 0x9DC5ADA82B70B59E, + 0xC5371912364CE305, + 0xF684DF56C3E01BC7, + 0x9A130B963A6C115C, + 0xC097CE7BC90715B3, + 0xF0BDC21ABB48DB20, + 0x96769950B50D88F4, + 0xBC143FA4E250EB31, + 0xEB194F8E1AE525FD, + 0x92EFD1B8D0CF37BE, + 0xB7ABC627050305AE, + 0xE596B7B0C643C719, + 0x8F7E32CE7BEA5C70, + 0xB35DBF821AE4F38C, + 0xE0352F62A19E306F, + 0x8C213D9DA502DE45, + 0xAF298D050E4395D7, + 0xDAF3F04651D47B4C, + 0x88D8762BF324CD10, + 0xAB0E93B6EFEE0054, + 0xD5D238A4ABE98068, + 0x85A36366EB71F041, + 0xA70C3C40A64E6C52, + 0xD0CF4B50CFE20766, + 0x82818F1281ED44A0, + 0xA321F2D7226895C8, + 0xCBEA6F8CEB02BB3A, + 0xFEE50B7025C36A08, + 0x9F4F2726179A2245, + 0xC722F0EF9D80AAD6, + 0xF8EBAD2B84E0D58C, + 0x9B934C3B330C8577, + 0xC2781F49FFCFA6D5, + 0xF316271C7FC3908B, + 0x97EDD871CFDA3A57, + 0xBDE94E8E43D0C8EC, + 0xED63A231D4C4FB27, + 0x945E455F24FB1CF9, + 0xB975D6B6EE39E437, + 0xE7D34C64A9C85D44, + 0x90E40FBEEA1D3A4B, + 0xB51D13AEA4A488DD, + 0xE264589A4DCDAB15, + 0x8D7EB76070A08AED, + 0xB0DE65388CC8ADA8, + 0xDD15FE86AFFAD912, + 0x8A2DBF142DFCC7AB, + 0xACB92ED9397BF996, + 0xD7E77A8F87DAF7FC, + 0x86F0AC99B4E8DAFD, + 0xA8ACD7C0222311BD, + 0xD2D80DB02AABD62C, + 0x83C7088E1AAB65DB, + 0xA4B8CAB1A1563F52, + 0xCDE6FD5E09ABCF27, + 0x80B05E5AC60B6178, + 0xA0DC75F1778E39D6, + 0xC913936DD571C84C, + 0xFB5878494ACE3A5F, + 0x9D174B2DCEC0E47B, + 0xC45D1DF942711D9A, + 0xF5746577930D6501, + 0x9968BF6ABBE85F20, + 0xBFC2EF456AE276E9, + 0xEFB3AB16C59B14A3, + 0x95D04AEE3B80ECE6, + 0xBB445DA9CA61281F, + 0xEA1575143CF97227, + 0x924D692CA61BE758, + 0xB6E0C377CFA2E12E, + 0xE498F455C38B997A, + 0x8EDF98B59A373FEC, + 0xB2977EE300C50FE7, + 0xDF3D5E9BC0F653E1, + 0x8B865B215899F46D, + 0xAE67F1E9AEC07188, + 0xDA01EE641A708DEA, + 0x884134FE908658B2, + 0xAA51823E34A7EEDF, + 0xD4E5E2CDC1D1EA96, + 0x850FADC09923329E, + 0xA6539930BF6BFF46, + 0xCFE87F7CEF46FF17, + 0x81F14FAE158C5F6E, + 0xA26DA3999AEF774A, + 0xCB090C8001AB551C, + 0xFDCB4FA002162A63, + 0x9E9F11C4014DDA7E, + 0xC646D63501A1511E, + 0xF7D88BC24209A565, + 0x9AE757596946075F, + 0xC1A12D2FC3978937, + 0xF209787BB47D6B85, + 0x9745EB4D50CE6333, + 0xBD176620A501FC00, + 0xEC5D3FA8CE427B00, + 0x93BA47C980E98CE0, + 0xB8A8D9BBE123F018, + 0xE6D3102AD96CEC1E, + 0x9043EA1AC7E41393, + 0xB454E4A179DD1877, + 0xE16A1DC9D8545E95, + 0x8CE2529E2734BB1D, + 0xB01AE745B101E9E4, + 0xDC21A1171D42645D, + 0x899504AE72497EBA, + 0xABFA45DA0EDBDE69, + 0xD6F8D7509292D603, + 0x865B86925B9BC5C2, + 0xA7F26836F282B733, + 0xD1EF0244AF2364FF, + 0x8335616AED761F1F, + 0xA402B9C5A8D3A6E7, + 0xCD036837130890A1, + 0x802221226BE55A65, + 0xA02AA96B06DEB0FE, + 0xC83553C5C8965D3D, + 0xFA42A8B73ABBF48D, + 0x9C69A97284B578D8, + 0xC38413CF25E2D70E, + 0xF46518C2EF5B8CD1, + 0x98BF2F79D5993803, + 0xBEEEFB584AFF8604, + 0xEEAABA2E5DBF6785, + 0x952AB45CFA97A0B3, + 0xBA756174393D88E0, + 0xE912B9D1478CEB17, + 0x91ABB422CCB812EF, + 0xB616A12B7FE617AA, + 0xE39C49765FDF9D95, + 0x8E41ADE9FBEBC27D, + 0xB1D219647AE6B31C, + 0xDE469FBD99A05FE3, + 0x8AEC23D680043BEE, + 0xADA72CCC20054AEA, + 0xD910F7FF28069DA4, + 0x87AA9AFF79042287, + 0xA99541BF57452B28, + 0xD3FA922F2D1675F2, + 0x847C9B5D7C2E09B7, + 0xA59BC234DB398C25, + 0xCF02B2C21207EF2F, + 0x8161AFB94B44F57D, + 0xA1BA1BA79E1632DC, + 0xCA28A291859BBF93, + 0xFCB2CB35E702AF78, + 0x9DEFBF01B061ADAB, + 0xC56BAEC21C7A1916, + 0xF6C69A72A3989F5C, + 0x9A3C2087A63F6399, + 0xC0CB28A98FCF3C80, + 0xF0FDF2D3F3C30B9F, + 0x969EB7C47859E744, + 0xBC4665B596706115, + 0xEB57FF22FC0C795A, + 0x9316FF75DD87CBD8, + 0xB7DCBF5354E9BECE, + 0xE5D3EF282A242E82, + 0x8FA475791A569D11, + 0xB38D92D760EC4455, + 0xE070F78D3927556B, + 0x8C469AB843B89563, + 0xAF58416654A6BABB, + 0xDB2E51BFE9D0696A, + 0x88FCF317F22241E2, + 0xAB3C2FDDEEAAD25B, + 0xD60B3BD56A5586F2, + 0x85C7056562757457, + 0xA738C6BEBB12D16D, + 0xD106F86E69D785C8, + 0x82A45B450226B39D, + 0xA34D721642B06084, + 0xCC20CE9BD35C78A5, + 0xFF290242C83396CE, + 0x9F79A169BD203E41, + 0xC75809C42C684DD1, + 0xF92E0C3537826146, + 0x9BBCC7A142B17CCC, + 0xC2ABF989935DDBFE, + 0xF356F7EBF83552FE, + 0x98165AF37B2153DF, + 0xBE1BF1B059E9A8D6, + 0xEDA2EE1C7064130C, + 0x9485D4D1C63E8BE8, + 0xB9A74A0637CE2EE1, + 0xE8111C87C5C1BA9A, + 0x910AB1D4DB9914A0, + 0xB54D5E4A127F59C8, + 0xE2A0B5DC971F303A, + 0x8DA471A9DE737E24, + 0xB10D8E1456105DAD, + 0xDD50F1996B947519, + 0x8A5296FFE33CC930, + 0xACE73CBFDC0BFB7B, + 0xD8210BEFD30EFA5A, + 0x8714A775E3E95C78, + 0xA8D9D1535CE3B396, + 0xD31045A8341CA07C, + 0x83EA2B892091E44E, + 0xA4E4B66B68B65D61, + 0xCE1DE40642E3F4B9, + 0x80D2AE83E9CE78F4, + 0xA1075A24E4421731, + 0xC94930AE1D529CFD, + 0xFB9B7CD9A4A7443C, + 0x9D412E0806E88AA6, + 0xC491798A08A2AD4F, + 0xF5B5D7EC8ACB58A3, + 0x9991A6F3D6BF1766, + 0xBFF610B0CC6EDD3F, + 0xEFF394DCFF8A948F, + 0x95F83D0A1FB69CD9, + 0xBB764C4CA7A44410, + 0xEA53DF5FD18D5514, + 0x92746B9BE2F8552C, + 0xB7118682DBB66A77, + 0xE4D5E82392A40515, + 0x8F05B1163BA6832D, + 0xB2C71D5BCA9023F8, + 0xDF78E4B2BD342CF7, + 0x8BAB8EEFB6409C1A, + 0xAE9672ABA3D0C321, + 0xDA3C0F568CC4F3E9, + 0x8865899617FB1871, + 0xAA7EEBFB9DF9DE8E, + 0xD51EA6FA85785631, + 0x8533285C936B35DF, + 0xA67FF273B8460357, + 0xD01FEF10A657842C, + 0x8213F56A67F6B29C, + 0xA298F2C501F45F43, + 0xCB3F2F7642717713, + 0xFE0EFB53D30DD4D8, + 0x9EC95D1463E8A507, + 0xC67BB4597CE2CE49, + 0xF81AA16FDC1B81DB, + 0x9B10A4E5E9913129, + 0xC1D4CE1F63F57D73, + 0xF24A01A73CF2DCD0, + 0x976E41088617CA02, + 0xBD49D14AA79DBC82, + 0xEC9C459D51852BA3, + 0x93E1AB8252F33B46, + 0xB8DA1662E7B00A17, + 0xE7109BFBA19C0C9D, + 0x906A617D450187E2, + 0xB484F9DC9641E9DB, + 0xE1A63853BBD26451, + 0x8D07E33455637EB3, + 0xB049DC016ABC5E60, + 0xDC5C5301C56B75F7, + 0x89B9B3E11B6329BB, + 0xAC2820D9623BF429, + 0xD732290FBACAF134, + 0x867F59A9D4BED6C0, + 0xA81F301449EE8C70, + 0xD226FC195C6A2F8C, + 0x83585D8FD9C25DB8, + 0xA42E74F3D032F526, + 0xCD3A1230C43FB26F, + 0x80444B5E7AA7CF85, + 0xA0555E361951C367, + 0xC86AB5C39FA63441, + 0xFA856334878FC151, + 0x9C935E00D4B9D8D2, + 0xC3B8358109E84F07, + 0xF4A642E14C6262C9, + 0x98E7E9CCCFBD7DBE, + 0xBF21E44003ACDD2D, + 0xEEEA5D5004981478, + 0x95527A5202DF0CCB, + 0xBAA718E68396CFFE, + 0xE950DF20247C83FD, + 0x91D28B7416CDD27E, + 0xB6472E511C81471E, + 0xE3D8F9E563A198E5, + 0x8E679C2F5E44FF8F, + 0xB201833B35D63F73, + 0xDE81E40A034BCF50, + 0x8B112E86420F6192, + 0xADD57A27D29339F6, + 0xD94AD8B1C7380874, + 0x87CEC76F1C830549, + 0xA9C2794AE3A3C69B, + 0xD433179D9C8CB841, + 0x849FEEC281D7F329, + 0xA5C7EA73224DEFF3, + 0xCF39E50FEAE16BF0, + 0x81842F29F2CCE376, + 0xA1E53AF46F801C53, + 0xCA5E89B18B602368, + 0xFCF62C1DEE382C42, + 0x9E19DB92B4E31BA9, + 0xC5A05277621BE294, + 0xF70867153AA2DB39, + 0x9A65406D44A5C903, + 0xC0FE908895CF3B44, + 0xF13E34AABB430A15, + 0x96C6E0EAB509E64D, + 0xBC789925624C5FE1, + 0xEB96BF6EBADF77D9, + 0x933E37A534CBAAE8, + 0xB80DC58E81FE95A1, + 0xE61136F2227E3B0A, + 0x8FCAC257558EE4E6, + 0xB3BD72ED2AF29E20, + 0xE0ACCFA875AF45A8, + 0x8C6C01C9498D8B89, + 0xAF87023B9BF0EE6B, + 0xDB68C2CA82ED2A06, + 0x892179BE91D43A44, + 0xAB69D82E364948D4, + 0xD6444E39C3DB9B0A, + 0x85EAB0E41A6940E6, + 0xA7655D1D2103911F, + 0xD13EB46469447567, + 0x82C730BEC1CAC961, + 0xA378FCEE723D7BB9, + 0xCC573C2A0ECCDAA7, + 0xFF6D0B3492801151, + 0x9FA42700DB900AD2, + 0xC78D30C112740D87, + 0xF9707CF1571110E9, + 0x9BE64E16D66AAA91, + 0xC2DFE19C8C055536, + 0xF397DA03AF06AA83, + 0x983EE8424D642A92, + 0xBE4EA252E0BD3537, + 0xEDE24AE798EC8284, + 0x94AD6ED0BF93D193, + 0xB9D8CA84EF78C5F7, + 0xE84EFD262B56F775, + 0x91315E37DB165AA9, + 0xB57DB5C5D1DBF153, + 0xE2DD23374652EDA8, + 0x8DCA36028BF3D489, + 0xB13CC3832EF0C9AC, + 0xDD8BF463FAACFC16, + 0x8A7778BE7CAC1D8E, + 0xAD1556EE1BD724F1, + 0xD85AACA9A2CCEE2E, + 0x8738ABEA05C014DD, + 0xA906D6E487301A14, + 0xD3488C9DA8FC2099, + 0x840D57E2899D945F, + 0xA510ADDB2C04F977, + 0xCE54D951F70637D5, + 0x80F507D33A63E2E5, + 0xA13249C808FCDB9F, + 0xC97EDC3A0B3C1286, + 0xFBDE93488E0B1728, + 0x9D6B1C0D58C6EE79, + 0xC4C5E310AEF8AA17, + 0xF5F75BD4DAB6D49D, + 0x99BA996508B244E2, + 0xC0293FBE4ADED61B, + 0xF0338FADDD968BA1, + 0x962039CCAA7E1745, + 0xBBA8483FD51D9D16, + 0xEA925A4FCA65045B, + 0x929B7871DE7F22B9, + 0xB742568E561EEB67, + 0xE512EC31EBA6A641, + 0x8F2BD39F334827E9, + 0xB2F6C887001A31E3, + 0xDFB47AA8C020BE5C, + 0x8BD0CCA9781476F9, + 0xAEC4FFD3D61994B8, + 0xDA763FC8CB9FF9E6, + 0x8889E7DD7F43FC2F, + 0xAAAC61D4DF14FB3B, + 0xD5577A4A16DA3A0A, + 0x8556AC6E4E486446, + 0xA6AC5789E1DA7D58, + 0xD0576D6C5A511CAE, + 0x8236A463B872B1ED, + 0xA2C44D7CA68F5E68, + 0xCB7560DBD0333602, + 0xFE52B912C4400382, + 0x9EF3B3ABBAA80231, + 0xC6B0A096A95202BE, + 0xF85CC8BC53A6836D, + 0x9B39FD75B4481224, + 0xC2087CD3215A16AD, + 0xF28A9C07E9B09C59, + 0x9796A184F20E61B7, + 0xBD7C49E62E91FA25, + 0xECDB5C5FBA3678AF, + 0x940919BBD4620B6D, + 0xB90B602AC97A8E48, + 0xE74E38357BD931DB, + 0x9090E3216D67BF29, + 0xB4B51BE9C8C1AEF3, + 0xE1E262E43AF21AAF, + 0x8D2D7DCEA4D750AE, + 0xB078DD424E0D24D9, + 0xDC971492E1906E0F, + 0x89DE6CDBCCFA44CA, + 0xAC560812C038D5FC, + 0xD76B8A1770470B7B, + 0x86A3364EA62C672D, + 0xA84C03E24FB780F8, + 0xD25F04DAE3A56136, + 0x837B6308CE475CC2, + 0xA45A3BCB01D933F2, + 0xCD70CABDC24F80EF, + 0x80667EB69971B095, + 0xA0801E643FCE1CBB, + 0xC8A025FD4FC1A3E9, + 0xFAC82F7CA3B20CE4, + 0x9CBD1DADE64F480E, + 0xC3EC65195FE31A12, + 0xF4E77E5FB7DBE096, + 0x9910AEFBD2E96C5E, + 0xBF54DABAC7A3C775, + 0xEF2A1169798CB953, + 0x957A4AE1EBF7F3D4, + 0xBAD8DD9A66F5F0C9, + 0xE98F150100B36CFB, + 0x91F96D20A070241D, + 0xB677C868C88C2D24, + 0xE415BA82FAAF386D, + 0x8E8D9491DCAD8344, + 0xB230F9B653D8E415, + 0xDEBD3823E8CF1D1A, + 0x8B36431671817230, + 0xAE03D3DC0DE1CEBD, + 0xD984C8D3115A426C, + 0x87F2FD83EAD86983, + 0xA9EFBCE4E58E83E4, + 0xD46BAC1E1EF224DD, + 0x84C34B92D357570A, + 0xA5F41E77882D2CCD, + 0xCF7126156A387800, + 0x81A6B7CD62634B00, + 0xA21065C0BAFC1DC0, + 0xCA947F30E9BB2530, + 0xFD399EFD2429EE7C, + 0x9E44035E369A350D, + 0xC5D50435C440C251, + 0xF74A45433550F2E5, + 0x9A8E6B4A015297CF, + 0xC132061C81A73DC3, + 0xF17E87A3A2110D34, + 0x96EF14C6454AA840, + 0xBCAAD9F7D69D5250, + 0xEBD59075CC44A6E4, + 0x93657A499FAAE84F, + 0xB83ED8DC0795A262, + 0xE64E8F13097B0AFB, + 0x8FF1196BE5ECE6DD, + 0xB3ED5FC6DF682094, + 0xE0E8B7B8974228B9, + 0x8C9172D35E895974, + 0xAFB5CF88362BAFD1, + 0xDBA3436A43B69BC5, + 0x89460A226A52215B, + 0xAB978CAB04E6A9B2, + 0xD67D6FD5C620541E, + 0x860E65E59BD43493, + 0xA791FF5F02C941B8, + 0xD1767F36C37B9226, + 0x82EA0F823A2D3B57, + 0xA3A49362C8B88A2D, + 0xCC8DB83B7AE6ACB9, + 0xFFB1264A59A057E7, + 0x9FCEB7EE780436F0, + 0xC7C265EA160544AC, + 0xF9B2FF649B8695D7, + 0x9C0FDF9EE1341DA7, + 0xC313D78699812510, + 0xF3D8CD683FE16E54, + 0x9867806127ECE4F5, + 0xBE81607971E81E32, + 0xEE21B897CE6225BE, + 0x94D5135EE0FD5797, + 0xBA0A5836993CAD7D, + 0xE88CEE443F8BD8DC, + 0x915814EAA7B76789, + 0xB5AE1A2551A5416C, + 0xE319A0AEA60E91C7, +]; + +static if (real.mant_dig >= 64) +static immutable align(16) ulong[1025] p10_coefficients_l = [ + 0x7132D332E3F204D5, + 0x8D7F87FF9CEE860A, + 0x70DF69FF842A278D, + 0xC68BA23FB29A58B8, + 0xB82E8ACF9F40EEE6, + 0xA63A2D8387112A9F, + 0xA7E45C72346ABAA4, + 0xD1DD738EC185694D, + 0xC654D07271E6C3A0, + 0xDBF5024787303A44, + 0x12F242D968FC48D5, + 0x17AED38FC33B5B0A, + 0x8ECD4439DA0518E6, + 0x7280954850865F20, + 0x4F20BA9A64A7F6E8, + 0x917474A07EE8FA51, + 0xB5D191C89EA338E5, + 0xE345F63AC64C071E, + 0x9C1773C977DF08E6, + 0x218EA85DEAEB6590, + 0x29F2527565A63EF4, + 0xF46EE712BF0FCEB0, + 0x18C5506BB769E12E, + 0x1EF6A486A544597A, + 0xA6B44DA84E956FD8, + 0x6830B089311D65E7, + 0x423CDCAB7D64BF61, + 0x52CC13D65CBDEF39, + 0xB3BF8C65F9F6B584, + 0x20AF6F7F787462E5, + 0x68DB4B5F56917B9E, + 0x81890F1B961AED43, + 0x61EB52E27BA1A893, + 0xFA66279B1A8A12B8, + 0x7C7FD8C0F0964BB3, + 0x1B9FCEF12CBBDEA0, + 0xE287C2AD77EAD648, + 0xAD94D9AC6AF2C5ED, + 0x98FA101785AF7768, + 0xBF38941D671B5542, + 0xF7835C9260711549, + 0x756433B6F88D5A9C, + 0x12BD40A4B6B0B143, + 0x4BB64866F22E6ECA, + 0xDEA3DA80AEBA0A7C, + 0x164CD120DA688D1B, + 0x5BE005691102B062, + 0xB96C0361AAA1AE3D, + 0x67C7043A154A19CC, + 0x01B8C5489A9CA040, + 0x01137B4D60A1E428, + 0xC1585A20B8CA5D32, + 0xB1AE70A8E6FCF47E, + 0x4F0D0669905E18CF, + 0xA2D04803F4759F02, + 0xCB845A04F19306C3, + 0x1F32B84316FBE43A, + 0x66FF6653DCBADD48, + 0x00BF3FE8D3E9949A, + 0x807787F18471FCE1, + 0x209569EDE58E7C19, + 0xA8BAC4695EF21B1F, + 0x6974BAC1DB5750F3, + 0x03D1E972522D2530, + 0x84C663CEE6B86E7C, + 0xD2FBFE615033450E, + 0x87BAFDF9A4401651, + 0xE9A9BD780D501BE5, + 0x520A166B0852116F, + 0xE68C9C05CA6695CB, + 0xA02FC3073D003B3E, + 0x241DD9E486202507, + 0x6D25505DA7A82E48, + 0x886EA475119239DA, + 0xEA8A4D9255F6C851, + 0xD296707B75BA3D33, + 0x073C0C9A5328CC7F, + 0xC90B0FC0E7F2FF9F, + 0x3DA6E9D890F7DFC3, + 0x0D10A44EB535D7B4, + 0xD054CD6262834DA1, + 0xA235005D7D921085, + 0xCAC24074DCF694A6, + 0x3D72D092143439D0, + 0x6667C25B4CA0A422, + 0x4001B2F21FC8CD2A, + 0x10021FAEA7BB0075, + 0x8A0153CD28D4E049, + 0x2C81A8C0730A185B, + 0xB7A212F08FCC9E72, + 0x12C54BD659DFE307, + 0x97769ECBF057DBC9, + 0xBD54467EEC6DD2BB, + 0x5654AC0F53C4A3B5, + 0x2BE9D71328B5CCA2, + 0xF6E44CD7F2E33FCB, + 0x1A4EB006F7CE07DF, + 0xA0E25C08B5C189D7, + 0x891AF30AE331EC4C, + 0x35B0D7E6CDFF33B0, + 0xC31D0DE0817F009C, + 0x73E45158A1DEC0C2, + 0x086EB2D7652B387A, + 0x4A8A5F8D3E760698, + 0x5D2CF7708E13883E, + 0x3478354CB1986A4D, + 0x00CB214FEEFF4270, + 0x00FDE9A3EABF130C, + 0xC13D640CE56ED7D0, + 0x98C65E880F6546E2, + 0x3EF7F62A133E989A, + 0x8EB5F3B4980E3EC1, + 0x3931B850DF08E738, + 0xC77E266516CB2106, + 0xF95DAFFE5C7DE948, + 0x5BDA8DFEF9CEB1CD, + 0x72D1317EB8425E40, + 0x0F857DDE6652F5D0, + 0xC9B36EAAFFF3D9A2, + 0x3C204A55BFF0D00B, + 0xCB285CEB2FED040E, + 0x5EF93A12FDF42288, + 0x76B78897BD712B2B, + 0xD4656ABDACCD75F5, + 0x24BF62B68C0069B9, + 0x2DEF3B642F008428, + 0xB96B0A3D3AC0A531, + 0xD3E2E66644B8673F, + 0x88DB9FFFD5E6810F, + 0x6B1287FFCB602152, + 0x62EB94FFDF1C14D3, + 0x7BA67A3FD6E31A08, + 0xDA9018CFCC9BE08A, + 0x91341F03BFC2D8AD, + 0x9AC0936257D9C76C, + 0xC170B83AEDD03947, + 0xF1CCE649A9444799, + 0x17200FEE09CAACC0, + 0x9CE813E98C3D57EF, + 0xC42218E3EF4CADEB, + 0xBA954F8E758FECB3, + 0xA93AA37212F3E7E0, + 0xD3894C4E97B0E1D8, + 0xE435CFB11ECE8D27, + 0xDD43439D66823071, + 0x14941484C022BC8D, + 0xECDC8CD2F815B5D8, + 0x6813B007B61B234E, + 0x82189C09A3A1EC21, + 0x714F618606453395, + 0x8DA339E787D6807A, + 0xF10C086169CC2099, + 0x16A7853CE21F945F, + 0x9C51668C1AA77977, + 0x4365C02F215157D5, + 0x0A1F981D74D2D6E5, + 0x4CA77E24D2078C9E, + 0xDFD15DAE06896FC6, + 0xEBE2DA8CC415E5DC, + 0x66DB912FF51B5F53, + 0x0092757BF2623727, + 0x205B896D777D6279, + 0xA8726BC8D55CBB17, + 0x128F06BB0AB3E9DD, + 0x1732C869CD60E454, + 0x0E7FBD42205C8EB4, + 0x521FAC92A873B261, + 0xE6A797B752909EFA, + 0x9028BED2939A635C, + 0x7432EE873880FC33, + 0x113FAA2906A13B40, + 0x4AC7CA59A424C508, + 0x5D79BCF00D2DF64A, + 0xF4D82C2C107973DC, + 0x79071B9B8A4BE86A, + 0x9748E2826CDEE284, + 0xFD1B1B2308169B25, + 0xFE30F0F5E50E20F7, + 0xBDBD2D335E51A935, + 0xAD2C788035E61382, + 0x4C3BCB5021AFCC31, + 0xDF4ABE242A1BBF3E, + 0xD71D6DAD34A2AF0D, + 0x8672648C40E5AD68, + 0x680EFDAF511F18C2, + 0x0212BD1B2566DEF3, + 0x014BB630F7604B58, + 0x419EA3BD35385E2E, + 0x52064CAC828675B9, + 0x7343EFEBD1940994, + 0x1014EBE6C5F90BF9, + 0xD41A26E077774EF7, + 0x8920B098955522B5, + 0x55B46E5F5D5535B1, + 0xEB2189F734AA831D, + 0xA5E9EC7501D523E4, + 0x47B233C92125366F, + 0x999EC0BB696E840A, + 0xC00670EA43CA250D, + 0x380406926A5E5728, + 0xC605083704F5ECF2, + 0xF7864A44C633682F, + 0x7AB3EE6AFBE0211D, + 0x5960EA05BAD82965, + 0x6FB92487298E33BE, + 0xA5D3B6D479F8E057, + 0x8F48A4899877186C, + 0x331ACDABFE94DE87, + 0x9FF0C08B7F1D0B15, + 0x07ECF0AE5EE44DDA, + 0xC9E82CD9F69D6150, + 0xBE311C083A225CD2, + 0x6DBD630A48AAF407, + 0x092CBBCCDAD5B108, + 0x25BBF56008C58EA5, + 0xAF2AF2B80AF6F24E, + 0x1AF5AF660DB4AEE2, + 0x50D98D9FC890ED4D, + 0xE50FF107BAB528A1, + 0x1E53ED49A96272C9, + 0x25E8E89C13BB0F7B, + 0x77B191618C54E9AD, + 0xD59DF5B9EF6A2418, + 0x4B0573286B44AD1E, + 0x4EE367F9430AEC33, + 0x229C41F793CDA73F, + 0x6B43527578C1110F, + 0x830A13896B78AAAA, + 0x23CC986BC656D554, + 0x2CBFBE86B7EC8AA9, + 0x7BF7D71432F3D6AA, + 0xDAF5CCD93FB0CC54, + 0xD1B3400F8F9CFF69, + 0x23100809B9C21FA2, + 0xABD40A0C2832A78A, + 0x16C90C8F323F516D, + 0xAE3DA7D97F6792E4, + 0x99CD11CFDF41779D, + 0x40405643D711D584, + 0x482835EA666B2572, + 0xDA3243650005EECF, + 0x90BED43E40076A83, + 0x5A7744A6E804A292, + 0x711515D0A205CB36, + 0x0D5A5B44CA873E04, + 0xE858790AFE9486C2, + 0x626E974DBE39A873, + 0xFB0A3D212DC81290, + 0x7CE66634BC9D0B9A, + 0x1C1FFFC1EBC44E80, + 0xA327FFB266B56220, + 0x4BF1FF9F0062BAA8, + 0x6F773FC3603DB4A9, + 0xCB550FB4384D21D4, + 0x7E2A53A146606A48, + 0x2EDA7444CBFC426D, + 0xFA911155FEFB5309, + 0x793555AB7EBA27CB, + 0x4BC1558B2F3458DF, + 0x9EB1AAEDFB016F16, + 0x465E15A979C1CADC, + 0x0BFACD89EC191ECA, + 0xCEF980EC671F667C, + 0x82B7E12780E7401B, + 0xD1B2ECB8B0908811, + 0x861FA7E6DCB4AA15, + 0x67A791E093E1D49A, + 0xE0C8BB2C5C6D24E0, + 0x58FAE9F773886E19, + 0xAF39A475506A899F, + 0x6D8406C952429603, + 0xC8E5087BA6D33B84, + 0xFB1E4A9A90880A65, + 0x5CF2EEA09A55067F, + 0xF42FAA48C0EA481F, + 0xF13B94DAF124DA27, + 0x76C53D08D6B70858, + 0x54768C4B0C64CA6E, + 0xA9942F5DCF7DFD0A, + 0xD3F93B35435D7C4C, + 0xC47BC5014A1A6DB0, + 0x359AB6419CA1091B, + 0xC30163D203C94B62, + 0x79E0DE63425DCF1D, + 0x985915FC12F542E5, + 0x3E6F5B7B17B2939E, + 0xA705992CEECF9C43, + 0x50C6FF782A838353, + 0xA4F8BF5635246428, + 0x871B7795E136BE99, + 0x28E2557B59846E3F, + 0x331AEADA2FE589CF, + 0x3FF0D2C85DEF7622, + 0x0FED077A756B53AA, + 0xD3E8495912C62894, + 0x64712DD7ABBBD95D, + 0xBD8D794D96AACFB4, + 0xECF0D7A0FC5583A1, + 0xF41686C49DB57245, + 0x311C2875C522CED6, + 0x7D633293366B828B, + 0xAE5DFF9C02033197, + 0xD9F57F830283FDFD, + 0xD072DF63C324FD7C, + 0x4247CB9E59F71E6D, + 0x52D9BE85F074E609, + 0x67902E276C921F8B, + 0x00BA1CD8A3DB53B7, + 0x80E8A40ECCD228A5, + 0x6122CD128006B2CE, + 0x796B805720085F81, + 0xCBE3303674053BB1, + 0xBEDBFC4411068A9D, + 0xEE92FB5515482D44, + 0x751BDD152D4D1C4B, + 0xD262D45A78A0635D, + 0x86FB897116C87C35, + 0xD45D35E6AE3D4DA1, + 0x8974836059CCA109, + 0x2BD1A438703FC94B, + 0x7B6306A34627DDCF, + 0x1A3BC84C17B1D543, + 0x20CABA5F1D9E4A94, + 0x547EB47B7282EE9C, + 0xE99E619A4F23AA43, + 0x6405FA00E2EC94D4, + 0xDE83BC408DD3DD05, + 0x9624AB50B148D446, + 0x3BADD624DD9B0957, + 0xE54CA5D70A80E5D6, + 0x5E9FCF4CCD211F4C, + 0x7647C3200069671F, + 0x29ECD9F40041E073, + 0xF468107100525890, + 0x7182148D4066EEB4, + 0xC6F14CD848405531, + 0xB8ADA00E5A506A7D, + 0xA6D90811F0E4851C, + 0x908F4A166D1DA663, + 0x9A598E4E043287FE, + 0x40EFF1E1853F29FE, + 0xD12BEE59E68EF47D, + 0x82BB74F8301958CE, + 0xE36A52363C1FAF02, + 0xDC44E6C3CB279AC2, + 0x29AB103A5EF8C0B9, + 0x7415D448F6B6F0E8, + 0x111B495B3464AD21, + 0xCAB10DD900BEEC35, + 0x3D5D514F40EEA742, + 0x0CB4A5A3112A5113, + 0x47F0E785EABA72AC, + 0x59ED216765690F57, + 0x306869C13EC3532C, + 0x1E414218C73A13FC, + 0xE5D1929EF90898FB, + 0xDF45F746B74ABF39, + 0x6B8BBA8C328EB784, + 0x066EA92F3F326565, + 0xC80A537B0EFEFEBE, + 0xBD06742CE95F5F37, + 0x2C48113823B73704, + 0xF75A15862CA504C5, + 0x9A984D73DBE722FB, + 0xC13E60D0D2E0EBBA, + 0x318DF905079926A9, + 0xFDF17746497F7053, + 0xFEB6EA8BEDEFA634, + 0xFE64A52EE96B8FC1, + 0x3DFDCE7AA3C673B1, + 0x06BEA10CA65C084F, + 0x486E494FCFF30A62, + 0x5A89DBA3C3EFCCFB, + 0xF89629465A75E01D, + 0xF6BBB397F1135824, + 0x746AA07DED582E2D, + 0xA8C2A44EB4571CDC, + 0x92F34D62616CE413, + 0x77B020BAF9C81D18, + 0x0ACE1474DC1D122F, + 0x0D819992132456BB, + 0x10E1FFF697ED6C69, + 0xCA8D3FFA1EF463C2, + 0xBD308FF8A6B17CB2, + 0xAC7CB3F6D05DDBDF, + 0x6BCDF07A423AA96B, + 0x86C16C98D2C953C6, + 0xE871C7BF077BA8B8, + 0x11471CD764AD4973, + 0xD598E40D3DD89BCF, + 0x4AFF1D108D4EC2C3, + 0xCEDF722A585139BA, + 0xC2974EB4EE658829, + 0x733D226229FEEA33, + 0x0806357D5A3F5260, + 0xCA07C2DCB0CF26F8, + 0xFC89B393DD02F0B6, + 0xBBAC2078D443ACE3, + 0xD54B944B84AA4C0E, + 0x0A9E795E65D4DF11, + 0x4D4617B5FF4A16D6, + 0x504BCED1BF8E4E46, + 0xE45EC2862F71E1D7, + 0x5D767327BB4E5A4D, + 0x3A6A07F8D510F870, + 0x890489F70A55368C, + 0x2B45AC74CCEA842F, + 0x3B0B8BC90012929D, + 0x09CE6EBB40173745, + 0xCC420A6A101D0516, + 0x9FA946824A12232E, + 0x47939822DC96ABF9, + 0x59787E2B93BC56F7, + 0x57EB4EDB3C55B65B, + 0xEDE622920B6B23F1, + 0xE95FAB368E45ECED, + 0x11DBCB0218EBB414, + 0xD652BDC29F26A11A, + 0x4BE76D3346F04960, + 0x6F70A4400C562DDC, + 0xCB4CCD500F6BB953, + 0x7E2000A41346A7A8, + 0x8ED400668C0C28C9, + 0x728900802F0F32FB, + 0x4F2B40A03AD2FFBA, + 0xE2F610C84987BFA8, + 0x0DD9CA7D2DF4D7C9, + 0x91503D1C79720DBB, + 0x75A44C6397CE912A, + 0xC986AFBE3EE11ABA, + 0xFBE85BADCE996169, + 0xFAE27299423FB9C3, + 0xDCCD879FC967D41A, + 0x5400E987BBC1C921, + 0x290123E9AAB23B69, + 0xF9A0B6720AAF6521, + 0xF808E40E8D5B3E6A, + 0xB60B1D1230B20E04, + 0xB1C6F22B5E6F48C3, + 0x1E38AEB6360B1AF3, + 0x25C6DA63C38DE1B0, + 0x579C487E5A38AD0E, + 0x2D835A9DF0C6D852, + 0xF8E431456CF88E66, + 0x1B8E9ECB641B5900, + 0xE272467E3D222F40, + 0x5B0ED81DCC6ABB10, + 0x98E947129FC2B4EA, + 0x3F2398D747B36224, + 0x8EEC7F0D19A03AAD, + 0x1953CF68300424AC, + 0x5FA8C3423C052DD7, + 0x3792F412CB06794D, + 0xE2BBD88BBEE40BD0, + 0x5B6ACEAEAE9D0EC4, + 0xF245825A5A445275, + 0xEED6E2F0F0D56713, + 0x55464DD69685606C, + 0xAA97E14C3C26B887, + 0xD53DD99F4B3066A8, + 0xE546A8038EFE4029, + 0xDE98520472BDD033, + 0x963E66858F6D4440, + 0xDDE7001379A44AA8, + 0x5560C018580D5D52, + 0xAAB8F01E6E10B4A7, + 0xCAB3961304CA70E8, + 0x3D607B97C5FD0D22, + 0x8CB89A7DB77C506B, + 0x77F3608E92ADB243, + 0x55F038B237591ED3, + 0x6B6C46DEC52F6688, + 0x2323AC4B3B3DA015, + 0xABEC975E0A0D081B, + 0x96E7BD358C904A21, + 0x7E50D64177DA2E55, + 0xDDE50BD1D5D0B9EA, + 0x955E4EC64B44E864, + 0xBD5AF13BEF0B113F, + 0xECB1AD8AEACDD58E, + 0x67DE18EDA5814AF2, + 0x80EACF948770CED7, + 0xA1258379A94D028D, + 0x096EE45813A04330, + 0x8BCA9D6E188853FC, + 0x775EA264CF55347E, + 0x95364AFE032A819D, + 0x3A83DDBD83F52205, + 0xC4926A9672793543, + 0x75B7053C0F178294, + 0x5324C68B12DD6338, + 0xD3F6FC16EBCA5E03, + 0x88F4BB1CA6BCF584, + 0x2B31E9E3D06C32E5, + 0x3AFF322E62439FCF, + 0x09BEFEB9FAD487C3, + 0x4C2EBE687989A9B4, + 0x0F9D37014BF60A10, + 0x538484C19EF38C94, + 0x2865A5F206B06FBA, + 0xF93F87B7442E45D4, + 0xF78F69A51539D749, + 0xB573440E5A884D1B, + 0x31680A88F8953031, + 0xFDC20D2B36BA7C3D, + 0x3D32907604691B4D, + 0xA63F9A49C2C1B110, + 0x0FCF80DC33721D54, + 0xD3C36113404EA4A9, + 0x645A1CAC083126E9, + 0x3D70A3D70A3D70A4, + 0xCCCCCCCCCCCCCCCD, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x4000000000000000, + 0x5000000000000000, + 0xA400000000000000, + 0x4D00000000000000, + 0xF020000000000000, + 0x6C28000000000000, + 0xC732000000000000, + 0x3C7F400000000000, + 0x4B9F100000000000, + 0x1E86D40000000000, + 0x1314448000000000, + 0x17D955A000000000, + 0x5DCFAB0800000000, + 0x5AA1CAE500000000, + 0xF14A3D9E40000000, + 0x6D9CCD05D0000000, + 0xE4820023A2000000, + 0xDDA2802C8A800000, + 0xD50B2037AD200000, + 0x4526F422CC340000, + 0x9670B12B7F410000, + 0x3C0CDD765F114000, + 0xA5880A69FB6AC800, + 0x8EEA0D047A457A00, + 0x72A4904598D6D880, + 0x47A6DA2B7F864750, + 0x999090B65F67D924, + 0xFFF4B4E3F741CF6D, + 0xBFF8F10E7A8921A4, + 0xAFF72D52192B6A0D, + 0x9BF4F8A69F764490, + 0x02F236D04753D5B5, + 0x01D762422C946591, + 0x424D3AD2B7B97EF5, + 0xD2E0898765A7DEB2, + 0x63CC55F49F88EB2F, + 0x3CBF6B71C76B25FB, + 0x8BEF464E3945EF7A, + 0x97758BF0E3CBB5AC, + 0x3D52EEED1CBEA317, + 0x4CA7AAA863EE4BDD, + 0x8FE8CAA93E74EF6A, + 0xB3E2FD538E122B45, + 0x60DBBCA87196B616, + 0xBC8955E946FE31CE, + 0x6BABAB6398BDBE41, + 0xC696963C7EED2DD2, + 0xFC1E1DE5CF543CA3, + 0x3B25A55F43294BCC, + 0x49EF0EB713F39EBF, + 0x6E3569326C784337, + 0x49C2C37F07965405, + 0xDC33745EC97BE906, + 0x69A028BB3DED71A4, + 0xC40832EA0D68CE0D, + 0xF50A3FA490C30190, + 0x792667C6DA79E0FA, + 0x577001B891185939, + 0xED4C0226B55E6F87, + 0x544F8158315B05B4, + 0x696361AE3DB1C721, + 0x03BC3A19CD1E38EA, + 0x04AB48A04065C724, + 0x62EB0D64283F9C76, + 0x3BA5D0BD324F8394, + 0xCA8F44EC7EE36479, + 0x7E998B13CF4E1ECC, + 0x9E3FEDD8C321A67F, + 0xC5CFE94EF3EA101E, + 0xBBA1F1D158724A13, + 0x2A8A6E45AE8EDC98, + 0xF52D09D71A3293BE, + 0x593C2626705F9C56, + 0x6F8B2FB00C77836C, + 0x0B6DFB9C0F956447, + 0x4724BD4189BD5EAC, + 0x58EDEC91EC2CB658, + 0x2F2967B66737E3ED, + 0xBD79E0D20082EE74, + 0xECD8590680A3AA11, + 0xE80E6F4820CC9496, + 0x3109058D147FDCDE, + 0xBD4B46F0599FD415, + 0x6C9E18AC7007C91A, + 0x03E2CF6BC604DDB0, + 0x84DB8346B786151D, + 0xE612641865679A64, + 0x4FCB7E8F3F60C07E, + 0xE3BE5E330F38F09E, + 0x5CADF5BFD3072CC5, + 0x73D9732FC7C8F7F7, + 0x2867E7FDDCDD9AFA, + 0xB281E1FD541501B9, + 0x1F225A7CA91A4227, + 0x3375788DE9B06958, + 0x0052D6B1641C83AE, + 0xC0678C5DBD23A49A, + 0xF840B7BA963646E0, + 0xB650E5A93BC3D898, + 0xA3E51F138AB4CEBE, + 0xC66F336C36B10137, + 0xB80B0047445D4185, + 0xA60DC059157491E6, + 0x87C89837AD68DB30, + 0x29BABE4598C311FC, + 0xF4296DD6FEF3D67B, + 0x1899E4A65F58660D, + 0x5EC05DCFF72E7F90, + 0x76707543F4FA1F74, + 0x6A06494A791C53A8, + 0x0487DB9D17636892, + 0x45A9D2845D3C42B7, + 0x0B8A2392BA45A9B2, + 0x8E6CAC7768D7141F, + 0x3207D795430CD927, + 0x7F44E6BD49E807B8, + 0x5F16206C9C6209A6, + 0x36DBA887C37A8C10, + 0xC2494954DA2C978A, + 0xF2DB9BAA10B7BD6C, + 0x6F92829494E5ACC7, + 0xCB772339BA1F17F9, + 0xFF2A760414536EFC, + 0xFEF5138519684ABB, + 0x7EB258665FC25D69, + 0xEF2F773FFBD97A62, + 0xAAFB550FFACFD8FA, + 0x95BA2A53F983CF39, + 0xDD945A747BF26184, + 0x94F971119AEEF9E4, + 0x7A37CD5601AAB85E, + 0xAC62E055C10AB33B, + 0x577B986B314D6009, + 0xED5A7E85FDA0B80B, + 0x14588F13BE847307, + 0x596EB2D8AE258FC9, + 0x6FCA5F8ED9AEF3BB, + 0x25DE7BB9480D5855, + 0xAF561AA79A10AE6A, + 0x1B2BA1518094DA05, + 0x90FB44D2F05D0843, + 0x353A1607AC744A54, + 0x42889B8997915CE9, + 0x69956135FEBADA11, + 0x43FAB9837E699096, + 0x94F967E45E03F4BB, + 0x1D1BE0EEBAC278F5, + 0x6462D92A69731732, + 0x7D7B8F7503CFDCFF, + 0x5CDA735244C3D43F, + 0x3A0888136AFA64A7, + 0x088AAA1845B8FDD1, + 0x8AAD549E57273D45, + 0x36AC54E2F678864B, + 0x84576A1BB416A7DE, + 0x656D44A2A11C51D5, + 0x9F644AE5A4B1B325, + 0x873D5D9F0DDE1FEF, + 0xA90CB506D155A7EA, + 0x09A7F12442D588F3, + 0x0C11ED6D538AEB2F, + 0x8F1668C8A86DA5FB, + 0xF96E017D694487BD, + 0x37C981DCC395A9AC, + 0x85BBE253F47B1417, + 0x93956D7478CCEC8E, + 0x387AC8D1970027B2, + 0x06997B05FCC0319F, + 0x441FECE3BDF81F03, + 0xD527E81CAD7626C4, + 0x8A71E223D8D3B075, + 0xF6872D5667844E49, + 0xB428F8AC016561DB, + 0xE13336D701BEBA52, + 0xECC0024661173473, + 0x27F002D7F95D0190, + 0x31EC038DF7B441F4, + 0x7E67047175A15271, + 0x0F0062C6E984D387, + 0x52C07B78A3E60868, + 0xA7709A56CCDF8A83, + 0x88A66076400BB692, + 0x6ACFF893D00EA436, + 0x0583F6B8C4124D43, + 0xC3727A337A8B704A, + 0x744F18C0592E4C5D, + 0x1162DEF06F79DF74, + 0x8ADDCB5645AC2BA8, + 0x6D953E2BD7173693, + 0xC8FA8DB6CCDD0437, + 0x1D9C9892400A22A2, + 0x2503BEB6D00CAB4B, + 0x2E44AE64840FD61E, + 0x5CEAECFED289E5D3, + 0x7425A83E872C5F47, + 0xD12F124E28F77719, + 0x82BD6B70D99AAA70, + 0x636CC64D1001550C, + 0x3C47F7E05401AA4F, + 0x65ACFAEC34810A71, + 0x7F1839A741A14D0D, + 0x1EDE48111209A051, + 0x934AED0AAB460432, + 0xF81DA84D5617853F, + 0x36251260AB9D668F, + 0xC1D72B7C6B426019, + 0xB24CF65B8612F820, + 0xDEE033F26797B628, + 0x169840EF017DA3B1, + 0x8E1F289560EE864F, + 0xF1A6F2BAB92A27E3, + 0xAE10AF696774B1DB, + 0xACCA6DA1E0A8EF29, + 0x17FD090A58D32AF3, + 0xDDFC4B4CEF07F5B0, + 0x4ABDAF101564F98E, + 0x9D6D1AD41ABE37F2, + 0x84C86189216DC5EE, + 0x32FD3CF5B4E49BB5, + 0x3FBC8C33221DC2A2, + 0x0FABAF3FEAA5334A, + 0x29CB4D87F2A7400E, + 0x743E20E9EF511012, + 0x914DA9246B255417, + 0x1AD089B6C2F7548E, + 0xA184AC2473B529B2, + 0xC9E5D72D90A2741E, + 0x7E2FA67C7A658893, + 0xDDBB901B98FEEAB8, + 0x552A74227F3EA565, + 0xD53A88958F87275F, + 0x8A892ABAF368F137, + 0x2D2B7569B0432D85, + 0x9C3B29620E29FC73, + 0x8349F3BA91B47B90, + 0x241C70A936219A74, + 0xED238CD383AA0111, + 0xF4363804324A40AB, + 0xB143C6053EDCD0D5, + 0xDD94B7868E94050A, + 0xCA7CF2B4191C8327, + 0xFD1C2F611F63A3F0, + 0xBC633B39673C8CEC, + 0xD5BE0503E085D814, + 0x4B2D8644D8A74E19, + 0xDDF8E7D60ED1219F, + 0xCABB90E5C942B503, + 0x3D6A751F3B936244, + 0x0CC512670A783AD5, + 0x27FB2B80668B24C5, + 0xB1F9F660802DEDF6, + 0x5E7873F8A0396974, + 0xDB0B487B6423E1E8, + 0x91CE1A9A3D2CDA63, + 0x7641A140CC7810FB, + 0xA9E904C87FCB0A9D, + 0x546345FA9FBDCD44, + 0xA97C177947AD4095, + 0x49ED8EABCCCC485D, + 0x5C68F256BFFF5A75, + 0x73832EEC6FFF3112, + 0xC831FD53C5FF7EAB, + 0xBA3E7CA8B77F5E56, + 0x28CE1BD2E55F35EB, + 0x7980D163CF5B81B3, + 0xD7E105BCC3326220, + 0x8DD9472BF3FEFAA8, + 0xB14F98F6F0FEB952, + 0x6ED1BF9A569F33D3, + 0x0A862F80EC4700C8, + 0xCD27BB612758C0FA, + 0x8038D51CB897789C, + 0xE0470A63E6BD56C3, + 0x1858CCFCE06CAC74, + 0x0F37801E0C43EBC9, + 0xD30560258F54E6BB, + 0x47C6B82EF32A2069, + 0x4CDC331D57FA5442, + 0xE0133FE4ADF8E952, + 0x58180FDDD97723A7, + 0x570F09EAA7EA7648, + 0x2CD2CC6551E513DA, + 0xF8077F7EA65E58D1, + 0xFB04AFAF27FAF783, + 0x79C5DB9AF1F9B563, + 0x18375281AE7822BC, + 0x8F2293910D0B15B6, + 0xB2EB3875504DDB23, + 0x5FA60692A46151EC, + 0xDBC7C41BA6BCD333, + 0x12B9B522906C0800, + 0xD768226B34870A00, + 0xE6A1158300D46640, + 0x60495AE3C1097FD0, + 0x385BB19CB14BDFC4, + 0x46729E03DD9ED7B5, + 0x6C07A2C26A8346D1, + 0xC7098B7305241886, + 0xB8CBEE4FC66D1EA7, + 0x737F74F1DC043328, + 0x505F522E53053FF2, + 0x647726B9E7C68FEF, + 0x5ECA783430DC19F5, + 0xB67D16413D132073, + 0xE41C5BD18C57E88F, + 0x8E91B962F7B6F15A, + 0x723627BBB5A4ADB0, + 0xCEC3B1AAA30DD91C, + 0x213A4F0AA5E8A7B2, + 0xA988E2CD4F62D19E, + 0x93EB1B80A33B8605, + 0xBC72F130660533C3, + 0xEB8FAD7C7F8680B4, + 0xA67398DB9F6820E1, + 0x88083F8943A1148D, + 0x6A0A4F6B948959B0, + 0x848CE34679ABB01C, + 0xF2D80E0C0C0B4E12, + 0x6F8E118F0F0E2196, + 0x4B7195F2D2D1A9FB, + 0x8F26FDB7C3C30A3D, + 0xB2F0BD25B4B3CCCC, + 0xDFACEC6F21E0C000, + 0x9798278AEA58EFFF, + 0x5EBF18B6D2779600, + 0xF66EDEE487157B80, + 0xB40A969DA8DADA5F, + 0x70869E228988C87C, + 0xCCA845AB2BEAFA9B, + 0x3FD25715F6E5B941, + 0x07E3766DBA4F93C9, + 0x89DC540928E378BB, + 0x2C53690B731C56EA, + 0x9BB421A727F1B652, + 0x42A12A10F1EE23E7, + 0x134974952E69ACE0, + 0x2C0DE8DD3D020C0C, + 0x771163148C428F0F, + 0x54D5BBD9AF5332D3, + 0x350595680D93FFC4, + 0x8246FAC210F8FFB5, + 0x62D8B97295373FA2, + 0xFDC773E79D4287C5, + 0x7D3950E1849329B7, + 0xDC87A519E5B7F424, + 0xA9D4C7302F92F897, + 0xD449F8FC3B77B6BC, + 0xC95C773B4A55A46B, + 0x7DD9CA850E7586C3, + 0x5D503D265212E874, + 0x34A44C6FE697A291, + 0x40E6AFC5F01EC59B, + 0x91205BB76C267701, + 0x356872A5473014C1, + 0xC2C28F4E98FC19F2, + 0xD9B999911F9D9037, + 0x1027FFF56784F445, + 0xD431FFF2C1663156, + 0x049F3FF7B8DFDED6, + 0x85C70FF5A717D68B, + 0x2738D3F310DDCC2E, + 0xB8838477EA8A9F9D, + 0xE6A46595E52D4784, + 0x604D7EFB5E789965, + 0x1C306F5D1B0B5FDF, + 0x633C8B3461CE37D7, + 0x3C0BAE017A41C5CD, + 0xC5874CC0EC691BA0, + 0xF6E91FF127836288, + 0xB4A367ED71643B2A, + 0x50E620F466DEA4FA, + 0xA51FA93180964E39, + 0x8E67937DE0BBE1C7, + 0x7900BC2EAC756D1C, + 0x5740EB3A5792C863, + 0x2D112608ED777A7C, + 0x5C2AB7C5946AAC8E, + 0xF33565B6F98557B1, + 0xF002BF24B7E6AD9D, + 0xB601B776F2F02C82, + 0xE3822554AFAC37A3, + 0xDC62AEA9DB97458C, + 0x537B5A54527D16EE, + 0x742D1874B38E2E55, + 0xD1385E91E071B9EA, + 0x45867636588E2865, + 0x4B7409E1F758D93F, + 0x5E510C5A752F0F8F, + 0xB5E54F71127AD373, + 0x71AF51A6AB8CC428, + 0x4E1B2610566FF531, + 0xA1A1EF946C0BF27E, + 0x250535BCC387778F, + 0x6E46832BF4695572, + 0x89D823F6F183AACF, + 0x9627167A56F24AC1, + 0xBBB0DC18ECAEDD72, + 0x6A9D131F27DA94CE, + 0xA2A22BF378E89D01, + 0x0B4AB6F05722C441, + 0x4E1D64AC6CEB7551, + 0x90D25EEBC4132953, + 0xF506F6A6B517F3A7, + 0xF248B450625DF091, + 0xD76D70B23D7AB65B, + 0x0D48CCDECCD963F2, + 0x109B0016800FBCEE, + 0xCA60E00E1009D615, + 0x3CF91811940C4B9A, + 0xCC375E15F90F5E80, + 0x3FA29ACDBBA99B10, + 0x8F8B41812A9401D4, + 0x336E11E175390249, + 0x80499659D28742DC, + 0x302DFDF8239489C9, + 0xBC397D762C79AC3C, + 0x2B47DCD3B798174B, + 0xDB0CEA0452BF0E8F, + 0x51D02485676ED232, + 0xA6442DA6C14A86BF, + 0xA7EA9C8838CE9437, + 0x91E543AA47023945, + 0xB65E9494D8C2C796, + 0xB1FB1CDD0779BCBE, + 0xDE79E41449582BED, + 0xD6185D195BAE36E9, + 0x05CF3A2FD94CE251, + 0x074308BBCFA01AE6, + 0x4913CAEAC388219F, + 0x6DAC5ED2BA351504, + 0x8917768768C25A44, + 0xAB5D542942F2F0D6, + 0x4B1A5499C9D7D685, + 0x1DE0E9C03C4DCC27, + 0x255924304B613F31, + 0x3757B69E2F1CC77E, + 0xC52DA445BAE3F95E, + 0xF6790D57299CF7B5, + 0xFA0BA8567A021AD1, + 0xF88E926C1882A186, + 0xF6B237071EA349E7, + 0xF45EC4C8E64C1C61, + 0x78BB3AFD8FEF91BD, + 0xD6EA09BCF3EB762C, + 0x0CA48C2C30E653B7, + 0x27E6D79B9E8FF452, + 0xF1E08D828633F167, + 0xAE58B0E327C0EDC0, + 0x4CF76E8DF8D89498, + 0x60354A31770EB9BE, + 0x78429CBDD4D2682E, + 0xCB29A1F6A503811D, + 0x7DF40A744E446164, + 0x1D710D1161D579BD, + 0xF266A82ADD256C16, + 0x2F005235946EC71C, + 0x3AC066C2F98A78E2, + 0xC4B84039DBF68B8E, + 0xB5E6504852F42E71, + 0xE35FE45A67B13A0D, + 0x0E1BEEB880CEC448, + 0xD1A2EA66A102755A, + 0x460BA500494312B1, + 0xEBC747202DC9EBAF, + 0xA6B918E8393C669A, + 0x90675F22478B8041, + 0x7A409B756CB73028, + 0x58D0C252C7E4FC33, + 0xAF04F2E779DE3B3F, + 0xDAC62FA15855CA0F, + 0x48BBDDC4D7359E49, + 0x5AEAD5360D0305DC, + 0x71A58A839043C753, + 0xA70776923A2A5C94, + 0x50C95436C8B4F3B9, + 0x64FBA9447AE230A7, + 0xBF1D49CACCCD5E68, + 0xEEE49C3D8000B602, + 0x6A9DC34CE000E383, + 0x02A29A100C008E32, + 0xC34B40940F00B1BE, + 0xF41E10B912C0DE2E, + 0x7892CA73ABB88ADD, + 0xD6B77D1096A6AD94, + 0xCC655C54BC5058F9, +]; diff --git a/source/mir/bignum/internal/kernel.d b/source/mir/bignum/internal/kernel.d index f6c7f4a7..fce9df7d 100644 --- a/source/mir/bignum/internal/kernel.d +++ b/source/mir/bignum/internal/kernel.d @@ -27,10 +27,10 @@ size_t multiply( c[a.length + b.length - 1] = 0; auto length = multiply( - cast(uint[]) c, + cast(uint[]) c[], a.toUints, b.toUints, - cast(uint[]) buffer, + cast(uint[]) buffer[], ); return length / 2 + length % 2; diff --git a/source/mir/bignum/low_level_view.d b/source/mir/bignum/low_level_view.d index d8d47d92..937a339b 100644 --- a/source/mir/bignum/low_level_view.d +++ b/source/mir/bignum/low_level_view.d @@ -99,8 +99,8 @@ struct BigUIntView(W) T opCast(T)() const if (isFloatingPoint!T && isMutable!T) { - import mir.bignum.internal.dec2float: decimalTo; - return normalized.coefficients.decimalTo!T; + import mir.bignum.internal.dec2float: binaryTo; + return normalized.coefficients.binaryTo!T; } static if (W.sizeof >= size_t.sizeof) @@ -119,10 +119,10 @@ struct BigUIntView(W) } else { - import mir.bignum.internal.dec2float: decimalToFp; + import mir.bignum.internal.dec2float: binaryToFp; auto coefficients = normalized.coefficients; return coefficients.length - ? coefficients.decimalToFp!coefficientSize + ? coefficients.binaryToFp!coefficientSize : Fp!coefficientSize.init; } } @@ -850,9 +850,9 @@ struct BigUIntView(W) +/ size_t cttz()() const @property @safe pure nothrow @nogc + in (coefficients.length) { import mir.bitop: cttz; - assert(coefficients.length); auto d = coefficients[]; size_t ret; do @@ -2286,7 +2286,9 @@ struct DecimalView(W) static if (!wordNormalized) coeff = coeff.normalized; - auto ret = decimalTo!T(coeff.coefficients, exponent); + auto ret = exponent != exponent.max ? + coeff.coefficients.decimalTo!T(exponent) : + coeff.length ? T.nan : T.infinity; if (sign) ret = -ret; return ret; @@ -2328,282 +2330,284 @@ unittest version(mir_bignum_test_llv) unittest { + import mir.test; + auto view = DecimalView!size_t(false, -8, BigUIntView!size_t.fromHexString("BEBC2000000011E1A3")); - assert (cast(float)view == 3.518437208883201171875E+013f); - assert (cast(double)view == 3.518437208883201171875E+013); + should(cast(float)view) == 3.518437208883201171875E+013f; + should(cast(double)view) == 3.518437208883201171875E+013; static if (real.mant_dig >= 64) - assert (cast(real)view == 3.518437208883201171875E+013L); + should(cast(real)view) == 3.518437208883201171875E+013L; view = DecimalView!size_t(true, -169, BigUIntView!size_t.fromHexString("5A174AEDA65CC")); - assert (cast(float)view == -0); - assert (cast(double)view == -0x1.1p-511); + should(cast(float)view) == -0; + should(cast(double)view) == -0x1.1p-511; static if (real.mant_dig >= 64) - assert (cast(real)view == -0x8.80000000000019fp-514L); + should(cast(real)view) == -0x8.80000000000019fp-514L; view = DecimalView!size_t(true, 293, BigUIntView!size_t.fromHexString("36496F6C4ED38")); - assert (cast(float)view == -float.infinity); - assert (cast(double)view == -9.55024478104888e+307); + should(cast(float)view) == -float.infinity; + should(cast(double)view) == -9.55024478104888e+307; static if (real.mant_dig >= 64) - assert (cast(real)view == -9.55024478104888e+307L); + should(cast(real)view) == -9.55024478104888e+307L; view = DecimalView!size_t(false, 0, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 1); - assert (cast(double)view == 1); + should(cast(float)view) == 1; + should(cast(double)view) == 1; static if (real.mant_dig >= 64) - assert (cast(real)view == 1L); + should(cast(real)view) == 1L; view = DecimalView!size_t(false, -5, BigUIntView!size_t.fromHexString("3")); - assert (cast(float)view == 3e-5f); - assert (cast(double)view == 3e-5); + should(cast(float)view) == 3e-5f; + should(cast(double)view) == 3e-5; static if (real.mant_dig >= 64) - assert (cast(real)view == 3e-5L); + should(cast(real)view) == 3e-5L; view = DecimalView!size_t(false, -1, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0.1f); - assert (cast(double)view == 0.1); + should(cast(float)view) == 0.1f; + should(cast(double)view) == 0.1; static if (real.mant_dig >= 64) - assert (cast(real)view == 0.1L); + should(cast(real)view) == 0.1L; view = DecimalView!size_t(false, 0, BigUIntView!size_t.fromHexString("3039")); - assert (cast(float)view == 12345.0f); - assert (cast(double)view == 12345.0); + should(cast(float)view) == 12345.0f; + should(cast(double)view) == 12345.0; static if (real.mant_dig >= 64) - assert (cast(real)view == 12345.0L); + should(cast(real)view) == 12345.0L; view = DecimalView!size_t(false, -7, BigUIntView!size_t.fromHexString("98967F")); - assert (cast(float)view == 0.9999999f); - assert (cast(double)view == 0.9999999); + should(cast(float)view) == 0.9999999f; + should(cast(double)view) == 0.9999999; static if (real.mant_dig >= 64) - assert (cast(real)view == 0.9999999L); + should(cast(real)view) == 0.9999999L; view = DecimalView!size_t(false, -324, BigUIntView!size_t.fromHexString("4F0CEDC95A718E")); - assert (cast(float)view == 0); - assert (cast(double)view == 2.2250738585072014e-308); + should(cast(float)view) == 0; + should(cast(double)view) == 2.2250738585072014e-308; static if (real.mant_dig >= 64) - assert (cast(real)view == 2.2250738585072014e-308L); + should(cast(real)view) == 2.2250738585072014e-308L; view = DecimalView!size_t(false, 0, BigUIntView!size_t.fromHexString("1FFFFFFFFFFFFFFFD")); - assert (cast(float)view == 36893488147419103229f); - assert (cast(double)view == 36893488147419103229.0); + should(cast(float)view) == 36893488147419103229f; + should(cast(double)view) == 36893488147419103229.0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x1FFFFFFFFFFFFFFFDp0L); + should(cast(real)view) == 0x1FFFFFFFFFFFFFFFDp0L; view = DecimalView!size_t(false, -33, BigUIntView!size_t.fromHexString("65")); - assert (cast(float)view == 101e-33f); - assert (cast(double)view == 101e-33); + should(cast(float)view) == 101e-33f; + should(cast(double)view) == 101e-33; static if (real.mant_dig >= 64) - assert (cast(real)view == 101e-33L); + should(cast(real)view) == 101e-33L; view = DecimalView!size_t(false, 23, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 1e23f); - assert (cast(double)view == 1e23); + should(cast(float)view) == 1e23f; + should(cast(double)view) == 1e23; static if (real.mant_dig >= 64) - assert (cast(real)view == 1e23L); + should(cast(real)view) == 1e23L; view = DecimalView!size_t(false, 23, BigUIntView!size_t.fromHexString("81B")); - assert (cast(float)view == 2075e23f); - assert (cast(double)view == 0xaba3d58a1f1a98p+32); + should(cast(float)view) == 2075e23f; + should(cast(double)view) == 0xaba3d58a1f1a98p+32; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xaba3d58a1f1a9cp+32L); + should(cast(real)view) == 0xaba3d58a1f1a9cp+32L; view = DecimalView!size_t(false, -23, BigUIntView!size_t.fromHexString("2209")); - assert (cast(float)view == 8713e-23f); - assert (cast(double)view == 0x1.9b75b4e7de2b9p-64); + should(cast(float)view) == 8713e-23f; + should(cast(double)view) == 0x1.9b75b4e7de2b9p-64; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xc.dbada73ef15c401p-67L); + should(cast(real)view) == 0xc.dbada73ef15c401p-67L; view = DecimalView!size_t(false, 300, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == float.infinity); - assert (cast(double)view == 0x1.7e43c8800759cp+996); + should(cast(float)view) == float.infinity; + should(cast(double)view) == 0x1.7e43c8800759cp+996; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xb.f21e44003acdd2dp+993L); + should(cast(real)view) == 0xb.f21e44003acdd2dp+993L; view = DecimalView!size_t(false, 245, BigUIntView!size_t.fromHexString("B3A73CEB227")); - assert (cast(float)view == float.infinity); - assert (cast(double)view == 0x1.48e3735333cb6p+857); + should(cast(float)view) == float.infinity; + should(cast(double)view) == 0x1.48e3735333cb6p+857; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xa.471b9a999e5b01ep+854L); + should(cast(real)view) == 0xa.471b9a999e5b01ep+854L; view = DecimalView!size_t(false, 0, BigUIntView!size_t.fromHexString("88BF4748507FB9900ADB624CCFF8D78897DC900FB0460327D4D86D327219")); - assert (cast(float)view == float.infinity); - assert (cast(double)view == 0x1.117e8e90a0ff7p+239); + should(cast(float)view) == float.infinity; + should(cast(double)view) == 0x1.117e8e90a0ff7p+239; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.8bf4748507fb99p+236L); + should(cast(real)view) == 0x8.8bf4748507fb99p+236L; view = DecimalView!size_t(false, -324, BigUIntView!size_t.fromHexString("5")); - assert (cast(float)view == 0); - assert (cast(double)view == 0x0.0000000000001p-1022); + should(cast(float)view) == 0; + should(cast(double)view) == 0x0.0000000000001p-1022; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.18995ce7aa0e1b2p-1077L); + should(cast(real)view) == 0x8.18995ce7aa0e1b2p-1077L; view = DecimalView!size_t(false, -324, BigUIntView!size_t.fromHexString("5B")); - assert (cast(float)view == 0); - assert (cast(double)view == 0x0.0000000000012p-1022); + should(cast(float)view) == 0; + should(cast(double)view) == 0x0.0000000000012p-1022; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x9.3594d9adeb09a55p-1073L); + should(cast(real)view) == 0x9.3594d9adeb09a55p-1073L; view = DecimalView!size_t(false, -322, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0x0.0000000000014p-1022); + should(cast(float)view) == 0; + should(cast(double)view) == 0x0.0000000000014p-1022; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xa.1ebfb4219491a1fp-1073L); + should(cast(real)view) == 0xa.1ebfb4219491a1fp-1073L; view = DecimalView!size_t(false, -320, BigUIntView!size_t.fromHexString("CA1CCB")); - assert (cast(float)view == 0); - assert (cast(double)view == 0x0.000063df832d9p-1022); + should(cast(float)view) == 0; + should(cast(double)view) == 0x0.000063df832d9p-1022; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xc.7bf065b215888c7p-1043L); + should(cast(real)view) == 0xc.7bf065b215888c7p-1043L; view = DecimalView!size_t(false, -319, BigUIntView!size_t.fromHexString("33CE7943FB")); - assert (cast(float)view == 0); - assert (cast(double)view == 0x1.000000000162p-1022); + should(cast(float)view) == 0; + should(cast(double)view) == 0x1.000000000162p-1022; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.000000000b103b6p-1025L); + should(cast(real)view) == 0x8.000000000b103b6p-1025L; view = DecimalView!size_t(false, -309, BigUIntView!size_t.fromHexString("15")); - assert (cast(float)view == 0); - assert (cast(double)view == 0x0.f19c2629ccf53p-1022); + should(cast(float)view) == 0; + should(cast(double)view) == 0x0.f19c2629ccf53p-1022; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xf.19c2629ccf52fc4p-1026L); + should(cast(real)view) == 0xf.19c2629ccf52fc4p-1026L; view = DecimalView!size_t(false, -340, BigUIntView!size_t.fromHexString("AF87023B9BF0EE")); - assert (cast(float)view == 0); - assert (cast(double)view == 0x0.0000000000001p-1022); + should(cast(float)view) == 0; + should(cast(double)view) == 0x0.0000000000001p-1022; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xf.fffffffffffff64p-1078L); + should(cast(real)view) == 0xf.fffffffffffff64p-1078L; view = DecimalView!size_t(false, 400, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == float.infinity); - assert (cast(double)view == double.infinity); + should(cast(float)view) == float.infinity; + should(cast(double)view) == double.infinity; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xd.a763fc8cb9ff9e6p+1325L); + should(cast(real)view) == 0xd.a763fc8cb9ff9e6p+1325L; view = DecimalView!size_t(false, 309, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == float.infinity); - assert (cast(double)view == double.infinity); + should(cast(float)view) == float.infinity; + should(cast(double)view) == double.infinity; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xb.201833b35d63f73p+1023L); + should(cast(real)view) == 0xb.201833b35d63f73p+1023L; view = DecimalView!size_t(false, 308, BigUIntView!size_t.fromHexString("2")); - assert (cast(float)view == float.infinity); - assert (cast(double)view == double.infinity); + should(cast(float)view) == float.infinity; + should(cast(double)view) == double.infinity; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.e679c2f5e44ff8fp+1021L); + should(cast(real)view) == 0x8.e679c2f5e44ff8fp+1021L; view = DecimalView!size_t(false, 308, BigUIntView!size_t.fromHexString("2")); - assert (cast(float)view == float.infinity); - assert (cast(double)view == double.infinity); + should(cast(float)view) == float.infinity; + should(cast(double)view) == double.infinity; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.e679c2f5e44ff8fp+1021L); + should(cast(real)view) == 0x8.e679c2f5e44ff8fp+1021L; view = DecimalView!size_t(false, 295, BigUIntView!size_t.fromHexString("1059949B7090")); - assert (cast(float)view == float.infinity); - assert (cast(double)view == double.infinity); + should(cast(float)view) == float.infinity; + should(cast(double)view) == double.infinity; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.00000000006955ap+1021L); + should(cast(real)view) == 0x8.00000000006955ap+1021L; view = DecimalView!size_t(false, 0, BigUIntView!size_t.fromHexString("0")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0L); + should(cast(real)view) == 0L; view = view; - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0L); + should(cast(real)view) == 0L; view = DecimalView!size_t(false, -325, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xa.5ced43b7e3e9188p-1083L); + should(cast(real)view) == 0xa.5ced43b7e3e9188p-1083L; view = DecimalView!size_t(false, -326, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.4a57695fe98746dp-1086L); + should(cast(real)view) == 0x8.4a57695fe98746dp-1086L; view = DecimalView!size_t(false, -500, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.33ada2003db9a8p-1664L); + should(cast(real)view) == 0x8.33ada2003db9a8p-1664L; view = DecimalView!size_t(false, -1000, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.68a9188a89e1467p-3325L); + should(cast(real)view) == 0x8.68a9188a89e1467p-3325L; view = DecimalView!size_t(false, -4999, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0L); + should(cast(real)view) == 0L; view = DecimalView!size_t(false, -10000, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0L); + should(cast(real)view) == 0L; view = DecimalView!size_t(false, -4969, BigUIntView!size_t.fromHexString("329659A941466C6B")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == real.min_normal * real.epsilon); + should(cast(real)view) == real.min_normal * real.epsilon; view = DecimalView!size_t(false, -15, BigUIntView!size_t.fromHexString("525DB0200FFAB")); - assert (cast(float)view == 1.448997445238699f); - assert (cast(double)view == 0x1.72f17f1f49aadp+0); + should(cast(float)view) == 1.448997445238699f; + should(cast(double)view) == 0x1.72f17f1f49aadp+0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xb.978bf8fa4d56cp-3L); + should(cast(real)view) == 0xb.978bf8fa4d56cp-3L; view = DecimalView!size_t(false, -15, BigUIntView!size_t.fromHexString("525DB0200FFAB")); - assert (cast(float)view == 1.448997445238699f); - assert (cast(double)view == 0x1.72f17f1f49aadp+0); + should(cast(float)view) == 1.448997445238699f; + should(cast(double)view) == 0x1.72f17f1f49aadp+0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xb.978bf8fa4d56cp-3L); + should(cast(real)view) == 0xb.978bf8fa4d56cp-3L; view = DecimalView!size_t(false, -325, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xa.5ced43b7e3e9188p-1083L); + should(cast(real)view) == 0xa.5ced43b7e3e9188p-1083L; view = DecimalView!size_t(false, -326, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0); - assert (cast(double)view == 0); + should(cast(float)view) == 0; + should(cast(double)view) == 0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8.4a57695fe98746dp-1086L); + should(cast(real)view) == 0x8.4a57695fe98746dp-1086L; view = DecimalView!size_t(false, 0, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 1); - assert (cast(double)view == 0x1p+0); + should(cast(float)view) == 1; + should(cast(double)view) == 0x1p+0; static if (real.mant_dig >= 64) - assert (cast(real)view == 0x8p-3L); + should(cast(real)view) == 0x8p-3L; view = DecimalView!size_t(false, -5, BigUIntView!size_t.fromHexString("3")); - assert (cast(float)view == 3e-5f); - assert (cast(double)view == 0x1.f75104d551d69p-16); + should(cast(float)view) == 3e-5f; + should(cast(double)view) == 0x1.f75104d551d69p-16; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xf.ba8826aa8eb4635p-19L); + should(cast(real)view) == 0xf.ba8826aa8eb4635p-19L; view = DecimalView!size_t(false, -1, BigUIntView!size_t.fromHexString("1")); - assert (cast(float)view == 0.1f); - assert (cast(double)view == 0x1.999999999999ap-4); + should(cast(float)view) == 0.1f; + should(cast(double)view) == 0x1.999999999999ap-4; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xc.ccccccccccccccdp-7L); + should(cast(real)view) == 0xc.ccccccccccccccdp-7L; view = DecimalView!size_t(false, -7, BigUIntView!size_t.fromHexString("98967F")); - assert (cast(float)view == 0.9999999f); - assert (cast(double)view == 0x1.fffffca501acbp-1); + should(cast(float)view) == 0.9999999f; + should(cast(double)view) == 0x1.fffffca501acbp-1; static if (real.mant_dig >= 64) - assert (cast(real)view == 0xf.ffffe5280d65435p-4L); + should(cast(real)view) == 0xf.ffffe5280d65435p-4L; } /++ diff --git a/source/mir/format.d b/source/mir/format.d index a86588bc..92acd274 100644 --- a/source/mir/format.d +++ b/source/mir/format.d @@ -1160,3 +1160,14 @@ size_t printBoolean(C)(bool c, ref C[5] buf) return 5; } } + + +/// Prints pointers +ref W print(C = char, W, T)(scope return ref W w, scope const T* c) +{ + import mir.enums: getEnumIndex, enumStrings; + import mir.utility: _expect; + if (c is null) + return w.print!C(null); + return w.print!C(HexAddress!size_t((()@trusted=>cast(size_t)cast(const void*)c)())); +} diff --git a/source/mir/parse.d b/source/mir/parse.d index 2fa2c454..ecce011c 100644 --- a/source/mir/parse.d +++ b/source/mir/parse.d @@ -12,18 +12,16 @@ version(mir_bignum_test) @safe pure @nogc unittest { + import mir.test: should; import mir.conv: to; - assert("123.0".to!double == 123); - assert("123".to!int == 123); - assert("123".to!byte == 123); + "123.0".to!double.should == 123; + "123".to!int.should == 123; + "123".to!byte.should == 123; import mir.small_string; alias S = SmallString!32; - assert(S("123.0").to!double == 123); - assert(S("123.").to!double == 123.); - assert(S(".123").to!double == .123); - assert(S("123").to!(immutable int) == 123); + "123.0".SmallString!32.to!double.should == 123; } import mir.primitives; @@ -81,42 +79,123 @@ T fromString(T, C)(scope const(C)[] str) } } +version(unittest) +{ + import core.stdc.stdlib: strtof, strtod, strtold; + private auto _assumePure(T)(scope return T t) { + import std.traits; + enum attrs = functionAttributes!T | FunctionAttribute.pure_; + return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t; + } + + private static @trusted float _stdc_parse(T : float)(string str){ auto endPtr = str.ptr + str.length; return _assumePure(&strtof)(str.ptr, &endPtr); } + private static @trusted double _stdc_parse(T : double)(string str){ auto endPtr = str.ptr + str.length; return _assumePure(&strtod)(str.ptr, &endPtr); } + private static @trusted real _stdc_parse(T : real)(string str){ auto endPtr = str.ptr + str.length; return _assumePure(&strtold)(str.ptr, &endPtr); } +} + /// version(mir_bignum_test) @safe pure @nogc unittest { - assert("123".fromString!int == 123); - static assert("-123".fromString!int == -123); + import mir.test; + "123".fromString!int.should == 123; - assert(".5".fromString!float == .5); - assert("12.3".fromString!double == 12.3); - assert("12.3".fromString!float == 12.3f); - assert("12.3".fromString!real == 12.3L); - assert("-12.3e-30".fromString!double == -12.3e-30); - assert("2.9802322387695312E-8".fromString!double == 2.9802322387695312E-8); + ".5".fromString!float.should == .5; + "12.3".fromString!double.should == 12.3; + "12.3".fromString!float.should == 12.3f; + "12.3".fromString!real.should == 12.3L; + "-12.3e-30".fromString!double.should == -12.3e-30; + "2.9802322387695312E-8".fromString!double.should == 2.9802322387695312E-8; // default support of underscores - assert("123_456.789_012".fromString!double == 123_456.789_012); - assert("12_34_56_78_90_12e-6".fromString!double == 123_456.789_012); + "123_456.789_012".fromString!double.should == 123_456.789_012; + "12_34_56_78_90_12e-6".fromString!double.should == 123_456.789_012; // default support of leading zeros - assert("010".fromString!double == 10.0); - assert("000010".fromString!double == 10.0); - assert("0000.10".fromString!double == 0.1); - assert("0000e10".fromString!double == 0); + "010".fromString!double.should == 10.0; + "000010".fromString!double.should == 10.0; + "0000.10".fromString!double.should == 0.1; + "0000e10".fromString!double.should == 0; - /// Test CTFE support - static assert("-12.3e-30".fromString!double == -0x1.f2f280b2414d5p-97); - static assert("+12.3e+30".fromString!double == 0x1.367ee3119d2bap+103); + version(all) {} else + version (TeslAlgoM) {} else + { + /// Test CTFE support + static assert("-123".fromString!int == -123); - static assert("1.448997445238699".fromString!double == 0x1.72f17f1f49aadp0); - static if (real.mant_dig >= 64) - static assert("1.448997445238699".fromString!real == 1.448997445238699L); + static assert("-12.3e-30".fromString!double == -0x1.f2f280b2414d5p-97); + static assert("+12.3e+30".fromString!double == 0x1.367ee3119d2bap+103); - static assert("3.518437208883201171875".fromString!float == 0x1.c25c26p+1); - static assert("3.518437208883201171875".fromString!double == 0x1.c25c268497684p+1); - static if (real.mant_dig >= 64) - static assert("3.518437208883201171875".fromString!real == 0xe.12e13424bb4232fp-2L); + static assert("1.448997445238699".fromString!double == 0x1.72f17f1f49aadp0); + static if (real.mant_dig >= 64) + static assert("1.448997445238699".fromString!real == 1.448997445238699L); + + static assert("3.518437208883201171875".fromString!float == 0x1.c25c26p+1); + static assert("3.518437208883201171875".fromString!double == 0x1.c25c268497684p+1); + static if (real.mant_dig >= 64) + static assert("3.518437208883201171875".fromString!real == 0xe.12e13424bb4232fp-2L); + } + + void test(string str) + { + version(CRuntime_DigitalMars) // No precise parsing at all + { + } + else + { + str.fromString!float.should == str._stdc_parse!float; + str.fromString!double.should == str._stdc_parse!double; + version (Windows) // No precise real parsing on windows + { + } + else + str.fromString!real.should == str._stdc_parse!real; + } + } + + test("2.5e-324"); + + // large + test("1e300"); + test("123456789.34567e250"); + test("943794359898089732078308743689303290943794359843568973207830874368930329."); + + // min normal + test("2.2250738585072014e-308"); + + // subnormals + test("5e-324"); + test("91e-324"); + test("1e-322"); + test("13245643e-320"); + test("2.22507385851e-308"); + test("2.1e-308"); + test("4.9406564584124654e-324"); + + // infinity + test("1e400"); + test("1e309"); + test("2e308"); + test("1.7976931348624e308"); + + // zero + test("0.0"); + test("1e-325"); + test("1e-326"); + test("1e-500"); + + // Triggers the tricky underflow case in AlgorithmM (for f32) + test("101e-33"); + // Triggers AlgorithmR + test("1e23"); + // Triggers another path through AlgorithmR + test("2075e23"); + // ... and yet another. + test("8713e-23"); + + // 2^65 - 3, triggers half-to-even with even significand + test("36893488147419103229.0"); + test("36893488147419103229"); // Related DMD Issues: // https://issues.dlang.org/show_bug.cgi?id=20951 @@ -125,18 +204,6 @@ version(mir_bignum_test) // https://issues.dlang.org/show_bug.cgi?id=20967 } -// unittest -// { -// import std.stdio; -// import mir.conv; -// import mir.format; -// text(double.min_normal).writeln; -// text(double.min_normal * double.epsilon).writeln; -// assert("2.2250738585072014e-308".fromString!double == double.min_normal); -// assert("5e-324".fromString!double == double.min_normal * double.epsilon); -// assert("2.5e-324".fromString!double == double.min_normal * double.epsilon); -// } - version(mir_bignum_test) @safe pure unittest { diff --git a/source/mir/stdio.d b/source/mir/stdio.d index 006dda9a..2902342d 100644 --- a/source/mir/stdio.d +++ b/source/mir/stdio.d @@ -7,6 +7,29 @@ module mir.stdio; static import core.stdc.stdio; +/// Writes values in a text form +void writeln(string separator = "", Args...)(auto ref const Args args) + if (Args.length > 0) +{ + dout.write!separator(args); + dout << endl; +} + +/// ditto +void write(string separator = "", Args...)(auto ref const Args args) + if (Args.length > 0) +{ + dout.write!separator(args); +} + +/// Writes values in a text form using nothrow $(LREF tout) +void dump(string separator = " ", Args...)(auto ref const Args args) + if (Args.length > 0) +{ + tout.write!separator(args); + tout << endl; +} + /// Standart output File dout()() @trusted nothrow @nogc @property { @@ -174,8 +197,10 @@ mixin template FileMemembers() template opBinary(string op : "<<") { /// - ref opBinary(T)(auto ref T value) return scope + ref opBinary(T)(auto ref const T value) return scope { + if (__ctfe) + return this; import mir.format: print; return print!char(this, value); } @@ -183,12 +208,40 @@ mixin template FileMemembers() /// Prints new line and flushes the stream ref opBinary(NewLine endl) return scope { + if (__ctfe) + return this; import mir.format: print; this.put(endl); this.flush; return this; } } + + /// Writes values in a text form + void writeln(string separator = "", Args...)(auto ref const Args args) + if (Args.length > 0) + { + write(args); + this << endl; + } + + /// ditto + void write(string separator = "", Args...)(auto ref const Args args) + if (Args.length > 0) + { + pragma(inline, false); + if (__ctfe) + return; + import mir.format: print, printStaticString; + foreach (i, ref arg; args) + { + print!char(this, arg); + static if (separator.length && i + 1 < args.length) + { + printStaticString!char(this, separator); + } + } + } } /++ diff --git a/source/mir/test.d b/source/mir/test.d index 6152c448..217af0c6 100644 --- a/source/mir/test.d +++ b/source/mir/test.d @@ -5,7 +5,13 @@ Authors: Ilya Yaroshenko +/ module mir.test; -import mir.exception: MirException; +import mir.exception: MirError; + +private noreturn assumeAllAttrAndCall(scope const void delegate() t) + @nogc pure nothrow @trusted { + (cast(const void delegate() @safe pure nothrow @nogc) t)(); + assert(0); +} /// struct ShouldApprox(T) @@ -19,19 +25,22 @@ struct ShouldApprox(T) T maxAbsDiff = 0x1p-20f; /// - bool opEquals(T expected, string file = __FILE__, int line = __LINE__) const + void opEquals(T expected, string file = __FILE__, int line = __LINE__) @safe pure nothrow @nogc { import mir.format: stringBuf, getData; import mir.math.common: approxEqual; if (value.approxEqual(expected, maxRelDiff, maxAbsDiff)) - return true; + return; auto buf = stringBuf; - throw new MirException(buf - << "expected approximately " << expected - << ", got " << value - << ", maxRelDiff = " << maxRelDiff - << ", maxAbsDiff = " << maxAbsDiff - << getData, file, line); + assumeAllAttrAndCall({ + throw new MirError(buf + << "expected approximately " << expected + << ", got " << value + << ", maxRelDiff = " << maxRelDiff + << ", maxAbsDiff = " << maxAbsDiff + << getData, file, line); + }); + assert(0); } } @@ -57,16 +66,18 @@ struct Should(T) T value; /// - bool opEquals(R)(const R expected, string file = __FILE__, int line = __LINE__) const + void opEquals(R)(const R expected, string file = __FILE__, int line = __LINE__) { import mir.format: stringBuf, getData; if (value == expected) - return true; + return; auto buf = stringBuf; - throw new MirException(buf - << "expected " << expected - << ", got " << value - << getData, file, line); + assumeAllAttrAndCall({ + throw new MirError(buf + << "expected " << expected + << ", got " << value + << getData, file, line); + }); } } @@ -85,18 +96,18 @@ unittest } /// -bool should(alias fun, T, R)(const T value, const R expected, string file = __FILE__, int line = __LINE__) +void should(alias fun, T, R)(const T value, const R expected, string file = __FILE__, int line = __LINE__) { import mir.functional; import mir.format: stringBuf, getData; if (naryFun!fun(value, expected)) - return true; + return; auto buf = stringBuf; buf << fun.stringof << " returns false" << " for a = " << value << ", b = " << expected; - throw new MirException(buf << getData, file, line); + throw new MirError(buf << getData, file, line); } ///