private void karsqr(int vp, FF x, int xp, FF t, int tp, int n) { int nd2; if (n == 1) { DBIG d = BIG.sqr(x.v[xp]); v[vp + 1].copy(d.Split(8 * ROM.MODBYTES)); v[vp].copy(d); return; } nd2 = n / 2; karsqr(vp, x, xp, t, tp + n, nd2); karsqr(vp + n, x, xp + nd2, t, tp + n, nd2); t.karmul(tp, x, xp, x, xp + nd2, t, tp + n, nd2); rinc(vp + nd2, t, tp, n); rinc(vp + nd2, t, tp, n); rnorm(vp + nd2, n); }
/* z=x*y, t is workspace */ private void karmul(int vp, FF x, int xp, FF y, int yp, FF t, int tp, int n) { int nd2; if (n == 1) { DBIG d = BIG.mul(x.v[xp], y.v[yp]); v[vp + 1] = d.Split(8 * ROM.MODBYTES); v[vp].copy(d); return; } nd2 = n / 2; radd(vp, x, xp, x, xp + nd2, nd2); //rnorm(vp,nd2); radd(vp + nd2, y, yp, y, yp + nd2, nd2); //rnorm(vp+nd2,nd2); t.karmul(tp, this, vp, this, vp + nd2, t, tp + n, nd2); karmul(vp, x, xp, y, yp, t, tp + n, nd2); karmul(vp + n, x, xp + nd2, y, yp + nd2, t, tp + n, nd2); t.rdec(tp, this, vp, n); t.rdec(tp, this, vp + n, n); rinc(vp + nd2, t, tp, n); rnorm(vp, 2 * n); }
/* reduce a DBIG to a BIG using the appropriate form of the modulus */ public static BIG mod(DBIG d) { BIG b; if (ROM.MODTYPE == ROM.PSEUDO_MERSENNE) { long v, tw; BIG t = d.Split(ROM.MODBITS); b = new BIG(d); unchecked { v = t.pmul((int)ROM.MConst); } tw = t.w[ROM.NLEN - 1]; t.w[ROM.NLEN - 1] &= ROM.TMASK; t.w[0] += (ROM.MConst * ((tw >> ROM.TBITS) + (v << (ROM.BASEBITS - ROM.TBITS)))); b.add(t); b.norm(); } if (ROM.MODTYPE == ROM.MONTGOMERY_FRIENDLY) { for (int i = 0; i < ROM.NLEN; i++) { d.w[ROM.NLEN + i] += d.muladd(d.w[i], ROM.MConst - 1, d.w[i], ROM.NLEN + i - 1); } b = new BIG(0); for (int i = 0; i < ROM.NLEN; i++) { b.w[i] = d.w[ROM.NLEN + i]; } b.norm(); } if (ROM.MODTYPE == ROM.NOT_SPECIAL) { BIG md = new BIG(ROM.Modulus); long m, carry; for (int i = 0; i < ROM.NLEN; i++) { if (ROM.MConst == -1) { m = (-d.w[i]) & ROM.MASK; } else { if (ROM.MConst == 1) { m = d.w[i]; } else { m = (ROM.MConst * d.w[i]) & ROM.MASK; } } carry = 0; for (int j = 0; j < ROM.NLEN; j++) { carry = d.muladd(m, md.w[j], carry, i + j); } d.w[ROM.NLEN + i] += carry; } b = new BIG(0); for (int i = 0; i < ROM.NLEN; i++) { b.w[i] = d.w[ROM.NLEN + i]; } b.norm(); } return(b); }
/// <summary> ///************** 64-bit specific *********************** </summary> /* reduce a DBIG to a BIG using the appropriate form of the modulus */ public static BIG Mod(DBIG d) { if (MODTYPE == PSEUDO_MERSENNE) { BIG b; long v, tw; BIG t = d.Split(MODBITS); b = new BIG(d); v = t.PMul(unchecked ((int)ROM.MConst)); t.Add(b); t.Norm(); tw = t.w[BIG.NLEN - 1]; t.w[BIG.NLEN - 1] &= FP.TMASK; t.w[0] += (ROM.MConst * ((tw >> TBITS) + (v << (BIG.BASEBITS - TBITS)))); t.Norm(); return(t); } if (FP.MODTYPE == MONTGOMERY_FRIENDLY) { BIG b; long[] cr = new long[2]; for (int i = 0; i < BIG.NLEN; i++) { cr = BIG.MulAdd(d.w[i], ROM.MConst - 1, d.w[i], d.w[BIG.NLEN + i - 1]); d.w[BIG.NLEN + i] += cr[0]; d.w[BIG.NLEN + i - 1] = cr[1]; } b = new BIG(0); for (int i = 0; i < BIG.NLEN; i++) { b.w[i] = d.w[BIG.NLEN + i]; } b.Norm(); return(b); } if (MODTYPE == GENERALISED_MERSENNE) { // GoldiLocks Only BIG b; BIG t = d.Split(MODBITS); b = new BIG(d); b.Add(t); DBIG dd = new DBIG(t); dd.Shl(MODBITS / 2); BIG tt = dd.Split(MODBITS); BIG lo = new BIG(dd); b.Add(tt); b.Add(lo); b.Norm(); tt.Shl(MODBITS / 2); b.Add(tt); long carry = b.w[BIG.NLEN - 1] >> TBITS; b.w[BIG.NLEN - 1] &= FP.TMASK; b.w[0] += carry; b.w[224 / BIG.BASEBITS] += carry << (224 % BIG.BASEBITS); b.Norm(); return(b); } if (MODTYPE == NOT_SPECIAL) { return(BIG.Monty(new BIG(ROM.Modulus), ROM.MConst, d)); } return(new BIG(0)); }