def test_ntt(): # Compare the naive NTT (O(N^2) complexity) # with the NTT based on the FFT scheme (O(N log N) complexity) a = gnum(numpy.random.randint(0, 1000, size=16)) af = ntt(a, False) ab = ntt(af, True) af_ref = ntt_naive(a, False) ab_ref = ntt_naive(af_ref, True) assert (a == ab).all() assert (af == af_ref).all() assert (ab == ab_ref).all()
def ref_lsh(data1, data2): data1 = ntt_cpu.gnum(data1) data2 = ntt_cpu.gnum(2)**data2 return ntt_cpu.gnum_to_u64(data1 * data2)
def ref_inv_pow2(data1): return ntt_cpu.gnum_to_u64(ntt_cpu.gnum(1) / ntt_cpu.gnum(2)**data1)
def ref_pow(data1, data2): data1 = ntt_cpu.gnum(data1) return ntt_cpu.gnum_to_u64(data1**data2)
def ref_mul(data1, data2): data1 = ntt_cpu.gnum(data1) data2 = ntt_cpu.gnum(data2) return ntt_cpu.gnum_to_u64(data1 * data2)
def ref_sub(data1, data2): data1 = ntt_cpu.gnum(data1) data2 = ntt_cpu.gnum(data2) return ntt_cpu.gnum_to_u64(data1 - data2)
def ref_add(data1, data2): data1 = ntt_cpu.gnum(data1) data2 = ntt_cpu.gnum(data2) return ntt_cpu.gnum_to_u64(data1 + data2)
def ref_prepare_for_mul(data1): coeff = ntt_cpu.gnum(0xffffffff) # 2**64 modulo (2**64-2**32+1) data1 = ntt_cpu.gnum(data1) return ntt_cpu.gnum_to_u64(data1 * coeff)
def ref_mul_prepared(data1, data2): coeff = ntt_cpu.gnum( 0xfffffffe00000001) # Inverse of 2**64 modulo (2**64-2**32+1) data1 = ntt_cpu.gnum(data1) data2 = ntt_cpu.gnum(data2) return ntt_cpu.gnum_to_u64(data1 * data2 * coeff)