Skip to content

Commit

Permalink
Merge pull request #6029 from BBasile/issue-14767
Browse files Browse the repository at this point in the history
fix issue 14767 - Support CTFE of BigInt under x86
merged-on-behalf-of: Jack Stouffer <jack@jackstouffer.com>
  • Loading branch information
dlang-bot authored Jan 24, 2018
2 parents 2174695 + 7bd9842 commit 3784831
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 5 deletions.
14 changes: 14 additions & 0 deletions std/bigint.d
Original file line number Diff line number Diff line change
Expand Up @@ -1775,3 +1775,17 @@ unittest
auto b = immutable BigInt("123");
assert(b == 123);
}

@system pure unittest // issue 14767
{
static immutable a = BigInt("340282366920938463463374607431768211455");
assert(a == BigInt("340282366920938463463374607431768211455"));

BigInt plusTwo(in BigInt n)
{
return n + 2;
}

enum BigInt test1 = BigInt(123);
enum BigInt test2 = plusTwo(test1);
}
150 changes: 145 additions & 5 deletions std/internal/math/biguintcore.d
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ module std.internal.math.biguintcore;

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

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

alias multibyteAdd = multibyteAddSub!('+');
alias multibyteSub = multibyteAddSub!('-');
Expand All @@ -52,6 +52,146 @@ import std.range.primitives;
import std.traits;

private:

// dipatchers to the right low-level primitives. Added to allow BigInt CTFE for
// 32 bit systems (issue 14767) although it's used by the other architectures too.
// See comments below in case it has to be refactored.
version(X86)
uint multibyteAddSub(char op)(uint[] dest, const(uint)[] src1, const (uint)[] src2, uint carry)
{
// must be checked before, otherwise D_InlineAsm_X86 is true.
if (__ctfe)
return std.internal.math.biguintnoasm.multibyteAddSub!op(dest, src1, src2, carry);
// Runtime.
else version(D_InlineAsm_X86)
return std.internal.math.biguintx86.multibyteAddSub!op(dest, src1, src2, carry);
// Runtime if no asm available.
else
return std.internal.math.biguintnoasm.multibyteAddSub!op(dest, src1, src2, carry);
}
// Any other architecture
else alias multibyteAddSub = std.internal.math.biguintnoasm.multibyteAddSub;

version(X86)
uint multibyteIncrementAssign(char op)(uint[] dest, uint carry)
{
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);
}
else alias multibyteIncrementAssign = std.internal.math.biguintnoasm.multibyteIncrementAssign;

version(X86)
uint multibyteShl()(uint[] dest, const(uint)[] src, uint numbits)
{
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);
}
else alias multibyteShl = std.internal.math.biguintnoasm.multibyteShl;

version(X86)
void multibyteShr()(uint[] dest, const(uint)[] src, uint numbits)
{
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);
}
else alias multibyteShr = std.internal.math.biguintnoasm.multibyteShr;

version(X86)
uint multibyteMul()(uint[] dest, const(uint)[] src, uint multiplier, uint carry)
{
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);
}
else alias multibyteMul = std.internal.math.biguintnoasm.multibyteMul;

version(X86)
uint multibyteMulAdd(char op)(uint[] dest, const(uint)[] src, uint multiplier, uint carry)
{
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);
}
else alias multibyteMulAdd = std.internal.math.biguintnoasm.multibyteMulAdd;

version(X86)
void multibyteMultiplyAccumulate()(uint[] dest, const(uint)[] left, const(uint)[] right)
{
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);
}
else alias multibyteMultiplyAccumulate = std.internal.math.biguintnoasm.multibyteMultiplyAccumulate;

version(X86)
uint multibyteDivAssign()(uint[] dest, uint divisor, uint overflow)
{
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);
}
else alias multibyteDivAssign = std.internal.math.biguintnoasm.multibyteDivAssign;

version(X86)
void multibyteAddDiagonalSquares()(uint[] dest, const(uint)[] src)
{
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);
}
else alias multibyteAddDiagonalSquares = std.internal.math.biguintnoasm.multibyteAddDiagonalSquares;

version(X86)
void multibyteTriangleAccumulate()(uint[] dest, const(uint)[] x)
{
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);
}
else alias multibyteTriangleAccumulate = std.internal.math.biguintnoasm.multibyteTriangleAccumulate;

version(X86)
void multibyteSquare()(BigDigit[] result, const(BigDigit)[] x)
{
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);
}
else alias multibyteSquare = std.internal.math.biguintnoasm.multibyteSquare;

// 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 3784831

Please sign in to comment.