Skip to content

Commit

Permalink
Merge pull request dotnet#4401 from axelheer/biginteger-readonly
Browse files Browse the repository at this point in the history
Mark members of BigInteger as readonly
  • Loading branch information
stephentoub committed Nov 12, 2015
2 parents 1d90ea6 + b9e3c7a commit aec9e02
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 90 deletions.
149 changes: 59 additions & 90 deletions src/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public struct BigInteger : IFormattable, IComparable, IComparable<BigInteger>, I

// For values int.MinValue < n <= int.MaxValue, the value is stored in sign
// and _bits is null. For all other values, sign is +1 or -1 and the bits are in _bits
internal int _sign;
internal uint[] _bits;
internal readonly int _sign;
internal readonly uint[] _bits;

// We have to make a choice of how to represent int.MinValue. This is the one
// value that fits in an int, but whose negation does not fit in an int.
Expand Down Expand Up @@ -552,17 +552,8 @@ public BigInteger(ulong value)
}

public BigInteger(Single value)
: this((Double)value)
{
if (Single.IsInfinity(value))
throw new OverflowException(SR.Overflow_BigIntInfinity);
if (Single.IsNaN(value))
throw new OverflowException(SR.Overflow_NotANumber);
Contract.EndContractBlock();

_sign = 0;
_bits = null;
SetBitsFromDouble(value);
AssertValid();
}

public BigInteger(Double value)
Expand All @@ -575,7 +566,61 @@ public BigInteger(Double value)

_sign = 0;
_bits = null;
SetBitsFromDouble(value);

int sign, exp;
ulong man;
bool fFinite;
NumericsHelpers.GetDoubleParts(value, out sign, out exp, out man, out fFinite);
Debug.Assert(sign == +1 || sign == -1);

if (man == 0)
{
this = BigInteger.Zero;
return;
}

Debug.Assert(man < (1UL << 53));
Debug.Assert(exp <= 0 || man >= (1UL << 52));

if (exp <= 0)
{
if (exp <= -kcbitUlong)
{
this = BigInteger.Zero;
return;
}
this = man >> -exp;
if (sign < 0)
_sign = -_sign;
}
else if (exp <= 11)
{
this = man << exp;
if (sign < 0)
_sign = -_sign;
}
else
{
// Overflow into at least 3 uints.
// Move the leading 1 to the high bit.
man <<= 11;
exp -= 11;

// Compute cu and cbit so that exp == 32 * cu - cbit and 0 <= cbit < 32.
int cu = (exp - 1) / kcbitUint + 1;
int cbit = cu * kcbitUint - exp;
Debug.Assert(0 <= cbit && cbit < kcbitUint);
Debug.Assert(cu >= 1);

// Populate the uints.
_bits = new uint[cu + 2];
_bits[cu + 1] = (uint)(man >> (cbit + kcbitUint));
_bits[cu] = (uint)(man >> cbit);
if (cbit > 0)
_bits[cu - 1] = (uint)man << (kcbitUint - cbit);
_sign = sign;
}

AssertValid();
}

Expand Down Expand Up @@ -1611,9 +1656,7 @@ public static explicit operator Decimal(BigInteger value)
public static BigInteger operator -(BigInteger value)
{
value.AssertValid();
value._sign = -value._sign;
value.AssertValid();
return value;
return new BigInteger(-value._sign, value._bits);
}

public static BigInteger operator +(BigInteger value)
Expand Down Expand Up @@ -1978,69 +2021,6 @@ private static BigInteger Subtract(uint[] leftBits, int leftSign, uint[] rightBi

#endregion public static operators


// ----- SECTION: internal instance utility methods ----------------*
#region internal instance utility methods

private void SetBitsFromDouble(Double value)
{
int sign, exp;
ulong man;
bool fFinite;
NumericsHelpers.GetDoubleParts(value, out sign, out exp, out man, out fFinite);
Debug.Assert(sign == +1 || sign == -1);

if (man == 0)
{
this = BigInteger.Zero;
return;
}

Debug.Assert(man < (1UL << 53));
Debug.Assert(exp <= 0 || man >= (1UL << 52));

if (exp <= 0)
{
if (exp <= -kcbitUlong)
{
this = BigInteger.Zero;
return;
}
this = man >> -exp;
if (sign < 0)
_sign = -_sign;
}
else if (exp <= 11)
{
this = man << exp;
if (sign < 0)
_sign = -_sign;
}
else
{
// Overflow into at least 3 uints.
// Move the leading 1 to the high bit.
man <<= 11;
exp -= 11;

// Compute cu and cbit so that exp == 32 * cu - cbit and 0 <= cbit < 32.
int cu = (exp - 1) / kcbitUint + 1;
int cbit = cu * kcbitUint - exp;
Debug.Assert(0 <= cbit && cbit < kcbitUint);
Debug.Assert(cu >= 1);

// Populate the uints.
_bits = new uint[cu + 2];
_bits[cu + 1] = (uint)(man >> (cbit + kcbitUint));
_bits[cu] = (uint)(man >> cbit);
if (cbit > 0)
_bits[cu - 1] = (uint)man << (kcbitUint - cbit);
_sign = sign;
}
}
#endregion internal instance utility methods


// ----- SECTION: internal static utility methods ----------------*
#region internal static utility methods
[Pure]
Expand All @@ -2052,17 +2032,6 @@ internal static int Length(uint[] rgu)
return rgu.Length;
}

internal static int BitLengthOfUInt(uint x)
{
int numBits = 0;
while (x > 0)
{
x >>= 1;
numBits++;
}
return numBits;
}

//
// GetPartsForBitManipulation -
//
Expand Down
3 changes: 3 additions & 0 deletions src/System.Runtime.Numerics/tests/BigInteger/cast_to.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ public static void RunSingleExplicitCastToBigIntegerTests()
// Single Explicit Cast to BigInteger: Single.PositiveInfinity
Assert.Throws<OverflowException>(() => { BigInteger temp = (BigInteger)Single.PositiveInfinity; });

// double.IsInfinity(float.MaxValue * 2.0f) == false, but we don't want this odd behavior here
Assert.Throws<OverflowException>(() => { BigInteger temp = (BigInteger)(float.MaxValue * 2.0f); });

// Single Explicit Cast to BigInteger: Single.Epsilon
VerifySingleExplicitCastToBigInteger(Single.Epsilon);

Expand Down

0 comments on commit aec9e02

Please sign in to comment.