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 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); }
private void _InitializeDivModResult() { m_divRes = OmgPool.GetZero(); m_divRaw = m_divRes.Raw; _InitializeModResult(); }
public RawNum Add(RawNum left, RawNum right) { m_result = OmgPool.GetRawZero(); _Add(left, right); return(m_result); }
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 static OmgNum Sqrt(OmgNum left) { if (left.IsZero()) { return(OmgPool.GetZero()); } if (left.IsNegative) { throw new OmgFailException("can't square root negative number"); } return(_Positive(m_rooter.Sqrt(left.Raw))); }
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 bool TryInverseByMod(OmgNum left, OmgNum mod, out OmgNum inverce) { RawNum gcd = m_gcder.ExtendedGcd(left.Raw, mod.Raw, out OmgNum x, out OmgNum y); y.Release(); bool result = (gcd.Size == 1) && (gcd.Digits[0] == 1); OmgPool.ReleaseNumber(gcd); inverce = (result) ? Mod(x, mod) : null; x.Release(); return(result); }
internal OmgNum Subtract(OmgNum left, OmgNum right) { if (left.IsNegative != right.IsNegative) { throw new OmgFailException("logic error"); } m_subRes = OmgPool.GetZero(); m_subRaw = m_subRes.Raw; _CalcSubtraction(left, right); _RemoveLeadingZeros(); return(m_subRes); }
public static OmgNum ToOmgNum(this string strNumber, uint _base = 10) { OmgNum result = OmgPool.GetZero(); RawNum rawNumber = result.Raw; result.IsNegative = StartsWithMinus(strNumber); m_converter.InputBase = _base; m_converter.Input = ParseDigits(strNumber); m_converter.Output = rawNumber.Digits; m_converter.Convert(); return(result); }
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 void _MakeGeronIteration() { OmgNum rootAprox = m_rootAprox.OmgWrapper(); var res = OmgOp.DivMod(m_targetSquareNum, rootAprox); res.mod.Release(); OmgNum sum = OmgOp.Add(rootAprox, res.div); res.div.Release(); sum.Raw.DivByTwo(); OmgPool.ReleaseNumber(m_buffer); m_buffer = m_rootAprox; m_rootAprox = sum.Raw; }
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); }
public static OmgNum ToOmgNum(this int number) { OmgNum result = OmgPool.GetZero(); if (number == 0) { return(result); } RawNum rawNumber = result.Raw; result.IsNegative = number < 0; UInt32 absNum = (UInt32)Math.Abs(number); rawNumber.Digits.Add((UInt16)(absNum & ((1 << 16) - 1))); if ((absNum >> 16) > 0) { rawNumber.Digits.Add((UInt16)(absNum >> 16)); } return(result); }
internal RawNum Pow(RawNum left, RawNum right, RawNum mod = null) { m_powRes = OmgPool.GetZero(); if (left.IsZero()) { return(m_powRes.Raw); } if (right.IsZero()) { m_powRes.Raw.Digits.Add(1); return(m_powRes.Raw); } if (mod == null) { return(_MakeFastPow(new OmgNum(left), right).Raw); } else { return(_MakeFastPow(new OmgNum(left), right, new OmgNum(mod)).Raw); } }
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; }
public void Release() { OmgPool.ReleaseNumber(Raw); Raw = null; }
private void _InitializeModResult() { m_modRes = OmgPool.GetZero(); m_modRaw = m_modRes.Raw; m_modLeadingZeros = 0; }