export function mod_exp(a, b, n) {
    let res = 1n;

    while (b > 0n) {
        if (b % 2n === 1n) {
            res = (res * a) % n;
        }

        b >>= 1n;
        a = (a * a) % n;
    }

    return res;
}

export function mod_inv(a, n) {
    let t = 0n;
    let new_t = 1n;
    let r = n;
    let new_r = a;

    while (new_r !== 0n) {
        let quotient = r / new_r;

        let t_temp = t;
        t = new_t;
        new_t = t_temp - quotient * new_t;

        let r_temp = r;
        r = new_r;
        new_r = r_temp - quotient * new_r;
    }

    if (t < 0) {
        t = t + n;
    }

    return t;
}

export function gcd(a, b) {
    // check a, b are correct types.
    a *= 1n;
    b *= 1n;
    while (b !== 0n) {
        let temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

window.mod_exp = mod_exp;
window.mod_inv = mod_inv;
window.gcd = gcd;
