public static long DivRem(long value1, long value2) { long remainder = 0; CSMath.DivRem(value1, value2, out remainder); return(remainder); }
/// <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); }
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; })); }
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); }
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)); }
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); }