use crypto::fieldq

fn bitrev7(n: Int) -> Int {
    let mut result = 0
    let mut val = n
    let mut i = 0
    while i < 7 {
        result = result * 2 + val % 2
        val = val / 2
        i = i + 1
    }
    return result
}

fn main() {
    // The Kyber reference table — check two possible formulas:
    // Formula A: zetas[k] = to_mont(17^{bitrev7(k)}) mod q
    // Formula B: zetas[k] = to_mont(17^{2*bitrev7(k)+1}) mod q

    let table = tensor_from_ints(-1044, -758, -359, -1517, 1493, 1422, 287, 202)

    println("=== Formula A: 17^{bitrev7(k)} ===")
    let mut k = 0
    while k < 8 {
        let br = bitrev7(k)
        let pow_a = fq_pow(17, br)
        let mont_a = fq_to_mont(pow_a)
        let tval = t_index_get(table, k)
        let m = ""
        if mont_a == tval { m = "OK" } else { m = "NO" }
        println("k=" + int_to_str(k) + " br=" + int_to_str(br) + " mont=" + int_to_str(mont_a) + " table=" + float_to_str(tval) + " " + m)
        k = k + 1
    }

    println("")
    println("=== Formula B: 17^{2*bitrev7(k)+1} ===")
    let mut k2 = 0
    while k2 < 8 {
        let br = bitrev7(k2)
        let exp_b = 2 * br + 1
        let pow_b = fq_pow(17, exp_b)
        let mont_b = fq_to_mont(pow_b)
        let tval = t_index_get(table, k2)
        let m = ""
        if mont_b == tval { m = "OK" } else { m = "NO" }
        println("k=" + int_to_str(k2) + " exp=" + int_to_str(exp_b) + " mont=" + int_to_str(mont_b) + " table=" + float_to_str(tval) + " " + m)
        k2 = k2 + 1
    }

    // Check entry 120 with both formulas
    println("")
    println("=== Index 120 check ===")
    let br120 = bitrev7(120)
    println("bitrev7(120) = " + int_to_str(br120))
    let pow_a120 = fq_pow(17, br120)
    println("Formula A: to_mont(17^" + int_to_str(br120) + ") = " + int_to_str(fq_to_mont(pow_a120)))
    let pow_b120 = fq_pow(17, 2 * br120 + 1)
    println("Formula B: to_mont(17^" + int_to_str(2 * br120 + 1) + ") = " + int_to_str(fq_to_mont(pow_b120)))
    println("Table value: 827")

    // What if we use fq_from_mont to decode 827?
    println("fq_from_mont(827) = " + int_to_str(fq_from_mont(827)))
    let decoded = fq_from_mont(827)
    // Is decoded a power of 17?
    let mut p = 0
    while p < 256 {
        if fq_pow(17, p) == decoded {
            println("827 decodes to 17^" + int_to_str(p))
        }
        p = p + 1
    }
}
