Ejemplo n.º 1
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;
        }
Ejemplo n.º 2
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);
            }
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        public bool Equal(RawNum left, RawNum right)
        {
            int sizeDif = right.Size - left.Size;

            if (sizeDif != 0)
            {
                return(false);
            }

            for (int i = 0; i < left.Size; i++)
            {
                if (right.Digits[i] != left.Digits[i])
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 5
0
        private bool _ModLessThan(RawNum right, bool strictly = true)
        {
            if (m_modRaw.Size - m_modLeadingZeros != right.Size)
            {
                return(m_modRaw.Size - m_modLeadingZeros < right.Size);
            }

            int commonSize = right.Size;

            for (int i = m_modLeadingZeros; i < m_modRaw.Size; i++)
            {
                int rightIndex = commonSize - (i - m_modLeadingZeros) - 1;
                if (m_modRaw.Digits[i] != right.Digits[rightIndex])
                {
                    return(m_modRaw.Digits[i] < right.Digits[rightIndex]);
                }
            }

            return(!strictly);
        }
Ejemplo n.º 6
0
        public bool Less(RawNum left, RawNum right)
        {
            int sizeDif = right.Size - left.Size;

            if (sizeDif != 0)
            {
                return(sizeDif > 0);
            }

            for (int i = left.Size - 1; i >= 0; i--)
            {
                Int32 diff = (Int32)right.Digits[i] - (Int32)left.Digits[i];
                if (diff != 0)
                {
                    return(diff > 0);
                }
            }

            return(false);
        }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
0
        private void _SubtractFromMod(RawNum subtrahend)
        {
            const UInt32 leadingBit = (1 << 16);

            UInt32 z = 0;

            for (int i = 0; i < m_modRaw.Size - m_modLeadingZeros; i++)
            {
                UInt32 modDig = m_modRaw.Digits[m_modRaw.Size - i - 1];
                UInt32 subDig = (i < subtrahend.Size) ? subtrahend.Digits[i] : 0;

                UInt32 sub = (leadingBit | modDig) - subDig - z;
                m_modRaw.Digits[m_modRaw.Size - i - 1] = sub & UInt16.MaxValue;

                z = (~sub & leadingBit) >> 16;
            }

            for (int i = m_modLeadingZeros; i < m_modRaw.Size && m_modRaw.Digits[i] == 0; i++)
            {
                m_modLeadingZeros++;
            }
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
0
        private UInt16 _FindDivDigit(RawNum right)
        {
            UInt32 down = 0, upper = UInt16.MaxValue;
            UInt32 answer = 0;

            while (upper >= down)
            {
                UInt32 tested = (upper + down) >> 1;
                _MultiplyByDigit(right, tested, m_buffer);

                if (_ModLessThan(m_buffer, strictly: true))
                {
                    upper = tested - 1;
                }
                else
                {
                    answer = tested;
                    down   = tested + 1;
                }
            }

            return((UInt16)answer);
        }
Ejemplo n.º 11
0
        private void _CalcDivMod(RawNum left, RawNum right)
        {
            int offset = left.Size - right.Size + 1;

            _CopyHead(left, right.Size - 1, m_modRaw);

            while (offset > 0)
            {
                m_modRaw.Digits.Add(left.Digits[--offset]);

                if (_ModLessThan(right))
                {
                    _AddZeroToResult();
                }
                else
                {
                    UInt16 divDigit = _FindDivDigit(right);
                    _MultiplyByDigit(right, divDigit, m_buffer);

                    _SubtractFromMod(m_buffer);
                    m_divRaw.Digits.Add(divDigit);
                }
            }
        }
Ejemplo n.º 12
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);
            }
        }
Ejemplo n.º 13
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);
        }
Ejemplo n.º 14
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);
        }
Ejemplo n.º 15
0
        private void _Subtract(RawNum left, RawNum right)
        {
            const UInt32 leadingBit = (1 << 16);
            UInt32       z          = 0;

            for (int i = 0; i < left.Size; i++)
            {
                UInt32 rightDig = (i < right.Size) ? right.Digits[i] : 0;

                UInt32 sub = (leadingBit | left.Digits[i]) - rightDig - z;

                if (i < right.Digits.Count)
                {
                    right.Digits[i] = sub & UInt16.MaxValue;
                }
                else
                {
                    right.Digits.Add(sub & UInt16.MaxValue);
                }


                z = (~sub & leadingBit) >> 16;
            }
        }
Ejemplo n.º 16
0
 internal OmgNum(RawNum raw)
 {
     this.Raw = raw;
 }
Ejemplo n.º 17
0
 private void _InitializeModResult()
 {
     m_modRes          = OmgPool.GetZero();
     m_modRaw          = m_modRes.Raw;
     m_modLeadingZeros = 0;
 }
Ejemplo n.º 18
0
 public OmgNum(OmgNum other)
 {
     this.Raw = OmgPool.GetRawZero();
     this.Raw.CopyFrom(other.Raw);
     this.IsNegative = other.IsNegative;
 }
Ejemplo n.º 19
0
 public void Release()
 {
     OmgPool.ReleaseNumber(Raw);
     Raw = null;
 }