/* a=1/a mod 2^256. This is very fast! */ public virtual void InvMod2m() { int i; BIG U = new BIG(0); BIG b = new BIG(0); BIG c = new BIG(0); U.Inc(InvMod256(LastBits(8))); for (i = 8; i < BIGBITS; i <<= 1) { U.Norm(); b.Copy(this); b.Mod2m(i); BIG t1 = SMul(U, b); t1.Shr(i); c.Copy(this); c.Shr(i); c.Mod2m(i); BIG t2 = SMul(U, c); t2.Mod2m(i); t1.Add(t2); t1.Norm(); b = SMul(t1, U); t1.Copy(b); t1.Mod2m(i); t2.One(); t2.Shl(i); t1.RSub(t2); t1.Norm(); t1.Shl(i); U.Add(t1); } U.Mod2m(BIGBITS); Copy(U); Norm(); }
/* divide this by m */ public virtual void Div(BIG m1) { int d, k = 0; Norm(); BIG e = new BIG(1); BIG m = new BIG(m1); BIG b = new BIG(this); BIG r = new BIG(0); Zero(); while (Comp(b, m) >= 0) { e.FShl(1); m.FShl(1); k++; } while (k > 0) { m.FShr(1); e.FShr(1); r.Copy(b); r.Sub(m); r.Norm(); d = (int)(1 - ((r.w[NLEN - 1] >> (CHUNK - 1)) & 1)); b.CMove(r, d); r.Copy(this); r.Add(e); r.Norm(); CMove(r, d); k--; } }
/* Return e.this+f.Q */ public ECP Mul2(BIG e, ECP Q, BIG f) { BIG te = new BIG(); BIG tf = new BIG(); BIG mt = new BIG(); ECP S = new ECP(); ECP T = new ECP(); ECP C = new ECP(); ECP[] W = new ECP[8]; sbyte[] w = new sbyte[1 + (BIG.NLEN * BIG.BASEBITS + 1) / 2]; int i, s, ns, nb; sbyte a, b; //affine(); //Q.affine(); te.Copy(e); tf.Copy(f); // precompute table W[1] = new ECP(); W[1].Copy(this); W[1].Sub(Q); W[2] = new ECP(); W[2].Copy(this); W[2].Add(Q); S.Copy(Q); S.Dbl(); W[0] = new ECP(); W[0].Copy(W[1]); W[0].Sub(S); W[3] = new ECP(); W[3].Copy(W[2]); W[3].Add(S); T.Copy(this); T.Dbl(); W[5] = new ECP(); W[5].Copy(W[1]); W[5].Add(T); W[6] = new ECP(); W[6].Copy(W[2]); W[6].Add(T); W[4] = new ECP(); W[4].Copy(W[5]); W[4].Sub(S); W[7] = new ECP(); W[7].Copy(W[6]); W[7].Add(S); // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction s = te.Parity(); te.Inc(1); te.Norm(); ns = te.Parity(); mt.Copy(te); mt.Inc(1); mt.Norm(); te.CMove(mt, s); T.CMove(this, ns); C.Copy(T); s = tf.Parity(); tf.Inc(1); tf.Norm(); ns = tf.Parity(); mt.Copy(tf); mt.Inc(1); mt.Norm(); tf.CMove(mt, s); S.CMove(Q, ns); C.Add(S); mt.Copy(te); mt.Add(tf); mt.Norm(); nb = 1 + (mt.NBits() + 1) / 2; // convert exponent to signed 2-bit window for (i = 0; i < nb; i++) { a = (sbyte)(te.LastBits(3) - 4); te.Dec(a); te.Norm(); te.FShr(2); b = (sbyte)(tf.LastBits(3) - 4); tf.Dec(b); tf.Norm(); tf.FShr(2); w[i] = (sbyte)(4 * a + b); } w[nb] = (sbyte)(4 * te.LastBits(3) + tf.LastBits(3)); S.Copy(W[(w[nb] - 1) / 2]); for (i = nb - 1; i >= 0; i--) { T.Select(W, w[i]); S.Dbl(); S.Dbl(); S.Add(T); } S.Sub(C); // apply correction S.Affine(); return(S); }
/* this=1/this mod p. Binary method */ public virtual void InvModp(BIG p) { Mod(p); BIG u = new BIG(this); BIG v = new BIG(p); BIG x1 = new BIG(1); BIG x2 = new BIG(0); BIG t = new BIG(0); BIG one = new BIG(1); while (Comp(u, one) != 0 && Comp(v, one) != 0) { while (u.Parity() == 0) { u.FShr(1); if (x1.Parity() != 0) { x1.Add(p); x1.Norm(); } x1.FShr(1); } while (v.Parity() == 0) { v.FShr(1); if (x2.Parity() != 0) { x2.Add(p); x2.Norm(); } x2.FShr(1); } if (Comp(u, v) >= 0) { u.Sub(v); u.Norm(); if (Comp(x1, x2) >= 0) { x1.Sub(x2); } else { t.Copy(p); t.Sub(x2); x1.Add(t); } x1.Norm(); } else { v.Sub(u); v.Norm(); if (Comp(x2, x1) >= 0) { x2.Sub(x1); } else { t.Copy(p); t.Sub(x1); x2.Add(t); } x2.Norm(); } } if (Comp(u, one) == 0) { Copy(x1); } else { Copy(x2); } }