public override string ToString() { if (IsZero(this)) { return("0"); } if (Equals(this, MIN_VALUE)) { // Special-case MIN_VALUE because neg(MIN_VALUE)==MIN_VALUE return("-9223372036854775808"); } if (IsNegative(this)) { return("-" + (-this).ToString()); } Long rem = this; String res = ""; while (!IsZero(rem)) { // Do several digits each time through the loop, so as to // minimize the calls to the very expensive emulated div. int tenPowerZeroes = 9; int tenPower = 1000000000; Long tenPowerLong = tenPower; Long remDivTenPower = (rem / tenPowerLong); String digits = "" + (int)((rem - (remDivTenPower * tenPowerLong))); rem = remDivTenPower; if (!IsZero(rem)) { int zeroesNeeded = tenPowerZeroes - digits.Length; for (; zeroesNeeded > 0; zeroesNeeded--) { digits = "0" + digits; } } res = digits + res; } return(res); }
public static Long ShiftRight(Long a, int n) { n &= 63; double shiftFact = Pow(n); double newHigh = Math.Floor(a.high / shiftFact); double newLow = Math.Floor(a.low / shiftFact); /* * Doing the above floors separately on each component is safe. If n<32, * a.high/shiftFact is guaranteed to be an integer already. For n>32, * a.high/shiftFact will have fractional bits, but we need to discard them * as they shift away. We will end up discarding all of a.low in this case, * as it divides out to entirely fractional. */ return(create(newLow, newHigh)); }
public static Long ShiftLeft(Long a, int n) { n &= 63; if (Equals(a, MIN_VALUE)) { if (n == 0) { return(a); } else { return(ZERO); } } if (IsNegative(a)) { return(-ShiftLeft((-a), n)); } double twoToN = Pow(n); double newHigh = a.high * twoToN % TWO_PWR_64_DBL; double newLow = a.low * twoToN; double diff = newLow - (newLow % TWO_PWR_32_DBL); newHigh += diff; newLow -= diff; if (newHigh >= TWO_PWR_63_DBL) { newHigh -= TWO_PWR_64_DBL; } return(new Long(newLow, newHigh)); }
public bool Equals(Long other) { return(Equals(this, other)); }
public static Long operator /(Long a, Long b) { if (IsZero(b)) { throw new DivideByZeroException(); } if (IsZero(a)) { return(ZERO); } if (a.Equals(MIN_VALUE)) { // handle a==MIN_VALUE carefully because of overflow issues if (b.Equals(ONE) || b.Equals(NEG_ONE)) { // this strange exception is described in JLS3 17.17.2 return(MIN_VALUE); } // at this point, abs(b) >= 2, so |a/b| < -MIN_VALUE Long halfa = ShiftRight(a, 1); Long approx = ShiftLeft((halfa / b), 1); Long rem = (a - (b * approx)); Assert((rem > MIN_VALUE)); return(approx + (rem / b)); } if (Equals(b, MIN_VALUE)) { Assert(!Equals(a, MIN_VALUE)); return(ZERO); } // To keep the implementation compact, make a and be // both be positive and swap the sign of the result // if necessary. if (IsNegative(a)) { if (IsNegative(b)) { return((-a) / (-b)); } else { return(-((-a) / b)); } } Assert(!IsNegative(a)); if (IsNegative(b)) { return(-(a / (-b))); } Assert(!IsNegative(b)); // Use float division to approximate the answer. // Repeat until the remainder is less than b. Long result = ZERO; Long remainder = a; while (remainder > b) { // approximate using float division Long deltaResult = (Long)(Math.Floor(ToDoubleRoundDown(remainder) / ToDoubleRoundUp(b))); if (IsZero(deltaResult)) { deltaResult = ONE; } Long deltaRem = (deltaResult * b); //Assert(deltaResult > ONE); //Assert(deltaRem < remainder); result = result + deltaResult; remainder = remainder - deltaRem; } return(result); }
public static Long operator *(Long a, Long b) { if (IsZero(a)) { return(ZERO); } if (IsZero(b)) { return(ZERO); } // handle MIN_VALUE carefully, because neg(MIN_VALUE)==MIN_VALUE if (Equals(a, MIN_VALUE)) { return(multByMinValue(b)); } if (Equals(b, MIN_VALUE)) { return(multByMinValue(a)); } // If either argument is negative, change it to positive, multiply, // and then negate the result. if (IsNegative(a)) { if (IsNegative(b)) { return((-a) * (-b)); } else { return(-((-a) * b)); } } Assert(!IsNegative(a)); if (IsNegative(b)) { return(-(a * (-b))); } Assert(!IsNegative(b)); // If both numbers are small, use float multiplication if ((a < TWO_PWR_24) && (b < TWO_PWR_24)) { return(create(((double)a) * ((double)b), 0.0)); } // Divide each number into 4 chunks of 16 bits, and then add // up 4x4 multiplies. Skip the six multiplies where the result // mod 2^64 would be 0. double a3 = a.high % TWO_PWR_48_DBL; double a4 = a.high - a3; double a1 = a.low % TWO_PWR_16_DBL; double a2 = a.low - a1; double b3 = b.high % TWO_PWR_48_DBL; double b4 = b.high - b3; double b1 = b.low % TWO_PWR_16_DBL; double b2 = b.low - b1; Long res = ZERO; res = AddTimes(res, a4, b1); res = AddTimes(res, a3, b2); res = AddTimes(res, a3, b1); res = AddTimes(res, a2, b3); res = AddTimes(res, a2, b2); res = AddTimes(res, a2, b1); res = AddTimes(res, a1, b4); res = AddTimes(res, a1, b3); res = AddTimes(res, a1, b2); res = AddTimes(res, a1, b1); return(res); }
private static Long multByMinValue(Long value) { if (IsOdd(value)) { return MIN_VALUE; } else { return ZERO; } }
private static bool IsZero(Long value) { return(value.low == 0.0 && value.high == 0.0); }
private static int LowBits(Long value) { if (value.low >= TWO_PWR_31_DBL) { return (int)(value.low - TWO_PWR_32_DBL); } else { return (int)value.low; } }
private static double ToDoubleRoundUp(Long a) { int magnitute = (int)(Math.Log(a.high) / LN_2); if (magnitute <= PRECISION_BITS) { return (double)a; } else { int diff = magnitute - PRECISION_BITS; int toAdd = (1 << diff) - 1; return a.high + (a.low + toAdd); } }
private static bool IsOdd(Long value) { return (LowBits(value) & 1) == 1; }
private static bool IsZero(Long value) { return value.low == 0.0 && value.high == 0.0; }
private static bool IsNegative(Long value) { return value.high < 0; }
public static bool Equals(Long left, Long right) { return ((left.low == right.low) && (left.high == right.high)); }
public bool Equals(Long other) { return Equals(this, other); }
public static bool Equals(Long left, Long right) { return((left.low == right.low) && (left.high == right.high)); }
private static bool IsNegative(Long value) { return(value.high < 0); }
public static Long ShiftLeft(Long a, int n) { n &= 63; if (Equals(a, MIN_VALUE)) { if (n == 0) { return a; } else { return ZERO; } } if (IsNegative(a)) { return (-ShiftLeft((-a), n)); } double twoToN = Pow(n); double newHigh = a.high * twoToN % TWO_PWR_64_DBL; double newLow = a.low * twoToN; double diff = newLow - (newLow % TWO_PWR_32_DBL); newHigh += diff; newLow -= diff; if (newHigh >= TWO_PWR_63_DBL) { newHigh -= TWO_PWR_64_DBL; } return new Long(newLow, newHigh); }
private static bool IsOdd(Long value) { return((LowBits(value) & 1) == 1); }
public static Long ShiftRight(Long a, int n) { n &= 63; double shiftFact = Pow(n); double newHigh = Math.Floor(a.high / shiftFact); double newLow = Math.Floor(a.low / shiftFact); /* * Doing the above floors separately on each component is safe. If n<32, * a.high/shiftFact is guaranteed to be an integer already. For n>32, * a.high/shiftFact will have fractional bits, but we need to discard them * as they shift away. We will end up discarding all of a.low in this case, * as it divides out to entirely fractional. */ return create(newLow, newHigh); }
/** * Logical right shift. It does not preserve the sign of the input. */ private static Long shru(Long a, int n) { n &= 63; Long sr = ShiftRight(a, n); if (IsNegative(a)) { // the following changes the high bits to 0, using // a formula from JLS3 section 15.19 sr = sr + ShiftLeft(TWO, 63 - n); } return sr; }
private static Long AddTimes(Long accum, double a, double b) { if (a == 0.0) { return accum; } if (b == 0.0) { return accum; } return (accum + create(a * b, 0.0)); }