Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        private void _InitializeDivModResult()
        {
            m_divRes = OmgPool.GetZero();
            m_divRaw = m_divRes.Raw;

            _InitializeModResult();
        }
Пример #4
0
        public RawNum Add(RawNum left, RawNum right)
        {
            m_result = OmgPool.GetRawZero();

            _Add(left, right);
            return(m_result);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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)));
        }
Пример #7
0
        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();
        }
Пример #8
0
        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);
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        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;
        }
Пример #14
0
        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);
            }
        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
        }
Пример #17
0
        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);
        }
Пример #18
0
        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);
        }
Пример #19
0
        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);
            }
        }
Пример #20
0
        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);
        }
Пример #21
0
 public OmgNum(OmgNum other)
 {
     this.Raw = OmgPool.GetRawZero();
     this.Raw.CopyFrom(other.Raw);
     this.IsNegative = other.IsNegative;
 }
Пример #22
0
 public void Release()
 {
     OmgPool.ReleaseNumber(Raw);
     Raw = null;
 }
Пример #23
0
 private void _InitializeModResult()
 {
     m_modRes          = OmgPool.GetZero();
     m_modRaw          = m_modRes.Raw;
     m_modLeadingZeros = 0;
 }