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); }
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); }
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 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 void Release() { OmgPool.ReleaseNumber(Raw); Raw = null; }