示例#1
0
文件: MPN.cs 项目: tspring/ioke
        /**
         * Multiply x[0:xlen-1] and y[0:ylen-1], and
         * write the result to dest[0:xlen+ylen-1].
         * The destination has to have space for xlen+ylen words,
         * even if the result might be one limb smaller.
         * This function requires that xlen >= ylen.
         * The destination must be distinct from either input operands.
         * All operands are unsigned.
         * This function is basically the same gmp's mpn_mul. */

        public static void mul(int[] dest,
                               int[] x, int xlen,
                               int[] y, int ylen)
        {
            dest[xlen] = MPN.mul_1(dest, x, xlen, y[0]);

            for (int i = 1; i < ylen; i++)
            {
                long yword = (long)y[i] & 0xffffffffL;
                long carry = 0;
                for (int j = 0; j < xlen; j++)
                {
                    carry += ((long)x[j] & 0xffffffffL) * yword
                             + ((long)dest[i + j] & 0xffffffffL);
                    dest[i + j] = (int)carry;
                    carry       = (long)(((ulong)carry) >> 32);
                }
                dest[i + xlen] = (int)carry;
            }
        }
示例#2
0
文件: MPN.cs 项目: tspring/ioke
        /** Calculate Greatest Common Divisior of x[0:len-1] and y[0:len-1].
         * Assumes both arguments are non-zero.
         * Leaves result in x, and returns len of result.
         * Also destroys y (actually sets it to a copy of the result). */

        public static int gcd(int[] x, int[] y, int len)
        {
            int i, word;

            // Find sh such that both x and y are divisible by 2**sh.
            for (i = 0; ; i++)
            {
                word = x[i] | y[i];
                if (word != 0)
                {
                    // Must terminate, since x and y are non-zero.
                    break;
                }
            }
            int initShiftWords = i;
            int initShiftBits  = findLowestBit(word);

            // Logically: sh = initShiftWords * 32 + initShiftBits

            // Temporarily devide both x and y by 2**sh.
            len -= initShiftWords;
            MPN.rshift0(x, x, initShiftWords, len, initShiftBits);
            MPN.rshift0(y, y, initShiftWords, len, initShiftBits);
            int[] odd_arg;   /* One of x or y which is odd. */
            int[] other_arg; /* The other one can be even or odd. */
            if ((x[0] & 1) != 0)
            {
                odd_arg   = x;
                other_arg = y;
            }
            else
            {
                odd_arg   = y;
                other_arg = x;
            }

            for (;;)
            {
                // Shift other_arg until it is odd; this doesn't
                // affect the gcd, since we divide by 2**k, which does not
                // divide odd_arg.
                for (i = 0; other_arg[i] == 0;)
                {
                    i++;
                }
                if (i > 0)
                {
                    int j;
                    for (j = 0; j < len - i; j++)
                    {
                        other_arg[j] = other_arg[j + i];
                    }
                    for ( ; j < len; j++)
                    {
                        other_arg[j] = 0;
                    }
                }
                i = findLowestBit(other_arg[0]);
                if (i > 0)
                {
                    MPN.rshift(other_arg, other_arg, 0, len, i);
                }

                // Now both odd_arg and other_arg are odd.

                // Subtract the smaller from the larger.
                // This does not change the result, since gcd(a-b,b)==gcd(a,b).
                i = MPN.cmp(odd_arg, other_arg, len);
                if (i == 0)
                {
                    break;
                }
                if (i > 0)
                {         // odd_arg > other_arg
                    MPN.sub_n(odd_arg, odd_arg, other_arg, len);
                    // Now odd_arg is even, so swap with other_arg;
                    int[] tmp = odd_arg; odd_arg = other_arg; other_arg = tmp;
                }
                else
                {         // other_arg > odd_arg
                    MPN.sub_n(other_arg, other_arg, odd_arg, len);
                }
                while (odd_arg[len - 1] == 0 && other_arg[len - 1] == 0)
                {
                    len--;
                }
            }
            if (initShiftWords + initShiftBits > 0)
            {
                if (initShiftBits > 0)
                {
                    int sh_out = MPN.lshift(x, initShiftWords, x, len, initShiftBits);
                    if (sh_out != 0)
                    {
                        x[(len++) + initShiftWords] = sh_out;
                    }
                }
                else
                {
                    for (i = len; --i >= 0;)
                    {
                        x[i + initShiftWords] = x[i];
                    }
                }
                for (i = initShiftWords; --i >= 0;)
                {
                    x[i] = 0;
                }
                len += initShiftWords;
            }
            return(len);
        }
示例#3
0
文件: MPN.cs 项目: tspring/ioke
        public static int set_str(int[] dest, byte[] str, int str_len, int _base)
        {
            int size = 0;

            if ((_base & (_base - 1)) == 0)
            {
                // The base is a power of 2.  Read the input string from
                // least to most significant character/digit.  */

                int next_bitpos      = 0;
                int bits_per_indigit = 0;
                for (int i = _base; (i >>= 1) != 0;)
                {
                    bits_per_indigit++;
                }
                int res_digit = 0;

                for (int i = str_len; --i >= 0;)
                {
                    int inp_digit = str[i];
                    res_digit   |= inp_digit << next_bitpos;
                    next_bitpos += bits_per_indigit;
                    if (next_bitpos >= 32)
                    {
                        dest[size++] = res_digit;
                        next_bitpos -= 32;
                        res_digit    = inp_digit >> (bits_per_indigit - next_bitpos);
                    }
                }

                if (res_digit != 0)
                {
                    dest[size++] = res_digit;
                }
            }
            else
            {
                // General case.  The base is not a power of 2.
                int indigits_per_limb = MPN.chars_per_word(_base);
                int str_pos           = 0;

                while (str_pos < str_len)
                {
                    int chunk = str_len - str_pos;
                    if (chunk > indigits_per_limb)
                    {
                        chunk = indigits_per_limb;
                    }
                    int res_digit = str[str_pos++];
                    int big_base  = _base;

                    while (--chunk > 0)
                    {
                        res_digit = res_digit * _base + str[str_pos++];
                        big_base *= _base;
                    }

                    int cy_limb;
                    if (size == 0)
                    {
                        cy_limb = res_digit;
                    }
                    else
                    {
                        cy_limb  = MPN.mul_1(dest, dest, size, big_base);
                        cy_limb += MPN.add_1(dest, dest, size, res_digit);
                    }
                    if (cy_limb != 0)
                    {
                        dest[size++] = cy_limb;
                    }
                }
            }
            return(size);
        }