// xR mod m public BigInteger convert(BigInteger x) { if (x == null) { return null; } BigInteger r = new BigInteger(); x.abs().dlShiftTo(this.m.t, r); r.divRemTo(this.m, null, r); if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) { this.m.subTo(r, r); } return r; }
// (protected) r = this * a, r != this,a (HAC 14.12) // "this" should be the larger one if appropriate. public void multiplyTo(BigInteger a, BigInteger r) { if (a == null) { return; } if (r == null) { r = new BigInteger(); } BigInteger x = this.abs(), y = a.abs(); int i = x.t; r.t = i + y.t; while (--i >= 0) { r.SetData(i, 0); } for (i = 0; i < y.t; ++i) { r.datas[i + x.t] = x.am(0, y.datas[i], r.datas, i, 0, x.t); } r.s = 0; r.clamp(); if (this.s != a.s) { ZERO.subTo(r, r); } }
// (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); } }