in commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Int128.java [146:198]
BigInteger toBigInteger() {
long h = hi;
long l = lo;
// Special cases
if (h == 0) {
return BigInteger.valueOf(l);
}
if (l == 0) {
return BigInteger.valueOf(h).shiftLeft(64);
}
// The representation is 2^64 * hi64 + lo64.
// Here we avoid evaluating the addition:
// BigInteger.valueOf(l).add(BigInteger.valueOf(h).shiftLeft(64))
// It is faster to create from bytes.
// BigInteger bytes are an unsigned integer in BigEndian format, plus a sign.
// If both values are positive we can use the values unchanged.
// Otherwise selective negation is used to create a positive magnitude
// and we track the sign.
// Note: Negation of -2^63 is valid to create an unsigned 2^63.
int sign = 1;
if ((h ^ l) < 0) {
// Opposite signs and lo64 is not zero.
// The lo64 bits are an adjustment to the magnitude of hi64
// to make it smaller.
// Here we rearrange to [2^64 * (hi64-1)] + [2^64 - lo64].
// The second term [2^64 - lo64] can use lo64 as an unsigned 64-bit integer.
// The first term [2^64 * (hi64-1)] does not work if low is zero.
// It would work if zero was detected and we carried the overflow
// bit up to h to make it equal to: (h - 1) + 1 == h.
// Instead lo64 == 0 is handled as a special case above.
if (h >= 0) {
// Treat (unchanged) low as an unsigned add
h = h - 1;
} else {
// As above with negation
h = ~h; // -h - 1
l = -l;
sign = -1;
}
} else if (h < 0) {
// Invert negative values to create the equivalent positive magnitude.
h = -h;
l = -l;
sign = -1;
}
return new BigInteger(sign,
ByteBuffer.allocate(Long.BYTES * 2)
.putLong(h).putLong(l).array());
}