예제 #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
        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);
        }