static inline gf8 do_op(char op, gf8 l, gf8 r) { if (op == '+' || op == '-') return add(l,r); if (op == '*') return multiply(l,r); if (op == '/') return multiply(l,inverse(r)); if (op == '^') return pol_pow(l,r); if (op == 'o') return smallest_nth_primitive_root_of_unity(l); if (op == 's') { uint i = 0; for (i = 0;i < r;++i) { printf("%u ",pol_pow(l,i)); } return pol_pow(l,i); } printf("unknown operator %c\n",op); exit(-1); }
void efftinv(uint P, uint Q, byte * f, byte *res ) { byte oN = smallest_nth_primitive_root_of_unity(P*Q); byte oQ = pol_pow(oN,P); uint pc = 0, qc = 0, k = 0; byte Qroot = 1; byte Nroot = 1; byte rowFFT[256][256] = {{0}}; // P x Q byte rootK = 0; oN = inverse(oN); oQ = inverse(oQ); for(qc = 0;qc < Q;++qc) { for(pc = 0;pc < P;++pc) { rootK = 1; for(k = 0;k < Q;++k) { // rowFFT[pc,qc] = SUM_{k=0}^{Q-1} byte term = 0; // A[k,pc] each term: f_{pc*Q+k} term = multiply(f[k*P+pc],rootK); rowFFT[pc][qc] = add(rowFFT[pc][qc],term); rootK = multiply(rootK, Qroot); } } Qroot = multiply(Qroot,oQ); } for(pc = 0;pc < P;++pc) { for(qc = 0;qc < Q;++qc) { rootK = 1; for(k = 0;k < P;++k) { byte term = 0; uint res_idx = pc*Q+qc; term = multiply(rowFFT[k][qc],rootK); res[res_idx] = add(res[res_idx],term); rootK = multiply(rootK, Nroot); } Nroot = multiply(Nroot,oN); } } }