Exemple #1
0
        Sub(Digits a, Digits b, Digits c, Digits mod, int n)
        {
            Debug.Assert(n > 0, "internal error");
            Digit alead = a[n - 1], blead = b[n - 1], mlead = mod[n - 1];
            int   itest;

            if (alead == blead)
            {
                itest = Digits.Compare(a, b, n - 1);
            }
            else
            {
                itest = alead < blead ? -1 : +1;
            }
            if (itest < 0)
            {
                if (blead >= mlead)
                {
                    ValidateData(b, mod, n);
                }
                int carry = Digits.AddSub(a, mod, b, c, n);
                Debug.Assert(carry == 0, "internal error");
            }
            else
            {
                if (alead >= mlead)
                {
                    Debug.Assert(false, "untested code");
                    ValidateData(a, mod, n);
                }
                uint borrow = Digits.Sub(a, b, c, n);
                Debug.Assert(borrow == 0, "internal error");
            }
        }
Exemple #2
0
        static void Mul22U(
            Digit[] mat
            , Digits vec1
            , Digits vec2
            , int lvec
            , Digits carrys
            )
        {
            Digit carry1 = 0, carry2 = 0;
            Digit m11 = mat[0], m12 = mat[1], m21 = mat[2], m22 = mat[3];

            if (m12 > Digit.MaxValue - m11 || m21 > Digit.MaxValue - m22)
            {
                throw new ArgumentException();
            }
            for (int i = 0; i != lvec; i++)
            {
                UInt64 prod11 = (UInt64)m11 * vec1[i] + carry1
                , prod21      = (UInt64)m21 * vec1[i] + carry2
                , prod12      = (UInt64)m12 * vec2[i] + Digit2.Lo(prod11)
                , prod22      = (UInt64)m22 * vec2[i] + Digit2.Lo(prod21);
                vec1[i] = Digit2.Lo(prod12);
                vec2[i] = Digit2.Lo(prod22);
                carry1  = Digit2.Hi(prod11) + Digit2.Hi(prod12);
                carry2  = Digit2.Hi(prod21) + Digit2.Hi(prod22);
            }
            carrys[0] = carry1;
            carrys[1] = carry2;
        }
Exemple #3
0
        Mul22S(Digit[] mat, Digits vec1, Digits vec2, int lvec, int[] carrys)
        {
            int   carry1 = 0, carry2 = 0;
            Digit m11 = mat[0], m12 = mat[1], m21 = mat[2], m22 = mat[3];

            if (((m11 | m12 | m21 | m22) & 1U << Digit.BitN - 1) != 0)
            {
                throw new ArgumentException();
            }
            for (int i = 0; i != lvec; i++)
            {
                UInt64 prod11 = (UInt64)m11 * vec1[i]
                , prod12      = (UInt64)m12 * vec2[i]
                , prod21      = (UInt64)m21 * vec1[i]
                , prod22      = (UInt64)m22 * vec2[i]
                , prod1       = unchecked (prod11 + (UInt64)carry1)
                , prod2       = unchecked (prod22 + (UInt64)carry2);
                prod1   = unchecked (prod1 - prod12);
                prod2   = unchecked (prod2 - prod21);
                vec1[i] = Digit2.Lo(prod1);
                vec2[i] = Digit2.Lo(prod2);
                carry1  = unchecked ((int)Digit2.Hi(prod1));
                carry2  = unchecked ((int)Digit2.Hi(prod2));
            }
            carrys[0] = carry1;
            carrys[1] = carry2;
        }
Exemple #4
0
        internal static int Compare(Digits a, int aN, Digits b, int bN)
        {
            int la = aN, lb = bN;

            while (la > lb)
            {
                if (a[la - 1] != 0)
                {
                    return(+1);
                }
                la--;
            }
            while (lb > la)
            {
                if (b[lb - 1] != 0)
                {
                    return(-1);
                }
                lb--;
            }
            Debug.Assert(la == lb, "internal error");
            while (la != 0)
            {
                if (a[la - 1] != b[la - 1])
                {
                    return(a[la - 1] > b[la - 1] ? +1 : -1);
                }
                la--;
            }
            return(0);
        }
Exemple #5
0
 internal void _Set(Digits from, int n)
 {
     for (int i = 0; i < n; i++)
     {
         this[i] = from[i];
     }
 }
Exemple #6
0
 internal static bool DivisibleBySomeLowPrime(Digits digits, int n)
 {
     if (n == 0 || (digits[0] & 1) == 0)
     {
         Debug.Assert(false, "untested code");
         return(true);
     }
     for (int l = 0; l != LowPrimesProduct.Length; l++)
     {
         Digit product    = LowPrimesProduct[l]
         , productInverse = Digit.TwoAdicInverse(product)
         , r = 0;
         for (int i = 0; i != n; i++)
         {
             Digit mulby;
             unchecked {
                 r += digits[i];
                 if (r < digits[i])
                 {
                     r -= product;
                 }
                 mulby = productInverse * r;
                 Debug.Assert(mulby * product == r, "internal error");
             }
             r = product - Digit2.Hi((UInt64)mulby * product);
         }
         if (Digit.OddGcd(r, product) != 1)
         {
             return(true);
         }
     }
     return(false);
 }
Exemple #7
0
        internal static void Shift(Digits a, int shiftBitN, Digits b, int n)
        {
            int itranslate = shiftBitN >= 0
                           ? shiftBitN / Digit.BitN
                           : -(-shiftBitN / Digit.BitN);

            ShiftLost(a, shiftBitN - Digit.BitN * itranslate, b, n);
            if (itranslate < 0)
            {
                Debug.Assert(false, "untested code");
                int dtranslate = -itranslate;
                for (int i = 0; i != n; i++)
                {
                    Debug.Assert(false, "untested code");
                    b[i] = i + dtranslate < n ? b[i + dtranslate] : 0;
                }
            }
            else if (itranslate > 0)
            {
                Debug.Assert(false, "untested code");
                int dtranslate = itranslate;
                for (int i = n; i-- != 0;)
                {
                    Debug.Assert(false, "untested code");
                    b[i] = i >= dtranslate ? b[i - dtranslate] : 0;
                }
            }
        }
Exemple #8
0
        BytesToDigits(byte[] bytes, int bytesI, Digits digits, int bitN)
        {
            if (bitN == 0)
            {
                Debug.Assert(false, "untested code"); return;
            }
            int digitN = (bitN + (Digit.BitN - 1)) / Digit.BitN;

            digits._SetAll(0, digitN);
            for (int iDigit = 0; iDigit != digitN; iDigit++)
            {
                int   byteNLeft = (bitN + 7) / 8 - 4 * iDigit;
                Digit digit     = 0;
                for (
                    int iByte = 0;
                    iByte != (4 > byteNLeft ? byteNLeft : 4);
                    iByte++
                    )
                {
                    digit
                        ^= (Digit)bytes[bytesI + byteNLeft - 1 - iByte] << 8 * iByte;
                }
                digits[iDigit] = digit;
            }
            digits[digitN - 1] &= Digit.MaxValue >> Digit.BitN * digitN - bitN;
        }
Exemple #9
0
        Mul(Digits a, int aN, Digits b, int bN, Digits c)
        {
            Debug.Assert(!c._Overlaps(a) && !c._Overlaps(b)
                         , "overlapping arguments");
            Digits p1, p2;
            int    i, n1, n2;

            if (aN > bN)
            {
                p1 = a;
                p2 = b;
                n1 = aN;
                n2 = bN;
            }
            else
            {
                p2 = a;
                p1 = b;
                n2 = aN;
                n1 = bN;
            }
            if (n2 == 0)
            {
                Debug.Assert(false, "untested code");
                c._SetAll(0, n1);
                return;
            }
            c[n1] = Mul(p1, p2[0], c, n1);
            for (i = 1; i != n2; i++)
            {
                c[i + n1] = Accumulate(p1, p2[i], c + i, n1);
            }
        }
Exemple #10
0
 internal static void ValidateData(Digits data, Digits mod, int n)
 {
     if (Digits.Compare(data, mod, n) >= 0)
     {
         throw new ArgumentException();
     }
 }
Exemple #11
0
        static void Random(Digits mod, Digits arr, int n, Random generator)
        {
            Debug.Assert(!arr._Overlaps(mod), "overlapping arguments");
            int sigDigitN = n;

            while (sigDigitN > 0 && mod[sigDigitN - 1] == 0)
            {
                Debug.Assert(false, "untested code");
                arr[sigDigitN - 1] = 0;
                sigDigitN--;
            }
            if (sigDigitN == 0)
            {
                throw new ArgumentException();
            }
            Digit nlead = mod[sigDigitN - 1];
            int   ntry  = 0;

            do
            {
                ntry++;
                Debug.Assert(ntry <= 100, "too many iterations");
                Digits.Random(arr, sigDigitN - 1, generator);
                arr[sigDigitN - 1] = Digit.Random(0, nlead, generator);
            } while (Digits.Compare(arr, mod, sigDigitN) >= 0);
        }
Exemple #12
0
 Random(Digits digits, int digitN, Random generator)
 {
     for (int i = 0; i < digitN; i++)
     {
         digits[i] = Digit.Random(generator);
     }
 }
Exemple #13
0
        static void Div(
            Digits numer
            , Digit den
            , Reciprocal recip
            , Digits q
            , int n
            , Digits r
            )
        {
            Digit carry = 0;
            int   nLeft = n;

            if (nLeft > 0 && numer[nLeft - 1] < den)
            {
                nLeft--;
                carry = numer[nLeft];
                if (q != null)
                {
                    q[nLeft] = 0;
                }
            }
            if (recip == null && nLeft < 2)
            {
                for (int i = nLeft; i-- != 0;)
                {
                    Digit qest = 0;
                    Digit2.Div((UInt64)carry << Digit.BitN | numer[i]
                               , den
                               , out qest
                               , out carry);
                    if (q != null)
                    {
                        q[i] = qest;
                    }
                }
            }
            else
            {
                if (recip == null)
                {
                    recip = new Reciprocal();
                    DivPrecondition(new Digits(new Digit[] { den }), 1, recip);
                }
                for (int i = nLeft; i-- != 0;)
                {
                    Digit qest = 0;
                    Digit2.Div((UInt64)carry << Digit.BitN | numer[i]
                               , den
                               , recip
                               , out qest
                               , out carry);
                    if (q != null)
                    {
                        q[i] = qest;
                    }
                }
            }
            r[0] = carry;
        }
Exemple #14
0
        void _MulFromLeft(Digits a, Digits b, Digits c)
        {
            Digits product = new Digits(2 * _digitN);

            Digits.Mul(a, _digitN, b, _digitN, product);
            Digits
            .Div(product, 2 * _digitN, _mod, _digitN, _leftRecip, null, c);
        }
Exemple #15
0
 internal void _Mul(Digits a, Digits b, Digits c)
 {
     Modular.ValidateData(a, _mod, _digitN);
     if (a != b)
     {
         Modular.ValidateData(b, _mod, _digitN);
     }
     _algorithm(a, b, c);
 }
Exemple #16
0
        static uint Add(Digits a, int aN, Digits b, int bN, Digits c)
        {
            if (aN < bN || aN < 0 || bN < 0)
            {
                throw new ArgumentException();
            }
            uint carry = Add(a, b, c, bN);

            return(Add(a + bN, carry, c + bN, aN - bN));
        }
Exemple #17
0
        internal static int SigDigitN(Digits a, int aN)
        {
            int i = aN;

            while (i != 0 && a[i - 1] == 0)
            {
                i--;
            }
            return(i);
        }
Exemple #18
0
 internal static int Compare(Digits a, Digits b, int n)
 {
     for (int i = n; i-- != 0;)
     {
         if (a[i] != b[i])
         {
             return(a[i] > b[i] ? +1 : -1);
         }
     }
     return(0);
 }
Exemple #19
0
        internal static uint Add(Digits a, Digits b, Digits c, int n)
        {
            uint carry = 0;

            for (int i = 0; i != n; i++)
            {
                Digit ai = a[i], bi = b[i], sum = unchecked (carry + (ai + bi));
                c[i]  = sum;
                carry = ((ai | bi) ^ (ai ^ bi) & sum) >> Digit.BitN - 1;
            }
            return(carry);
        }
Exemple #20
0
        internal static int SigBitN(Digits a, int aN)
        {
            int sigDigitN = SigDigitN(a, aN);

            if (sigDigitN == 0)
            {
                Debug.Assert(false, "untested code");
                return(0);
            }
            return((int)((sigDigitN - 1) * Digit.BitN
                         + Digit.SigBitN(a[sigDigitN - 1])));
        }
Exemple #21
0
        Accumulate(Digits a, Digit mult, Digits b, int n)
        {
            Digit carry = 0;

            for (int i = 0; i != n; i++)
            {
                UInt64 dtemp = (UInt64)mult * a[i] + b[i] + carry;
                b[i]  = Digit2.Lo(dtemp);
                carry = Digit2.Hi(dtemp);
            }
            return(carry);
        }
Exemple #22
0
        internal static Digit Mul(Digits a, Digit mult, Digits b, int n)
        {
            Digit carry = 0;

            for (int i = 0; i != n; i++)
            {
                UInt64 dtemp = (UInt64)mult * a[i] + carry;
                b[i]  = Digit2.Lo(dtemp);
                carry = Digit2.Hi(dtemp);
            }
            return(carry);
        }
Exemple #23
0
        internal static uint Sub(Digits a, Digits b, Digits c, int n)
        {
            uint borrow = 0;

            for (int i = 0; i != n; i++)
            {
                Digit ai = a[i], bi = b[i], sum = unchecked (ai - bi - borrow);
                c[i]   = sum;
                borrow = (ai ^ (ai ^ bi | ai ^ sum)) >> Digit.BitN - 1;
            }
            return(borrow);
        }
Exemple #24
0
 DigitsToBytes(Digits digits, byte[] bytes, int byteI, int bitN)
 {
     for (int i = 0; i != (bitN + (Digit.BitN - 1)) / Digit.BitN; i++)
     {
         Digit dvalue    = digits[i];
         int   byteNLeft = (bitN + 7) / 8 - 4 * i;
         for (int j = 0; j != (byteNLeft > 4 ? 4 : byteNLeft); j++)
         {
             bytes[byteI + byteNLeft - 1 - j] = (byte)(dvalue & 0xff);
             dvalue >>= 8;
         }
     }
 }
Exemple #25
0
        void _BucketMul(UInt32 ibucket, Digits mult, Temps2000 temps)
        {
            Digits bloc = temps._bucket[ibucket];

            if (temps._bucketBusy[ibucket])
            {
                _Mul(bloc, mult, bloc);
            }
            else
            {
                temps._bucketBusy[ibucket] = true;
                bloc._Set(mult, _digitN);
            }
        }
Exemple #26
0
        void _MulFromRight(Digits a, Digits b, Digits c)
        {
            Digit minv = _rightRecip
            , minva0 = unchecked (minv * a[0])
            , mul1 = b[0]
            , mul2 = unchecked (minva0 * mul1)
            , carry1 = Digit2.Hi((UInt64)mul1 * a[0])
            , carry2 = Digit2.Hi((UInt64)mul2 * _mod[0]);
            UInt64 prod1, prod2;

            Debug.Assert(unchecked (mul1 * a[0]) == unchecked (mul2 * _mod[0])
                         , "internal error");
            Digits temp1 = new Digits(_digitN), temp2 = new Digits(_digitN);

            for (int i = 1; i != _digitN; i++)
            {
                prod1        = (UInt64)mul1 * a[i] + carry1;
                prod2        = (UInt64)mul2 * _mod[i] + carry2;
                temp1[i - 1] = Digit2.Lo(prod1);
                temp2[i - 1] = Digit2.Lo(prod2);
                carry1       = Digit2.Hi(prod1);
                carry2       = Digit2.Hi(prod2);
            }
            temp1[_digitN - 1] = carry1;
            temp2[_digitN - 1] = carry2;
            for (int j = 1; j != _digitN; j++)
            {
                mul1  = b[j];
                mul2  = unchecked (minva0 * mul1 + minv * (temp1[0] - temp2[0]));
                prod1 = (UInt64)mul1 * a[0] + temp1[0];
                prod2 = (UInt64)mul2 * _mod[0] + temp2[0];
                Debug.Assert(Digit2.Lo(prod1) == Digit2.Lo(prod2)
                             , "internal error");
                carry1 = Digit2.Hi(prod1);
                carry2 = Digit2.Hi(prod2);
                for (int i = 1; i != _digitN; i++)
                {
                    prod1        = (UInt64)mul1 * a[i] + temp1[i] + carry1;
                    prod2        = (UInt64)mul2 * _mod[i] + temp2[i] + carry2;
                    temp1[i - 1] = Digit2.Lo(prod1);
                    temp2[i - 1] = Digit2.Lo(prod2);
                    carry1       = Digit2.Hi(prod1);
                    carry2       = Digit2.Hi(prod2);
                }
                temp1[_digitN - 1] = carry1;
                temp2[_digitN - 1] = carry2;
            }
            Modular.Sub(temp1, temp2, c, _mod, _digitN);
        }
Exemple #27
0
        DivPrecondition(Digits denom, int denomN, Reciprocal recip)
        {
            if (denom == null)
            {
                throw new ArgumentNullException();
            }
            if (denomN == 0 || denom[denomN - 1] == 0)
            {
                throw new ArgumentException();
            }
            int   recipBitShift = Digit.BitN - Digit.SigBitN(denom[denomN - 1]);
            Digit dlead2        = denom[denomN - 1]
            , dlead1            = denomN >= 2 ? denom[denomN - 2] : 0
            , dlead0            = denomN >= 3 ? denom[denomN - 3] : 0
            , dShiftHi          = dlead2 << recipBitShift
                         | dlead1 >> 1 >> Digit.BitN - 1 - recipBitShift
                , dShiftLo = dlead1 << recipBitShift
                         | dlead0 >> 1 >> Digit.BitN - 1 - recipBitShift;
            Digit recipMpy, r;

            Digit2.Div((UInt64)(Digit.MaxValue - dShiftHi) << Digit.BitN
                       | Digit.MaxValue - dShiftLo
                       , dShiftHi
                       , out recipMpy
                       , out r);
            if (Digit2.Hi((UInt64)recipMpy * dShiftLo) > r)
            {
                recipMpy -= 1;
            }
            r = (Digit.MaxValue >> recipBitShift) - denom[denomN - 1];
            for (int id = denomN; id-- != 0 && r < recipMpy;)
            {
                UInt64 test1 = (UInt64)r << Digit.BitN
                               | Digit.MaxValue - (id > 0 ? denom[id - 1] : 0)
                    , test2 = (UInt64)recipMpy * denom[id];
                if (test2 > test1)
                {
                    recipMpy -= 1; break;
                }
                test1 = test1 - test2;
                r     = Digit2.Lo(test1);
                if (Digit2.Hi(test1) != 0)
                {
                    break;
                }
            }
            recip._shiftBitN  = recipBitShift;
            recip._multiplier = recipMpy;
        }
Exemple #28
0
        NonZeroRandom(Digits mod, Digits arr, int n, Random generator)
        {
            if (Digits.Compare(mod, 1U, n) <= 0)
            {
                throw new ArgumentException();
            }
            int ntry = 0;

            do
            {
                ntry++;
                Debug.Assert(ntry <= 100, "too many iterations");
                Random(mod, arr, n, generator);
            } while (Digits.SigDigitN(arr, n) == 0);
        }
Exemple #29
0
        Decumulate(Digits a, Digit mult, Digits b, int n)
        {
            Digit borrow = 0;

            for (int i = 0; i != n; i++)
            {
                UInt64 dtemp;
                unchecked {
                    dtemp = (UInt64)b[i] - borrow - (UInt64)mult * a[i];
                }
                b[i] = Digit2.Lo(dtemp);
                unchecked { borrow = 0 - Digit2.Hi(dtemp); }
            }
            return(borrow);
        }
Exemple #30
0
        internal static void Neg(Digits a, Digits b, Digits mod, int n)
        {
            Digit allZero = 0;

            for (int i = 0; i != n; i++)
            {
                allZero |= a[i]; b[i] = a[i];
            }
            if (allZero != 0)
            {
                if (Digits.Sub(mod, b, b, n) != 0)
                {
                    throw new ArgumentException();
                }
            }
        }