Skip to content

Commit

Permalink
fix issue 14767 - Support CTFE of BigInt under x86
Browse files Browse the repository at this point in the history
  • Loading branch information
Basile Burg committed Jan 14, 2018
1 parent 2c0adf0 commit f2c5ee3
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 2 deletions.
6 changes: 6 additions & 0 deletions std/bigint.d
Expand Up @@ -1761,3 +1761,9 @@ unittest
auto b = immutable BigInt("123");
assert(b == 123);
}

@safe pure unittest // issue 14767
{
static immutable a = BigInt("340282366920938463463374607431768211455");
assert(a == BigInt("340282366920938463463374607431768211455"));
}
131 changes: 129 additions & 2 deletions std/internal/math/biguintcore.d
Expand Up @@ -35,13 +35,16 @@ module std.internal.math.biguintcore;

version(D_InlineAsm_X86)
{
import std.internal.math.biguintx86;
static import std.internal.math.biguintx86;
}
else
{
import std.internal.math.biguintnoasm;
static import std.internal.math.biguintnoasm;
}

import std.internal.math.biguintnoasm : BigDigit, KARATSUBALIMIT,
KARATSUBASQUARELIMIT;

alias multibyteAdd = multibyteAddSub!('+');
alias multibyteSub = multibyteAddSub!('-');

Expand All @@ -52,6 +55,130 @@ import std.range.primitives;
import std.traits;

private:

// compile-time & run-time dipatchers to allows BigInt CTFE for 32 bit OS.

pragma(inline, true)
uint multibyteAddSub(char op)(uint[] dest, const(uint)[] src1, const (uint)[] src2, uint carry) pure
{
if (__ctfe)
return std.internal.math.biguintnoasm.multibyteAddSub!op(dest, src1, src2, carry);
else version(D_InlineAsm_X86)
return std.internal.math.biguintx86.multibyteAddSub!op(dest, src1, src2, carry);
else
return std.internal.math.biguintnoasm.multibyteAddSub!op(dest, src1, src2, carry);
}

pragma(inline, true)
uint multibyteIncrementAssign(char op)(uint[] dest, uint carry) pure
{
if (__ctfe)
return std.internal.math.biguintnoasm.multibyteIncrementAssign!op(dest, carry);
else version(D_InlineAsm_X86)
return std.internal.math.biguintx86.multibyteIncrementAssign!op(dest, carry);
else
return std.internal.math.biguintnoasm.multibyteIncrementAssign!op(dest, carry);
}

pragma(inline, true)
uint multibyteShl()(uint[] dest, const(uint)[] src, uint numbits) pure
{
if (__ctfe)
return std.internal.math.biguintnoasm.multibyteShl(dest, src, numbits);
else version(D_InlineAsm_X86)
return std.internal.math.biguintx86.multibyteShl(dest, src, numbits);
else
return std.internal.math.biguintnoasm.multibyteShl(dest, src, numbits);
}

pragma(inline, true)
void multibyteShr()(uint[] dest, const(uint)[] src, uint numbits) pure
{
if (__ctfe)
std.internal.math.biguintnoasm.multibyteShr(dest, src, numbits);
else version(D_InlineAsm_X86)
std.internal.math.biguintx86.multibyteShr(dest, src, numbits);
else
std.internal.math.biguintnoasm.multibyteShr(dest, src, numbits);
}

pragma(inline, true)
uint multibyteMul()(uint[] dest, const(uint)[] src, uint multiplier, uint carry) pure
{
if (__ctfe)
return std.internal.math.biguintnoasm.multibyteMul(dest, src, multiplier, carry);
else version(D_InlineAsm_X86)
return std.internal.math.biguintx86.multibyteMul(dest, src, multiplier, carry);
else
return std.internal.math.biguintnoasm.multibyteMul(dest, src, multiplier, carry);
}

pragma(inline, true)
uint multibyteMulAdd(char op)(uint[] dest, const(uint)[] src, uint multiplier, uint carry) pure
{
if (__ctfe)
return std.internal.math.biguintnoasm.multibyteMulAdd!op(dest, src, multiplier, carry);
else version(D_InlineAsm_X86)
return std.internal.math.biguintx86.multibyteMulAdd!op(dest, src, multiplier, carry);
else
return std.internal.math.biguintnoasm.multibyteMulAdd!op(dest, src, multiplier, carry);
}

pragma(inline, true)
void multibyteMultiplyAccumulate()(uint[] dest, const(uint)[] left, const(uint)[] right) pure
{
if (__ctfe)
std.internal.math.biguintnoasm.multibyteMultiplyAccumulate(dest, left, right);
else version(D_InlineAsm_X86)
std.internal.math.biguintx86.multibyteMultiplyAccumulate(dest, left, right);
else
std.internal.math.biguintnoasm.multibyteMultiplyAccumulate(dest, left, right);
}

pragma(inline, true)
uint multibyteDivAssign()(uint[] dest, uint divisor, uint overflow) pure
{
if (__ctfe)
return std.internal.math.biguintnoasm.multibyteDivAssign(dest, divisor, overflow);
else version(D_InlineAsm_X86)
return std.internal.math.biguintx86.multibyteDivAssign(dest, divisor, overflow);
else
return std.internal.math.biguintnoasm.multibyteDivAssign(dest, divisor, overflow);
}

pragma(inline, true)
void multibyteAddDiagonalSquares()(uint[] dest, const(uint)[] src) pure
{
if (__ctfe)
std.internal.math.biguintnoasm.multibyteAddDiagonalSquares(dest, src);
else version(D_InlineAsm_X86)
std.internal.math.biguintx86.multibyteAddDiagonalSquares(dest, src);
else
std.internal.math.biguintnoasm.multibyteAddDiagonalSquares(dest, src);
}

pragma(inline, true)
void multibyteTriangleAccumulate()(uint[] dest, const(uint)[] x) pure
{
if (__ctfe)
std.internal.math.biguintnoasm.multibyteTriangleAccumulate(dest, x);
else version(D_InlineAsm_X86)
std.internal.math.biguintx86.multibyteTriangleAccumulate(dest, x);
else
std.internal.math.biguintnoasm.multibyteTriangleAccumulate(dest, x);
}

pragma(inline, true)
void multibyteSquare()(BigDigit[] result, const(BigDigit) [] x) pure
{
if (__ctfe)
std.internal.math.biguintnoasm.multibyteSquare(result, x);
else version(D_InlineAsm_X86)
std.internal.math.biguintx86.multibyteSquare(result, x);
else
std.internal.math.biguintnoasm.multibyteSquare(result, x);
}

// Limits for when to switch between algorithms.
// Half the size of the data cache.
@nogc nothrow pure size_t getCacheLimit()
Expand Down

0 comments on commit f2c5ee3

Please sign in to comment.