private void _FindDivModSolution(RawNum left, RawNum right) { if (_IsTrivial(left, right)) { m_modRaw.CopyFrom(left); return; } m_buffer = OmgPool.GetRawZero(); _CalcDivMod(left, right); OmgPool.ReleaseNumber(m_buffer); m_divRaw.Digits.Reverse(); m_modRaw.Digits.Reverse(); }
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); }
private void _DivModByTwo(OmgNum num) { var rawNum = num.Raw; if (!rawNum.IsZero() && ((rawNum.Digits[0] & 1) == 1)) { m_modRaw.Digits.Add(1); } m_divRaw.CopyFrom(rawNum); m_divRaw.DivByTwo(); }
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 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); }