Esempio n. 1
0
        public static long DivRem(long value1, long value2)
        {
            long remainder = 0;

            CSMath.DivRem(value1, value2, out remainder);
            return(remainder);
        }
Esempio n. 2
0
        /// <summary>
        ///     Finds the remainder of dividend/divisor.
        /// </summary>
        /// <param name="dividend">The number to be divided.</param>
        /// <param name="divisor">The number to be divided by.</param>
        /// <returns name="remainder">The remainder of the division.</returns>
        /// <search>remainder</search>
        public static long DivRem(long dividend, long divisor)
        {
            long remainder;

            CSMath.DivRem(dividend, divisor, out remainder);
            return(remainder);
        }
Esempio n. 3
0
        public static int Mod(long a, long b)
        {
            var isError = CheckWhetherNumberIsZero(b);

            if (isError)
            {
                return(0);
            }

            return(HandleBinaryOperation(a, b, () =>
            {
                long result;
                SystemMath.DivRem(a, b, out result);

                return result;
            }));
        }
Esempio n. 4
0
        internal static bool Parse(string s, NumberStyles style, IFormatProvider fp, bool tryParse, out long result, out Exception exc)
        {
            result = 0;
            exc    = null;

            if (s == null)
            {
                if (!tryParse)
                {
                    exc = new ArgumentNullException("s");
                }
                return(false);
            }

            if (s.Length == 0)
            {
                if (!tryParse)
                {
                    exc = Int32.GetFormatException();
                }
                return(false);
            }

            NumberFormatInfo nfi = null;

            if (fp != null)
            {
                Type typeNFI = typeof(System.Globalization.NumberFormatInfo);
                nfi = fp.GetFormat(typeNFI) as NumberFormatInfo;
            }
            if (nfi == null)
            {
                nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
            }

            if (!Int32.CheckStyle(style, tryParse, ref exc))
            {
                return(false);
            }

            bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
            bool AllowHexSpecifier   = (style & NumberStyles.AllowHexSpecifier) != 0;
            bool AllowThousands      = (style & NumberStyles.AllowThousands) != 0;
            bool AllowDecimalPoint   = (style & NumberStyles.AllowDecimalPoint) != 0;
            bool AllowParentheses    = (style & NumberStyles.AllowParentheses) != 0;
            bool AllowTrailingSign   = (style & NumberStyles.AllowTrailingSign) != 0;
            bool AllowLeadingSign    = (style & NumberStyles.AllowLeadingSign) != 0;
            bool AllowTrailingWhite  = (style & NumberStyles.AllowTrailingWhite) != 0;
            bool AllowLeadingWhite   = (style & NumberStyles.AllowLeadingWhite) != 0;
            bool AllowExponent       = (style & NumberStyles.AllowExponent) != 0;

            int pos = 0;

            if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
            {
                return(false);
            }

            bool foundOpenParentheses = false;
            bool negative             = false;
            bool foundSign            = false;
            bool foundCurrency        = false;

            // Pre-number stuff
            if (AllowParentheses && s [pos] == '(')
            {
                foundOpenParentheses = true;
                foundSign            = true;
                negative             = true;     // MS always make the number negative when there parentheses
                                                 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
                pos++;
                if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                {
                    return(false);
                }

                if (s.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
                {
                    if (!tryParse)
                    {
                        exc = Int32.GetFormatException();
                    }
                    return(false);
                }

                if (s.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
                {
                    if (!tryParse)
                    {
                        exc = Int32.GetFormatException();
                    }
                    return(false);
                }
            }

            if (AllowLeadingSign && !foundSign)
            {
                // Sign + Currency
                Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative);
                if (foundSign)
                {
                    if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (AllowCurrencySymbol)
                    {
                        Int32.FindCurrency(ref pos, s, nfi,
                                           ref foundCurrency);
                        if (foundCurrency && AllowLeadingWhite &&
                            !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                        {
                            return(false);
                        }
                    }
                }
            }

            if (AllowCurrencySymbol && !foundCurrency)
            {
                // Currency + sign
                Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency);
                if (foundCurrency)
                {
                    if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (foundCurrency)
                    {
                        if (!foundSign && AllowLeadingSign)
                        {
                            Int32.FindSign(ref pos, s, nfi, ref foundSign,
                                           ref negative);
                            if (foundSign && AllowLeadingWhite &&
                                !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                            {
                                return(false);
                            }
                        }
                    }
                }
            }

            long number          = 0;
            int  nDigits         = 0;
            int  decimalPointPos = -1;
            int  digitValue;
            char hexDigit;

            // Number stuff
            while (pos < s.Length)
            {
                if (!Int32.ValidDigit(s [pos], AllowHexSpecifier))
                {
                    if (AllowThousands &&
                        (Int32.FindOther(ref pos, s, nfi.NumberGroupSeparator) ||
                         Int32.FindOther(ref pos, s, nfi.CurrencyGroupSeparator)))
                    {
                        continue;
                    }

                    if (AllowDecimalPoint && decimalPointPos < 0 &&
                        (Int32.FindOther(ref pos, s, nfi.NumberDecimalSeparator) ||
                         Int32.FindOther(ref pos, s, nfi.CurrencyDecimalSeparator)))
                    {
                        decimalPointPos = nDigits;
                        continue;
                    }

                    break;
                }

                nDigits++;

                if (AllowHexSpecifier)
                {
                    hexDigit = s [pos++];
                    if (Char.IsDigit(hexDigit))
                    {
                        digitValue = (int)(hexDigit - '0');
                    }
                    else if (Char.IsLower(hexDigit))
                    {
                        digitValue = (int)(hexDigit - 'a' + 10);
                    }
                    else
                    {
                        digitValue = (int)(hexDigit - 'A' + 10);
                    }

                    ulong unumber = (ulong)number;

                    // IMPROVME: We could avoid catching OverflowException
                    try {
                        number = (long)checked (unumber * 16ul + (ulong)digitValue);
                    } catch (OverflowException e) {
                        if (!tryParse)
                        {
                            exc = e;
                        }
                        return(false);
                    }

                    continue;
                }

                try {
                    // Calculations done as negative
                    // (abs (MinValue) > abs (MaxValue))
                    number = checked (number * 10 - (long)(s [pos++] - '0'));
                } catch (OverflowException) {
                    if (!tryParse)
                    {
                        exc = new OverflowException("Value too large or too small.");
                    }
                    return(false);
                }
            }

            // Post number stuff
            if (nDigits == 0)
            {
                if (!tryParse)
                {
                    exc = Int32.GetFormatException();
                }
                return(false);
            }

            int exponent = 0;

            if (AllowExponent)
            {
                if (Int32.FindExponent(ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
                {
                    return(false);
                }
            }

            if (AllowTrailingSign && !foundSign)
            {
                // Sign + Currency
                Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative);
                if (foundSign && pos < s.Length)
                {
                    if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                }
            }

            if (AllowCurrencySymbol && !foundCurrency)
            {
                if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc))
                {
                    return(false);
                }

                // Currency + sign
                Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency);
                if (foundCurrency && pos < s.Length)
                {
                    if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (!foundSign && AllowTrailingSign)
                    {
                        Int32.FindSign(ref pos, s, nfi, ref foundSign,
                                       ref negative);
                    }
                }
            }

            if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc))
            {
                return(false);
            }

            if (foundOpenParentheses)
            {
                if (pos >= s.Length || s [pos++] != ')')
                {
                    if (!tryParse)
                    {
                        exc = Int32.GetFormatException();
                    }
                    return(false);
                }
                if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc))
                {
                    return(false);
                }
            }

            if (pos < s.Length && s [pos] != '\u0000')
            {
                if (!tryParse)
                {
                    exc = Int32.GetFormatException();
                }
                return(false);
            }

            if (!negative && !AllowHexSpecifier)
            {
                try {
                    number = checked (-number);
                } catch (OverflowException e) {
                    if (!tryParse)
                    {
                        exc = e;
                    }
                    return(false);
                }
            }

            if (decimalPointPos >= 0)
            {
                exponent = exponent - nDigits + decimalPointPos;
            }

            if (exponent < 0)
            {
                //
                // Any non-zero values after decimal point are not allowed
                //
                long remainder;
                number = Math.DivRem(number, (long)Math.Pow(10, -exponent), out remainder);
                if (remainder != 0)
                {
                    if (!tryParse)
                    {
                        exc = new OverflowException("Value too large or too small.");
                    }
                    return(false);
                }
            }
            else if (exponent > 0)
            {
                //
                // result *= 10^exponent
                //
                // Reduce the risk of throwing an overflow exc
                //
                double res = checked (Math.Pow(10, exponent) * number);
                if (res < MinValue || res > MaxValue)
                {
                    if (!tryParse)
                    {
                        exc = new OverflowException("Value too large or too small.");
                    }
                    return(false);
                }

                number = (long)res;
            }

            result = number;
            return(true);
        }
Esempio n. 5
0
            private static bool DigitGen(ref DiyFp mp, int precision, char *digits, out int length, out int k)
            {
                // Split the input mp to two parts. Part 1 is integral. Part 2 can be used to calculate
                // fractional.
                //
                // mp: the input DiyFp scaled by cached power.
                // K: final kappa.
                // p1: part 1.
                // p2: part 2.

                Debug.Assert(precision > 0);
                Debug.Assert(digits != null);
                Debug.Assert(mp.e >= Alpha);
                Debug.Assert(mp.e <= Gamma);

                ulong mpF = mp.f;
                int   mpE = mp.e;

                var one = new DiyFp(1UL << -mpE, mpE);

                ulong oneF    = one.f;
                int   oneNegE = -one.e;

                ulong ulp = 1;

                uint  p1 = (uint)(mpF >> oneNegE);
                ulong p2 = mpF & (oneF - 1);

                // When p2 (fractional part) is zero, we can predicate if p1 is good to produce the numbers in requested digit count:
                //
                // - When requested digit count >= 11, p1 is not be able to exhaust the count as 10^(11 - 1) > uint.MaxValue >= p1.
                // - When p1 < 10^(count - 1), p1 is not be able to exhaust the count.
                // - Otherwise, p1 may have chance to exhaust the count.
                if ((p2 == 0) && ((precision >= 11) || (p1 < s_CachedPowerOfTen[precision - 1])))
                {
                    length = 0;
                    k      = 0;
                    return(false);
                }

                // Note: The code in the paper simply assigns div to Ten9 and kappa to 10 directly.
                // That means we need to check if any leading zero of the generated
                // digits during the while loop, which hurts the performance.
                //
                // Now if we can estimate what the div and kappa, we do not need to check the leading zeros.
                // The idea is to find the biggest power of 10 that is less than or equal to the given number.
                // Then we don't need to worry about the leading zeros and we can get 10% performance gain.
                int index = 0;

                BiggestPowerTenLessThanOrEqualTo(p1, (DiyFp.SignificandLength - oneNegE), out uint div, out int kappa);
                kappa++;

                // Produce integral.
                while (kappa > 0)
                {
                    int d = (int)(Math.DivRem(p1, div, out p1));
                    digits[index] = (char)('0' + d);

                    index++;
                    precision--;
                    kappa--;

                    if (precision == 0)
                    {
                        break;
                    }

                    div /= 10;
                }

                // End up here if we already exhausted the digit count.
                if (precision == 0)
                {
                    ulong rest = ((ulong)(p1) << oneNegE) + p2;

                    length = index;
                    k      = kappa;

                    return(RoundWeed(
                               digits,
                               index,
                               rest,
                               ((ulong)(div)) << oneNegE,
                                   ulp,
                                   ref k
                               ));
                }

                // We have to generate digits from part2 if we have requested digit count left
                // and part2 is greater than ulp.
                while ((precision > 0) && (p2 > ulp))
                {
                    p2 *= 10;

                    int d = (int)(p2 >> oneNegE);
                    digits[index] = (char)('0' + d);

                    index++;
                    precision--;
                    kappa--;

                    p2 &= (oneF - 1);

                    ulp *= 10;
                }

                // If we haven't exhausted the requested digit counts, the Grisu3 algorithm fails.
                if (precision != 0)
                {
                    length = 0;
                    k      = 0;
                    return(false);
                }

                length = index;
                k      = kappa;

                return(RoundWeed(digits, index, p2, oneF, ulp, ref k));
            }
Esempio n. 6
0
        internal static bool Parse(string s, NumberStyles style, IFormatProvider provider, bool tryParse, out ulong result, out Exception exc)
        {
            result = 0;
            exc    = null;

            if (s == null)
            {
                if (!tryParse)
                {
                    exc = new ArgumentNullException("s");
                }
                return(false);
            }

            if (s.Length == 0)
            {
                if (!tryParse)
                {
                    exc = Int32.GetFormatException();
                }
                return(false);
            }

            NumberFormatInfo nfi = null;

            if (provider != null)
            {
                Type typeNFI = typeof(NumberFormatInfo);
                nfi = (NumberFormatInfo)provider.GetFormat(typeNFI);
            }
            if (nfi == null)
            {
                nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
            }

            if (!Int32.CheckStyle(style, tryParse, ref exc))
            {
                return(false);
            }

            bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
            bool AllowHexSpecifier   = (style & NumberStyles.AllowHexSpecifier) != 0;
            bool AllowThousands      = (style & NumberStyles.AllowThousands) != 0;
            bool AllowDecimalPoint   = (style & NumberStyles.AllowDecimalPoint) != 0;
            bool AllowParentheses    = (style & NumberStyles.AllowParentheses) != 0;
            bool AllowTrailingSign   = (style & NumberStyles.AllowTrailingSign) != 0;
            bool AllowLeadingSign    = (style & NumberStyles.AllowLeadingSign) != 0;
            bool AllowTrailingWhite  = (style & NumberStyles.AllowTrailingWhite) != 0;
            bool AllowLeadingWhite   = (style & NumberStyles.AllowLeadingWhite) != 0;
            bool AllowExponent       = (style & NumberStyles.AllowExponent) != 0;

            int pos = 0;

            if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
            {
                return(false);
            }

            bool foundOpenParentheses = false;
            bool negative             = false;
            bool foundSign            = false;
            bool foundCurrency        = false;

            // Pre-number stuff
            if (AllowParentheses && s [pos] == '(')
            {
                foundOpenParentheses = true;
                foundSign            = true;
                negative             = true;     // MS always make the number negative when there parentheses
                                                 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
                pos++;
                if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                {
                    return(false);
                }

                if (s.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
                {
                    if (!tryParse)
                    {
                        exc = Int32.GetFormatException();
                    }
                    return(false);
                }

                if (s.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
                {
                    if (!tryParse)
                    {
                        exc = Int32.GetFormatException();
                    }
                    return(false);
                }
            }

            if (AllowLeadingSign && !foundSign)
            {
                // Sign + Currency
                Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative);
                if (foundSign)
                {
                    if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (AllowCurrencySymbol)
                    {
                        Int32.FindCurrency(ref pos, s, nfi,
                                           ref foundCurrency);
                        if (foundCurrency && AllowLeadingWhite &&
                            !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                        {
                            return(false);
                        }
                    }
                }
            }

            if (AllowCurrencySymbol && !foundCurrency)
            {
                // Currency + sign
                Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency);
                if (foundCurrency)
                {
                    if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (foundCurrency)
                    {
                        if (!foundSign && AllowLeadingSign)
                        {
                            Int32.FindSign(ref pos, s, nfi, ref foundSign,
                                           ref negative);
                            if (foundSign && AllowLeadingWhite &&
                                !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                            {
                                return(false);
                            }
                        }
                    }
                }
            }

            ulong number          = 0;
            int   nDigits         = 0;
            int   decimalPointPos = -1;
            ulong digitValue;
            char  hexDigit;

            // Number stuff
            // Just the same as Int32, but this one adds instead of substract
            while (pos < s.Length)
            {
                if (!Int32.ValidDigit(s [pos], AllowHexSpecifier))
                {
                    if (AllowThousands &&
                        (Int32.FindOther(ref pos, s, nfi.NumberGroupSeparator) ||
                         Int32.FindOther(ref pos, s, nfi.CurrencyGroupSeparator)))
                    {
                        continue;
                    }

                    if (AllowDecimalPoint && decimalPointPos < 0 &&
                        (Int32.FindOther(ref pos, s, nfi.NumberDecimalSeparator) ||
                         Int32.FindOther(ref pos, s, nfi.CurrencyDecimalSeparator)))
                    {
                        decimalPointPos = nDigits;
                        continue;
                    }

                    break;
                }

                nDigits++;

                if (AllowHexSpecifier)
                {
                    hexDigit = s [pos++];
                    if (Char.IsDigit(hexDigit))
                    {
                        digitValue = (ulong)(hexDigit - '0');
                    }
                    else if (Char.IsLower(hexDigit))
                    {
                        digitValue = (ulong)(hexDigit - 'a' + 10);
                    }
                    else
                    {
                        digitValue = (ulong)(hexDigit - 'A' + 10);
                    }

                    if (tryParse)
                    {
                        // Any number above 32 will do
                        bool can_overflow = number > 0xffff;

                        number = number * 16 + digitValue;

                        if (can_overflow && number < 16)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        number = checked (number * 16 + digitValue);
                    }

                    continue;
                }

                try {
                    number = checked (number * 10 + (ulong)(s [pos++] - '0'));
                } catch (OverflowException) {
                    if (!tryParse)
                    {
                        exc = new OverflowException(Locale.GetText("Value too large or too small."));
                    }
                    return(false);
                }
            }

            // Post number stuff
            if (nDigits == 0)
            {
                if (!tryParse)
                {
                    exc = Int32.GetFormatException();
                }
                return(false);
            }

            int exponent = 0;

            if (AllowExponent)
            {
                if (Int32.FindExponent(ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
                {
                    return(false);
                }
            }

            if (AllowTrailingSign && !foundSign)
            {
                // Sign + Currency
                Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative);
                if (foundSign && pos < s.Length)
                {
                    if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                }
            }

            if (AllowCurrencySymbol && !foundCurrency)
            {
                if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc))
                {
                    return(false);
                }

                // Currency + sign
                Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency);
                if (foundCurrency && pos < s.Length)
                {
                    if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (!foundSign && AllowTrailingSign)
                    {
                        Int32.FindSign(ref pos, s, nfi, ref foundSign,
                                       ref negative);
                    }
                }
            }

            if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc))
            {
                return(false);
            }

            if (foundOpenParentheses)
            {
                if (pos >= s.Length || s [pos++] != ')')
                {
                    if (!tryParse)
                    {
                        exc = Int32.GetFormatException();
                    }
                    return(false);
                }
                if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc))
                {
                    return(false);
                }
            }

            if (pos < s.Length && s [pos] != '\u0000')
            {
                if (!tryParse)
                {
                    exc = Int32.GetFormatException();
                }
                return(false);
            }

            // -0 is legal but other negative values are not
            if (negative && (number > 0))
            {
                if (!tryParse)
                {
                    exc = new OverflowException(
                        Locale.GetText("Negative number"));
                }
                return(false);
            }

            if (decimalPointPos >= 0)
            {
                exponent = exponent - nDigits + decimalPointPos;
            }

            if (exponent < 0)
            {
                //
                // Any non-zero values after decimal point are not allowed
                //
                long remainder;
                number = (ulong)Math.DivRem((long)number, (long)Math.Pow(10, -exponent), out remainder);
                if (remainder != 0)
                {
                    if (!tryParse)
                    {
                        exc = new OverflowException("Value too large or too small.");
                    }
                    return(false);
                }
            }
            else if (exponent > 0)
            {
                //
                // result *= 10^exponent
                //
                // Reduce the risk of throwing an overflow exc
                //
                double res = checked (Math.Pow(10, exponent) * number);
                if (res < MinValue || res > MaxValue)
                {
                    if (!tryParse)
                    {
                        exc = new OverflowException("Value too large or too small.");
                    }
                    return(false);
                }

                number = (ulong)res;
            }

            result = number;
            return(true);
        }