--- ./Runtime/Microsoft.Dynamic/Math/BigIntegerV2.cs 2009-10-19 13:36:38.000000000 -0400 +++ /cvs/mcs/class/System.Numerics/System.Numerics/BigInteger.cs 2009-10-31 12:13:55.000000000 -0400 @@ -12,7 +12,6 @@ * * * ***************************************************************************/ -#if CLR2 using System; using System.Collections.Generic; @@ -20,8 +19,6 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text; -using Microsoft.Contracts; -using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Math { /// @@ -104,7 +101,8 @@ /// (inverse of ToByteArray()) /// public static BigInteger Create(byte[] v) { - ContractUtils.RequiresNotNull(v, "v"); + if (v == null) + throw new ArgumentNullException ("v"); if (v.Length == 0) return Create(0); int byteCount = v.Length; @@ -339,10 +337,13 @@ [CLSCompliant(false)] public BigInteger(int sign, params uint[] data) { - ContractUtils.RequiresNotNull(data, "data"); - ContractUtils.Requires(sign >= -1 && sign <= +1, "sign"); + if (data == null) + throw new ArgumentNullException ("data"); + if (!(sign >= -1 && sign <= +1)) + throw new ArgumentException ("sign"); int length = GetLength(data); - ContractUtils.Requires(length == 0 || sign != 0, "sign"); + if (!(length == 0 || sign != 0)) + throw new ArgumentException ("sign"); this.data = data; this.sign = (short)(length == 0 ? 0 : sign); @@ -507,7 +508,7 @@ } public bool TryToFloat64(out double result) { - return StringUtils.TryParseDouble(ToString(10), + return double.TryParse(ToString(10), System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out result); @@ -1355,17 +1356,92 @@ return this * this; } - [Confined] public override string ToString() { return ToString(10); } - [Confined] - public string ToString(int radix) { - return MathUtils.BigIntegerToString(copy(data), sign, radix); + // generated by scripts/radix_generator.py + private static readonly uint[] maxCharsPerDigit = { 0, 0, 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }; + private static readonly uint[] groupRadixValues = { 0, 0, 2147483648, 3486784401, 1073741824, 1220703125, 2176782336, 1977326743, 1073741824, 3486784401, 1000000000, 2357947691, 429981696, 815730721, 1475789056, 2562890625, 268435456, 410338673, 612220032, 893871739, 1280000000, 1801088541, 2494357888, 3404825447, 191102976, 244140625, 308915776, 387420489, 481890304, 594823321, 729000000, 887503681, 1073741824, 1291467969, 1544804416, 1838265625, 2176782336 }; + + public static ArgumentOutOfRangeException MakeArgumentOutOfRangeException(string paramName, object actualValue, string message) { + return new ArgumentOutOfRangeException(paramName, string.Format("{0} (actual value is '{1}')", message, actualValue)); + } + + internal static string BigIntegerToString(uint[] d, int sign, int radix) { + if (radix < 2) { + throw MakeArgumentOutOfRangeException("radix", radix, "radix must be >= 2"); + } + if (radix > 36) { + throw MakeArgumentOutOfRangeException("radix", radix, "radix must be <= 36"); + } + + int dl = d.Length; + if (dl == 0) { + return "0"; + } + + List digitGroups = new List(); + + uint groupRadix = groupRadixValues[radix]; + while (dl > 0) { + uint rem = div(d, ref dl, groupRadix); + digitGroups.Add(rem); + } + + StringBuilder ret = new StringBuilder(); + if (sign == -1) { + ret.Append("-"); + } + + int digitIndex = digitGroups.Count - 1; + + char[] tmpDigits = new char[maxCharsPerDigit[radix]]; + + AppendRadix((uint)digitGroups[digitIndex--], (uint)radix, tmpDigits, ret, false); + while (digitIndex >= 0) { + AppendRadix((uint)digitGroups[digitIndex--], (uint)radix, tmpDigits, ret, true); + } + return ret.Length == 0 ? "0" : ret.ToString(); + } + + private static uint div(uint[] n, ref int nl, uint d) { + ulong rem = 0; + int i = nl; + bool seenNonZero = false; + while (--i >= 0) { + rem <<= BitsPerDigit; + rem |= n[i]; + uint v = (uint)(rem / d); + n[i] = v; + if (v == 0) { + if (!seenNonZero) nl--; + } else { + seenNonZero = true; + } + rem %= d; + } + return (uint)rem; + } + + private static void AppendRadix(uint rem, uint radix, char[] tmp, StringBuilder buf, bool leadingZeros) { + const string symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + int digits = tmp.Length; + int i = digits; + while (i > 0 && (leadingZeros || rem != 0)) { + uint digit = rem % radix; + rem /= radix; + tmp[--i] = symbols[(int)digit]; + } + if (leadingZeros) buf.Append(tmp); + else buf.Append(tmp, i, digits - i); + } + + public string ToString(int radix) { + return BigIntegerToString(copy(data), sign, radix); } - [Confined] public override int GetHashCode() { // The Object.GetHashCode function needs to be consistent with the Object.Equals function. // Languages that build on top of this may have a more flexible equality function and @@ -1395,12 +1471,10 @@ } } - [Confined] public override bool Equals(object obj) { return Equals(obj as BigInteger); } - [StateIndependent] public bool Equals(BigInteger other) { if (object.ReferenceEquals(other, null)) return false; return this == other; @@ -1492,17 +1566,14 @@ #region IConvertible Members - [Confined] public TypeCode GetTypeCode() { return TypeCode.Object; } - [Confined] public bool ToBoolean(IFormatProvider provider) { return this != Zero; } - [Confined] public byte ToByte(IFormatProvider provider) { uint ret; if (AsUInt32(out ret) && (ret & ~0xFF) == 0) { @@ -1561,7 +1632,6 @@ return trimmedBytes; } - [Confined] public char ToChar(IFormatProvider provider) { int ret; if (AsInt32(out ret) && (ret <= Char.MaxValue) && (ret >= Char.MinValue)) { @@ -1570,24 +1640,20 @@ throw new OverflowException("big integer won't fit into char"); } - [Confined] public DateTime ToDateTime(IFormatProvider provider) { throw new NotImplementedException(); } - [Confined] public decimal ToDecimal(IFormatProvider provider) { decimal ret; if (AsDecimal(out ret)) return ret; throw new OverflowException("big integer won't fit into decimal"); } - [Confined] public double ToDouble(IFormatProvider provider) { return ToFloat64(); } - [Confined] public short ToInt16(IFormatProvider provider) { int ret; if (AsInt32(out ret) && (ret <= short.MaxValue) && (ret >= short.MinValue)) { @@ -1596,7 +1662,6 @@ throw new OverflowException("big integer won't fit into short"); } - [Confined] public int ToInt32(IFormatProvider provider) { int ret; if (AsInt32(out ret)) { @@ -1605,7 +1670,6 @@ throw new OverflowException("big integer won't fit into int"); } - [Confined] public long ToInt64(IFormatProvider provider) { long ret; if (AsInt64(out ret)) { @@ -1614,7 +1678,7 @@ throw new OverflowException("big integer won't fit into long"); } - [CLSCompliant(false), Confined] + [CLSCompliant(false)] public sbyte ToSByte(IFormatProvider provider) { int ret; if (AsInt32(out ret) && (ret <= sbyte.MaxValue) && (ret >= sbyte.MinValue)) { @@ -1623,17 +1687,14 @@ throw new OverflowException("big integer won't fit into sbyte"); } - [Confined] public float ToSingle(IFormatProvider provider) { return checked((float)ToDouble(provider)); } - [Confined] public string ToString(IFormatProvider provider) { return ToString(); } - [Confined] public object ToType(Type conversionType, IFormatProvider provider) { if (conversionType == typeof(BigInteger)) { return this; @@ -1641,7 +1702,7 @@ throw new NotImplementedException(); } - [CLSCompliant(false), Confined] + [CLSCompliant(false)] public ushort ToUInt16(IFormatProvider provider) { uint ret; if (AsUInt32(out ret) && ret <= ushort.MaxValue) { @@ -1650,7 +1711,7 @@ throw new OverflowException("big integer won't fit into ushort"); } - [CLSCompliant(false), Confined] + [CLSCompliant(false)] public uint ToUInt32(IFormatProvider provider) { uint ret; if (AsUInt32(out ret)) { @@ -1659,7 +1720,7 @@ throw new OverflowException("big integer won't fit into uint"); } - [CLSCompliant(false), Confined] + [CLSCompliant(false)] public ulong ToUInt64(IFormatProvider provider) { ulong ret; if (AsUInt64(out ret)) { @@ -1724,4 +1785,3 @@ #endregion } } -#endif