Problem 806

f(n) mod 1e9+7 for n=100000. Losing indices mirror-pair to sum 2^n-1, so f(n) = k*(2^n-1)/2 mod M where k = sum over XOR-zero triples (a,b,c) with a+b+c=n of the Hanoi generating-function coefficient. Pure Flow port of the native C solver.

Answer94394343
Output94394343
StatusPASS
Native helperno
Runtime90 ms
Peak memory5376 KB
Time complexityO(n) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n)O(n * k)
Space complexityO(n^2)O(n)
ApproachFlow solutionKey search and XOR decryption
VerdictUnknown

Flow source

# Project Euler 806: Nim on Towers of Hanoi.
# f(n) mod 1e9+7 for n=100000. Losing indices mirror-pair to sum 2^n-1,
# so f(n) = k*(2^n-1)/2 mod M where k = sum over XOR-zero triples (a,b,c)
# with a+b+c=n of the Hanoi generating-function coefficient.
# Pure Flow port of the native C solver.

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
}

const MOD: i64 = 1000000007
const INV2: i64 = 500000004

function mod_pow(a0: i64, e0: i64) -> i64 {
    let mut r: i64 = 1
    let mut a: i64 = a0 % MOD
    let mut e: i64 = e0
    while e != 0 {
        if e % 2 == 1 {
            r = r * a % MOD
        }
        a = a * a % MOD
        e = e / 2
    }
    return r
}

# Precompute factorials, inverses, inverse-factorials, powers of 2.
function precompute(nmax: i64, fact_arr: ptr<i64>, inv_arr: ptr<i64>, invfact_arr: ptr<i64>, pow2_arr: ptr<i64>) -> void {
    fact_arr[0] = 1
    let mut i: i64 = 1
    while i <= nmax {
        fact_arr[i] = fact_arr[i - 1] * i % MOD
        i = i + 1
    }

    inv_arr[1] = 1
    i = 2
    while i <= nmax {
        inv_arr[i] = MOD - (MOD / i) * inv_arr[MOD % i] % MOD
        i = i + 1
    }

    invfact_arr[nmax] = mod_pow(fact_arr[nmax], MOD - 2)
    i = nmax
    while i >= 1 {
        invfact_arr[i - 1] = invfact_arr[i] * i % MOD
        i = i - 1
    }

    pow2_arr[0] = 1
    i = 1
    while i <= nmax {
        pow2_arr[i] = pow2_arr[i - 1] * 2 % MOD
        i = i + 1
    }
}

# Open-addressing cache for denom_coeff keyed on packed (a,b,c).
let mut cache_cap: i64 = 0
let mut cache_keys: ptr<i64> = null
let mut cache_vals: ptr<i64> = null

function pack_key(a: i64, b: i64, c: i64) -> i64 {
    # a, b, c <= 100005 < 2^17, so 51 bits total.
    return (a << 34) | (b << 17) | c
}

function cache_init(cap: i64) -> void {
    cache_cap = cap
    cache_keys = calloc(cap, 8) as ptr<i64>
    cache_vals = calloc(cap, 8) as ptr<i64>
    let mut i: i64 = 0
    while i < cap {
        cache_keys[i] = -1
        i = i + 1
    }
}

function cache_find(key: i64, out: ptr<i64>) -> i32 {
    let mask: i64 = cache_cap - 1
    let mut h: i64 = key & mask
    while cache_keys[h] != -1 {
        if cache_keys[h] == key {
            out[0] = cache_vals[h]
            return 1
        }
        h = (h + 1) & mask
    }
    return 0
}

function cache_insert(key: i64, val: i64) -> void {
    let mask: i64 = cache_cap - 1
    let mut h: i64 = key & mask
    while cache_keys[h] != -1 {
        if cache_keys[h] == key {
            cache_vals[h] = val
            return
        }
        h = (h + 1) & mask
    }
    cache_keys[h] = key
    cache_vals[h] = val
}

# Coefficient of x^a y^b z^c in 1 / (1 - x^2 - y^2 - z^2 - 2xyz).
function denom_coeff(a: i64, b: i64, c: i64, fact_arr: ptr<i64>, inv_arr: ptr<i64>, invfact_arr: ptr<i64>, pow2_arr: ptr<i64>) -> i64 {
    if a < 0 || b < 0 || c < 0 {
        return 0
    }
    if ((a ^ b) % 2 != 0) || ((a ^ c) % 2 != 0) {
        return 0
    }

    let key: i64 = pack_key(a, b, c)
    let outp: ptr<i64> = calloc(1, 8) as ptr<i64>
    if cache_find(key, outp) != 0 {
        let rv: i64 = outp[0]
        free(outp)
        return rv
    }
    free(outp)

    let mut minabc: i64 = a
    if b < minabc {
        minabc = b
    }
    if c < minabc {
        minabc = c
    }

    let mut ans: i64 = 0
    let mut i: i64 = a % 2
    let mut done: i32 = 0
    if i > minabc {
        done = 1
    }
    let mut A: i64 = (a - i) / 2
    let mut B: i64 = (b - i) / 2
    let mut C: i64 = (c - i) / 2
    let mut m: i64 = (a + b + c - i) / 2

    let mut term: i64 = pow2_arr[i]
    term = term * fact_arr[m] % MOD
    term = term * invfact_arr[i] % MOD
    term = term * invfact_arr[A] % MOD
    term = term * invfact_arr[B] % MOD
    term = term * invfact_arr[C] % MOD

    while done == 0 {
        ans = ans + term
        if ans >= MOD {
            ans = ans - MOD
        }

        let i2: i64 = i + 2
        if i2 > minabc {
            done = 1
        } else {
            # term_{i+2} / term_i = 4*A*B*C / (m*(i+1)*(i+2))
            let mut ratio: i64 = (4 * A) % MOD
            ratio = ratio * B % MOD
            ratio = ratio * C % MOD
            ratio = ratio * inv_arr[m] % MOD
            ratio = ratio * inv_arr[i + 1] % MOD
            ratio = ratio * inv_arr[i + 2] % MOD

            term = term * ratio % MOD

            i = i2
            A = A - 1
            B = B - 1
            C = C - 1
            m = m - 1
        }
    }

    cache_insert(key, ans)
    return ans
}

# Coefficient in Fy with numerator (1+y)(1+x+z-y).
function full_coeff(a: i64, b: i64, c: i64, fact_arr: ptr<i64>, inv_arr: ptr<i64>, invfact_arr: ptr<i64>, pow2_arr: ptr<i64>) -> i64 {
    let mut res: i64 = denom_coeff(a, b, c, fact_arr, inv_arr, invfact_arr, pow2_arr)
    res = res + denom_coeff(a - 1, b, c, fact_arr, inv_arr, invfact_arr, pow2_arr)
    if res >= MOD {
        res = res - MOD
    }
    res = res + denom_coeff(a, b, c - 1, fact_arr, inv_arr, invfact_arr, pow2_arr)
    if res >= MOD {
        res = res - MOD
    }
    res = res + denom_coeff(a - 1, b - 1, c, fact_arr, inv_arr, invfact_arr, pow2_arr)
    if res >= MOD {
        res = res - MOD
    }
    res = res + denom_coeff(a, b - 1, c - 1, fact_arr, inv_arr, invfact_arr, pow2_arr)
    if res >= MOD {
        res = res - MOD
    }
    res = res - denom_coeff(a, b - 2, c, fact_arr, inv_arr, invfact_arr, pow2_arr)
    if res < 0 {
        res = res + MOD
    }
    return res
}

function main() -> i32 {
    let n: i64 = 100000

    if n % 2 != 0 {
        printf("%lld\n", 0)
        return 0
    }

    let nmax: i64 = n + 5
    let fact_arr: ptr<i64> = calloc(nmax + 1, 8) as ptr<i64>
    let inv_arr: ptr<i64> = calloc(nmax + 1, 8) as ptr<i64>
    let invfact_arr: ptr<i64> = calloc(nmax + 1, 8) as ptr<i64>
    let pow2_arr: ptr<i64> = calloc(nmax + 1, 8) as ptr<i64>

    precompute(nmax, fact_arr, inv_arr, invfact_arr, pow2_arr)
    cache_init(1 << 16)

    # gen_triples: enumerate ordered triples (a,b,c) with a+b+c=n, a xor b xor c = 0.
    # For even n, each set bit at position p>=1 gives 3 choices.
    let bits: ptr<i64> = calloc(32, 8) as ptr<i64>
    let mut nbits: i64 = 0
    let mut x: i64 = n
    let mut p: i64 = 0
    while x != 0 {
        if x % 2 == 1 {
            bits[nbits] = p
            nbits = nbits + 1
        }
        x = x / 2
        p = p + 1
    }

    let mut total: i64 = 1
    let mut bi: i64 = 0
    while bi < nbits {
        if bits[bi] != 0 {
            total = total * 3
        }
        bi = bi + 1
    }

    let triples: ptr<i64> = calloc(total * 3, 8) as ptr<i64>
    triples[0] = 0
    triples[1] = 0
    triples[2] = 0
    let mut n_triples: i64 = 1

    bi = 0
    while bi < nbits {
        let pp: i64 = bits[bi]
        if pp == 0 {
        } else {
            let v: i64 = 1 << (pp - 1)
            let cur: i64 = n_triples
            let mut j: i64 = 0
            while j < cur {
                let ta: i64 = triples[j * 3]
                let tb: i64 = triples[j * 3 + 1]
                let tc: i64 = triples[j * 3 + 2]
                triples[j * 3] = ta + v
                triples[j * 3 + 1] = tb + v
                triples[j * 3 + 2] = tc
                triples[(cur + j) * 3] = ta + v
                triples[(cur + j) * 3 + 1] = tb
                triples[(cur + j) * 3 + 2] = tc + v
                triples[(2 * cur + j) * 3] = ta
                triples[(2 * cur + j) * 3 + 1] = tb + v
                triples[(2 * cur + j) * 3 + 2] = tc + v
                j = j + 1
            }
            n_triples = 3 * cur
        }
        bi = bi + 1
    }

    let mut k: i64 = 0
    let mut t: i64 = 0
    while t < n_triples {
        k = k + full_coeff(triples[t * 3], triples[t * 3 + 1], triples[t * 3 + 2], fact_arr, inv_arr, invfact_arr, pow2_arr)
        if k >= MOD {
            k = k - MOD
        }
        t = t + 1
    }

    let val: i64 = (pow2_arr[n] - 1 + MOD) % MOD
    let result: i64 = k * val % MOD * INV2 % MOD

    printf("%lld\n", result)

    free(fact_arr)
    free(inv_arr)
    free(invfact_arr)
    free(pow2_arr)
    free(cache_keys)
    free(cache_vals)
    free(triples)
    free(bits)
    return 0
}

Generated C

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Flow runtime helpers */
typedef struct flow_temp_node { struct flow_temp_node* next; } flow_temp_node;
static flow_temp_node* flow_temp_head = NULL;
static int flow_temp_atexit_set = 0;
__attribute__((unused)) static void flow_temp_free_all(void) {
    while (flow_temp_head) {
        flow_temp_node* n = flow_temp_head;
        flow_temp_head = n->next;
        free(n);
    }
}
__attribute__((unused)) static void* flow_temp_alloc(size_t nbytes) {
    flow_temp_node* node = (flow_temp_node*)malloc(sizeof(flow_temp_node) + nbytes);
    if (!node) return NULL;
    node->next = flow_temp_head;
    flow_temp_head = node;
    if (!flow_temp_atexit_set) {
        flow_temp_atexit_set = 1;
        atexit(flow_temp_free_all);
    }
    return (void*)(node + 1);
}
#ifndef FLOW_DIAG
#define FLOW_DIAG(msg) fprintf(stderr, "%s", (msg))
#endif
#ifndef FLOW_LOG
#define FLOW_LOG(fmt, ...) printf(fmt, __VA_ARGS__)
#endif
#ifndef FLOW_LOG_EMPTY
#define FLOW_LOG_EMPTY(fmt) printf(fmt)
#endif
static char* flow_strcat(const char* a, const char* b) {
    size_t la = strlen(a ? a : ""), lb = strlen(b ? b : "");
    char* r = (char*)flow_temp_alloc(la + lb + 1);
    if (!r) return NULL;
    if (la) memcpy(r, a, la);
    if (lb) memcpy(r + la, b, lb);
    r[la + lb] = '\0';
    return r;
}

#define __flow_in_arr(arr, val) __extension__ ({ \
    int _found = 0; \
    size_t _n = sizeof(arr)/sizeof((arr)[0]); \
    for (size_t _i = 0; _i < _n; _i++) { \
        if ((arr)[_i] == (val)) { _found = 1; break; } \
    } _found; })

/* Unified fault handler (MISRA #279) — override with -DFLOW_FAULT_HANDLER=fn */
#ifndef FLOW_FAULT_HANDLER
__attribute__((unused)) static inline void flow_fault_handler(const char* msg) {
    fprintf(stderr, "flow: %s\n", msg ? msg : "fault");
    abort();
#if defined(__GNUC__) || defined(__clang__)
    __builtin_unreachable();
#endif
}
#else
#define flow_fault_handler FLOW_FAULT_HANDLER
#endif
#define flow_div_by_zero_handler() flow_fault_handler("division by zero")
#define flow_shift_ub_handler() flow_fault_handler("invalid shift (amount out of range or left-shift of negative)")

#ifndef FLOW_CHECKED_DIV
#define FLOW_CHECKED_DIV(L, R) (((R) != 0) ? ((L) / (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_MOD
#define FLOW_CHECKED_MOD(L, R) (((R) != 0) ? ((L) % (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHL
#define FLOW_CHECKED_SHL(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull)) && ((L) >= 0)) ? ((L) << (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHR
#define FLOW_CHECKED_SHR(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull))) ? ((L) >> (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif

#include <math.h>

void* _ui_state = NULL;

static inline float i32_to_f32(int32_t v) { return (float)v; }

/* Host stub for @gpu kernels (device codegen replaces this). */
static inline int32_t gpu_thread_id(void) { return 0; }

int64_t mod_pow_i64_i64(int64_t a0, int64_t e0);
void precompute_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t nmax, int64_t* fact_arr, int64_t* inv_arr, int64_t* invfact_arr, int64_t* pow2_arr);
int64_t pack_key_i64_i64_i64(int64_t a, int64_t b, int64_t c);
void cache_init_i64(int64_t cap);
int32_t cache_find_i64_ptr_i64(int64_t key, int64_t* out);
void cache_insert_i64_i64(int64_t key, int64_t val);
int64_t denom_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t a, int64_t b, int64_t c, int64_t* fact_arr, int64_t* inv_arr, int64_t* invfact_arr, int64_t* pow2_arr);
int64_t full_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t a, int64_t b, int64_t c, int64_t* fact_arr, int64_t* inv_arr, int64_t* invfact_arr, int64_t* pow2_arr);
int32_t main(void);

static const int64_t MOD = 1000000007;
static const int64_t INV2 = 500000004;

/* Module statics */
static int64_t cache_cap = 0;
static int64_t* cache_keys = NULL;
static int64_t* cache_vals = NULL;



int64_t mod_pow_i64_i64(int64_t a0, int64_t e0) {
    int64_t r = 1;
    int64_t a = FLOW_CHECKED_MOD((a0), (MOD));
    int64_t e = e0;
    while (e != 0) {
        if (FLOW_CHECKED_MOD((e), (2)) == 1) {
            r = FLOW_CHECKED_MOD(((r * a)), (MOD));
        }
        a = FLOW_CHECKED_MOD(((a * a)), (MOD));
        e = FLOW_CHECKED_DIV((e), (2));
    }
    return r;
}

void precompute_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t nmax, int64_t* fact_arr, int64_t* inv_arr, int64_t* invfact_arr, int64_t* pow2_arr) {
    fact_arr[0] = 1;
    int64_t i = 1;
    while (i <= nmax) {
        fact_arr[i] = FLOW_CHECKED_MOD(((fact_arr[(i - 1)] * i)), (MOD));
        i = (i + 1);
    }
    inv_arr[1] = 1;
    i = 2;
    while (i <= nmax) {
        inv_arr[i] = (MOD - FLOW_CHECKED_MOD(((FLOW_CHECKED_DIV((MOD), (i)) * inv_arr[FLOW_CHECKED_MOD((MOD), (i))])), (MOD)));
        i = (i + 1);
    }
    invfact_arr[nmax] = mod_pow_i64_i64(fact_arr[nmax], (MOD - 2));
    i = nmax;
    while (i >= 1) {
        invfact_arr[(i - 1)] = FLOW_CHECKED_MOD(((invfact_arr[i] * i)), (MOD));
        i = (i - 1);
    }
    pow2_arr[0] = 1;
    i = 1;
    while (i <= nmax) {
        pow2_arr[i] = FLOW_CHECKED_MOD(((pow2_arr[(i - 1)] * 2)), (MOD));
        i = (i + 1);
    }
}

int64_t pack_key_i64_i64_i64(int64_t a, int64_t b, int64_t c) {
    return ((FLOW_CHECKED_SHL((a), (34)) | FLOW_CHECKED_SHL((b), (17))) | c);
}

void cache_init_i64(int64_t cap) {
    cache_cap = cap;
    cache_keys = ((int64_t*)(calloc(cap, 8)));
    cache_vals = ((int64_t*)(calloc(cap, 8)));
    int64_t i = 0;
    while (i < cap) {
        cache_keys[i] = (-1);
        i = (i + 1);
    }
}

int32_t cache_find_i64_ptr_i64(int64_t key, int64_t* out) {
    int64_t mask = (cache_cap - 1);
    int64_t h = (key & mask);
    while (cache_keys[h] != (-1)) {
        if (cache_keys[h] == key) {
            out[0] = cache_vals[h];
            return 1;
        }
        h = ((h + 1) & mask);
    }
    return 0;
}

void cache_insert_i64_i64(int64_t key, int64_t val) {
    int64_t mask = (cache_cap - 1);
    int64_t h = (key & mask);
    while (cache_keys[h] != (-1)) {
        if (cache_keys[h] == key) {
            cache_vals[h] = val;
            return;
        }
        h = ((h + 1) & mask);
    }
    cache_keys[h] = key;
    cache_vals[h] = val;
}

int64_t denom_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t a, int64_t b, int64_t c, int64_t* fact_arr, int64_t* inv_arr, int64_t* invfact_arr, int64_t* pow2_arr) {
    if (((a < 0 || b < 0) || c < 0)) {
        return 0;
    }
    if ((FLOW_CHECKED_MOD(((a ^ b)), (2)) != 0 || FLOW_CHECKED_MOD(((a ^ c)), (2)) != 0)) {
        return 0;
    }
    int64_t key = pack_key_i64_i64_i64(a, b, c);
    int64_t* outp = (int64_t*)(((int64_t*)(calloc(1, 8))));
    if (cache_find_i64_ptr_i64(key, outp) != 0) {
        int64_t rv = outp[0];
        free(outp);
        return rv;
    }
    free(outp);
    int64_t minabc = a;
    if (b < minabc) {
        minabc = b;
    }
    if (c < minabc) {
        minabc = c;
    }
    int64_t ans = 0;
    int64_t i = FLOW_CHECKED_MOD((a), (2));
    int32_t done = 0;
    if (i > minabc) {
        done = 1;
    }
    int64_t A = FLOW_CHECKED_DIV(((a - i)), (2));
    int64_t B = FLOW_CHECKED_DIV(((b - i)), (2));
    int64_t C = FLOW_CHECKED_DIV(((c - i)), (2));
    int64_t m = FLOW_CHECKED_DIV(((((a + b) + c) - i)), (2));
    int64_t term = pow2_arr[i];
    term = FLOW_CHECKED_MOD(((term * fact_arr[m])), (MOD));
    term = FLOW_CHECKED_MOD(((term * invfact_arr[i])), (MOD));
    term = FLOW_CHECKED_MOD(((term * invfact_arr[A])), (MOD));
    term = FLOW_CHECKED_MOD(((term * invfact_arr[B])), (MOD));
    term = FLOW_CHECKED_MOD(((term * invfact_arr[C])), (MOD));
    while (done == 0) {
        ans = (ans + term);
        if (ans >= MOD) {
            ans = (ans - MOD);
        }
        int64_t i2 = (i + 2);
        if (i2 > minabc) {
            done = 1;
        } else {
            int64_t ratio = FLOW_CHECKED_MOD(((4 * A)), (MOD));
            ratio = FLOW_CHECKED_MOD(((ratio * B)), (MOD));
            ratio = FLOW_CHECKED_MOD(((ratio * C)), (MOD));
            ratio = FLOW_CHECKED_MOD(((ratio * inv_arr[m])), (MOD));
            ratio = FLOW_CHECKED_MOD(((ratio * inv_arr[(i + 1)])), (MOD));
            ratio = FLOW_CHECKED_MOD(((ratio * inv_arr[(i + 2)])), (MOD));
            term = FLOW_CHECKED_MOD(((term * ratio)), (MOD));
            i = i2;
            A = (A - 1);
            B = (B - 1);
            C = (C - 1);
            m = (m - 1);
        }
    }
    cache_insert_i64_i64(key, ans);
    return ans;
}

int64_t full_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t a, int64_t b, int64_t c, int64_t* fact_arr, int64_t* inv_arr, int64_t* invfact_arr, int64_t* pow2_arr) {
    int64_t res = denom_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(a, b, c, fact_arr, inv_arr, invfact_arr, pow2_arr);
    res = (res + denom_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64((a - 1), b, c, fact_arr, inv_arr, invfact_arr, pow2_arr));
    if (res >= MOD) {
        res = (res - MOD);
    }
    res = (res + denom_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(a, b, (c - 1), fact_arr, inv_arr, invfact_arr, pow2_arr));
    if (res >= MOD) {
        res = (res - MOD);
    }
    res = (res + denom_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64((a - 1), (b - 1), c, fact_arr, inv_arr, invfact_arr, pow2_arr));
    if (res >= MOD) {
        res = (res - MOD);
    }
    res = (res + denom_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(a, (b - 1), (c - 1), fact_arr, inv_arr, invfact_arr, pow2_arr));
    if (res >= MOD) {
        res = (res - MOD);
    }
    res = (res - denom_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(a, (b - 2), c, fact_arr, inv_arr, invfact_arr, pow2_arr));
    if (res < 0) {
        res = (res + MOD);
    }
    return res;
}

int32_t main(void) {
    int64_t n = 100000;
    if (FLOW_CHECKED_MOD((n), (2)) != 0) {
        printf("%lld\n", 0);
        return 0;
    }
    int64_t nmax = (n + 5);
    int64_t* fact_arr = (int64_t*)(((int64_t*)(calloc((nmax + 1), 8))));
    int64_t* inv_arr = (int64_t*)(((int64_t*)(calloc((nmax + 1), 8))));
    int64_t* invfact_arr = (int64_t*)(((int64_t*)(calloc((nmax + 1), 8))));
    int64_t* pow2_arr = (int64_t*)(((int64_t*)(calloc((nmax + 1), 8))));
    precompute_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(nmax, fact_arr, inv_arr, invfact_arr, pow2_arr);
    cache_init_i64(FLOW_CHECKED_SHL((1), (16)));
    int64_t* bits = (int64_t*)(((int64_t*)(calloc(32, 8))));
    int64_t nbits = 0;
    int64_t x = n;
    int64_t p = 0;
    while (x != 0) {
        if (FLOW_CHECKED_MOD((x), (2)) == 1) {
            bits[nbits] = p;
            nbits = (nbits + 1);
        }
        x = FLOW_CHECKED_DIV((x), (2));
        p = (p + 1);
    }
    int64_t total = 1;
    int64_t bi = 0;
    while (bi < nbits) {
        if (bits[bi] != 0) {
            total = (total * 3);
        }
        bi = (bi + 1);
    }
    int64_t* triples = (int64_t*)(((int64_t*)(calloc((total * 3), 8))));
    triples[0] = 0;
    triples[1] = 0;
    triples[2] = 0;
    int64_t n_triples = 1;
    bi = 0;
    while (bi < nbits) {
        int64_t pp = bits[bi];
        if (pp == 0) {
        } else {
            int64_t v = FLOW_CHECKED_SHL((1), ((pp - 1)));
            int64_t cur = n_triples;
            int64_t j = 0;
            while (j < cur) {
                int64_t ta = triples[(j * 3)];
                int64_t tb = triples[((j * 3) + 1)];
                int64_t tc = triples[((j * 3) + 2)];
                triples[(j * 3)] = (ta + v);
                triples[((j * 3) + 1)] = (tb + v);
                triples[((j * 3) + 2)] = tc;
                triples[((cur + j) * 3)] = (ta + v);
                triples[(((cur + j) * 3) + 1)] = tb;
                triples[(((cur + j) * 3) + 2)] = (tc + v);
                triples[(((2 * cur) + j) * 3)] = ta;
                triples[((((2 * cur) + j) * 3) + 1)] = (tb + v);
                triples[((((2 * cur) + j) * 3) + 2)] = (tc + v);
                j = (j + 1);
            }
            n_triples = (3 * cur);
        }
        bi = (bi + 1);
    }
    int64_t k = 0;
    int64_t t = 0;
    while (t < n_triples) {
        k = (k + full_coeff_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(triples[(t * 3)], triples[((t * 3) + 1)], triples[((t * 3) + 2)], fact_arr, inv_arr, invfact_arr, pow2_arr));
        if (k >= MOD) {
            k = (k - MOD);
        }
        t = (t + 1);
    }
    int64_t val = FLOW_CHECKED_MOD((((pow2_arr[n] - 1) + MOD)), (MOD));
    int64_t result = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD(((k * val)), (MOD)) * INV2)), (MOD));
    printf("%lld\n", result);
    free(fact_arr);
    free(inv_arr);
    free(invfact_arr);
    free(pow2_arr);
    free(cache_keys);
    free(cache_vals);
    free(triples);
    free(bits);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  // Constant: MOD
  llvm.mlir.global internal constant @MOD(1000000007 : i64) : i64
  // Constant: INV2
  llvm.mlir.global internal constant @INV2(500000004 : i64) : i64
  func.func @mod_pow(%arg0: i64, %arg1: i64) -> i64 {
    %0 = arith.constant 1 : i32
    %1 = arith.extsi %0 : i32 to i64
    %2 = llvm.mlir.constant(1 : i64) : i64
    %3 = llvm.alloca %2 x i64 : (i64) -> !llvm.ptr
    llvm.store %1, %3 : i64, !llvm.ptr
    %4 = llvm.mlir.addressof @MOD : !llvm.ptr
    %5 = llvm.load %4 : !llvm.ptr -> i64
    %6 = arith.remsi %arg0, %5 : i64
    %7 = llvm.mlir.constant(1 : i64) : i64
    %8 = llvm.alloca %7 x i64 : (i64) -> !llvm.ptr
    llvm.store %6, %8 : i64, !llvm.ptr
    %9 = llvm.mlir.constant(1 : i64) : i64
    %10 = llvm.alloca %9 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %10 : i64, !llvm.ptr
    cf.br ^bb0
    ^bb0:
    %11 = llvm.load %10 : !llvm.ptr -> i64
    %12 = arith.constant 0 : i32
    %14 = arith.extsi %12 : i32 to i64
    %13 = arith.cmpi ne, %11, %14 : i64
    cf.cond_br %13, ^bb1, ^bb2
    ^bb1:
      %15 = llvm.load %10 : !llvm.ptr -> i64
      %16 = arith.constant 2 : i32
      %18 = arith.extsi %16 : i32 to i64
      %17 = arith.remsi %15, %18 : i64
      %19 = arith.constant 1 : i32
      %21 = arith.extsi %19 : i32 to i64
      %20 = arith.cmpi eq, %17, %21 : i64
      cf.cond_br %20, ^bb3, ^bb4
      ^bb3:
        %22 = llvm.load %3 : !llvm.ptr -> i64
        %23 = llvm.load %8 : !llvm.ptr -> i64
        %24 = arith.muli %22, %23 : i64
        %25 = llvm.mlir.addressof @MOD : !llvm.ptr
        %26 = llvm.load %25 : !llvm.ptr -> i64
        %27 = arith.remsi %24, %26 : i64
        llvm.store %27, %3 : i64, !llvm.ptr
        cf.br ^bb5
      ^bb4:
        cf.br ^bb5
      ^bb5:
      %28 = llvm.load %8 : !llvm.ptr -> i64
      %29 = llvm.load %8 : !llvm.ptr -> i64
      %30 = arith.muli %28, %29 : i64
      %31 = llvm.mlir.addressof @MOD : !llvm.ptr
      %32 = llvm.load %31 : !llvm.ptr -> i64
      %33 = arith.remsi %30, %32 : i64
      llvm.store %33, %8 : i64, !llvm.ptr
      %34 = llvm.load %10 : !llvm.ptr -> i64
      %35 = arith.constant 2 : i32
      %37 = arith.extsi %35 : i32 to i64
      %36 = arith.divsi %34, %37 : i64
      llvm.store %36, %10 : i64, !llvm.ptr
      cf.br ^bb0
    ^bb2:
    %38 = llvm.load %3 : !llvm.ptr -> i64
    func.return %38 : i64
  }
  func.func @precompute(%arg0: i64, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr) -> () {
    %39 = arith.constant 1 : i32
    %40 = arith.constant 0 : i32
    %41 = arith.extsi %39 : i32 to i64
    %42 = arith.extsi %40 : i32 to i64
    %43 = llvm.getelementptr %arg1[%42] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %41, %43 : i64, !llvm.ptr
    %44 = arith.constant 1 : i32
    %45 = arith.extsi %44 : i32 to i64
    %46 = llvm.mlir.constant(1 : i64) : i64
    %47 = llvm.alloca %46 x i64 : (i64) -> !llvm.ptr
    llvm.store %45, %47 : i64, !llvm.ptr
    cf.br ^bb6
    ^bb6:
    %48 = llvm.load %47 : !llvm.ptr -> i64
    %49 = arith.cmpi sle, %48, %arg0 : i64
    cf.cond_br %49, ^bb7, ^bb8
    ^bb7:
      %51 = llvm.load %47 : !llvm.ptr -> i64
      %52 = arith.constant 1 : i32
      %54 = arith.extsi %52 : i32 to i64
      %53 = arith.subi %51, %54 : i64
      %55 = llvm.getelementptr %arg1[%53] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %50 = llvm.load %55 : !llvm.ptr -> i64
      %56 = llvm.load %47 : !llvm.ptr -> i64
      %57 = arith.muli %50, %56 : i64
      %58 = llvm.mlir.addressof @MOD : !llvm.ptr
      %59 = llvm.load %58 : !llvm.ptr -> i64
      %60 = arith.remsi %57, %59 : i64
      %61 = llvm.load %47 : !llvm.ptr -> i64
      %62 = llvm.getelementptr %arg1[%61] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %60, %62 : i64, !llvm.ptr
      %63 = llvm.load %47 : !llvm.ptr -> i64
      %64 = arith.constant 1 : i32
      %66 = arith.extsi %64 : i32 to i64
      %65 = arith.addi %63, %66 : i64
      llvm.store %65, %47 : i64, !llvm.ptr
      cf.br ^bb6
    ^bb8:
    %67 = arith.constant 1 : i32
    %68 = arith.constant 1 : i32
    %69 = arith.extsi %67 : i32 to i64
    %70 = arith.extsi %68 : i32 to i64
    %71 = llvm.getelementptr %arg2[%70] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %69, %71 : i64, !llvm.ptr
    %72 = arith.constant 2 : i32
    %73 = arith.extsi %72 : i32 to i64
    llvm.store %73, %47 : i64, !llvm.ptr
    cf.br ^bb9
    ^bb9:
    %74 = llvm.load %47 : !llvm.ptr -> i64
    %75 = arith.cmpi sle, %74, %arg0 : i64
    cf.cond_br %75, ^bb10, ^bb11
    ^bb10:
      %76 = llvm.mlir.addressof @MOD : !llvm.ptr
      %77 = llvm.load %76 : !llvm.ptr -> i64
      %78 = llvm.mlir.addressof @MOD : !llvm.ptr
      %79 = llvm.load %78 : !llvm.ptr -> i64
      %80 = llvm.load %47 : !llvm.ptr -> i64
      %81 = arith.divsi %79, %80 : i64
      %83 = llvm.mlir.addressof @MOD : !llvm.ptr
      %84 = llvm.load %83 : !llvm.ptr -> i64
      %85 = llvm.load %47 : !llvm.ptr -> i64
      %86 = arith.remsi %84, %85 : i64
      %87 = llvm.getelementptr %arg2[%86] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %82 = llvm.load %87 : !llvm.ptr -> i64
      %88 = arith.muli %81, %82 : i64
      %89 = llvm.mlir.addressof @MOD : !llvm.ptr
      %90 = llvm.load %89 : !llvm.ptr -> i64
      %91 = arith.remsi %88, %90 : i64
      %92 = arith.subi %77, %91 : i64
      %93 = llvm.load %47 : !llvm.ptr -> i64
      %94 = llvm.getelementptr %arg2[%93] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %92, %94 : i64, !llvm.ptr
      %95 = llvm.load %47 : !llvm.ptr -> i64
      %96 = arith.constant 1 : i32
      %98 = arith.extsi %96 : i32 to i64
      %97 = arith.addi %95, %98 : i64
      llvm.store %97, %47 : i64, !llvm.ptr
      cf.br ^bb9
    ^bb11:
    %101 = llvm.getelementptr %arg1[%arg0] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %100 = llvm.load %101 : !llvm.ptr -> i64
    %102 = llvm.mlir.addressof @MOD : !llvm.ptr
    %103 = llvm.load %102 : !llvm.ptr -> i64
    %104 = arith.constant 2 : i32
    %106 = arith.extsi %104 : i32 to i64
    %105 = arith.subi %103, %106 : i64
    %99 = func.call @mod_pow(%100, %105) : (i64, i64) -> i64
    %107 = llvm.getelementptr %arg3[%arg0] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %99, %107 : i64, !llvm.ptr
    llvm.store %arg0, %47 : i64, !llvm.ptr
    cf.br ^bb12
    ^bb12:
    %108 = llvm.load %47 : !llvm.ptr -> i64
    %109 = arith.constant 1 : i32
    %111 = arith.extsi %109 : i32 to i64
    %110 = arith.cmpi sge, %108, %111 : i64
    cf.cond_br %110, ^bb13, ^bb14
    ^bb13:
      %113 = llvm.load %47 : !llvm.ptr -> i64
      %114 = llvm.getelementptr %arg3[%113] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %112 = llvm.load %114 : !llvm.ptr -> i64
      %115 = llvm.load %47 : !llvm.ptr -> i64
      %116 = arith.muli %112, %115 : i64
      %117 = llvm.mlir.addressof @MOD : !llvm.ptr
      %118 = llvm.load %117 : !llvm.ptr -> i64
      %119 = arith.remsi %116, %118 : i64
      %120 = llvm.load %47 : !llvm.ptr -> i64
      %121 = arith.constant 1 : i32
      %123 = arith.extsi %121 : i32 to i64
      %122 = arith.subi %120, %123 : i64
      %124 = llvm.getelementptr %arg3[%122] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %119, %124 : i64, !llvm.ptr
      %125 = llvm.load %47 : !llvm.ptr -> i64
      %126 = arith.constant 1 : i32
      %128 = arith.extsi %126 : i32 to i64
      %127 = arith.subi %125, %128 : i64
      llvm.store %127, %47 : i64, !llvm.ptr
      cf.br ^bb12
    ^bb14:
    %129 = arith.constant 1 : i32
    %130 = arith.constant 0 : i32
    %131 = arith.extsi %129 : i32 to i64
    %132 = arith.extsi %130 : i32 to i64
    %133 = llvm.getelementptr %arg4[%132] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %131, %133 : i64, !llvm.ptr
    %134 = arith.constant 1 : i32
    %135 = arith.extsi %134 : i32 to i64
    llvm.store %135, %47 : i64, !llvm.ptr
    cf.br ^bb15
    ^bb15:
    %136 = llvm.load %47 : !llvm.ptr -> i64
    %137 = arith.cmpi sle, %136, %arg0 : i64
    cf.cond_br %137, ^bb16, ^bb17
    ^bb16:
      %139 = llvm.load %47 : !llvm.ptr -> i64
      %140 = arith.constant 1 : i32
      %142 = arith.extsi %140 : i32 to i64
      %141 = arith.subi %139, %142 : i64
      %143 = llvm.getelementptr %arg4[%141] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %138 = llvm.load %143 : !llvm.ptr -> i64
      %144 = arith.constant 2 : i32
      %146 = arith.extsi %144 : i32 to i64
      %145 = arith.muli %138, %146 : i64
      %147 = llvm.mlir.addressof @MOD : !llvm.ptr
      %148 = llvm.load %147 : !llvm.ptr -> i64
      %149 = arith.remsi %145, %148 : i64
      %150 = llvm.load %47 : !llvm.ptr -> i64
      %151 = llvm.getelementptr %arg4[%150] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %149, %151 : i64, !llvm.ptr
      %152 = llvm.load %47 : !llvm.ptr -> i64
      %153 = arith.constant 1 : i32
      %155 = arith.extsi %153 : i32 to i64
      %154 = arith.addi %152, %155 : i64
      llvm.store %154, %47 : i64, !llvm.ptr
      cf.br ^bb15
    ^bb17:
    func.return
  }
  // Module static: cache_cap
  llvm.mlir.global internal @cache_cap(0 : i64) : i64
  // Module static: cache_keys
  llvm.mlir.global internal @cache_keys() {addr_space = 0 : i32} : !llvm.ptr {
    %156 = llvm.mlir.zero : !llvm.ptr
    llvm.return %156 : !llvm.ptr
  }
  // Module static: cache_vals
  llvm.mlir.global internal @cache_vals() {addr_space = 0 : i32} : !llvm.ptr {
    %157 = llvm.mlir.zero : !llvm.ptr
    llvm.return %157 : !llvm.ptr
  }
  func.func @pack_key(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    %158 = arith.constant 34 : i32
    %160 = arith.extsi %158 : i32 to i64
    %159 = arith.shli %arg0, %160 : i64
    %161 = arith.constant 17 : i32
    %163 = arith.extsi %161 : i32 to i64
    %162 = arith.shli %arg1, %163 : i64
    %164 = arith.ori %159, %162 : i64
    %165 = arith.ori %164, %arg2 : i64
    func.return %165 : i64
  }
  func.func @cache_init(%arg0: i64) -> () {
    %166 = llvm.mlir.addressof @cache_cap : !llvm.ptr
    llvm.store %arg0, %166 : i64, !llvm.ptr
    %168 = arith.constant 8 : i32
    %169 = arith.extsi %168 : i32 to i64
    %167 = func.call @calloc(%arg0, %169) : (i64, i64) -> !llvm.ptr
    %170 = llvm.mlir.addressof @cache_keys : !llvm.ptr
    llvm.store %167, %170 : !llvm.ptr, !llvm.ptr
    %172 = arith.constant 8 : i32
    %173 = arith.extsi %172 : i32 to i64
    %171 = func.call @calloc(%arg0, %173) : (i64, i64) -> !llvm.ptr
    %174 = llvm.mlir.addressof @cache_vals : !llvm.ptr
    llvm.store %171, %174 : !llvm.ptr, !llvm.ptr
    %175 = arith.constant 0 : i32
    %176 = arith.extsi %175 : i32 to i64
    %177 = llvm.mlir.constant(1 : i64) : i64
    %178 = llvm.alloca %177 x i64 : (i64) -> !llvm.ptr
    llvm.store %176, %178 : i64, !llvm.ptr
    cf.br ^bb18
    ^bb18:
    %179 = llvm.load %178 : !llvm.ptr -> i64
    %180 = arith.cmpi slt, %179, %arg0 : i64
    cf.cond_br %180, ^bb19, ^bb20
    ^bb19:
      %181 = arith.constant 1 : i32
      %183 = arith.constant 0 : i32
      %182 = arith.subi %183, %181 : i32
      %184 = llvm.mlir.addressof @cache_keys : !llvm.ptr
      %185 = llvm.load %184 : !llvm.ptr -> !llvm.ptr
      %186 = llvm.load %178 : !llvm.ptr -> i64
      %187 = arith.extsi %182 : i32 to i64
      %188 = llvm.getelementptr %185[%186] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %187, %188 : i64, !llvm.ptr
      %189 = llvm.load %178 : !llvm.ptr -> i64
      %190 = arith.constant 1 : i32
      %192 = arith.extsi %190 : i32 to i64
      %191 = arith.addi %189, %192 : i64
      llvm.store %191, %178 : i64, !llvm.ptr
      cf.br ^bb18
    ^bb20:
    func.return
  }
  func.func @cache_find(%arg0: i64, %arg1: !llvm.ptr) -> i32 {
    %193 = llvm.mlir.addressof @cache_cap : !llvm.ptr
    %194 = llvm.load %193 : !llvm.ptr -> i64
    %195 = arith.constant 1 : i32
    %197 = arith.extsi %195 : i32 to i64
    %196 = arith.subi %194, %197 : i64
    %198 = arith.andi %arg0, %196 : i64
    %199 = llvm.mlir.constant(1 : i64) : i64
    %200 = llvm.alloca %199 x i64 : (i64) -> !llvm.ptr
    llvm.store %198, %200 : i64, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %202 = llvm.mlir.addressof @cache_keys : !llvm.ptr
    %203 = llvm.load %202 : !llvm.ptr -> !llvm.ptr
    %204 = llvm.load %200 : !llvm.ptr -> i64
    %205 = llvm.getelementptr %203[%204] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %201 = llvm.load %205 : !llvm.ptr -> i64
    %206 = arith.constant 1 : i32
    %208 = arith.constant 0 : i32
    %207 = arith.subi %208, %206 : i32
    %210 = arith.extsi %207 : i32 to i64
    %209 = arith.cmpi ne, %201, %210 : i64
    cf.cond_br %209, ^bb22, ^bb23
    ^bb22:
      %212 = llvm.mlir.addressof @cache_keys : !llvm.ptr
      %213 = llvm.load %212 : !llvm.ptr -> !llvm.ptr
      %214 = llvm.load %200 : !llvm.ptr -> i64
      %215 = llvm.getelementptr %213[%214] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %211 = llvm.load %215 : !llvm.ptr -> i64
      %216 = arith.cmpi eq, %211, %arg0 : i64
      cf.cond_br %216, ^bb24, ^bb25
      ^bb24:
        %218 = llvm.mlir.addressof @cache_vals : !llvm.ptr
        %219 = llvm.load %218 : !llvm.ptr -> !llvm.ptr
        %220 = llvm.load %200 : !llvm.ptr -> i64
        %221 = llvm.getelementptr %219[%220] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %217 = llvm.load %221 : !llvm.ptr -> i64
        %222 = arith.constant 0 : i32
        %223 = arith.extsi %222 : i32 to i64
        %224 = llvm.getelementptr %arg1[%223] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %217, %224 : i64, !llvm.ptr
        %225 = arith.constant 1 : i32
        func.return %225 : i32
      ^bb25:
        cf.br ^bb26
      ^bb26:
      %226 = llvm.load %200 : !llvm.ptr -> i64
      %227 = arith.constant 1 : i32
      %229 = arith.extsi %227 : i32 to i64
      %228 = arith.addi %226, %229 : i64
      %230 = arith.andi %228, %196 : i64
      llvm.store %230, %200 : i64, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    %231 = arith.constant 0 : i32
    func.return %231 : i32
  }
  func.func @cache_insert(%arg0: i64, %arg1: i64) -> () {
    %232 = llvm.mlir.addressof @cache_cap : !llvm.ptr
    %233 = llvm.load %232 : !llvm.ptr -> i64
    %234 = arith.constant 1 : i32
    %236 = arith.extsi %234 : i32 to i64
    %235 = arith.subi %233, %236 : i64
    %237 = arith.andi %arg0, %235 : i64
    %238 = llvm.mlir.constant(1 : i64) : i64
    %239 = llvm.alloca %238 x i64 : (i64) -> !llvm.ptr
    llvm.store %237, %239 : i64, !llvm.ptr
    cf.br ^bb27
    ^bb27:
    %241 = llvm.mlir.addressof @cache_keys : !llvm.ptr
    %242 = llvm.load %241 : !llvm.ptr -> !llvm.ptr
    %243 = llvm.load %239 : !llvm.ptr -> i64
    %244 = llvm.getelementptr %242[%243] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %240 = llvm.load %244 : !llvm.ptr -> i64
    %245 = arith.constant 1 : i32
    %247 = arith.constant 0 : i32
    %246 = arith.subi %247, %245 : i32
    %249 = arith.extsi %246 : i32 to i64
    %248 = arith.cmpi ne, %240, %249 : i64
    cf.cond_br %248, ^bb28, ^bb29
    ^bb28:
      %251 = llvm.mlir.addressof @cache_keys : !llvm.ptr
      %252 = llvm.load %251 : !llvm.ptr -> !llvm.ptr
      %253 = llvm.load %239 : !llvm.ptr -> i64
      %254 = llvm.getelementptr %252[%253] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %250 = llvm.load %254 : !llvm.ptr -> i64
      %255 = arith.cmpi eq, %250, %arg0 : i64
      cf.cond_br %255, ^bb30, ^bb31
      ^bb30:
        %256 = llvm.mlir.addressof @cache_vals : !llvm.ptr
        %257 = llvm.load %256 : !llvm.ptr -> !llvm.ptr
        %258 = llvm.load %239 : !llvm.ptr -> i64
        %259 = llvm.getelementptr %257[%258] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %arg1, %259 : i64, !llvm.ptr
        func.return
      ^bb31:
        cf.br ^bb32
      ^bb32:
      %260 = llvm.load %239 : !llvm.ptr -> i64
      %261 = arith.constant 1 : i32
      %263 = arith.extsi %261 : i32 to i64
      %262 = arith.addi %260, %263 : i64
      %264 = arith.andi %262, %235 : i64
      llvm.store %264, %239 : i64, !llvm.ptr
      cf.br ^bb27
    ^bb29:
    %265 = llvm.mlir.addressof @cache_keys : !llvm.ptr
    %266 = llvm.load %265 : !llvm.ptr -> !llvm.ptr
    %267 = llvm.load %239 : !llvm.ptr -> i64
    %268 = llvm.getelementptr %266[%267] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %arg0, %268 : i64, !llvm.ptr
    %269 = llvm.mlir.addressof @cache_vals : !llvm.ptr
    %270 = llvm.load %269 : !llvm.ptr -> !llvm.ptr
    %271 = llvm.load %239 : !llvm.ptr -> i64
    %272 = llvm.getelementptr %270[%271] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %arg1, %272 : i64, !llvm.ptr
    func.return
  }
  func.func @denom_coeff(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr, %arg6: !llvm.ptr) -> i64 {
    %273 = arith.constant 0 : i32
    %275 = arith.extsi %273 : i32 to i64
    %274 = arith.cmpi slt, %arg0, %275 : i64
    %276 = scf.if %274 -> (i1) {
      %277 = arith.constant true
      scf.yield %277 : i1
    } else {
      %278 = arith.constant 0 : i32
      %280 = arith.extsi %278 : i32 to i64
      %279 = arith.cmpi slt, %arg1, %280 : i64
      scf.yield %279 : i1
    }
    %281 = scf.if %276 -> (i1) {
      %282 = arith.constant true
      scf.yield %282 : i1
    } else {
      %283 = arith.constant 0 : i32
      %285 = arith.extsi %283 : i32 to i64
      %284 = arith.cmpi slt, %arg2, %285 : i64
      scf.yield %284 : i1
    }
    cf.cond_br %281, ^bb33, ^bb34
    ^bb33:
      %286 = arith.constant 0 : i32
      %287 = arith.extsi %286 : i32 to i64
      func.return %287 : i64
    ^bb34:
      cf.br ^bb35
    ^bb35:
    %288 = arith.xori %arg0, %arg1 : i64
    %289 = arith.constant 2 : i32
    %291 = arith.extsi %289 : i32 to i64
    %290 = arith.remsi %288, %291 : i64
    %292 = arith.constant 0 : i32
    %294 = arith.extsi %292 : i32 to i64
    %293 = arith.cmpi ne, %290, %294 : i64
    %295 = scf.if %293 -> (i1) {
      %296 = arith.constant true
      scf.yield %296 : i1
    } else {
      %297 = arith.xori %arg0, %arg2 : i64
      %298 = arith.constant 2 : i32
      %300 = arith.extsi %298 : i32 to i64
      %299 = arith.remsi %297, %300 : i64
      %301 = arith.constant 0 : i32
      %303 = arith.extsi %301 : i32 to i64
      %302 = arith.cmpi ne, %299, %303 : i64
      scf.yield %302 : i1
    }
    cf.cond_br %295, ^bb36, ^bb37
    ^bb36:
      %304 = arith.constant 0 : i32
      %305 = arith.extsi %304 : i32 to i64
      func.return %305 : i64
    ^bb37:
      cf.br ^bb38
    ^bb38:
    %306 = func.call @pack_key(%arg0, %arg1, %arg2) : (i64, i64, i64) -> i64
    %308 = arith.constant 1 : i32
    %309 = arith.constant 8 : i32
    %310 = arith.extsi %308 : i32 to i64
    %311 = arith.extsi %309 : i32 to i64
    %307 = func.call @calloc(%310, %311) : (i64, i64) -> !llvm.ptr
    %312 = func.call @cache_find(%306, %307) : (i64, !llvm.ptr) -> i32
    %313 = arith.constant 0 : i32
    %314 = arith.cmpi ne, %312, %313 : i32
    cf.cond_br %314, ^bb39, ^bb40
    ^bb39:
      %316 = arith.constant 0 : i32
      %317 = arith.extsi %316 : i32 to i64
      %318 = llvm.getelementptr %307[%317] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %315 = llvm.load %318 : !llvm.ptr -> i64
      func.call @free(%307) : (!llvm.ptr) -> ()
      func.return %315 : i64
    ^bb40:
      cf.br ^bb41
    ^bb41:
    func.call @free(%307) : (!llvm.ptr) -> ()
    %321 = llvm.mlir.constant(1 : i64) : i64
    %322 = llvm.alloca %321 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg0, %322 : i64, !llvm.ptr
    %323 = llvm.load %322 : !llvm.ptr -> i64
    %324 = arith.cmpi slt, %arg1, %323 : i64
    cf.cond_br %324, ^bb42, ^bb43
    ^bb42:
      llvm.store %arg1, %322 : i64, !llvm.ptr
      cf.br ^bb44
    ^bb43:
      cf.br ^bb44
    ^bb44:
    %325 = llvm.load %322 : !llvm.ptr -> i64
    %326 = arith.cmpi slt, %arg2, %325 : i64
    cf.cond_br %326, ^bb45, ^bb46
    ^bb45:
      llvm.store %arg2, %322 : i64, !llvm.ptr
      cf.br ^bb47
    ^bb46:
      cf.br ^bb47
    ^bb47:
    %327 = arith.constant 0 : i32
    %328 = arith.extsi %327 : i32 to i64
    %329 = llvm.mlir.constant(1 : i64) : i64
    %330 = llvm.alloca %329 x i64 : (i64) -> !llvm.ptr
    llvm.store %328, %330 : i64, !llvm.ptr
    %331 = arith.constant 2 : i32
    %333 = arith.extsi %331 : i32 to i64
    %332 = arith.remsi %arg0, %333 : i64
    %334 = llvm.mlir.constant(1 : i64) : i64
    %335 = llvm.alloca %334 x i64 : (i64) -> !llvm.ptr
    llvm.store %332, %335 : i64, !llvm.ptr
    %336 = arith.constant 0 : i32
    %337 = llvm.mlir.constant(1 : i64) : i64
    %338 = llvm.alloca %337 x i32 : (i64) -> !llvm.ptr
    llvm.store %336, %338 : i32, !llvm.ptr
    %339 = llvm.load %335 : !llvm.ptr -> i64
    %340 = llvm.load %322 : !llvm.ptr -> i64
    %341 = arith.cmpi sgt, %339, %340 : i64
    cf.cond_br %341, ^bb48, ^bb49
    ^bb48:
      %342 = arith.constant 1 : i32
      llvm.store %342, %338 : i32, !llvm.ptr
      cf.br ^bb50
    ^bb49:
      cf.br ^bb50
    ^bb50:
    %343 = llvm.load %335 : !llvm.ptr -> i64
    %344 = arith.subi %arg0, %343 : i64
    %345 = arith.constant 2 : i32
    %347 = arith.extsi %345 : i32 to i64
    %346 = arith.divsi %344, %347 : i64
    %348 = llvm.mlir.constant(1 : i64) : i64
    %349 = llvm.alloca %348 x i64 : (i64) -> !llvm.ptr
    llvm.store %346, %349 : i64, !llvm.ptr
    %350 = llvm.load %335 : !llvm.ptr -> i64
    %351 = arith.subi %arg1, %350 : i64
    %352 = arith.constant 2 : i32
    %354 = arith.extsi %352 : i32 to i64
    %353 = arith.divsi %351, %354 : i64
    %355 = llvm.mlir.constant(1 : i64) : i64
    %356 = llvm.alloca %355 x i64 : (i64) -> !llvm.ptr
    llvm.store %353, %356 : i64, !llvm.ptr
    %357 = llvm.load %335 : !llvm.ptr -> i64
    %358 = arith.subi %arg2, %357 : i64
    %359 = arith.constant 2 : i32
    %361 = arith.extsi %359 : i32 to i64
    %360 = arith.divsi %358, %361 : i64
    %362 = llvm.mlir.constant(1 : i64) : i64
    %363 = llvm.alloca %362 x i64 : (i64) -> !llvm.ptr
    llvm.store %360, %363 : i64, !llvm.ptr
    %364 = arith.addi %arg0, %arg1 : i64
    %365 = arith.addi %364, %arg2 : i64
    %366 = llvm.load %335 : !llvm.ptr -> i64
    %367 = arith.subi %365, %366 : i64
    %368 = arith.constant 2 : i32
    %370 = arith.extsi %368 : i32 to i64
    %369 = arith.divsi %367, %370 : i64
    %371 = llvm.mlir.constant(1 : i64) : i64
    %372 = llvm.alloca %371 x i64 : (i64) -> !llvm.ptr
    llvm.store %369, %372 : i64, !llvm.ptr
    %374 = llvm.load %335 : !llvm.ptr -> i64
    %375 = llvm.getelementptr %arg6[%374] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %373 = llvm.load %375 : !llvm.ptr -> i64
    %376 = llvm.mlir.constant(1 : i64) : i64
    %377 = llvm.alloca %376 x i64 : (i64) -> !llvm.ptr
    llvm.store %373, %377 : i64, !llvm.ptr
    %378 = llvm.load %377 : !llvm.ptr -> i64
    %380 = llvm.load %372 : !llvm.ptr -> i64
    %381 = llvm.getelementptr %arg3[%380] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %379 = llvm.load %381 : !llvm.ptr -> i64
    %382 = arith.muli %378, %379 : i64
    %383 = llvm.mlir.addressof @MOD : !llvm.ptr
    %384 = llvm.load %383 : !llvm.ptr -> i64
    %385 = arith.remsi %382, %384 : i64
    llvm.store %385, %377 : i64, !llvm.ptr
    %386 = llvm.load %377 : !llvm.ptr -> i64
    %388 = llvm.load %335 : !llvm.ptr -> i64
    %389 = llvm.getelementptr %arg5[%388] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %387 = llvm.load %389 : !llvm.ptr -> i64
    %390 = arith.muli %386, %387 : i64
    %391 = llvm.mlir.addressof @MOD : !llvm.ptr
    %392 = llvm.load %391 : !llvm.ptr -> i64
    %393 = arith.remsi %390, %392 : i64
    llvm.store %393, %377 : i64, !llvm.ptr
    %394 = llvm.load %377 : !llvm.ptr -> i64
    %396 = llvm.load %349 : !llvm.ptr -> i64
    %397 = llvm.getelementptr %arg5[%396] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %395 = llvm.load %397 : !llvm.ptr -> i64
    %398 = arith.muli %394, %395 : i64
    %399 = llvm.mlir.addressof @MOD : !llvm.ptr
    %400 = llvm.load %399 : !llvm.ptr -> i64
    %401 = arith.remsi %398, %400 : i64
    llvm.store %401, %377 : i64, !llvm.ptr
    %402 = llvm.load %377 : !llvm.ptr -> i64
    %404 = llvm.load %356 : !llvm.ptr -> i64
    %405 = llvm.getelementptr %arg5[%404] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %403 = llvm.load %405 : !llvm.ptr -> i64
    %406 = arith.muli %402, %403 : i64
    %407 = llvm.mlir.addressof @MOD : !llvm.ptr
    %408 = llvm.load %407 : !llvm.ptr -> i64
    %409 = arith.remsi %406, %408 : i64
    llvm.store %409, %377 : i64, !llvm.ptr
    %410 = llvm.load %377 : !llvm.ptr -> i64
    %412 = llvm.load %363 : !llvm.ptr -> i64
    %413 = llvm.getelementptr %arg5[%412] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %411 = llvm.load %413 : !llvm.ptr -> i64
    %414 = arith.muli %410, %411 : i64
    %415 = llvm.mlir.addressof @MOD : !llvm.ptr
    %416 = llvm.load %415 : !llvm.ptr -> i64
    %417 = arith.remsi %414, %416 : i64
    llvm.store %417, %377 : i64, !llvm.ptr
    cf.br ^bb51
    ^bb51:
    %418 = llvm.load %338 : !llvm.ptr -> i32
    %419 = arith.constant 0 : i32
    %420 = arith.cmpi eq, %418, %419 : i32
    cf.cond_br %420, ^bb52, ^bb53
    ^bb52:
      %421 = llvm.load %330 : !llvm.ptr -> i64
      %422 = llvm.load %377 : !llvm.ptr -> i64
      %423 = arith.addi %421, %422 : i64
      llvm.store %423, %330 : i64, !llvm.ptr
      %424 = llvm.load %330 : !llvm.ptr -> i64
      %425 = llvm.mlir.addressof @MOD : !llvm.ptr
      %426 = llvm.load %425 : !llvm.ptr -> i64
      %427 = arith.cmpi sge, %424, %426 : i64
      cf.cond_br %427, ^bb54, ^bb55
      ^bb54:
        %428 = llvm.load %330 : !llvm.ptr -> i64
        %429 = llvm.mlir.addressof @MOD : !llvm.ptr
        %430 = llvm.load %429 : !llvm.ptr -> i64
        %431 = arith.subi %428, %430 : i64
        llvm.store %431, %330 : i64, !llvm.ptr
        cf.br ^bb56
      ^bb55:
        cf.br ^bb56
      ^bb56:
      %432 = llvm.load %335 : !llvm.ptr -> i64
      %433 = arith.constant 2 : i32
      %435 = arith.extsi %433 : i32 to i64
      %434 = arith.addi %432, %435 : i64
      %436 = llvm.load %322 : !llvm.ptr -> i64
      %437 = arith.cmpi sgt, %434, %436 : i64
      cf.cond_br %437, ^bb57, ^bb58
      ^bb57:
        %438 = arith.constant 1 : i32
        llvm.store %438, %338 : i32, !llvm.ptr
        cf.br ^bb59
      ^bb58:
        %439 = arith.constant 4 : i32
        %440 = llvm.load %349 : !llvm.ptr -> i64
        %442 = arith.extsi %439 : i32 to i64
        %441 = arith.muli %442, %440 : i64
        %443 = llvm.mlir.addressof @MOD : !llvm.ptr
        %444 = llvm.load %443 : !llvm.ptr -> i64
        %445 = arith.remsi %441, %444 : i64
        %446 = llvm.mlir.constant(1 : i64) : i64
        %447 = llvm.alloca %446 x i64 : (i64) -> !llvm.ptr
        llvm.store %445, %447 : i64, !llvm.ptr
        %448 = llvm.load %447 : !llvm.ptr -> i64
        %449 = llvm.load %356 : !llvm.ptr -> i64
        %450 = arith.muli %448, %449 : i64
        %451 = llvm.mlir.addressof @MOD : !llvm.ptr
        %452 = llvm.load %451 : !llvm.ptr -> i64
        %453 = arith.remsi %450, %452 : i64
        llvm.store %453, %447 : i64, !llvm.ptr
        %454 = llvm.load %447 : !llvm.ptr -> i64
        %455 = llvm.load %363 : !llvm.ptr -> i64
        %456 = arith.muli %454, %455 : i64
        %457 = llvm.mlir.addressof @MOD : !llvm.ptr
        %458 = llvm.load %457 : !llvm.ptr -> i64
        %459 = arith.remsi %456, %458 : i64
        llvm.store %459, %447 : i64, !llvm.ptr
        %460 = llvm.load %447 : !llvm.ptr -> i64
        %462 = llvm.load %372 : !llvm.ptr -> i64
        %463 = llvm.getelementptr %arg4[%462] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %461 = llvm.load %463 : !llvm.ptr -> i64
        %464 = arith.muli %460, %461 : i64
        %465 = llvm.mlir.addressof @MOD : !llvm.ptr
        %466 = llvm.load %465 : !llvm.ptr -> i64
        %467 = arith.remsi %464, %466 : i64
        llvm.store %467, %447 : i64, !llvm.ptr
        %468 = llvm.load %447 : !llvm.ptr -> i64
        %470 = llvm.load %335 : !llvm.ptr -> i64
        %471 = arith.constant 1 : i32
        %473 = arith.extsi %471 : i32 to i64
        %472 = arith.addi %470, %473 : i64
        %474 = llvm.getelementptr %arg4[%472] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %469 = llvm.load %474 : !llvm.ptr -> i64
        %475 = arith.muli %468, %469 : i64
        %476 = llvm.mlir.addressof @MOD : !llvm.ptr
        %477 = llvm.load %476 : !llvm.ptr -> i64
        %478 = arith.remsi %475, %477 : i64
        llvm.store %478, %447 : i64, !llvm.ptr
        %479 = llvm.load %447 : !llvm.ptr -> i64
        %481 = llvm.load %335 : !llvm.ptr -> i64
        %482 = arith.constant 2 : i32
        %484 = arith.extsi %482 : i32 to i64
        %483 = arith.addi %481, %484 : i64
        %485 = llvm.getelementptr %arg4[%483] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %480 = llvm.load %485 : !llvm.ptr -> i64
        %486 = arith.muli %479, %480 : i64
        %487 = llvm.mlir.addressof @MOD : !llvm.ptr
        %488 = llvm.load %487 : !llvm.ptr -> i64
        %489 = arith.remsi %486, %488 : i64
        llvm.store %489, %447 : i64, !llvm.ptr
        %490 = llvm.load %377 : !llvm.ptr -> i64
        %491 = llvm.load %447 : !llvm.ptr -> i64
        %492 = arith.muli %490, %491 : i64
        %493 = llvm.mlir.addressof @MOD : !llvm.ptr
        %494 = llvm.load %493 : !llvm.ptr -> i64
        %495 = arith.remsi %492, %494 : i64
        llvm.store %495, %377 : i64, !llvm.ptr
        llvm.store %434, %335 : i64, !llvm.ptr
        %496 = llvm.load %349 : !llvm.ptr -> i64
        %497 = arith.constant 1 : i32
        %499 = arith.extsi %497 : i32 to i64
        %498 = arith.subi %496, %499 : i64
        llvm.store %498, %349 : i64, !llvm.ptr
        %500 = llvm.load %356 : !llvm.ptr -> i64
        %501 = arith.constant 1 : i32
        %503 = arith.extsi %501 : i32 to i64
        %502 = arith.subi %500, %503 : i64
        llvm.store %502, %356 : i64, !llvm.ptr
        %504 = llvm.load %363 : !llvm.ptr -> i64
        %505 = arith.constant 1 : i32
        %507 = arith.extsi %505 : i32 to i64
        %506 = arith.subi %504, %507 : i64
        llvm.store %506, %363 : i64, !llvm.ptr
        %508 = llvm.load %372 : !llvm.ptr -> i64
        %509 = arith.constant 1 : i32
        %511 = arith.extsi %509 : i32 to i64
        %510 = arith.subi %508, %511 : i64
        llvm.store %510, %372 : i64, !llvm.ptr
        cf.br ^bb59
      ^bb59:
      cf.br ^bb51
    ^bb53:
    %513 = llvm.load %330 : !llvm.ptr -> i64
    func.call @cache_insert(%306, %513) : (i64, i64) -> ()
    %514 = llvm.load %330 : !llvm.ptr -> i64
    func.return %514 : i64
  }
  func.func @full_coeff(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr, %arg6: !llvm.ptr) -> i64 {
    %515 = func.call @denom_coeff(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6) : (i64, i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %516 = llvm.mlir.constant(1 : i64) : i64
    %517 = llvm.alloca %516 x i64 : (i64) -> !llvm.ptr
    llvm.store %515, %517 : i64, !llvm.ptr
    %518 = llvm.load %517 : !llvm.ptr -> i64
    %520 = arith.constant 1 : i32
    %522 = arith.extsi %520 : i32 to i64
    %521 = arith.subi %arg0, %522 : i64
    %519 = func.call @denom_coeff(%521, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6) : (i64, i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %523 = arith.addi %518, %519 : i64
    llvm.store %523, %517 : i64, !llvm.ptr
    %524 = llvm.load %517 : !llvm.ptr -> i64
    %525 = llvm.mlir.addressof @MOD : !llvm.ptr
    %526 = llvm.load %525 : !llvm.ptr -> i64
    %527 = arith.cmpi sge, %524, %526 : i64
    cf.cond_br %527, ^bb60, ^bb61
    ^bb60:
      %528 = llvm.load %517 : !llvm.ptr -> i64
      %529 = llvm.mlir.addressof @MOD : !llvm.ptr
      %530 = llvm.load %529 : !llvm.ptr -> i64
      %531 = arith.subi %528, %530 : i64
      llvm.store %531, %517 : i64, !llvm.ptr
      cf.br ^bb62
    ^bb61:
      cf.br ^bb62
    ^bb62:
    %532 = llvm.load %517 : !llvm.ptr -> i64
    %534 = arith.constant 1 : i32
    %536 = arith.extsi %534 : i32 to i64
    %535 = arith.subi %arg2, %536 : i64
    %533 = func.call @denom_coeff(%arg0, %arg1, %535, %arg3, %arg4, %arg5, %arg6) : (i64, i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %537 = arith.addi %532, %533 : i64
    llvm.store %537, %517 : i64, !llvm.ptr
    %538 = llvm.load %517 : !llvm.ptr -> i64
    %539 = llvm.mlir.addressof @MOD : !llvm.ptr
    %540 = llvm.load %539 : !llvm.ptr -> i64
    %541 = arith.cmpi sge, %538, %540 : i64
    cf.cond_br %541, ^bb63, ^bb64
    ^bb63:
      %542 = llvm.load %517 : !llvm.ptr -> i64
      %543 = llvm.mlir.addressof @MOD : !llvm.ptr
      %544 = llvm.load %543 : !llvm.ptr -> i64
      %545 = arith.subi %542, %544 : i64
      llvm.store %545, %517 : i64, !llvm.ptr
      cf.br ^bb65
    ^bb64:
      cf.br ^bb65
    ^bb65:
    %546 = llvm.load %517 : !llvm.ptr -> i64
    %548 = arith.constant 1 : i32
    %550 = arith.extsi %548 : i32 to i64
    %549 = arith.subi %arg0, %550 : i64
    %551 = arith.constant 1 : i32
    %553 = arith.extsi %551 : i32 to i64
    %552 = arith.subi %arg1, %553 : i64
    %547 = func.call @denom_coeff(%549, %552, %arg2, %arg3, %arg4, %arg5, %arg6) : (i64, i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %554 = arith.addi %546, %547 : i64
    llvm.store %554, %517 : i64, !llvm.ptr
    %555 = llvm.load %517 : !llvm.ptr -> i64
    %556 = llvm.mlir.addressof @MOD : !llvm.ptr
    %557 = llvm.load %556 : !llvm.ptr -> i64
    %558 = arith.cmpi sge, %555, %557 : i64
    cf.cond_br %558, ^bb66, ^bb67
    ^bb66:
      %559 = llvm.load %517 : !llvm.ptr -> i64
      %560 = llvm.mlir.addressof @MOD : !llvm.ptr
      %561 = llvm.load %560 : !llvm.ptr -> i64
      %562 = arith.subi %559, %561 : i64
      llvm.store %562, %517 : i64, !llvm.ptr
      cf.br ^bb68
    ^bb67:
      cf.br ^bb68
    ^bb68:
    %563 = llvm.load %517 : !llvm.ptr -> i64
    %565 = arith.constant 1 : i32
    %567 = arith.extsi %565 : i32 to i64
    %566 = arith.subi %arg1, %567 : i64
    %568 = arith.constant 1 : i32
    %570 = arith.extsi %568 : i32 to i64
    %569 = arith.subi %arg2, %570 : i64
    %564 = func.call @denom_coeff(%arg0, %566, %569, %arg3, %arg4, %arg5, %arg6) : (i64, i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %571 = arith.addi %563, %564 : i64
    llvm.store %571, %517 : i64, !llvm.ptr
    %572 = llvm.load %517 : !llvm.ptr -> i64
    %573 = llvm.mlir.addressof @MOD : !llvm.ptr
    %574 = llvm.load %573 : !llvm.ptr -> i64
    %575 = arith.cmpi sge, %572, %574 : i64
    cf.cond_br %575, ^bb69, ^bb70
    ^bb69:
      %576 = llvm.load %517 : !llvm.ptr -> i64
      %577 = llvm.mlir.addressof @MOD : !llvm.ptr
      %578 = llvm.load %577 : !llvm.ptr -> i64
      %579 = arith.subi %576, %578 : i64
      llvm.store %579, %517 : i64, !llvm.ptr
      cf.br ^bb71
    ^bb70:
      cf.br ^bb71
    ^bb71:
    %580 = llvm.load %517 : !llvm.ptr -> i64
    %582 = arith.constant 2 : i32
    %584 = arith.extsi %582 : i32 to i64
    %583 = arith.subi %arg1, %584 : i64
    %581 = func.call @denom_coeff(%arg0, %583, %arg2, %arg3, %arg4, %arg5, %arg6) : (i64, i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %585 = arith.subi %580, %581 : i64
    llvm.store %585, %517 : i64, !llvm.ptr
    %586 = llvm.load %517 : !llvm.ptr -> i64
    %587 = arith.constant 0 : i32
    %589 = arith.extsi %587 : i32 to i64
    %588 = arith.cmpi slt, %586, %589 : i64
    cf.cond_br %588, ^bb72, ^bb73
    ^bb72:
      %590 = llvm.load %517 : !llvm.ptr -> i64
      %591 = llvm.mlir.addressof @MOD : !llvm.ptr
      %592 = llvm.load %591 : !llvm.ptr -> i64
      %593 = arith.addi %590, %592 : i64
      llvm.store %593, %517 : i64, !llvm.ptr
      cf.br ^bb74
    ^bb73:
      cf.br ^bb74
    ^bb74:
    %594 = llvm.load %517 : !llvm.ptr -> i64
    func.return %594 : i64
  }
  func.func @main() -> i32 {
    %595 = arith.constant 100000 : i32
    %596 = arith.extsi %595 : i32 to i64
    %597 = arith.constant 2 : i32
    %599 = arith.extsi %597 : i32 to i64
    %598 = arith.remsi %596, %599 : i64
    %600 = arith.constant 0 : i32
    %602 = arith.extsi %600 : i32 to i64
    %601 = arith.cmpi ne, %598, %602 : i64
    cf.cond_br %601, ^bb75, ^bb76
    ^bb75:
      %603 = llvm.mlir.addressof @str_0 : !llvm.ptr
      %604 = arith.constant 0 : i32
      %605 = llvm.call @printf(%603, %604) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i32) -> i32
      %606 = arith.constant 0 : i32
      func.return %606 : i32
    ^bb76:
      cf.br ^bb77
    ^bb77:
    %607 = arith.constant 5 : i32
    %609 = arith.extsi %607 : i32 to i64
    %608 = arith.addi %596, %609 : i64
    %611 = arith.constant 1 : i32
    %613 = arith.extsi %611 : i32 to i64
    %612 = arith.addi %608, %613 : i64
    %614 = arith.constant 8 : i32
    %615 = arith.extsi %614 : i32 to i64
    %610 = func.call @calloc(%612, %615) : (i64, i64) -> !llvm.ptr
    %617 = arith.constant 1 : i32
    %619 = arith.extsi %617 : i32 to i64
    %618 = arith.addi %608, %619 : i64
    %620 = arith.constant 8 : i32
    %621 = arith.extsi %620 : i32 to i64
    %616 = func.call @calloc(%618, %621) : (i64, i64) -> !llvm.ptr
    %623 = arith.constant 1 : i32
    %625 = arith.extsi %623 : i32 to i64
    %624 = arith.addi %608, %625 : i64
    %626 = arith.constant 8 : i32
    %627 = arith.extsi %626 : i32 to i64
    %622 = func.call @calloc(%624, %627) : (i64, i64) -> !llvm.ptr
    %629 = arith.constant 1 : i32
    %631 = arith.extsi %629 : i32 to i64
    %630 = arith.addi %608, %631 : i64
    %632 = arith.constant 8 : i32
    %633 = arith.extsi %632 : i32 to i64
    %628 = func.call @calloc(%630, %633) : (i64, i64) -> !llvm.ptr
    func.call @precompute(%608, %610, %616, %622, %628) : (i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
    %636 = arith.constant 1 : i32
    %637 = arith.constant 16 : i32
    %638 = arith.shli %636, %637 : i32
    %639 = arith.extsi %638 : i32 to i64
    func.call @cache_init(%639) : (i64) -> ()
    %641 = arith.constant 32 : i32
    %642 = arith.constant 8 : i32
    %643 = arith.extsi %641 : i32 to i64
    %644 = arith.extsi %642 : i32 to i64
    %640 = func.call @calloc(%643, %644) : (i64, i64) -> !llvm.ptr
    %645 = arith.constant 0 : i32
    %646 = arith.extsi %645 : i32 to i64
    %647 = llvm.mlir.constant(1 : i64) : i64
    %648 = llvm.alloca %647 x i64 : (i64) -> !llvm.ptr
    llvm.store %646, %648 : i64, !llvm.ptr
    %649 = llvm.mlir.constant(1 : i64) : i64
    %650 = llvm.alloca %649 x i64 : (i64) -> !llvm.ptr
    llvm.store %596, %650 : i64, !llvm.ptr
    %651 = arith.constant 0 : i32
    %652 = arith.extsi %651 : i32 to i64
    %653 = llvm.mlir.constant(1 : i64) : i64
    %654 = llvm.alloca %653 x i64 : (i64) -> !llvm.ptr
    llvm.store %652, %654 : i64, !llvm.ptr
    cf.br ^bb78
    ^bb78:
    %655 = llvm.load %650 : !llvm.ptr -> i64
    %656 = arith.constant 0 : i32
    %658 = arith.extsi %656 : i32 to i64
    %657 = arith.cmpi ne, %655, %658 : i64
    cf.cond_br %657, ^bb79, ^bb80
    ^bb79:
      %659 = llvm.load %650 : !llvm.ptr -> i64
      %660 = arith.constant 2 : i32
      %662 = arith.extsi %660 : i32 to i64
      %661 = arith.remsi %659, %662 : i64
      %663 = arith.constant 1 : i32
      %665 = arith.extsi %663 : i32 to i64
      %664 = arith.cmpi eq, %661, %665 : i64
      cf.cond_br %664, ^bb81, ^bb82
      ^bb81:
        %666 = llvm.load %654 : !llvm.ptr -> i64
        %667 = llvm.load %648 : !llvm.ptr -> i64
        %668 = llvm.getelementptr %640[%667] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %666, %668 : i64, !llvm.ptr
        %669 = llvm.load %648 : !llvm.ptr -> i64
        %670 = arith.constant 1 : i32
        %672 = arith.extsi %670 : i32 to i64
        %671 = arith.addi %669, %672 : i64
        llvm.store %671, %648 : i64, !llvm.ptr
        cf.br ^bb83
      ^bb82:
        cf.br ^bb83
      ^bb83:
      %673 = llvm.load %650 : !llvm.ptr -> i64
      %674 = arith.constant 2 : i32
      %676 = arith.extsi %674 : i32 to i64
      %675 = arith.divsi %673, %676 : i64
      llvm.store %675, %650 : i64, !llvm.ptr
      %677 = llvm.load %654 : !llvm.ptr -> i64
      %678 = arith.constant 1 : i32
      %680 = arith.extsi %678 : i32 to i64
      %679 = arith.addi %677, %680 : i64
      llvm.store %679, %654 : i64, !llvm.ptr
      cf.br ^bb78
    ^bb80:
    %681 = arith.constant 1 : i32
    %682 = arith.extsi %681 : i32 to i64
    %683 = llvm.mlir.constant(1 : i64) : i64
    %684 = llvm.alloca %683 x i64 : (i64) -> !llvm.ptr
    llvm.store %682, %684 : i64, !llvm.ptr
    %685 = arith.constant 0 : i32
    %686 = arith.extsi %685 : i32 to i64
    %687 = llvm.mlir.constant(1 : i64) : i64
    %688 = llvm.alloca %687 x i64 : (i64) -> !llvm.ptr
    llvm.store %686, %688 : i64, !llvm.ptr
    cf.br ^bb84
    ^bb84:
    %689 = llvm.load %688 : !llvm.ptr -> i64
    %690 = llvm.load %648 : !llvm.ptr -> i64
    %691 = arith.cmpi slt, %689, %690 : i64
    cf.cond_br %691, ^bb85, ^bb86
    ^bb85:
      %693 = llvm.load %688 : !llvm.ptr -> i64
      %694 = llvm.getelementptr %640[%693] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %692 = llvm.load %694 : !llvm.ptr -> i64
      %695 = arith.constant 0 : i32
      %697 = arith.extsi %695 : i32 to i64
      %696 = arith.cmpi ne, %692, %697 : i64
      cf.cond_br %696, ^bb87, ^bb88
      ^bb87:
        %698 = llvm.load %684 : !llvm.ptr -> i64
        %699 = arith.constant 3 : i32
        %701 = arith.extsi %699 : i32 to i64
        %700 = arith.muli %698, %701 : i64
        llvm.store %700, %684 : i64, !llvm.ptr
        cf.br ^bb89
      ^bb88:
        cf.br ^bb89
      ^bb89:
      %702 = llvm.load %688 : !llvm.ptr -> i64
      %703 = arith.constant 1 : i32
      %705 = arith.extsi %703 : i32 to i64
      %704 = arith.addi %702, %705 : i64
      llvm.store %704, %688 : i64, !llvm.ptr
      cf.br ^bb84
    ^bb86:
    %707 = llvm.load %684 : !llvm.ptr -> i64
    %708 = arith.constant 3 : i32
    %710 = arith.extsi %708 : i32 to i64
    %709 = arith.muli %707, %710 : i64
    %711 = arith.constant 8 : i32
    %712 = arith.extsi %711 : i32 to i64
    %706 = func.call @calloc(%709, %712) : (i64, i64) -> !llvm.ptr
    %713 = arith.constant 0 : i32
    %714 = arith.constant 0 : i32
    %715 = arith.extsi %713 : i32 to i64
    %716 = arith.extsi %714 : i32 to i64
    %717 = llvm.getelementptr %706[%716] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %715, %717 : i64, !llvm.ptr
    %718 = arith.constant 0 : i32
    %719 = arith.constant 1 : i32
    %720 = arith.extsi %718 : i32 to i64
    %721 = arith.extsi %719 : i32 to i64
    %722 = llvm.getelementptr %706[%721] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %720, %722 : i64, !llvm.ptr
    %723 = arith.constant 0 : i32
    %724 = arith.constant 2 : i32
    %725 = arith.extsi %723 : i32 to i64
    %726 = arith.extsi %724 : i32 to i64
    %727 = llvm.getelementptr %706[%726] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %725, %727 : i64, !llvm.ptr
    %728 = arith.constant 1 : i32
    %729 = arith.extsi %728 : i32 to i64
    %730 = llvm.mlir.constant(1 : i64) : i64
    %731 = llvm.alloca %730 x i64 : (i64) -> !llvm.ptr
    llvm.store %729, %731 : i64, !llvm.ptr
    %732 = arith.constant 0 : i32
    %733 = arith.extsi %732 : i32 to i64
    llvm.store %733, %688 : i64, !llvm.ptr
    cf.br ^bb90
    ^bb90:
    %734 = llvm.load %688 : !llvm.ptr -> i64
    %735 = llvm.load %648 : !llvm.ptr -> i64
    %736 = arith.cmpi slt, %734, %735 : i64
    cf.cond_br %736, ^bb91, ^bb92
    ^bb91:
      %738 = llvm.load %688 : !llvm.ptr -> i64
      %739 = llvm.getelementptr %640[%738] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %737 = llvm.load %739 : !llvm.ptr -> i64
      %740 = arith.constant 0 : i32
      %742 = arith.extsi %740 : i32 to i64
      %741 = arith.cmpi eq, %737, %742 : i64
      cf.cond_br %741, ^bb93, ^bb94
      ^bb93:
        cf.br ^bb95
      ^bb94:
        %743 = arith.constant 1 : i32
        %744 = arith.constant 1 : i32
        %746 = arith.extsi %744 : i32 to i64
        %745 = arith.subi %737, %746 : i64
        %748 = arith.extsi %743 : i32 to i64
        %747 = arith.shli %748, %745 : i64
        %749 = llvm.load %731 : !llvm.ptr -> i64
        %750 = arith.constant 0 : i32
        %751 = arith.extsi %750 : i32 to i64
        %752 = llvm.mlir.constant(1 : i64) : i64
        %753 = llvm.alloca %752 x i64 : (i64) -> !llvm.ptr
        llvm.store %751, %753 : i64, !llvm.ptr
        cf.br ^bb96
        ^bb96:
        %754 = llvm.load %753 : !llvm.ptr -> i64
        %755 = arith.cmpi slt, %754, %749 : i64
        cf.cond_br %755, ^bb97, ^bb98
        ^bb97:
          %757 = llvm.load %753 : !llvm.ptr -> i64
          %758 = arith.constant 3 : i32
          %760 = arith.extsi %758 : i32 to i64
          %759 = arith.muli %757, %760 : i64
          %761 = llvm.getelementptr %706[%759] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %756 = llvm.load %761 : !llvm.ptr -> i64
          %763 = llvm.load %753 : !llvm.ptr -> i64
          %764 = arith.constant 3 : i32
          %766 = arith.extsi %764 : i32 to i64
          %765 = arith.muli %763, %766 : i64
          %767 = arith.constant 1 : i32
          %769 = arith.extsi %767 : i32 to i64
          %768 = arith.addi %765, %769 : i64
          %770 = llvm.getelementptr %706[%768] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %762 = llvm.load %770 : !llvm.ptr -> i64
          %772 = llvm.load %753 : !llvm.ptr -> i64
          %773 = arith.constant 3 : i32
          %775 = arith.extsi %773 : i32 to i64
          %774 = arith.muli %772, %775 : i64
          %776 = arith.constant 2 : i32
          %778 = arith.extsi %776 : i32 to i64
          %777 = arith.addi %774, %778 : i64
          %779 = llvm.getelementptr %706[%777] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %771 = llvm.load %779 : !llvm.ptr -> i64
          %780 = arith.addi %756, %747 : i64
          %781 = llvm.load %753 : !llvm.ptr -> i64
          %782 = arith.constant 3 : i32
          %784 = arith.extsi %782 : i32 to i64
          %783 = arith.muli %781, %784 : i64
          %785 = llvm.getelementptr %706[%783] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %780, %785 : i64, !llvm.ptr
          %786 = arith.addi %762, %747 : i64
          %787 = llvm.load %753 : !llvm.ptr -> i64
          %788 = arith.constant 3 : i32
          %790 = arith.extsi %788 : i32 to i64
          %789 = arith.muli %787, %790 : i64
          %791 = arith.constant 1 : i32
          %793 = arith.extsi %791 : i32 to i64
          %792 = arith.addi %789, %793 : i64
          %794 = llvm.getelementptr %706[%792] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %786, %794 : i64, !llvm.ptr
          %795 = llvm.load %753 : !llvm.ptr -> i64
          %796 = arith.constant 3 : i32
          %798 = arith.extsi %796 : i32 to i64
          %797 = arith.muli %795, %798 : i64
          %799 = arith.constant 2 : i32
          %801 = arith.extsi %799 : i32 to i64
          %800 = arith.addi %797, %801 : i64
          %802 = llvm.getelementptr %706[%800] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %771, %802 : i64, !llvm.ptr
          %803 = arith.addi %756, %747 : i64
          %804 = llvm.load %753 : !llvm.ptr -> i64
          %805 = arith.addi %749, %804 : i64
          %806 = arith.constant 3 : i32
          %808 = arith.extsi %806 : i32 to i64
          %807 = arith.muli %805, %808 : i64
          %809 = llvm.getelementptr %706[%807] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %803, %809 : i64, !llvm.ptr
          %810 = llvm.load %753 : !llvm.ptr -> i64
          %811 = arith.addi %749, %810 : i64
          %812 = arith.constant 3 : i32
          %814 = arith.extsi %812 : i32 to i64
          %813 = arith.muli %811, %814 : i64
          %815 = arith.constant 1 : i32
          %817 = arith.extsi %815 : i32 to i64
          %816 = arith.addi %813, %817 : i64
          %818 = llvm.getelementptr %706[%816] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %762, %818 : i64, !llvm.ptr
          %819 = arith.addi %771, %747 : i64
          %820 = llvm.load %753 : !llvm.ptr -> i64
          %821 = arith.addi %749, %820 : i64
          %822 = arith.constant 3 : i32
          %824 = arith.extsi %822 : i32 to i64
          %823 = arith.muli %821, %824 : i64
          %825 = arith.constant 2 : i32
          %827 = arith.extsi %825 : i32 to i64
          %826 = arith.addi %823, %827 : i64
          %828 = llvm.getelementptr %706[%826] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %819, %828 : i64, !llvm.ptr
          %829 = arith.constant 2 : i32
          %831 = arith.extsi %829 : i32 to i64
          %830 = arith.muli %831, %749 : i64
          %832 = llvm.load %753 : !llvm.ptr -> i64
          %833 = arith.addi %830, %832 : i64
          %834 = arith.constant 3 : i32
          %836 = arith.extsi %834 : i32 to i64
          %835 = arith.muli %833, %836 : i64
          %837 = llvm.getelementptr %706[%835] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %756, %837 : i64, !llvm.ptr
          %838 = arith.addi %762, %747 : i64
          %839 = arith.constant 2 : i32
          %841 = arith.extsi %839 : i32 to i64
          %840 = arith.muli %841, %749 : i64
          %842 = llvm.load %753 : !llvm.ptr -> i64
          %843 = arith.addi %840, %842 : i64
          %844 = arith.constant 3 : i32
          %846 = arith.extsi %844 : i32 to i64
          %845 = arith.muli %843, %846 : i64
          %847 = arith.constant 1 : i32
          %849 = arith.extsi %847 : i32 to i64
          %848 = arith.addi %845, %849 : i64
          %850 = llvm.getelementptr %706[%848] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %838, %850 : i64, !llvm.ptr
          %851 = arith.addi %771, %747 : i64
          %852 = arith.constant 2 : i32
          %854 = arith.extsi %852 : i32 to i64
          %853 = arith.muli %854, %749 : i64
          %855 = llvm.load %753 : !llvm.ptr -> i64
          %856 = arith.addi %853, %855 : i64
          %857 = arith.constant 3 : i32
          %859 = arith.extsi %857 : i32 to i64
          %858 = arith.muli %856, %859 : i64
          %860 = arith.constant 2 : i32
          %862 = arith.extsi %860 : i32 to i64
          %861 = arith.addi %858, %862 : i64
          %863 = llvm.getelementptr %706[%861] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %851, %863 : i64, !llvm.ptr
          %864 = llvm.load %753 : !llvm.ptr -> i64
          %865 = arith.constant 1 : i32
          %867 = arith.extsi %865 : i32 to i64
          %866 = arith.addi %864, %867 : i64
          llvm.store %866, %753 : i64, !llvm.ptr
          cf.br ^bb96
        ^bb98:
        %868 = arith.constant 3 : i32
        %870 = arith.extsi %868 : i32 to i64
        %869 = arith.muli %870, %749 : i64
        llvm.store %869, %731 : i64, !llvm.ptr
        cf.br ^bb95
      ^bb95:
      %871 = llvm.load %688 : !llvm.ptr -> i64
      %872 = arith.constant 1 : i32
      %874 = arith.extsi %872 : i32 to i64
      %873 = arith.addi %871, %874 : i64
      llvm.store %873, %688 : i64, !llvm.ptr
      cf.br ^bb90
    ^bb92:
    %875 = arith.constant 0 : i32
    %876 = arith.extsi %875 : i32 to i64
    %877 = llvm.mlir.constant(1 : i64) : i64
    %878 = llvm.alloca %877 x i64 : (i64) -> !llvm.ptr
    llvm.store %876, %878 : i64, !llvm.ptr
    %879 = arith.constant 0 : i32
    %880 = arith.extsi %879 : i32 to i64
    %881 = llvm.mlir.constant(1 : i64) : i64
    %882 = llvm.alloca %881 x i64 : (i64) -> !llvm.ptr
    llvm.store %880, %882 : i64, !llvm.ptr
    cf.br ^bb99
    ^bb99:
    %883 = llvm.load %882 : !llvm.ptr -> i64
    %884 = llvm.load %731 : !llvm.ptr -> i64
    %885 = arith.cmpi slt, %883, %884 : i64
    cf.cond_br %885, ^bb100, ^bb101
    ^bb100:
      %886 = llvm.load %878 : !llvm.ptr -> i64
      %889 = llvm.load %882 : !llvm.ptr -> i64
      %890 = arith.constant 3 : i32
      %892 = arith.extsi %890 : i32 to i64
      %891 = arith.muli %889, %892 : i64
      %893 = llvm.getelementptr %706[%891] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %888 = llvm.load %893 : !llvm.ptr -> i64
      %895 = llvm.load %882 : !llvm.ptr -> i64
      %896 = arith.constant 3 : i32
      %898 = arith.extsi %896 : i32 to i64
      %897 = arith.muli %895, %898 : i64
      %899 = arith.constant 1 : i32
      %901 = arith.extsi %899 : i32 to i64
      %900 = arith.addi %897, %901 : i64
      %902 = llvm.getelementptr %706[%900] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %894 = llvm.load %902 : !llvm.ptr -> i64
      %904 = llvm.load %882 : !llvm.ptr -> i64
      %905 = arith.constant 3 : i32
      %907 = arith.extsi %905 : i32 to i64
      %906 = arith.muli %904, %907 : i64
      %908 = arith.constant 2 : i32
      %910 = arith.extsi %908 : i32 to i64
      %909 = arith.addi %906, %910 : i64
      %911 = llvm.getelementptr %706[%909] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %903 = llvm.load %911 : !llvm.ptr -> i64
      %887 = func.call @full_coeff(%888, %894, %903, %610, %616, %622, %628) : (i64, i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
      %912 = arith.addi %886, %887 : i64
      llvm.store %912, %878 : i64, !llvm.ptr
      %913 = llvm.load %878 : !llvm.ptr -> i64
      %914 = llvm.mlir.addressof @MOD : !llvm.ptr
      %915 = llvm.load %914 : !llvm.ptr -> i64
      %916 = arith.cmpi sge, %913, %915 : i64
      cf.cond_br %916, ^bb102, ^bb103
      ^bb102:
        %917 = llvm.load %878 : !llvm.ptr -> i64
        %918 = llvm.mlir.addressof @MOD : !llvm.ptr
        %919 = llvm.load %918 : !llvm.ptr -> i64
        %920 = arith.subi %917, %919 : i64
        llvm.store %920, %878 : i64, !llvm.ptr
        cf.br ^bb104
      ^bb103:
        cf.br ^bb104
      ^bb104:
      %921 = llvm.load %882 : !llvm.ptr -> i64
      %922 = arith.constant 1 : i32
      %924 = arith.extsi %922 : i32 to i64
      %923 = arith.addi %921, %924 : i64
      llvm.store %923, %882 : i64, !llvm.ptr
      cf.br ^bb99
    ^bb101:
    %926 = llvm.getelementptr %628[%596] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %925 = llvm.load %926 : !llvm.ptr -> i64
    %927 = arith.constant 1 : i32
    %929 = arith.extsi %927 : i32 to i64
    %928 = arith.subi %925, %929 : i64
    %930 = llvm.mlir.addressof @MOD : !llvm.ptr
    %931 = llvm.load %930 : !llvm.ptr -> i64
    %932 = arith.addi %928, %931 : i64
    %933 = llvm.mlir.addressof @MOD : !llvm.ptr
    %934 = llvm.load %933 : !llvm.ptr -> i64
    %935 = arith.remsi %932, %934 : i64
    %936 = llvm.load %878 : !llvm.ptr -> i64
    %937 = arith.muli %936, %935 : i64
    %938 = llvm.mlir.addressof @MOD : !llvm.ptr
    %939 = llvm.load %938 : !llvm.ptr -> i64
    %940 = arith.remsi %937, %939 : i64
    %941 = llvm.mlir.addressof @INV2 : !llvm.ptr
    %942 = llvm.load %941 : !llvm.ptr -> i64
    %943 = arith.muli %940, %942 : i64
    %944 = llvm.mlir.addressof @MOD : !llvm.ptr
    %945 = llvm.load %944 : !llvm.ptr -> i64
    %946 = arith.remsi %943, %945 : i64
    %947 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %948 = llvm.call @printf(%947, %946) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    func.call @free(%610) : (!llvm.ptr) -> ()
    func.call @free(%616) : (!llvm.ptr) -> ()
    func.call @free(%622) : (!llvm.ptr) -> ()
    func.call @free(%628) : (!llvm.ptr) -> ()
    %954 = llvm.mlir.addressof @cache_keys : !llvm.ptr
    %955 = llvm.load %954 : !llvm.ptr -> !llvm.ptr
    func.call @free(%955) : (!llvm.ptr) -> ()
    %957 = llvm.mlir.addressof @cache_vals : !llvm.ptr
    %958 = llvm.load %957 : !llvm.ptr -> !llvm.ptr
    func.call @free(%958) : (!llvm.ptr) -> ()
    func.call @free(%706) : (!llvm.ptr) -> ()
    func.call @free(%640) : (!llvm.ptr) -> ()
    %961 = arith.constant 0 : i32
    func.return %961 : i32
  }
}