Merge branch 'BigIntegerParse'
authorMartin Midtgaard <martin.midtgaard@gmail.com>
Fri, 7 Feb 2014 10:23:37 +0000 (11:23 +0100)
committerMartin Midtgaard <martin.midtgaard@gmail.com>
Fri, 7 Feb 2014 10:23:37 +0000 (11:23 +0100)
1  2 
mcs/class/System.Numerics/System.Numerics/BigInteger.cs
mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs

index a05d403988bf87e95298ae18060194a7c037208b,da634fdc5f4237dffe86a13942b978d6b7df9bcc..4205d8ccdca4ce8fe1b718d0546ea08550a6b9eb
@@@ -473,20 -473,10 +473,20 @@@ namespace System.Numerics 
                                return (((long)high) << 32) | low;
                        }
  
 -                      if (high > 0x80000000u)
 +                      /*
 +                      We cannot represent negative numbers smaller than long.MinValue.
 +                      Those values are encoded into what look negative numbers, so negating
 +                      them produces a positive value, that's why it's safe to check for that
 +                      condition.
 +
 +                      long.MinValue works fine since it's bigint encoding looks like a negative
 +                      number, but since long.MinValue == -long.MinValue, we're good.
 +                      */
 +
 +                      long result = - ((((long)high) << 32) | (long)low);
 +                      if (result > 0)
                                throw new OverflowException ();
 -
 -                      return - ((((long)high) << 32) | (long)low);
 +                      return result;
                }
  
                [CLSCompliantAttribute (false)]
                        Exception ex;
                        return Parse (value, true, out result, out ex);
                }
-               
- #if NET_4_0
-               [MonoTODO]
                public static BigInteger Parse (string value, NumberStyles style)
                {
-                       throw new NotImplementedException ();
+                       return Parse (value, style, null);
                }
  
-               [MonoTODO]
                public static BigInteger Parse (string value, IFormatProvider provider)
                {
-                       throw new NotImplementedException ();
+                       return Parse (value, NumberStyles.Integer, provider);
                }
  
-               [MonoTODO]
                public static BigInteger Parse (
                        string value, NumberStyles style, IFormatProvider provider)
                {
-                       throw new InvalidOperationException ();
+                       Exception exc;
+                       BigInteger res;
+                       if (!Parse (value, style, provider, false, out res, out exc))
+                               throw exc;
+                       return res;
                }
-               
-               [MonoTODO]
                public static bool TryParse (
                        string value, NumberStyles style, IFormatProvider provider,
                        out BigInteger result)
                {
-                       throw new NotImplementedException ();
+                       Exception exc;
+                       if (!Parse (value, style, provider, true, out result, out exc)) {
+                               result = Zero;
+                               return false;
+                       }
+                       return true;
+               }
+               internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
+               {
+                       result = Zero;
+                       exc = null;
+                       if (s == null) {
+                               if (!tryParse)
+                                       exc = new ArgumentNullException ("s");
+                               return false;
+                       }
+                       if (s.Length == 0) {
+                               if (!tryParse)
+                                       exc = GetFormatException ();
+                               return false;
+                       }
+                       NumberFormatInfo nfi = null;
+                       if (fp != null) {
+                               Type typeNFI = typeof(System.Globalization.NumberFormatInfo);
+                               nfi = (NumberFormatInfo)fp.GetFormat (typeNFI);
+                       }
+                       if (nfi == null)
+                               nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
+                       if (!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 && !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 && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
+                                       return false;
+                               if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
+                                       if (!tryParse)
+                                               exc = GetFormatException ();
+                                       return false;
+                               }
+                               
+                               if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
+                                       if (!tryParse)
+                                               exc = GetFormatException ();
+                                       return false;
+                               }
+                       }
+                       if (AllowLeadingSign && !foundSign) {
+                               // Sign + Currency
+                               FindSign (ref pos, s, nfi, ref foundSign, ref negative);
+                               if (foundSign) {
+                                       if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
+                                               return false;
+                                       if (AllowCurrencySymbol) {
+                                               FindCurrency (ref pos, s, nfi,
+                                                             ref foundCurrency);
+                                               if (foundCurrency && AllowLeadingWhite &&
+                                                       !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
+                                                       return false;
+                                       }
+                               }
+                       }
+                       
+                       if (AllowCurrencySymbol && !foundCurrency) {
+                               // Currency + sign
+                               FindCurrency (ref pos, s, nfi, ref foundCurrency);
+                               if (foundCurrency) {
+                                       if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
+                                               return false;
+                                       if (foundCurrency) {
+                                               if (!foundSign && AllowLeadingSign) {
+                                                       FindSign (ref pos, s, nfi, ref foundSign,
+                                                                 ref negative);
+                                                       if (foundSign && AllowLeadingWhite &&
+                                                               !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
+                                                               return false;
+                                               }
+                                       }
+                               }
+                       }
+                       BigInteger number = Zero;
+                       int nDigits = 0;
+                       int decimalPointPos = -1;
+                       byte digitValue;
+                       char hexDigit;
+                       bool firstHexDigit = true;
+                       // Number stuff
+                       while (pos < s.Length) {
+                               if (!ValidDigit (s [pos], AllowHexSpecifier)) {
+                                       if (AllowThousands &&
+                                               (FindOther (ref pos, s, nfi.NumberGroupSeparator)
+                                               || FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
+                                               continue;
+                                       if (AllowDecimalPoint && decimalPointPos < 0 &&
+                                               (FindOther (ref pos, s, nfi.NumberDecimalSeparator)
+                                               || FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
+                                               decimalPointPos = nDigits;
+                                               continue;
+                                       }
+                                       break;
+                               }
+                               nDigits++;
+                               if (AllowHexSpecifier) {
+                                       hexDigit = s [pos++];
+                                       if (Char.IsDigit (hexDigit))
+                                               digitValue = (byte)(hexDigit - '0');
+                                       else if (Char.IsLower (hexDigit))
+                                               digitValue = (byte)(hexDigit - 'a' + 10);
+                                       else
+                                               digitValue = (byte)(hexDigit - 'A' + 10);
+                                       if (firstHexDigit && (byte)digitValue >= 8)
+                                               negative = true;
+                                       number = number * 16 + digitValue;
+                                       firstHexDigit = false;
+                                       continue;
+                               }
+                               number = number * 10 + (byte)(s [pos++] - '0');
+                       }
+                       // Post number stuff
+                       if (nDigits == 0) {
+                               if (!tryParse)
+                                       exc = GetFormatException ();
+                               return false;
+                       }
+                       //signed hex value
+                       if (AllowHexSpecifier && negative) {
+                               //number = 123456;
+                               BigInteger mask = BigInteger.Pow(16, nDigits) - 1;
+                               number = (number ^ mask) + 1;
+                       }
+                       int exponent = 0;
+                       if (AllowExponent)
+                               if (FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
+                                       return false;
+                       if (AllowTrailingSign && !foundSign) {
+                               // Sign + Currency
+                               FindSign (ref pos, s, nfi, ref foundSign, ref negative);
+                               if (foundSign && pos < s.Length) {
+                                       if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
+                                               return false;
+                               }
+                       }
+                       
+                       if (AllowCurrencySymbol && !foundCurrency) {
+                               if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
+                                       return false;
+                               
+                               // Currency + sign
+                               FindCurrency (ref pos, s, nfi, ref foundCurrency);
+                               if (foundCurrency  && pos < s.Length) {
+                                       if (AllowTrailingWhite  && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
+                                               return false;
+                                       if (!foundSign && AllowTrailingSign)
+                                               FindSign (ref pos, s, nfi, ref foundSign,
+                                                         ref negative);
+                               }
+                       }
+                       
+                       if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
+                               return false;
+                       if (foundOpenParentheses) {
+                               if (pos >= s.Length || s [pos++] != ')') {
+                                       if (!tryParse)
+                                               exc = GetFormatException ();
+                                       return false;
+                               }
+                               if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
+                                       return false;
+                       }
+                       if (pos < s.Length && s [pos] != '\u0000') {
+                               if (!tryParse)
+                                       exc = GetFormatException ();
+                               return false;
+                       }
+                       if (decimalPointPos >= 0)
+                               exponent = exponent - nDigits + decimalPointPos;
+                       
+                       if (exponent < 0) {
+                               //
+                               // Any non-zero values after decimal point are not allowed
+                               //
+                               BigInteger remainder;
+                               number = BigInteger.DivRem(number, BigInteger.Pow(10, -exponent), out remainder);
+                               if (!remainder.IsZero) {
+                                       if (!tryParse)
+                                               exc = new OverflowException ("Value too large or too small. exp="+exponent+" rem = " + remainder + " pow = " + BigInteger.Pow(10, -exponent));
+                                       return false;
+                               }
+                       } else if (exponent > 0) {
+                               number = BigInteger.Pow(10, exponent) * number;
+                       }
+                       if (number.sign == 0)
+                               result = number;
+                       else if (negative)
+                               result = new BigInteger (-1, number.data);
+                       else
+                               result = new BigInteger (1, number.data);
+                       return true;
+               }
+               internal static bool CheckStyle (NumberStyles style, bool tryParse, ref Exception exc)
+               {
+                       if ((style & NumberStyles.AllowHexSpecifier) != 0) {
+                               NumberStyles ne = style ^ NumberStyles.AllowHexSpecifier;
+                               if ((ne & NumberStyles.AllowLeadingWhite) != 0)
+                                       ne ^= NumberStyles.AllowLeadingWhite;
+                               if ((ne & NumberStyles.AllowTrailingWhite) != 0)
+                                       ne ^= NumberStyles.AllowTrailingWhite;
+                               if (ne != 0) {
+                                       if (!tryParse)
+                                               exc = new ArgumentException (
+                                                       "With AllowHexSpecifier only " + 
+                                                       "AllowLeadingWhite and AllowTrailingWhite " + 
+                                                       "are permitted.");
+                                       return false;
+                               }
+                       } else if ((uint) style > (uint) NumberStyles.Any){
+                               if (!tryParse)
+                                       exc = new ArgumentException ("Not a valid number style");
+                               return false;
+                       }
+                       return true;
                }
- #endif
                
+               internal static bool JumpOverWhite (ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)
+               {
+                       while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
+                               pos++;
+                       if (reportError && pos >= s.Length) {
+                               if (!tryParse)
+                                       exc = GetFormatException ();
+                               return false;
+                       }
+                       return true;
+               }
+               internal static void FindSign (ref int pos, string s, NumberFormatInfo nfi, 
+                                     ref bool foundSign, ref bool negative)
+               {
+                       if ((pos + nfi.NegativeSign.Length) <= s.Length &&
+                           string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) {
+                               negative = true;
+                               foundSign = true;
+                               pos += nfi.NegativeSign.Length;
+                       } else if ((pos + nfi.PositiveSign.Length) <= s.Length &&
+                           string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) {
+                               negative = false;
+                               pos += nfi.PositiveSign.Length;
+                               foundSign = true;
+                       } 
+               }
+               internal static void FindCurrency (ref int pos,
+                                                string s, 
+                                                NumberFormatInfo nfi,
+                                                ref bool foundCurrency)
+               {
+                       if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
+                            s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
+                               foundCurrency = true;
+                               pos += nfi.CurrencySymbol.Length;
+                       } 
+               }
+               internal static bool FindExponent (ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
+               {
+                       exponent = 0;
+                       if (pos >= s.Length || (s [pos] != 'e' && s[pos] != 'E')) {
+                               exc = null;
+                               return false;
+                       }
+                       var i = pos + 1;
+                       if (i == s.Length) {
+                               exc = tryParse ? null : GetFormatException ();
+                               return true;
+                       }
+                       bool negative = false;
+                       if (s [i] == '-') {
+                               negative = true;
+                               if(++i == s.Length){
+                                       exc = tryParse ? null : GetFormatException ();
+                                       return true;
+                               }
+                       }
+                       if (s [i] == '+' && ++i == s.Length) {
+                               exc = tryParse ? null : GetFormatException ();
+                               return true;
+                       }
+                       long exp = 0; // temp long value
+                       for (; i < s.Length; i++) {
+                               if (!Char.IsDigit (s [i]))  {
+                                       exc = tryParse ? null : GetFormatException ();
+                                       return true;
+                               }
+                               // Reduce the risk of throwing an overflow exc
+                               exp = checked (exp * 10 - (int) (s [i] - '0'));
+                               if (exp < Int32.MinValue || exp > Int32.MaxValue) {
+                                       exc = tryParse ? null : new OverflowException ("Value too large or too small.");
+                                       return true;
+                               }
+                       }
+                       // exp value saved as negative
+                       if(!negative)
+                               exp = -exp;
+                       exc = null;
+                       exponent = (int)exp;
+                       pos = i;
+                       return true;
+               }
+               internal static bool FindOther (ref int pos, string s, string other)
+               {
+                       if ((pos + other.Length) <= s.Length &&
+                            s.Substring (pos, other.Length) == other) {
+                               pos += other.Length;
+                               return true;
+                       } 
+                       return false;
+               }
+               internal static bool ValidDigit (char e, bool allowHex)
+               {
+                       if (allowHex)
+                               return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
+                       return Char.IsDigit (e);
+               }
  
                static Exception GetFormatException ()
                {
index a5ec016bb3ee37ce9b16e17e566b0ff36772416f,17393554c984f96f9f3c776e44a68995f1f03ed8..127f618d971c103ce3875b25e3d9ab98e52c72f6
@@@ -49,6 -49,29 +49,29 @@@ namespace MonoTests.System.Numeric
                        huge_add
                };
  
+               private NumberFormatInfo Nfi = NumberFormatInfo.InvariantInfo;
+               private NumberFormatInfo NfiUser;
+               [TestFixtureSetUp]
+               public void SetUpFixture() 
+               {
+                       NfiUser = new NumberFormatInfo ();
+                       NfiUser.CurrencyDecimalDigits = 3;
+                       NfiUser.CurrencyDecimalSeparator = ":";
+                       NfiUser.CurrencyGroupSeparator = "/";
+                       NfiUser.CurrencyGroupSizes = new int[] { 2, 1, 0 };
+                       NfiUser.CurrencyNegativePattern = 10;  // n $-
+                       NfiUser.CurrencyPositivePattern = 3;  // n $
+                       NfiUser.CurrencySymbol = "XYZ";
+                       NfiUser.PercentDecimalDigits = 1;
+                       NfiUser.PercentDecimalSeparator = ";";
+                       NfiUser.PercentGroupSeparator = "~";
+                       NfiUser.PercentGroupSizes = new int[] { 1 };
+                       NfiUser.PercentNegativePattern = 2;
+                       NfiUser.PercentPositivePattern = 2;
+                       NfiUser.PercentSymbol = "%%%";
+               }
                [Test]
                public void Mul () {
                        long[] values = new long [] { -1000000000L, -1000, -1, 0, 1, 1000, 100000000L };
                        Assert.AreEqual (10, (int)BigInteger.Parse("+10"), "#7");
                        Assert.AreEqual (10, (int)BigInteger.Parse("10 "), "#8");
                        Assert.AreEqual (-10, (int)BigInteger.Parse("-10 "), "#9");
+                       Assert.AreEqual (10, (int)BigInteger.Parse("    10 "), "#10");
+                       Assert.AreEqual (-10, (int)BigInteger.Parse("  -10 "), "#11");
+                       Assert.AreEqual (-1, (int)BigInteger.Parse("F", NumberStyles.AllowHexSpecifier), "#12");
+                       Assert.AreEqual (-8, (int)BigInteger.Parse("8", NumberStyles.AllowHexSpecifier), "#13");
+                       Assert.AreEqual (8, (int)BigInteger.Parse("08", NumberStyles.AllowHexSpecifier), "#14");
+                       Assert.AreEqual (15, (int)BigInteger.Parse("0F", NumberStyles.AllowHexSpecifier), "#15");
+                       Assert.AreEqual (-1, (int)BigInteger.Parse("FF", NumberStyles.AllowHexSpecifier), "#16");
+                       Assert.AreEqual (255, (int)BigInteger.Parse("0FF", NumberStyles.AllowHexSpecifier), "#17");
+                       Assert.AreEqual (-17, (int)BigInteger.Parse("   (17)   ", NumberStyles.AllowParentheses | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite), "#18");
+                       Assert.AreEqual (-23, (int)BigInteger.Parse("  -23  ", NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite), "#19");
+                       Assert.AreEqual (300000, (int)BigInteger.Parse("3E5", NumberStyles.AllowExponent), "#20");
+                       Assert.AreEqual (250, (int)BigInteger.Parse("2"+Nfi.NumberDecimalSeparator+"5E2", NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint), "#21");//2.5E2 = 250
+                       Assert.AreEqual (25, (int)BigInteger.Parse("2500E-2", NumberStyles.AllowExponent), "#22");
+                       Assert.AreEqual ("136236974127783066520110477975349088954559032721408", BigInteger.Parse("136236974127783066520110477975349088954559032721408", NumberStyles.None).ToString(), "#23");
+                       Assert.AreEqual ("136236974127783066520110477975349088954559032721408", BigInteger.Parse("136236974127783066520110477975349088954559032721408").ToString(), "#24");
+                       try {
+                               BigInteger.Parse ("2E3.0", NumberStyles.AllowExponent); // decimal notation for the exponent
+                               Assert.Fail ("#25");
+                       } catch (FormatException) {
+                       }
+                       try {
+                               Int32.Parse ("2.09E1",  NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent);
+                               Assert.Fail ("#26");
+                       } catch (OverflowException) {
+                       }
                }
  
                [Test]
  
                        Assert.IsTrue (BigInteger.TryParse ("-010", out x), "#11");
                        Assert.AreEqual (-10, (int)x, "#12");
+                       //Number style and format provider
+                       Assert.IsFalse (BigInteger.TryParse ("null", NumberStyles.None, null, out x), "#13");
+                       Assert.AreEqual (0, (int)x, "#14");
+                       Assert.IsFalse (BigInteger.TryParse ("-10", NumberStyles.None, null, out x), "#15");
+                       Assert.IsFalse (BigInteger.TryParse ("(10)", NumberStyles.None, null, out x), "#16");
+                       Assert.IsFalse (BigInteger.TryParse (" 10", NumberStyles.None, null, out x), "#17");
+                       Assert.IsFalse (BigInteger.TryParse ("10 ", NumberStyles.None, null, out x), "#18");
+                       
+                       Assert.IsTrue (BigInteger.TryParse ("-10", NumberStyles.AllowLeadingSign, null, out x), "#19");
+                       Assert.AreEqual (-10, (int)x, "#20");
+                       Assert.IsTrue (BigInteger.TryParse ("(10)", NumberStyles.AllowParentheses, null, out x), "#21");
+                       Assert.AreEqual (-10, (int)x, "#22");
+                       Assert.IsTrue (BigInteger.TryParse (" 10", NumberStyles.AllowLeadingWhite, null, out x), "#23");
+                       Assert.AreEqual (10, (int)x, "#24");
+                       Assert.IsTrue (BigInteger.TryParse ("10 ", NumberStyles.AllowTrailingWhite, null, out x), "#25");
+                       Assert.AreEqual (10, (int)x, "#26");
+                       Assert.IsFalse (BigInteger.TryParse ("$10", NumberStyles.None, null, out x), "#26");
+                       Assert.IsFalse (BigInteger.TryParse ("$10", NumberStyles.None, Nfi, out x), "#27");
+                       Assert.IsFalse (BigInteger.TryParse ("%10", NumberStyles.None, Nfi, out x), "#28");
+                       Assert.IsFalse (BigInteger.TryParse ("10 ", NumberStyles.None, null, out x), "#29");
+                       Assert.IsTrue (BigInteger.TryParse ("10", NumberStyles.None, null, out x), "#30");
+                       Assert.AreEqual (10, (int)x, "#31");
+                       Assert.IsTrue (BigInteger.TryParse (Nfi.CurrencySymbol + "10", NumberStyles.AllowCurrencySymbol, Nfi, out x), "#32");
+                       Assert.AreEqual (10, (int)x, "#33");
+                       Assert.IsFalse (BigInteger.TryParse ("%10", NumberStyles.AllowCurrencySymbol, Nfi, out x), "#34");
+               }
+               [Test]
+               public void TestUserCurrency ()
+               {
+                       const int val1 = -1234567;
+                       const int val2 = 1234567;
+                       string s = "";
+                       BigInteger v;
+                       s = val1.ToString ("c", NfiUser);
+                       Assert.AreEqual ("1234/5/67:000 XYZ-", s, "Currency value type 1 is not what we want to try to parse");
+                       v = BigInteger.Parse ("1234/5/67:000   XYZ-", NumberStyles.Currency, NfiUser);
+                       Assert.AreEqual (val1, (int)v);
+                       s = val2.ToString ("c", NfiUser);
+                       Assert.AreEqual ("1234/5/67:000 XYZ", s, "Currency value type 2 is not what we want to try to parse");
+                       v = BigInteger.Parse (s, NumberStyles.Currency, NfiUser);
+                       Assert.AreEqual (val2, (int)v);
                }
  
                [Test]
                        a = new BigInteger ();
                        Assert.AreEqual (BigInteger.Zero.GetHashCode (), a.GetHashCode (), "#15");
                }
 +
 +              [Test]
 +              public void Bug16526 ()
 +              {
 +                      var x = BigInteger.Pow(2, 63);
 +                      x *= -1;
 +                      x -= 1;
 +                      Assert.AreEqual ("-9223372036854775809", x.ToString (), "#1");
 +                      try {
 +                              x = (long)x;
 +                              Assert.Fail ("#2 Must OVF");
 +                      } catch (OverflowException) {
 +                      }
 +              }
        }
  }