예제 #1
0
 // x = x/R mod m (HAC 14.32)
 public void reduce(BigInteger x)
 {
     if (x == null)
     {
         return;
     }
     while (x.t <= this.mt2)
     {
         // pad x so am has enough room later
         x.SetData(x.t++, 0);
     }
     for (int i = 0; i < this.m.t; ++i)
     {
         // faster way of calculating u0 = x[i]*mp mod DV
         int j = x.datas[i] & 0x7fff;
         int u0 = (j * this.mpl + (((j * this.mph + (x.datas[i] >> 15) * this.mpl) & this.um) << 15))
             & x.DM;
         // use am to combine the multiply-shift-add into one call
         j = i + this.m.t;
         x.datas[j] += this.m.am(0, u0, x.datas, i, 0, this.m.t);
         // propagate carry
         while (x.datas[j] >= x.DV)
         {
             x.datas[j] -= x.DV;
             x.datas[++j]++;
         }
     }
     x.clamp();
     x.drShiftTo(this.m.t, x);
     if (x.compareTo(this.m) >= 0)
     {
         x.subTo(this.m, x);
     }
 }
예제 #2
0
        // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
        // r != q, this != m. q or r may be null.
        public void divRemTo(BigInteger m, BigInteger q, BigInteger r)
        {
            if (m == null)
            {
                return;
            }
            if (q == null)
            {
                q = new BigInteger();
            }
            if (r == null)
            {
                r = new BigInteger();
            }

            BigInteger pm = m.abs();
            if (pm.t <= 0)
            {
                return;
            }
            BigInteger pt = this.abs();
            if (pt.t < pm.t)
            {
                if (q != null)
                {
                    q.fromInt(0);
                }
                if (r != null)
                {
                    this.copyTo(r);
                }
                return;
            }

            BigInteger y = new BigInteger();
            int ts = this.s, ms = m.s;
            int nsh = this.DB - nbits(pm.datas[pm.t - 1]); // normalize modulus
            if (nsh > 0)
            {
                pm.lShiftTo(nsh, y);
                pt.lShiftTo(nsh, r);
            }
            else
            {
                pm.copyTo(y);
                pt.copyTo(r);
            }
            int ys = y.t;
            int y0 = y.datas[ys - 1];
            if (y0 == 0)
            {
                return;
            }
            long yt = (long)y0 * (1 << this.F1) + ((ys > 1) ? y.datas[ys - 2] >> this.F2 : 0);
            double d1 = (double)this.FV / yt;
            double d2 = (double)((long)1 << this.F1) / yt;
            int e = 1 << this.F2;
            int i = r.t, j = i - ys;
            BigInteger t = (q == null) ? new BigInteger() : q;
            y.dlShiftTo(j, t);
            if (r.compareTo(t) >= 0)
            {
                r.SetData(r.t++, 1);
                r.subTo(t, r);
            }
            ONE.dlShiftTo(ys, t);
            t.subTo(y, y); // "negative" y so we can replace sub with am later
            while (y.t < ys)
            {
                y.SetData(y.t++, 0);
            }
            while (--j >= 0)
            {
                // Estimate quotient digit
                int qd = (r.datas[--i] == y0) ? this.DM
                    : Convert.ToInt32(Math.Floor((double)r.datas[i] * d1 + (double)(r.datas[i - 1] + e) * d2));
                int tmp = y.am(0, qd, r.datas, j, 0, ys);
                if ((r.datas[i] += tmp) < qd)
                {
                    // Try it out
                    y.dlShiftTo(j, t);
                    r.subTo(t, r);
                    while (r.datas[i] < --qd)
                    {
                        r.subTo(t, r);
                    }
                }
            }
            if (q != null)
            {
                r.drShiftTo(ys, q);
                if (ts != ms)
                {
                    ZERO.subTo(q, q);
                }
            }
            r.t = ys;
            r.clamp();
            if (nsh > 0)
            {
                r.rShiftTo(nsh, r); // Denormalize remainder
            }
            if (ts < 0)
            {
                ZERO.subTo(r, r);
            }
        }