private static Expression BigIntConstant(BigInt value) { int ival; if (value.AsInt32(out ival)) { return(Expression.Call( new Func <int, BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(), Constant(ival) )); } long lval; if (value.AsInt64(out lval)) { return(Expression.Call( new Func <long, BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(), Constant(lval) )); } return(Expression.Call( new Func <bool, byte[], BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(), Constant(value.Sign < 0), CreateArray <byte>(value.Abs().ToByteArray()) )); }
public static BigInt Random(this Random generator, BigInt limit) { ContractUtils.Requires(limit.Sign > 0, "limit"); ContractUtils.RequiresNotNull(generator, "generator"); BigInt res = BigInt.Zero; while (true) { // if we've run out of significant digits, we can return the total if (limit == BigInt.Zero) { return(res); } // if we're small enough to fit in an int, do so int iLimit; if (limit.AsInt32(out iLimit)) { return(res + generator.Next(iLimit)); } // get the 3 or 4 uppermost bytes that fit into an int int hiData; byte[] data = limit.ToByteArray(); int index = data.Length; while (data[--index] == 0) { ; } if (data[index] < 0x80) { hiData = data[index] << 24; data[index--] = (byte)0; } else { hiData = 0; } hiData |= data[index] << 16; data[index--] = (byte)0; hiData |= data[index] << 8; data[index--] = (byte)0; hiData |= data[index]; data[index--] = (byte)0; // get a uniform random number for the uppermost portion of the bigint byte[] randomData = new byte[index + 2]; generator.NextBytes(randomData); randomData[index + 1] = (byte)0; res += new BigInt(randomData); res += (BigInt)generator.Next(hiData) << ((index + 1) * 8); // sum it with a uniform random number for the remainder of the bigint limit = new BigInt(data); } }
public static BigInt Random(this Random generator, BigInt limit) { ContractUtils.Requires(limit.Sign > 0, "limit"); ContractUtils.RequiresNotNull(generator, "generator"); BigInt res = BigInt.Zero; while (true) { // if we've run out of significant digits, we can return the total if (limit == BigInt.Zero) { return res; } // if we're small enough to fit in an int, do so int iLimit; if (limit.AsInt32(out iLimit)) { return res + generator.Next(iLimit); } // get the 3 or 4 uppermost bytes that fit into an int int hiData; byte[] data = limit.ToByteArray(); int index = data.Length; while (data[--index] == 0) ; if (data[index] < 0x80) { hiData = data[index] << 24; data[index--] = (byte)0; } else { hiData = 0; } hiData |= data[index] << 16; data[index--] = (byte)0; hiData |= data[index] << 8; data[index--] = (byte)0; hiData |= data[index]; data[index--] = (byte)0; // get a uniform random number for the uppermost portion of the bigint byte[] randomData = new byte[index + 2]; generator.NextBytes(randomData); randomData[index + 1] = (byte)0; res += new BigInt(randomData); res += (BigInt)generator.Next(hiData) << ((index + 1) * 8); // sum it with a uniform random number for the remainder of the bigint limit = new BigInt(data); } }