Пример #1
0
            /* bi_residue() is technically the same as bi_mod(), but it uses the
             * appropriate reduction technique (which is bi_mod() when doing classical
             * reduction). */
            // #define bi_residue(A, B)         bi_mod(A, B)

            internal bigint bi_square(bigint B)
            {
                return(this.bi_multiply(B.bi_copy(), B));
            }
Пример #2
0
            /* @brief Does both division and modulo calculations.
             * Used extensively when doing classical reduction.
             * @param ctx [in]  The bigint session context.
             * @param u [in]    A bigint which is the numerator.
             * @param v [in]    Either the denominator or the modulus depending on the mode.
             * @param is_mod [n] Determines if this is a normal division (0) or a reduction
             * (1).
             * @return  The result of the division/reduction. */
            internal bigint bi_divide(bigint u, bigint v, bool is_mod)
            {
                int  n           = v.size;
                int  m           = u.size - n;
                int  j           = 0;
                int  orig_u_size = u.size;
                byte mod_offset  = this.mod_offset;
                uint d;
                uint q_dash;

                /* if doing reduction and we are < mod, then return mod */
                if (is_mod && bi_compare(v, u) > 0)
                {
                    bi_free(v);
                    return(u);
                }
                bigint quotient = this.Allocate((short)(m + 1));
                bigint tmp_u    = this.Allocate((short)(n + 1));

                v = v.trim();        /* make sure we have no leading 0's */
                d = (uint)((ulong)COMP_RADIX / ((ulong)v.V1 + 1));
                /* clear things to start with */
                quotient.comps.Zeroize();
                /* normalise */
                if (d > 1)
                {
                    u = bi_int_multiply(u, d);
                    if (is_mod)
                    {
                        v = bi_normalised_mod[mod_offset];
                    }
                    else
                    {
                        v = bi_int_multiply(v, d);
                    }
                }
                if (orig_u_size == u.size)   /* new digit position u0 */
                {
                    u.more_comps((short)(orig_u_size + 1));
                }

                do
                {
                    /* get a temporary short version of u */
                    Buffer.BlockCopy(u.comps, u.size - n - 1 - j, tmp_u.comps,
                                     0, sizeof(uint) * (n + 1));
                    /* calculate q' */
                    if (tmp_u.U(0) == v.V1)
                    {
                        q_dash = (uint)(COMP_RADIX - 1);
                    }
                    else
                    {
                        q_dash = (uint)(((ulong)tmp_u.U(0) * COMP_RADIX + tmp_u.U(1)) / v.V1);

                        if ((v.size > 1) && (0 != v.V2))
                        {
                            /* we are implementing the following:
                             * if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) -
                             *      q_dash*V1)*COMP_RADIX) + U(2))) ... */
                            uint inner = (uint)((ulong)COMP_RADIX * tmp_u.U(0) + tmp_u.U(1) - (ulong)q_dash * v.V1);
                            if ((ulong)v.V2 * q_dash > (ulong)inner * COMP_RADIX + tmp_u.U(2))
                            {
                                q_dash--;
                            }
                        }
                    }

                    /* multiply and subtract */
                    if (0 != q_dash)
                    {
                        bool is_negative;
                        tmp_u = bi_subtract(tmp_u, bi_int_multiply(v.bi_copy(), q_dash), out is_negative);
                        tmp_u.more_comps((short)(n + 1));
                        quotient.SetQ(j, q_dash);

                        /* add back */
                        if (is_negative)
                        {
                            quotient.SetQ(j, quotient.GetQ(j) - 1);
                            tmp_u = bi_add(tmp_u, v.bi_copy());
                            /* lop off the carry */
                            tmp_u.size--;
                            v.size--;
                        }
                    }
                    else
                    {
                        quotient.SetQ(j, 0);
                    }
                    /* copy back to u */
                    Buffer.BlockCopy(tmp_u.comps, 0, u.comps, u.size - n - 1 - j,
                                     sizeof(uint) * (n + 1));
                } while (++j <= m);
                bi_free(tmp_u);
                bi_free(v);

                if (is_mod)   /* get the remainder */
                {
                    bi_free(quotient);
                    return(bi_int_divide(u.trim(), d));
                }
                else   /* get the quotient */
                {
                    bi_free(u);
                    return(quotient.trim());
                }
            }