internal RawNum GetRandom(RawNum min, RawNum max) { m_result = OmgPool.GetRawZero(); bool maxComplete = false; bool minComplete = false; for (int i = max.Size - 1; i >= 0; i--) { int digMin = (minComplete || i >= min.Size) ? 0 : (int)min.Digits[i]; int digMax = (maxComplete) ? (1 << 16) : (int)max.Digits[i]; if (maxComplete || i != 0) { digMax += 1; } UInt16 generated = (UInt16)m_rand.Next(digMin, digMax); m_result.Digits.Add(generated); maxComplete |= generated < (int)max.Digits[i]; minComplete |= generated > 0; } m_result.Digits.Reverse(); m_result.RemoveLeadingZeros(); return(m_result); }
internal RawNum ExtendedGcd(RawNum left, RawNum right, out OmgNum x, out OmgNum y) { if (left.IsZero()) { x = 0.ToOmgNum(); y = 1.ToOmgNum(); RawNum gcd = OmgPool.GetRawZero(); gcd.CopyFrom(right); return(gcd); } var divModRes = OmgOp.DivMod(right.OmgWrapper(), left.OmgWrapper()); RawNum gcdRes = ExtendedGcd(divModRes.mod.Raw, left, out OmgNum x2, out OmgNum y2); divModRes.mod.Release(); OmgNum multRes = OmgOp.Multiply(divModRes.div, x2); divModRes.div.Release(); x = OmgOp.Subtract(y2, multRes); y2.Release(); multRes.Release(); y = x2; return(gcdRes); }
internal RawNum Sqrt(RawNum left) { m_targetSquare = left; m_targetSquareNum = m_targetSquare.OmgWrapper(); m_rootAprox = OmgPool.GetRawZero(); m_buffer = OmgPool.GetRawZero(); _FillInitialApproximation(); while (!_AproxEqualToBuffer()) { var aproxCopy = OmgPool.GetRawZero(); aproxCopy.CopyFrom(m_rootAprox); var bufferCopy = OmgPool.GetRawZero(); bufferCopy.CopyFrom(m_buffer); _MakeGeronIteration(); if (OmgOp.Equal(aproxCopy.OmgWrapper(), m_buffer.OmgWrapper()) && OmgOp.Equal(bufferCopy.OmgWrapper(), m_rootAprox.OmgWrapper()) && OmgOp.Less(m_rootAprox.OmgWrapper(), m_buffer.OmgWrapper())) { break; } OmgPool.ReleaseNumber(bufferCopy); OmgPool.ReleaseNumber(aproxCopy); } OmgPool.ReleaseNumber(m_buffer); return(m_rootAprox); }
public RawNum Add(RawNum left, RawNum right) { m_result = OmgPool.GetRawZero(); _Add(left, right); return(m_result); }
private void _FindModSolution(RawNum left, RawNum right) { if (_IsTrivial(left, right)) { m_modRaw.CopyFrom(left); return; } m_buffer = OmgPool.GetRawZero(); _CalcMod(left, right); OmgPool.ReleaseNumber(m_buffer); m_modRaw.Digits.Reverse(); }
public static OmgNum FromByteArray(byte[] bytes) { RawNum num = OmgPool.GetRawZero(); for (int i = 0; i < bytes.Length - 1; i += 2) { byte least = bytes[i]; byte elder = (i + 1 < bytes.Length - 1) ? bytes[i + 1] : (byte)0; num.Digits.Add((UInt32)(least | elder << 8)); } OmgNum decoded = new OmgNum(num); decoded.IsNegative = bytes[bytes.Length - 1] > 0; return(decoded); }
private (RawNum head, RawNum tail) _SeparateHead(RawNum num, int n) { (RawNum head, RawNum tail)res = (OmgPool.GetRawZero(), OmgPool.GetRawZero()); for (int i = 0; i < num.Size; i++) { if (i < n / 2) { res.tail.Digits.Add(num.Digits[i]); } else { res.head.Digits.Add(num.Digits[i]); } } return(res); }
private OmgNum _MakeFastPow(OmgNum left, RawNum right, OmgNum mod) { if (right.IsZero()) { var res = OmgPool.GetRawZero(); res.Digits.Add(1); return(new OmgNum(res)); } var rightCopy = OmgPool.GetRawZero(); rightCopy.CopyFrom(right); bool even = (rightCopy.Digits[0] & 1) == 0; if (even) { rightCopy.DivByTwo(); var p = _MakeFastPow(left, rightCopy, mod); OmgNum powSquare = OmgOp.Multiply(p, p); OmgNum powSquareModded = OmgOp.Mod(powSquare, mod); powSquare.Release(); p.Release(); OmgPool.ReleaseNumber(rightCopy); return(powSquareModded); } else { _SubOne(rightCopy); var p = _MakeFastPow(left, rightCopy, mod); OmgNum powPlusOne = OmgOp.Multiply(p, left); OmgNum powPlusOneModded = OmgOp.Mod(powPlusOne, mod); powPlusOne.Release(); p.Release(); OmgPool.ReleaseNumber(rightCopy); return(powPlusOneModded); } }
internal RawNum FindGcd(RawNum left, RawNum right) { if (left.IsZero()) { RawNum gcd = OmgPool.GetRawZero(); gcd.CopyFrom(right); return(gcd); } var divModRes = OmgOp.DivMod(right.OmgWrapper(), left.OmgWrapper()); divModRes.div.Release(); RawNum gcdRes = FindGcd(divModRes.mod.Raw, left); divModRes.mod.Release(); return(gcdRes); }
internal RawNum GenerateWithBitlength(int bitLength) { m_result = OmgPool.GetRawZero(); int intermediateDigits = bitLength / 16; for (int i = 0; i < intermediateDigits; i++) { m_result.Digits.Add((UInt32)m_rand.Next(1 << 16)); } int restBits = bitLength % 16; if (restBits > 0) { m_result.Digits.Add((UInt32)m_rand.Next(1 << restBits)); } m_result.RemoveLeadingZeros(); return(m_result); }
internal RawNum Multiply(RawNum left, RawNum right) { m_multRaw = OmgPool.GetRawZero(); if (left.IsZero() || right.IsZero()) { return(m_multRaw); } if (left.Size < right.Size) { _Swap(ref left, ref right); } _MakeMult(left, right); while (m_multRaw.Size > 0 && m_multRaw.Digits[m_multRaw.Size - 1] == 0) { m_multRaw.Digits.RemoveAt(m_multRaw.Size - 1); } return(m_multRaw); }
internal RawNum MultiplyKaratsuba(RawNum left, RawNum right) { if (left.IsZero() || right.IsZero()) { return(OmgPool.GetRawZero()); } int n = Math.Min(left.Size, right.Size); (RawNum head, RawNum tail)leftSep = _SeparateHead(left, n); (RawNum head, RawNum tail)rightSep = _SeparateHead(right, n); RawNum headsProd = Multiply(leftSep.head, rightSep.head); RawNum tailsProd = Multiply(leftSep.tail, rightSep.tail); RawNum headTail = Multiply(leftSep.head, rightSep.tail); RawNum tailHead = Multiply(leftSep.tail, rightSep.head); OmgNum midSum = OmgOp.Add(new OmgNum(headTail), new OmgNum(tailHead)); m_multRaw = OmgPool.GetRawZero(); m_multRaw.CopyFrom(tailsProd); midSum.Raw.Digits.InsertRange(0, Enumerable.Repeat <uint>(0, n)); headsProd.Digits.InsertRange(0, Enumerable.Repeat <uint>(0, 2 * n)); OmgNum res = OmgOp.Add(new OmgNum(tailsProd), midSum); OmgNum finalRes = OmgOp.Add(new OmgNum(headsProd), res); midSum.Release(); res.Release(); OmgPool.ReleaseNumber(headTail); OmgPool.ReleaseNumber(tailHead); return(finalRes.Raw); }
public OmgNum(OmgNum other) { this.Raw = OmgPool.GetRawZero(); this.Raw.CopyFrom(other.Raw); this.IsNegative = other.IsNegative; }