// Like GetBitCount(Abs(x)), except 0 maps to 0 public static int BitLength(BigInteger x) { if (x.IsZero()) { return 0; } return x.Abs().GetBitCount(); }
/// <summary> /// Test for shift overflow on negative BigIntegers /// </summary> /// <param name="self">Value before shifting</param> /// <param name="result">Value after shifting</param> /// <returns>-1 if we overflowed, otherwise result</returns> /// <remarks> /// Negative Bignums are supposed to look like they are stored in 2s complement infinite bit string, /// a negative number should always have spare 1s available for on the left hand side for right shifting. /// E.g. 8 == ...0001000; -8 == ...1110111, where the ... means that the left hand value is repeated indefinitely. /// The test here checks whether we have overflowed into the infinite 1s. /// [Arguably this should get factored into the BigInteger class.] /// </remarks> private static BigInteger/*!*/ ShiftOverflowCheck(BigInteger/*!*/ self, BigInteger/*!*/ result) { if (self.IsNegative() && result.IsZero()) { return -1; } return result; }
/*!*/ private static BigInteger SignedGcd(BigInteger/*!*/ a, BigInteger/*!*/ b) { while (!b.IsZero()) { BigInteger t = b; b = a % b; a = t; } return a; }
private static string/*!*/ ToDigits(BigInteger/*!*/ val, int radix, bool lower) { if (val.IsZero()) { return "0"; } StringBuilder str = new StringBuilder(); while (val != 0) { int digit = (int)(val % radix); if (digit < 10) str.Append((char)((digit) + '0')); else if (lower) str.Append((char)((digit - 10) + 'a')); else str.Append((char)((digit - 10) + 'A')); val /= radix; } StringBuilder res = new StringBuilder(str.Length); for (int i = str.Length - 1; i >= 0; i--) { res.Append(str[i]); } return res.ToString(); }
public static string/*!*/ __format__(CodeContext/*!*/ context, BigInteger/*!*/ self, [NotNull]string/*!*/ formatSpec) { StringFormatSpec spec = StringFormatSpec.FromString(formatSpec); if (spec.Precision != null) { throw PythonOps.ValueError("Precision not allowed in integer format specifier"); } BigInteger val = self; if (self < 0) { val = -self; } string digits; switch (spec.Type) { case 'n': CultureInfo culture = PythonContext.GetContext(context).NumericCulture; if (culture == CultureInfo.InvariantCulture) { // invariant culture maps to CPython's C culture, which doesn't // include any formatting info. goto case 'd'; } digits = ToCultureString(val, PythonContext.GetContext(context).NumericCulture); break; case null: case 'd': digits = val.ToString(); break; case '%': if (val == BigInteger.Zero) { digits = "0.000000%"; } else { digits = val.ToString() + "00.000000%"; } break; case 'e': digits = ToExponent(val, true, 6, 7); break; case 'E': digits = ToExponent(val, false, 6, 7); break; case 'f': if (val != BigInteger.Zero) { digits = val.ToString() + ".000000"; } else { digits = "0.000000"; } break; case 'F': if (val != BigInteger.Zero) { digits = val.ToString() + ".000000"; } else { digits = "0.000000"; } break; case 'g': if (val >= 1000000) { digits = ToExponent(val, true, 0, 6); } else { digits = val.ToString(); } break; case 'G': if (val >= 1000000) { digits = ToExponent(val, false, 0, 6); } else { digits = val.ToString(); } break; case 'X': digits = AbsToHex(val, false); break; case 'x': digits = AbsToHex(val, true); break; case 'o': // octal digits = ToOctal(val, true); break; case 'b': // binary digits = ToBinary(val, false, true); break; case 'c': // single char int iVal; if (spec.Sign != null) { throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'"); } else if (!self.AsInt32(out iVal)) { throw PythonOps.OverflowError("long int too large to convert to int"); } else if(iVal < Char.MinValue || iVal > Char.MaxValue) { throw PythonOps.OverflowError("%c arg not in range(0x10000)"); } digits = Builtin.chr(iVal); break; default: throw PythonOps.ValueError("Unknown format code '{0}'", spec.Type.ToString()); } Debug.Assert(digits[0] != '-'); return spec.AlignNumericText(digits, self.IsZero(), self.IsPositive()); }
public static bool __nonzero__(BigInteger x) { return !x.IsZero(); }