Skip to content

Commit

Permalink
Sulong: big integer fp128
Browse files Browse the repository at this point in the history
  • Loading branch information
Palez committed Feb 24, 2023
1 parent b68c66d commit dedc275
Showing 1 changed file with 59 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -608,8 +608,13 @@ boolean fitsInLong(@CachedLibrary("this.buffer") InteropLibrary interop) {
}

@ExportMessage
static boolean fitsInBigInteger(@SuppressWarnings("unused") FP128Buffer receiver) {
return false;
boolean fitsInBigInteger(@CachedLibrary("this.buffer") InteropLibrary interop) {
try {
asBigInteger(interop);
return true;
} catch (UnsupportedMessageException ex) {
return false;
}
}

@ExportMessage
Expand Down Expand Up @@ -700,15 +705,65 @@ long asLong(@CachedLibrary("this.buffer") InteropLibrary interop) throws Unsuppo

@ExportMessage
BigInteger asBigInteger(@CachedLibrary("this.buffer") InteropLibrary interop) throws UnsupportedMessageException {
long unbiasedExponent;
long expSignFraction;
long fractionLong;
try {
long expSignFraction = interop.readBufferLong(buffer, ByteOrder.LITTLE_ENDIAN, 8);
expSignFraction = interop.readBufferLong(buffer, ByteOrder.LITTLE_ENDIAN, 8);
if ((expSignFraction & FP128Number.EXPONENT_MASK) == FP128Number.EXPONENT_MASK) {
// NaN or infinity
throw UnsupportedMessageException.create();
}

unbiasedExponent = getUnbiasedExponent(expSignFraction);
fractionLong = interop.readBufferLong(buffer, ByteOrder.LITTLE_ENDIAN, 0);
} catch (InvalidBufferOffsetException ex) {
throw UnsupportedMessageException.create();
}
return null;
return toBigInteger(fractionLong, expSignFraction, unbiasedExponent);
}

@TruffleBoundary
private static BigInteger toBigInteger(long longFraction, long expSignFraction, long unbiasedExponent) throws UnsupportedMessageException {
BigInteger bigIntegerFraction = toUnsignedBigInteger(longFraction, expSignFraction, unbiasedExponent);
int shift = (int) (FP128Number.FRACTION_BIT_WIDTH - unbiasedExponent - 1);
BigInteger ret;
if (shift >= 0) {
ret = bigIntegerFraction.shiftRight(shift);
BigInteger fractionBack = ret.shiftLeft(shift);
if (!bigIntegerFraction.equals(fractionBack)) {
// not a whole number
throw UnsupportedMessageException.create();
}
} else {
ret = bigIntegerFraction.shiftLeft(-shift);
}

if ((expSignFraction & FP128Number.SIGN_MASK) == 0) {
return ret;
} else {
return ret.negate();
}
}

private static BigInteger toUnsignedBigInteger(long fraction, long expSignFraction, long unbiasedExponent) {
if (fraction >= 0L) {
return BigInteger.valueOf(fraction);
} else {
long upper = (expSignFraction & FP128Number.FRACTION_MASK) << (unbiasedExponent - FP128Number.EXPONENT_POSITION);
long lower = fraction;

int upper1 = (int) ((upper << 1) + ((lower >>> FP128Number.DOUBLE_SIGN_POS) + (1 << FP128Number.EXPONENT_POSITION)));
int lower1 = (int) (lower & FP128Number.DOUBLE_SIGN_POS);

return (BigInteger.valueOf(Integer.toUnsignedLong(upper1))).shiftLeft(63).add(BigInteger.valueOf(Integer.toUnsignedLong(lower1)));

// upper -- part -- 48 bits
// lower -- whole -- 64 bits -- might be negative
// upper1 = upper shift left by 1 + lower right shift by 63 + (1 << 48)
// lower1 = lower masked by 63 bits
// BigInteger bi = upper1 left shift by 63 bits + lower1
}
}

@ExportMessage
Expand Down

0 comments on commit dedc275

Please sign in to comment.