/*------------------------------------------------------------------*/ static void poly_xpow(poly_t res, u_int32_t shift, u_int32_t n, poly_t mod, u_int32_t p) { /* Modular exponentiation of polynomials with finite-field coefficients, i.e. res = (x-shift) ^ n % mod with all polynomial coefficients reduced modulo p. n is assumed nonzero */ poly_t modnorm; u_int32_t msw; u_int32_t i, d; u_int32_t buf[2*NUM_POLY_COEFFS] = {0}; u_int64_t psq; poly_make_monic(modnorm, mod, p); d = modnorm->degree; OP1(0) = shift; OP1(1) = 1; for (i = 0; i <= d; i++) MOD(i) = modnorm->coef[i]; msw = 0x80000000; while (!(n & msw)) { msw >>= 1; } msw >>= 1; psq = (u_int64_t)p * (u_int64_t)p; /* use left-to-right binary exponentiation, not the right-to-left variety. For factor base generation the base always has degree less than modnorm, and the left-to-right method preserves that, saving time during modular multiplication */ while (msw) { poly_expo_square(buf, d, p, psq); if (n & msw) { poly_expo_modmul(buf, d, shift, p, psq); } msw >>= 1; } res->degree = d; for (i = 0; i <= d; i++) res->coef[i] = OP1(i); poly_fix_degree(res); }
int read_opcode(void) { uint16_t inst; if (cpu.PC == MEM_SIZE) return EOF; if (cpu.PC == rom_size) return END_ROM; inst = (mem[cpu.PC]<<8) | mem[cpu.PC+1]; op1 = OP1(inst); op2 = OP2(inst); op3 = OP3(inst); op4 = OP4(inst); cpu.PC += 2; return cpu.PC; }
/*------------------------------------------------------------------*/ static void poly_expo_square(u_int32_t *buf, u_int32_t dm, u_int32_t p, u_int64_t psq) { /* OP1 = OP1 * OP1 mod MOD OP1 and MOD are both of degree dm */ u_int32_t i; u_int32_t q; u_int64_t acc[NUM_POLY_COEFFS]; for (i = 0; i < dm; i++) acc[i] = (u_int64_t) (OP1(i)) * (u_int64_t)(OP1(dm-1)); for (i = dm - 2; (int32_t)i >= 0; i--) { q = mp_mod64(acc[dm-1], p); switch(dm-1) { case 7: acc[7] = sqr_mac(OP1(7), OP1(i), acc[6], q, MOD(7), psq); case 6: acc[6] = sqr_mac(OP1(6), OP1(i), acc[5], q, MOD(6), psq); case 5: acc[5] = sqr_mac(OP1(5), OP1(i), acc[4], q, MOD(5), psq); case 4: acc[4] = sqr_mac(OP1(4), OP1(i), acc[3], q, MOD(4), psq); case 3: acc[3] = sqr_mac(OP1(3), OP1(i), acc[2], q, MOD(3), psq); case 2: acc[2] = sqr_mac(OP1(2), OP1(i), acc[1], q, MOD(2), psq); case 1: acc[1] = sqr_mac(OP1(1), OP1(i), acc[0], q, MOD(1), psq); case 0: acc[0] = sqr_mac0(OP1(0), OP1(i), q, MOD(0), psq); break; } } for (i = 0; i < dm; i++) OP1(i) = mp_mod64(acc[i], p); }
/*------------------------------------------------------------------*/ static void poly_expo_modmul(u_int32_t *buf, u_int32_t dm, u_int32_t shift, u_int32_t p, u_int64_t psq) { /* OP1 = OP1 * (x - shift) mod MOD OP1 and MOD are of degree dm */ u_int32_t q; u_int32_t zero = 0; q = OP1(dm-1); switch(dm-1) { case 7: OP1(7) = mul_mac(OP1(7), shift, OP1(6), q, MOD(7), p, psq); case 6: OP1(6) = mul_mac(OP1(6), shift, OP1(5), q, MOD(6), p, psq); case 5: OP1(5) = mul_mac(OP1(5), shift, OP1(4), q, MOD(5), p, psq); case 4: OP1(4) = mul_mac(OP1(4), shift, OP1(3), q, MOD(4), p, psq); case 3: OP1(3) = mul_mac(OP1(3), shift, OP1(2), q, MOD(3), p, psq); case 2: OP1(2) = mul_mac(OP1(2), shift, OP1(1), q, MOD(2), p, psq); case 1: OP1(1) = mul_mac(OP1(1), shift, OP1(0), q, MOD(1), p, psq); case 0: OP1(0) = mul_mac(OP1(0), shift, zero, q, MOD(0), p, psq); break; } }