diff options
Diffstat (limited to 'examples/scala-js/library/src/main/scala/scala/scalajs/runtime/RuntimeLong.scala')
-rw-r--r-- | examples/scala-js/library/src/main/scala/scala/scalajs/runtime/RuntimeLong.scala | 686 |
1 files changed, 686 insertions, 0 deletions
diff --git a/examples/scala-js/library/src/main/scala/scala/scalajs/runtime/RuntimeLong.scala b/examples/scala-js/library/src/main/scala/scala/scalajs/runtime/RuntimeLong.scala new file mode 100644 index 0000000..3bd6fb6 --- /dev/null +++ b/examples/scala-js/library/src/main/scala/scala/scalajs/runtime/RuntimeLong.scala @@ -0,0 +1,686 @@ +package scala.scalajs.runtime + +import scala.annotation.tailrec + +/** + * emulate a Java-Long using three integers. + * taken from gwt LongLib: + * com.google.gwt.lang.LongLib + * + * only used by runtime + * + * holds values l, m, h (low, middle, high) + * s.t. (x.l + ((long) x.m << 22) + ((long) x.h << 44)) is equal to + * the original value + */ +final class RuntimeLong( + val l: Int, + val m: Int, + val h: Int +) extends Number with Comparable[java.lang.Long] { x => + + import RuntimeLong._ + + /** Construct from an Int. + * This is the implementation of RuntimeLong.fromInt() in a way that does not + * require to load to module RuntimeLong. + */ + def this(value: Int) = this( + value & RuntimeLong.MASK, + (value >> RuntimeLong.BITS) & RuntimeLong.MASK, + if (value < 0) RuntimeLong.MASK_2 else 0) + + /** Creates a new RuntimeLong but masks bits as follows: + * l & MASK, m & MASK, h & MASK_2 + */ + @inline private def masked(l: Int, m: Int, h: Int) = + new RuntimeLong(l & MASK, m & MASK, h & MASK_2) + + def toByte: Byte = toInt.toByte + def toShort: Short = toInt.toShort + def toChar: Char = toInt.toChar + def toInt: Int = l | (m << BITS) + def toLong: Long = x.asInstanceOf[Long] + def toFloat: Float = toDouble.toFloat + def toDouble: Double = + if (isMinValue) -9223372036854775808.0 + else if (isNegative) -((-x).toDouble) + else l + m * TWO_PWR_22_DBL + h * TWO_PWR_44_DBL + + // java.lang.Number + override def byteValue(): Byte = toByte + override def shortValue(): Short = toShort + def intValue(): Int = toInt + def longValue(): Long = toLong + def floatValue(): Float = toFloat + def doubleValue(): Double = toDouble + + // java.lang.Comparable + overload taking scala.Long + def compareTo(that: RuntimeLong): Int = + if (this equals that) 0 else if (this > that) 1 else -1 + def compareTo(that: java.lang.Long): Int = + compareTo(that.asInstanceOf[RuntimeLong]) + + def unary_~ : RuntimeLong = masked(~x.l, ~x.m, ~x.h) + def unary_+ : RuntimeLong = x + def unary_- : RuntimeLong = { + val neg0 = (~x.l + 1) & MASK + val neg1 = (~x.m + (if (neg0 == 0) 1 else 0)) & MASK + val neg2 = (~x.h + (if (neg0 == 0 && neg1 == 0) 1 else 0)) & MASK_2 + new RuntimeLong(neg0, neg1, neg2) + } + + def +(y: String): String = x.toString + y + + def <<(n_in: Int): RuntimeLong = { + /* crop MSB. Note: This will cause (2L << 65 == 2L << 1) + * apparently this is as specified + */ + val n = n_in & 63 + + if (n < BITS) { + val remBits = BITS - n + masked(x.l << n, + (x.m << n) | (x.l >> remBits), + (x.h << n) | (x.m >> remBits)) + } else if (n < BITS01) { + val shfBits = n - BITS + val remBits = BITS01 - n + masked(0, x.l << shfBits, (x.m << shfBits) | (x.l >> remBits)) + } else { + masked(0, 0, x.l << (n - BITS01)) + } + + } + + /** + * logical right shift + */ + def >>>(n_in: Int): RuntimeLong = { + val n = n_in & 63 + if (n < BITS) { + val remBits = BITS - n + masked((x.l >> n) | (x.m << remBits), + // FIXME is this really >> and not >>>?? + (x.m >> n) | (x.h << remBits), + x.h >>> n) + } else if (n < BITS01) { + val shfBits = n - BITS + val remBits = BITS01 - n + // FIXME is this really >> and not >>>?? + masked((x.m >> shfBits) | (x.h << remBits), + x.h >>> shfBits, 0) + } else { + masked(x.h >>> (n - BITS01), 0, 0) + } + } + + /** + * arithmetic right shift + */ + def >>(n_in: Int): RuntimeLong = { + val n = n_in & 63; + + // Sign extend x.h + val negative = (x.h & SIGN_BIT_VALUE) != 0 + val xh = if (negative) x.h | ~MASK_2 else x.h + + if (n < BITS) { + val remBits = BITS - n + // FIXME IMHO the first two >> should be >>> + masked((x.l >> n) | (x.m << remBits), + (x.m >> n) | (xh << remBits), + xh >> n) + } else if (n < BITS01) { + val shfBits = n - BITS + val remBits = BITS01 - n + // FIXME IMHO the first >> should be >>> + masked((x.m >> shfBits) | (xh << remBits), + xh >> shfBits, + if (negative) MASK_2 else 0) + } else { + masked(xh >> (n - BITS01), + if (negative) MASK else 0, + if (negative) MASK_2 else 0) + } + + } + + def equals(y: RuntimeLong): Boolean = + x.l == y.l && x.m == y.m && x.h == y.h + + override def equals(that: Any): Boolean = that match { + case y: RuntimeLong => x.equals(y) + case _ => false + } + + def notEquals(that: RuntimeLong) = !equals(that) + + override def hashCode(): Int = { + (this ^ (this >>> 32)).toInt + } + + @inline + def <(y: RuntimeLong): Boolean = y > x + @inline + def <=(y: RuntimeLong): Boolean = y >= x + + def >(y: RuntimeLong): Boolean = { + if (!x.isNegative) + y.isNegative || + x.h > y.h || + x.h == y.h && x.m > y.m || + x.h == y.h && x.m == y.m && x.l > y.l + else !( + !y.isNegative || + x.h < y.h || + x.h == y.h && x.m < y.m || + x.h == y.h && x.m == y.m && x.l <= y.l + ) + } + + def >=(y: RuntimeLong): Boolean = { + if (!x.isNegative) + y.isNegative || + x.h > y.h || + x.h == y.h && x.m > y.m || + x.h == y.h && x.m == y.m && x.l >= y.l + else !( + !y.isNegative || + x.h < y.h || + x.h == y.h && x.m < y.m || + x.h == y.h && x.m == y.m && x.l < y.l + ) + } + + def |(y: RuntimeLong): RuntimeLong = + new RuntimeLong(x.l | y.l, x.m | y.m, x.h | y.h) + def &(y: RuntimeLong): RuntimeLong = + new RuntimeLong(x.l & y.l, x.m & y.m, x.h & y.h) + def ^(y: RuntimeLong): RuntimeLong = + new RuntimeLong(x.l ^ y.l, x.m ^ y.m, x.h ^ y.h) + + def +(y: RuntimeLong): RuntimeLong = { + val sum0 = x.l + y.l + val sum1 = x.m + y.m + (sum0 >> BITS) + val sum2 = x.h + y.h + (sum1 >> BITS) + masked(sum0, sum1, sum2) + } + + /** + * subtraction + * note: gwt implements this individually + */ + def -(y: RuntimeLong): RuntimeLong = x + (-y) + + // This assumes that BITS == 22 + def *(y: RuntimeLong): RuntimeLong = { + + /** divides v in 13bit chunks */ + @inline def chunk13(v: RuntimeLong) = ( + v.l & 0x1fff, + (v.l >> 13) | ((v.m & 0xf) << 9), + (v.m >> 4) & 0x1fff, + (v.m >> 17) | ((v.h & 0xff) << 5), + (v.h & 0xfff00) >> 8 + ) + + val (a0, a1, a2, a3, a4) = chunk13(x) + val (b0, b1, b2, b3, b4) = chunk13(y) + + // Compute partial products + // Optimization: if b is small, avoid multiplying by parts that are 0 + var p0 = a0 * b0; // << 0 + var p1 = a1 * b0; // << 13 + var p2 = a2 * b0; // << 26 + var p3 = a3 * b0; // << 39 + var p4 = a4 * b0; // << 52 + + if (b1 != 0) { + p1 += a0 * b1; + p2 += a1 * b1; + p3 += a2 * b1; + p4 += a3 * b1; + } + if (b2 != 0) { + p2 += a0 * b2; + p3 += a1 * b2; + p4 += a2 * b2; + } + if (b3 != 0) { + p3 += a0 * b3; + p4 += a1 * b3; + } + if (b4 != 0) { + p4 += a0 * b4; + } + + // Accumulate into 22-bit chunks: + // .........................................c10|...................c00| + // |....................|..................xxxx|xxxxxxxxxxxxxxxxxxxxxx| p0 + // |....................|......................|......................| + // |....................|...................c11|......c01.............| + // |....................|....xxxxxxxxxxxxxxxxxx|xxxxxxxxx.............| p1 + // |....................|......................|......................| + // |.................c22|...............c12....|......................| + // |..........xxxxxxxxxx|xxxxxxxxxxxxxxxxxx....|......................| p2 + // |....................|......................|......................| + // |.................c23|..c13.................|......................| + // |xxxxxxxxxxxxxxxxxxxx|xxxxx.................|......................| p3 + // |....................|......................|......................| + // |.........c24........|......................|......................| + // |xxxxxxxxxxxx........|......................|......................| p4 + + val c00 = p0 & 0x3fffff; + val c01 = (p1 & 0x1ff) << 13; + val c0 = c00 + c01; + + val c10 = p0 >> 22; + val c11 = p1 >> 9; + val c12 = (p2 & 0x3ffff) << 4; + val c13 = (p3 & 0x1f) << 17; + val c1 = c10 + c11 + c12 + c13; + + val c22 = p2 >> 18; + val c23 = p3 >> 5; + val c24 = (p4 & 0xfff) << 8; + val c2 = c22 + c23 + c24; + + // Propagate high bits from c0 -> c1, c1 -> c2 + val c1n = c1 + (c0 >> BITS) + + masked(c0, c1n, c2 + (c1n >> BITS)) + } + + def /(y: RuntimeLong): RuntimeLong = (x divMod y)(0) + def %(y: RuntimeLong): RuntimeLong = (x divMod y)(1) + + //override def getClass(): Class[Long] = null + + def toBinaryString: String = { + val zeros = "0000000000000000000000" // 22 zeros + @inline def padBinary22(i: Int) = { + val s = Integer.toBinaryString(i) + zeros.substring(s.length) + s + } + + if (h != 0) Integer.toBinaryString(h) + padBinary22(m) + padBinary22(l) + else if (m != 0) Integer.toBinaryString(m) + padBinary22(l) + else Integer.toBinaryString(l) + } + + def toHexString: String = { + val zeros = "000000" // 6 zeros + @inline def padHex(i: Int, len: Int) = { + val s = Integer.toHexString(i) + zeros.substring(s.length + (6-len)) + s + } + + val mp = m >> 2 + val lp = l | ((m & 0x3) << BITS) + + if (h != 0) Integer.toHexString(h) + padHex(mp, 5) + padHex(lp, 6) + else if (mp != 0) Integer.toHexString(mp) + padHex(lp, 6) + else Integer.toHexString(lp) + } + + def toOctalString: String = { + val zeros = "0000000" // 7 zeros + @inline def padOctal7(i: Int) = { + val s = Integer.toOctalString(i) + zeros.substring(s.length) + s + } + + val lp = l & (MASK >> 1) + val mp = ((m & (MASK >> 2)) << 1) | (l >> (BITS - 1)) + val hp = (h << 2) | (m >> (BITS - 2)) + + if (hp != 0) Integer.toOctalString(hp) + padOctal7(mp) + padOctal7(lp) + else if (mp != 0) Integer.toOctalString(mp) + padOctal7(lp) + else Integer.toOctalString(lp) + } + + // Any API // + + override def toString: String = { + if (isZero) "0" + // Check for MinValue, because its not negatable + else if (isMinValue) "-9223372036854775808" + else if (isNegative) "-" + (-x).toString + else { + val tenPow9 = TenPow9 // local copy to access CachedConstants only once + + @tailrec + @inline + def toString0(v: RuntimeLong, acc: String): String = + if (v.isZero) acc + else { + val quotRem = v.divMod(tenPow9) + val quot = quotRem(0) + val rem = quotRem(1) + + val digits = rem.toInt.toString + val zeroPrefix = + if (quot.isZero) "" + else "000000000".substring(digits.length) // (9 - digits.length) zeros + + toString0(quot, zeroPrefix + digits + acc) + } + + toString0(x, "") + } + } + + def bitCount: Int = + Integer.bitCount(l) + Integer.bitCount(m) + Integer.bitCount(h) + + // helpers // + + @inline private def isZero = l == 0 && m == 0 && h == 0 + @inline private def isMinValue = x.equals(MinValue) + @inline private def isNegative = (h & SIGN_BIT_VALUE) != 0 + @inline private def abs = if (isNegative) -x else x + + def signum: RuntimeLong = + if (isNegative) MinusOne else if (isZero) Zero else One + + def numberOfLeadingZeros: Int = + if (h != 0) Integer.numberOfLeadingZeros(h) - (32 - BITS2) + else if (m != 0) Integer.numberOfLeadingZeros(m) - (32 - BITS) + (64 - BITS01) + else Integer.numberOfLeadingZeros(l) - (32 - BITS) + (64 - BITS) + + def numberOfTrailingZeros: Int = + if (l != 0) Integer.numberOfTrailingZeros(l) + else if (m != 0) Integer.numberOfTrailingZeros(m) + BITS + else Integer.numberOfTrailingZeros(h) + BITS01 + + /** return log_2(x) if power of 2 or -1 otherwise */ + private def powerOfTwo = + if (h == 0 && m == 0 && l != 0 && (l & (l - 1)) == 0) + Integer.numberOfTrailingZeros(l) + else if (h == 0 && m != 0 && l == 0 && (m & (m - 1)) == 0) + Integer.numberOfTrailingZeros(m) + BITS + else if (h != 0 && m == 0 && l == 0 && (h & (h - 1)) == 0) + Integer.numberOfTrailingZeros(h) + BITS01 + else + -1 + + private def setBit(bit: Int) = + if (bit < BITS) + new RuntimeLong(l | (1 << bit), m, h) + else if (bit < BITS01) + new RuntimeLong(l, m | (1 << (bit - BITS)), h) + else + new RuntimeLong(l, m, h | (1 << (bit - BITS01))) + + private def divMod(y: RuntimeLong): scala.scalajs.js.Array[RuntimeLong] = { + import scala.scalajs.js + if (y.isZero) throw new ArithmeticException("/ by zero") + else if (x.isZero) js.Array(Zero, Zero) + else if (y.isMinValue) { + // MinValue / MinValue == 1, rem = 0 + // otherwise == 0, rem x + if (x.isMinValue) js.Array(One, Zero) + else js.Array(Zero, x) + } else { + val xNegative = x.isNegative + val yNegative = y.isNegative + + val xMinValue = x.isMinValue + + val pow = y.powerOfTwo + if (pow >= 0) { + if (xMinValue) { + val z = x >> pow + js.Array(if (yNegative) -z else z, Zero) + } else { + // x is not min value, so we can calculate absX + val absX = x.abs + val absZ = absX >> pow + val z = if (xNegative ^ yNegative) -absZ else absZ + val remAbs = absX.maskRight(pow) + val rem = if (xNegative) -remAbs else remAbs + js.Array(z, rem) + } + } else { + val absY = y.abs + + val newX = { + if (xMinValue) + MaxValue + else { + val absX = x.abs + if (absX < absY) + return js.Array(Zero, x) // <-- ugly but fast + else + absX + } + } + divModHelper(newX, absY, xNegative, yNegative, xMinValue) + } + } + } + + @inline + private def maskRight(bits: Int) = { + if (bits <= BITS) + new RuntimeLong(l & ((1 << bits) - 1), 0, 0) + else if (bits <= BITS01) + new RuntimeLong(l, m & ((1 << (bits - BITS)) - 1), 0) + else + new RuntimeLong(l, m, h & ((1 << (bits - BITS01)) - 1)) + } + + /** + * performs division in "normal cases" + * @param x absolute value of the numerator + * @param y absolute value of the denominator + * @param xNegative whether numerator was negative + * @param yNegative whether denominator was negative + * @param xMinValue whether numerator was Long.minValue + */ + @inline + private def divModHelper(x: RuntimeLong, y: RuntimeLong, + xNegative: Boolean, yNegative: Boolean, + xMinValue: Boolean): scala.scalajs.js.Array[RuntimeLong] = { + import scala.scalajs.js + + @inline + @tailrec + def divide0(shift: Int, yShift: RuntimeLong, curX: RuntimeLong, + quot: RuntimeLong): (RuntimeLong, RuntimeLong) = + if (shift < 0 || curX.isZero) (quot, curX) else { + val newX = curX - yShift + if (!newX.isNegative) + divide0(shift-1, yShift >> 1, newX, quot.setBit(shift)) + else + divide0(shift-1, yShift >> 1, curX, quot) + } + + val shift = y.numberOfLeadingZeros - x.numberOfLeadingZeros + val yShift = y << shift + + val (absQuot, absRem) = divide0(shift, yShift, x, Zero) + + val quot = if (xNegative ^ yNegative) -absQuot else absQuot + val rem = + if (xNegative && xMinValue) -absRem - One + else if (xNegative) -absRem + else absRem + + js.Array(quot, rem) + } + + /* + * Methods of scala.Long + * The following methods are only here to properly support reflective calls + * on longs. YOU MUST NOT USE THESE METHODS. + */ + + //protected def unary_~ : Long = ~toLong // already defined + //protected def unary_+ : Long = toLong // already defined + //protected def unary_- : Long = -toLong // already defined + + //protected def <<(y: Int): Long = toLong << y // already defined + protected def <<(y: Long): Long = toLong << y + //protected def >>>(y: Int): Long = toLong >>> y // already defined + protected def >>>(y: Long): Long = toLong >>> y + //protected def >>(y: Int): Long = toLong >> y // already defined + protected def >>(y: Long): Long = toLong >> y + + protected def ==(y: Byte): Boolean = toLong == y + protected def ==(y: Short): Boolean = toLong == y + protected def ==(y: Char): Boolean = toLong == y + protected def ==(y: Int): Boolean = toLong == y + protected def ==(y: Long): Boolean = toLong == y + protected def ==(y: Float): Boolean = toLong == y + protected def ==(y: Double): Boolean = toLong == y + + protected def !=(y: Byte): Boolean = toLong != y + protected def !=(y: Short): Boolean = toLong != y + protected def !=(y: Char): Boolean = toLong != y + protected def !=(y: Int): Boolean = toLong != y + protected def !=(y: Long): Boolean = toLong != y + protected def !=(y: Float): Boolean = toLong != y + protected def !=(y: Double): Boolean = toLong != y + + protected def <(y: Byte): Boolean = toLong < y + protected def <(y: Short): Boolean = toLong < y + protected def <(y: Char): Boolean = toLong < y + protected def <(y: Int): Boolean = toLong < y + protected def <(y: Long): Boolean = toLong < y + protected def <(y: Float): Boolean = toLong < y + protected def <(y: Double): Boolean = toLong < y + + protected def <=(y: Byte): Boolean = toLong <= y + protected def <=(y: Short): Boolean = toLong <= y + protected def <=(y: Char): Boolean = toLong <= y + protected def <=(y: Int): Boolean = toLong <= y + protected def <=(y: Long): Boolean = toLong <= y + protected def <=(y: Float): Boolean = toLong <= y + protected def <=(y: Double): Boolean = toLong <= y + + protected def >(y: Byte): Boolean = toLong > y + protected def >(y: Short): Boolean = toLong > y + protected def >(y: Char): Boolean = toLong > y + protected def >(y: Int): Boolean = toLong > y + protected def >(y: Long): Boolean = toLong > y + protected def >(y: Float): Boolean = toLong > y + protected def >(y: Double): Boolean = toLong > y + + protected def >=(y: Byte): Boolean = toLong >= y + protected def >=(y: Short): Boolean = toLong >= y + protected def >=(y: Char): Boolean = toLong >= y + protected def >=(y: Int): Boolean = toLong >= y + protected def >=(y: Long): Boolean = toLong >= y + protected def >=(y: Float): Boolean = toLong >= y + protected def >=(y: Double): Boolean = toLong >= y + + protected def |(y: Byte): Long = toLong | y + protected def |(y: Short): Long = toLong | y + protected def |(y: Char): Long = toLong | y + protected def |(y: Int): Long = toLong | y + protected def |(y: Long): Long = toLong | y + + protected def &(y: Byte): Long = toLong & y + protected def &(y: Short): Long = toLong & y + protected def &(y: Char): Long = toLong & y + protected def &(y: Int): Long = toLong & y + protected def &(y: Long): Long = toLong & y + + protected def ^(y: Byte): Long = toLong ^ y + protected def ^(y: Short): Long = toLong ^ y + protected def ^(y: Char): Long = toLong ^ y + protected def ^(y: Int): Long = toLong ^ y + protected def ^(y: Long): Long = toLong ^ y + + protected def +(y: Byte): Long = toLong + y + protected def +(y: Short): Long = toLong + y + protected def +(y: Char): Long = toLong + y + protected def +(y: Int): Long = toLong + y + protected def +(y: Long): Long = toLong + y + protected def +(y: Float): Float = toLong + y + protected def +(y: Double): Double = toLong + y + + protected def -(y: Byte): Long = toLong - y + protected def -(y: Short): Long = toLong - y + protected def -(y: Char): Long = toLong - y + protected def -(y: Int): Long = toLong - y + protected def -(y: Long): Long = toLong - y + protected def -(y: Float): Float = toLong - y + protected def -(y: Double): Double = toLong - y + + protected def *(y: Byte): Long = toLong - y + protected def *(y: Short): Long = toLong - y + protected def *(y: Char): Long = toLong - y + protected def *(y: Int): Long = toLong - y + protected def *(y: Long): Long = toLong - y + protected def *(y: Float): Float = toLong - y + protected def *(y: Double): Double = toLong - y + + protected def /(y: Byte): Long = toLong / y + protected def /(y: Short): Long = toLong / y + protected def /(y: Char): Long = toLong / y + protected def /(y: Int): Long = toLong / y + protected def /(y: Long): Long = toLong / y + protected def /(y: Float): Float = toLong / y + protected def /(y: Double): Double = toLong / y + + protected def %(y: Byte): Long = toLong % y + protected def %(y: Short): Long = toLong % y + protected def %(y: Char): Long = toLong % y + protected def %(y: Int): Long = toLong % y + protected def %(y: Long): Long = toLong % y + protected def %(y: Float): Float = toLong % y + protected def %(y: Double): Double = toLong % y + +} + +object RuntimeLong { + + /** number of relevant bits in each Long.l and Long.m */ + private final val BITS = 22 + /** number of relevant bits in Long.l and Long.m together */ + private final val BITS01 = 2 * BITS + /** number of relevant bits in Long.h */ + private final val BITS2 = 64 - BITS01 + /** bitmask for Long.l and Long.m */ + private final val MASK = (1 << BITS) - 1 + /** bitmask for Long.h */ + private final val MASK_2 = (1 << BITS2) - 1 + + private[runtime] final val SIGN_BIT = BITS2 - 1 + private[runtime] final val SIGN_BIT_VALUE = 1 << SIGN_BIT + private[runtime] final val TWO_PWR_15_DBL = 0x8000 * 1.0 + private[runtime] final val TWO_PWR_16_DBL = 0x10000 * 1.0 + private[runtime] final val TWO_PWR_22_DBL = 0x400000 * 1.0 + private[runtime] final val TWO_PWR_31_DBL = TWO_PWR_16_DBL * TWO_PWR_15_DBL + private[runtime] final val TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL + private[runtime] final val TWO_PWR_44_DBL = TWO_PWR_22_DBL * TWO_PWR_22_DBL + private[runtime] final val TWO_PWR_63_DBL = TWO_PWR_32_DBL * TWO_PWR_31_DBL + + // Cache the instances for some "literals" used in this implementation + val Zero = new RuntimeLong( 0, 0, 0) // 0L + val One = new RuntimeLong( 1, 0, 0) // 1L + val MinusOne = new RuntimeLong( MASK, MASK, MASK_2) // -1L + val MinValue = new RuntimeLong( 0, 0, 524288) // Long.MinValue + val MaxValue = new RuntimeLong(4194303, 4194303, 524287) // Long.MaxValue + val TenPow9 = new RuntimeLong(1755648, 238, 0) // 1000000000L with 9 zeros + + def fromDouble(value: Double): RuntimeLong = { + if (java.lang.Double.isNaN(value)) Zero + else if (value < -TWO_PWR_63_DBL) MinValue + else if (value >= TWO_PWR_63_DBL) MaxValue + else if (value < 0) -fromDouble(-value) + else { + var acc = value + val a2 = if (acc >= TWO_PWR_44_DBL) (acc / TWO_PWR_44_DBL).toInt else 0 + acc -= a2 * TWO_PWR_44_DBL + val a1 = if (acc >= TWO_PWR_22_DBL) (acc / TWO_PWR_22_DBL).toInt else 0 + acc -= a1 * TWO_PWR_22_DBL + val a0 = acc.toInt + new RuntimeLong(a0, a1, a2) + } + } + +} |