コード例 #1
0
        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);
        }
コード例 #2
0
        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));
        }
コード例 #3
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));
        }
コード例 #4
0
 public bool Equals(Long other)
 {
     return(Equals(this, other));
 }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 private static Long multByMinValue(Long value)
 {
     if (IsOdd(value))
     {
         return MIN_VALUE;
     }
     else
     {
         return ZERO;
     }
 }
コード例 #8
0
 private static bool IsZero(Long value)
 {
     return(value.low == 0.0 && value.high == 0.0);
 }
コード例 #9
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 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;
     }
 }
コード例 #10
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 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);
     }
 }
コード例 #11
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 private static bool IsOdd(Long value)
 {
     return (LowBits(value) & 1) == 1;
 }
コード例 #12
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 private static bool IsZero(Long value)
 {
     return value.low == 0.0 && value.high == 0.0;
 }
コード例 #13
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 private static bool IsNegative(Long value)
 {
     return value.high < 0;
 }
コード例 #14
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 public static bool Equals(Long left, Long right)
 {
     return ((left.low == right.low) && (left.high == right.high));
 }
コード例 #15
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 public bool Equals(Long other)
 {
     return Equals(this, other);
 }
コード例 #16
0
 public static bool Equals(Long left, Long right)
 {
     return((left.low == right.low) && (left.high == right.high));
 }
コード例 #17
0
 private static bool IsNegative(Long value)
 {
     return(value.high < 0);
 }
コード例 #18
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
        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);
        }
コード例 #19
0
 private static bool IsOdd(Long value)
 {
     return((LowBits(value) & 1) == 1);
 }
コード例 #20
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
        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);
        }
コード例 #21
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
        /**
         * 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;
        }
コード例 #22
0
ファイル: Long.cs プロジェクト: xToast/JSIL.Hacks
 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));
 }