Problem 929

Compute F(10^5) mod 1111124111, where F(n) counts compositions of n whose maximal runs of equal parts all have odd length. Uses NTT (Number Theoretic Transform) with 3 primes and CRT for exact polynomial multiplication, plus Newton iteration for series inversion. Pure Flow port of the native C solver.

Answer57322484
Output57322484
StatusPASS
Native helperno
Runtime1610 ms
Peak memory30560 KB
Time complexityO(n^2) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^2)O(n log n)
Space complexityO(n^2)O(n)
ApproachFlow solutionChinese Remainder Theorem
VerdictSuboptimal

Flow source

# Project Euler 929: Odd-Run Compositions
# Compute F(10^5) mod 1111124111, where F(n) counts compositions of n
# whose maximal runs of equal parts all have odd length.
# Uses NTT (Number Theoretic Transform) with 3 primes and CRT
# for exact polynomial multiplication, plus Newton iteration for
# series inversion.
# Pure Flow port of the native C solver.

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
    function malloc(n: i64) -> ptr<void>
    function realloc(p: ptr<void>, n: i64) -> ptr<void>
    function printf(fmt: ptr<i8>, ...) -> i32
}

const MOD: i64 = 1111124111
const N: i32 = 100000

# NTT primes
const NTT_P0: i64 = 998244353
const NTT_P1: i64 = 1004535809
const NTT_P2: i64 = 754974721
const NTT_G0: i64 = 3
const NTT_G1: i64 = 3
const NTT_G2: i64 = 11

# CRT precomputed coefficients
let mut p1_mod_p2_inv: i64 = 0
let mut p12_mod_p3_inv: i64 = 0
let mut p1_mod_MOD: i64 = 0
let mut p12_mod_MOD: i64 = 0

# NTT bit-reversal
let mut ntt_rev: ptr<i32> = null as ptr<i32>
let mut ntt_rev_n: i32 = 0

function mulmod(a: i64, b: i64, mod: i64) -> i64 {
    return ((a as i128) * (b as i128) % (mod as i128)) as i64
}

function powmod(a0: i64, e0: i64, mod: i64) -> i64 {
    let mut r: i64 = 1 % mod
    let mut a: i64 = a0 % mod
    if a < 0 { a = a + mod }
    let mut e: i64 = e0
    while e > 0 {
        if (e & 1) != 0 { r = mulmod(r, a, mod) }
        a = mulmod(a, a, mod)
        e = e >> 1
    }
    return r
}

function modinv(a: i64, mod: i64) -> i64 {
    return powmod(a, mod - 2, mod)
}

function ntt_bitrev(n: i32) -> void {
    if ntt_rev_n != n {
        ntt_rev = (realloc(ntt_rev as ptr<void>, (n as i64) * 4)) as ptr<i32>
        ntt_rev_n = n
    }
    let mut logn: i32 = 0
    let mut tmp: i32 = n
    while tmp > 1 {
        logn = logn + 1
        tmp = tmp >> 1
    }
    ntt_rev[0] = 0
    let mut i: i32 = 1
    while i < n {
        ntt_rev[i] = (ntt_rev[i >> 1] >> 1) | ((i & 1) << (logn - 1))
        i = i + 1
    }
}

function ntt(a: ptr<i64>, n: i32, invert: i32, mod: i64, gen: i64) -> void {
    let mut i: i32 = 0
    while i < n {
        let j: i32 = ntt_rev[i]
        if i < j {
            let t: i64 = a[i]
            a[i] = a[j]
            a[j] = t
        }
        i = i + 1
    }

    let mut len: i32 = 2
    while len <= n {
        let half: i32 = len >> 1
        let mut w: i64 = 0
        if invert != 0 {
            w = powmod(gen, (mod - 1) - (mod - 1) / (len as i64), mod)
        } else {
            w = powmod(gen, (mod - 1) / (len as i64), mod)
        }
        let mut ii: i32 = 0
        while ii < n {
            let mut wk: i64 = 1
            let mut jj: i32 = 0
            while jj < half {
                let u: i64 = a[ii + jj]
                let v: i64 = mulmod(a[ii + jj + half], wk, mod)
                a[ii + jj] = (u + v) % mod
                a[ii + jj + half] = ((u - v) % mod + mod) % mod
                wk = mulmod(wk, w, mod)
                jj = jj + 1
            }
            ii = ii + len
        }
        len = len << 1
    }

    if invert != 0 {
        let inv_n: i64 = modinv((n as i64), mod)
        let mut iii: i32 = 0
        while iii < n {
            a[iii] = mulmod(a[iii], inv_n, mod)
            iii = iii + 1
        }
    }
}

# Convolution mod MOD using 3-prime NTT + CRT.
# Returns result in a freshly allocated array of size `limit`.
function conv_mod(a: ptr<i64>, na: i32, b: ptr<i64>, nb: i32, limit0: i32) -> ptr<i64> {
    if na == 0 || nb == 0 { return null as ptr<i64> }

    let full_len: i32 = na + nb - 1
    let mut limit: i32 = limit0
    if limit > full_len { limit = full_len }
    if limit <= 0 { return null as ptr<i64> }

    # Small case: naive
    if (na as i64) * (nb as i64) <= 16384 {
        let res: ptr<i64> = (calloc((limit as i64), 8)) as ptr<i64>
        let mut i: i32 = 0
        while i < na {
            if a[i] == 0 {
                i = i + 1
                continue
            }
            let mut maxj: i32 = nb
            if limit - i < maxj { maxj = limit - i }
            let mut j: i32 = 0
            while j < maxj {
                res[i + j] = (res[i + j] + a[i] * b[j]) % MOD
                if res[i + j] < 0 { res[i + j] = res[i + j] + MOD }
                j = j + 1
            }
            i = i + 1
        }
        return res
    }

    let mut n_ntt: i32 = 1
    while n_ntt < full_len {
        n_ntt = n_ntt << 1
    }
    ntt_bitrev(n_ntt)

    let res: ptr<i64> = (calloc((limit as i64), 8)) as ptr<i64>

    # Compute NTT for each prime
    let ntt_results: array<ptr<i64>, 3> = [null as ptr<i64>, null as ptr<i64>, null as ptr<i64>]
    let ntt_primes: array<i64, 3> = [NTT_P0, NTT_P1, NTT_P2]
    let ntt_gens: array<i64, 3> = [NTT_G0, NTT_G1, NTT_G2]

    let mut pi: i32 = 0
    while pi < 3 {
        let mod: i64 = ntt_primes[pi]
        let gen: i64 = ntt_gens[pi]

        let fa: ptr<i64> = (calloc((n_ntt as i64), 8)) as ptr<i64>
        let fb: ptr<i64> = (calloc((n_ntt as i64), 8)) as ptr<i64>

        let mut i: i32 = 0
        while i < na {
            fa[i] = a[i] % mod
            i = i + 1
        }
        i = 0
        while i < nb {
            fb[i] = b[i] % mod
            i = i + 1
        }

        ntt(fa, n_ntt, 0, mod, gen)
        ntt(fb, n_ntt, 0, mod, gen)

        let mut ii: i32 = 0
        while ii < n_ntt {
            fa[ii] = mulmod(fa[ii], fb[ii], mod)
            ii = ii + 1
        }

        ntt(fa, n_ntt, 1, mod, gen)
        ntt_results[pi] = fa
        free(fb as ptr<void>)
        pi = pi + 1
    }

    # CRT via Garner's algorithm
    let mut i: i32 = 0
    while i < limit {
        let a1: i64 = ntt_results[0][i]
        let a2: i64 = ntt_results[1][i]
        let a3: i64 = ntt_results[2][i]

        # Step 2: x mod p1*p2
        let mut t2: i64 = ((a2 - a1) % NTT_P1 + NTT_P1) % NTT_P1
        t2 = mulmod(t2, p1_mod_p2_inv, NTT_P1)
        let x12_mod: i64 = (a1 % MOD + mulmod(p1_mod_MOD, t2 % MOD, MOD)) % MOD

        # Step 3: x mod p1*p2*p3
        let mut x12_mod_p3: i64 = (a1 % NTT_P2 + mulmod(NTT_P0 % NTT_P2, t2, NTT_P2)) % NTT_P2
        if x12_mod_p3 < 0 { x12_mod_p3 = x12_mod_p3 + NTT_P2 }
        let mut t3: i64 = ((a3 - x12_mod_p3) % NTT_P2 + NTT_P2) % NTT_P2
        t3 = mulmod(t3, p12_mod_p3_inv, NTT_P2)
        res[i] = (x12_mod + mulmod(p12_mod_MOD, t3 % MOD, MOD)) % MOD
        if res[i] < 0 { res[i] = res[i] + MOD }
        i = i + 1
    }

    free(ntt_results[0] as ptr<void>)
    free(ntt_results[1] as ptr<void>)
    free(ntt_results[2] as ptr<void>)

    return res
}

# Series inversion via Newton iteration.
function series_inverse(f: ptr<i64>, n_terms: i32) -> ptr<i64> {
    if n_terms <= 0 { return null as ptr<i64> }

    let mut f0: i64 = f[0] % MOD
    if f0 < 0 { f0 = f0 + MOD }

    let g0: i64 = modinv(f0, MOD)
    let g: ptr<i64> = (calloc((n_terms as i64), 8)) as ptr<i64>
    g[0] = g0

    let mut m: i32 = 1
    while m < n_terms {
        let mut m2: i32 = m * 2
        if m2 > n_terms { m2 = n_terms }

        let fg: ptr<i64> = conv_mod(f, m2, g, m, m2)

        let mut i: i32 = 0
        while i < m2 {
            fg[i] = (-fg[i]) % MOD
            if fg[i] < 0 { fg[i] = fg[i] + MOD }
            i = i + 1
        }
        fg[0] = (fg[0] + 2) % MOD

        let g_new: ptr<i64> = conv_mod(g, m, fg, m2, m2)

        let mut ii: i32 = 0
        while ii < m2 {
            g[ii] = g_new[ii]
            ii = ii + 1
        }

        free(fg as ptr<void>)
        free(g_new as ptr<void>)
        m = m2
    }

    return g
}

function init_crt() -> void {
    p1_mod_p2_inv = modinv(NTT_P0 % NTT_P1, NTT_P1)
    let p12_mod_p3: i64 = mulmod(NTT_P0 % NTT_P2, NTT_P1 % NTT_P2, NTT_P2)
    p12_mod_p3_inv = modinv(p12_mod_p3, NTT_P2)
    p1_mod_MOD = NTT_P0 % MOD
    p12_mod_MOD = mulmod(NTT_P0 % MOD, NTT_P1 % MOD, MOD)
}

function main() -> i32 {
    init_crt()

    # Fibonacci numbers mod MOD
    let fib: ptr<i64> = (calloc((N + 1) as i64, 8)) as ptr<i64>
    fib[1] = 1
    if N >= 2 { fib[2] = 1 }
    let mut i: i32 = 3
    while i <= N {
        let mut x: i64 = fib[i - 1] + fib[i - 2]
        if x >= MOD { x = x - MOD }
        fib[i] = x
        i = i + 1
    }

    # Sieve: s[n] = sum_{d|n} (-1)^(d-1) * Fib[d] mod MOD
    let s: ptr<i64> = (calloc((N + 1) as i64, 8)) as ptr<i64>
    let mut d: i32 = 1
    while d <= N {
        let mut val: i64 = fib[d]
        if (d & 1) == 0 { val = MOD - val }
        let mut k: i32 = d
        while k <= N {
            let mut x: i64 = s[k] + val
            if x >= MOD { x = x - MOD }
            s[k] = x
            k = k + d
        }
        d = d + 1
    }

    # f(x) = 1 - S(x)
    let f: ptr<i64> = (calloc((N + 1) as i64, 8)) as ptr<i64>
    f[0] = 1
    let mut ii: i32 = 1
    while ii <= N {
        f[ii] = (MOD - s[ii]) % MOD
        if f[ii] < 0 { f[ii] = f[ii] + MOD }
        ii = ii + 1
    }

    # t = 1 / f
    let t: ptr<i64> = series_inverse(f, N + 1)

    let mut result: i64 = t[N] % MOD
    if result < 0 { result = result + MOD }

    free(fib as ptr<void>)
    free(s as ptr<void>)
    free(f as ptr<void>)
    free(t as ptr<void>)

    printf("%lld\n", result)
    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 mulmod_i64_i64_i64(int64_t a, int64_t b, int64_t mod);
int64_t powmod_i64_i64_i64(int64_t a0, int64_t e0, int64_t mod);
int64_t modinv_i64_i64(int64_t a, int64_t mod);
void ntt_bitrev_i32(int32_t n);
void ntt_ptr_i64_i32_i32_i64_i64(int64_t* a, int32_t n, int32_t invert, int64_t mod, int64_t gen);
int64_t* conv_mod_ptr_i64_i32_ptr_i64_i32_i32(int64_t* a, int32_t na, int64_t* b, int32_t nb, int32_t limit0);
int64_t* series_inverse_ptr_i64_i32(int64_t* f, int32_t n_terms);
void init_crt(void);
int32_t main(void);

static const int64_t MOD = 1111124111;
static const int32_t N = 100000;
static const int64_t NTT_P0 = 998244353;
static const int64_t NTT_P1 = 1004535809;
static const int64_t NTT_P2 = 754974721;
static const int64_t NTT_G0 = 3;
static const int64_t NTT_G1 = 3;
static const int64_t NTT_G2 = 11;

/* Module statics */
static int64_t p1_mod_p2_inv = 0;
static int64_t p12_mod_p3_inv = 0;
static int64_t p1_mod_MOD = 0;
static int64_t p12_mod_MOD = 0;
static int32_t* ntt_rev = ((int32_t*)(NULL));
static int32_t ntt_rev_n = 0;






int64_t mulmod_i64_i64_i64(int64_t a, int64_t b, int64_t mod) {
    return ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(a)) * ((__int128)(b)))), (((__int128)(mod))))));
}

int64_t powmod_i64_i64_i64(int64_t a0, int64_t e0, int64_t mod) {
    int64_t r = FLOW_CHECKED_MOD((1), (mod));
    int64_t a = FLOW_CHECKED_MOD((a0), (mod));
    if (a < 0) {
        a = (a + mod);
    }
    int64_t e = e0;
    while (e > 0) {
        if ((e & 1) != 0) {
            r = mulmod_i64_i64_i64(r, a, mod);
        }
        a = mulmod_i64_i64_i64(a, a, mod);
        e = FLOW_CHECKED_SHR((e), (1));
    }
    return r;
}

int64_t modinv_i64_i64(int64_t a, int64_t mod) {
    return powmod_i64_i64_i64(a, (mod - 2), mod);
}

void ntt_bitrev_i32(int32_t n) {
    if (ntt_rev_n != n) {
        ntt_rev = ((int32_t*)(realloc(((void*)(ntt_rev)), (((int64_t)(n)) * 4))));
        ntt_rev_n = n;
    }
    int32_t logn = 0;
    int32_t tmp = n;
    while (tmp > 1) {
        logn = (logn + 1);
        tmp = FLOW_CHECKED_SHR((tmp), (1));
    }
    ntt_rev[0] = 0;
    int32_t i = 1;
    while (i < n) {
        ntt_rev[i] = (FLOW_CHECKED_SHR((ntt_rev[FLOW_CHECKED_SHR((i), (1))]), (1)) | FLOW_CHECKED_SHL(((i & 1)), ((logn - 1))));
        i = (i + 1);
    }
}

void ntt_ptr_i64_i32_i32_i64_i64(int64_t* a, int32_t n, int32_t invert, int64_t mod, int64_t gen) {
    int32_t i = 0;
    while (i < n) {
        int32_t j = ntt_rev[i];
        if (i < j) {
            int64_t t = a[i];
            a[i] = a[j];
            a[j] = t;
        }
        i = (i + 1);
    }
    int32_t len = 2;
    while (len <= n) {
        int32_t half = FLOW_CHECKED_SHR((len), (1));
        int64_t w = 0;
        if (invert != 0) {
            w = powmod_i64_i64_i64(gen, ((mod - 1) - FLOW_CHECKED_DIV(((mod - 1)), (((int64_t)(len))))), mod);
        } else {
            w = powmod_i64_i64_i64(gen, FLOW_CHECKED_DIV(((mod - 1)), (((int64_t)(len)))), mod);
        }
        int32_t ii = 0;
        while (ii < n) {
            int64_t wk = 1;
            int32_t jj = 0;
            while (jj < half) {
                int64_t u = a[(ii + jj)];
                int64_t v = mulmod_i64_i64_i64(a[((ii + jj) + half)], wk, mod);
                a[(ii + jj)] = FLOW_CHECKED_MOD(((u + v)), (mod));
                a[((ii + jj) + half)] = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD(((u - v)), (mod)) + mod)), (mod));
                wk = mulmod_i64_i64_i64(wk, w, mod);
                jj = (jj + 1);
            }
            ii = (ii + len);
        }
        len = FLOW_CHECKED_SHL((len), (1));
    }
    if (invert != 0) {
        int64_t inv_n = modinv_i64_i64(((int64_t)(n)), mod);
        int32_t iii = 0;
        while (iii < n) {
            a[iii] = mulmod_i64_i64_i64(a[iii], inv_n, mod);
            iii = (iii + 1);
        }
    }
}

int64_t* conv_mod_ptr_i64_i32_ptr_i64_i32_i32(int64_t* a, int32_t na, int64_t* b, int32_t nb, int32_t limit0) {
    if ((na == 0 || nb == 0)) {
        return ((int64_t*)(NULL));
    }
    int32_t full_len = ((na + nb) - 1);
    int32_t limit = limit0;
    if (limit > full_len) {
        limit = full_len;
    }
    if (limit <= 0) {
        return ((int64_t*)(NULL));
    }
    if ((((int64_t)(na)) * ((int64_t)(nb))) <= 16384) {
        int64_t* res = (int64_t*)(((int64_t*)(calloc(((int64_t)(limit)), 8))));
        int32_t i = 0;
        while (i < na) {
            if (a[i] == 0) {
                i = (i + 1);
                continue;
            }
            int32_t maxj = nb;
            if ((limit - i) < maxj) {
                maxj = (limit - i);
            }
            int32_t j = 0;
            while (j < maxj) {
                res[(i + j)] = FLOW_CHECKED_MOD(((res[(i + j)] + (a[i] * b[j]))), (MOD));
                if (res[(i + j)] < 0) {
                    res[(i + j)] = (res[(i + j)] + MOD);
                }
                j = (j + 1);
            }
            i = (i + 1);
        }
        return res;
    }
    int32_t n_ntt = 1;
    while (n_ntt < full_len) {
        n_ntt = FLOW_CHECKED_SHL((n_ntt), (1));
    }
    ntt_bitrev_i32(n_ntt);
    int64_t* res = (int64_t*)(((int64_t*)(calloc(((int64_t)(limit)), 8))));
    int64_t* ntt_results[3] = { ((int64_t*)(NULL)), ((int64_t*)(NULL)), ((int64_t*)(NULL)) };
    int64_t ntt_primes[3] = { NTT_P0, NTT_P1, NTT_P2 };
    int64_t ntt_gens[3] = { NTT_G0, NTT_G1, NTT_G2 };
    int32_t pi = 0;
    while (pi < 3) {
        int64_t mod = (((unsigned)(pi) < 3) ? ntt_primes[pi] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(pi), 3), flow_fault_handler("array index out of bounds"), ntt_primes[0]));
        int64_t gen = (((unsigned)(pi) < 3) ? ntt_gens[pi] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(pi), 3), flow_fault_handler("array index out of bounds"), ntt_gens[0]));
        int64_t* fa = (int64_t*)(((int64_t*)(calloc(((int64_t)(n_ntt)), 8))));
        int64_t* fb = (int64_t*)(((int64_t*)(calloc(((int64_t)(n_ntt)), 8))));
        int32_t i = 0;
        while (i < na) {
            fa[i] = FLOW_CHECKED_MOD((a[i]), (mod));
            i = (i + 1);
        }
        i = 0;
        while (i < nb) {
            fb[i] = FLOW_CHECKED_MOD((b[i]), (mod));
            i = (i + 1);
        }
        ntt_ptr_i64_i32_i32_i64_i64(fa, n_ntt, 0, mod, gen);
        ntt_ptr_i64_i32_i32_i64_i64(fb, n_ntt, 0, mod, gen);
        int32_t ii = 0;
        while (ii < n_ntt) {
            fa[ii] = mulmod_i64_i64_i64(fa[ii], fb[ii], mod);
            ii = (ii + 1);
        }
        ntt_ptr_i64_i32_i32_i64_i64(fa, n_ntt, 1, mod, gen);
        ntt_results[pi] = fa;
        free(((void*)(fb)));
        pi = (pi + 1);
    }
    int32_t i = 0;
    while (i < limit) {
        int64_t a1 = (((unsigned)(0) < 3) ? ntt_results[0] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(0), 3), flow_fault_handler("array index out of bounds"), ntt_results[0]))[i];
        int64_t a2 = (((unsigned)(1) < 3) ? ntt_results[1] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(1), 3), flow_fault_handler("array index out of bounds"), ntt_results[0]))[i];
        int64_t a3 = (((unsigned)(2) < 3) ? ntt_results[2] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(2), 3), flow_fault_handler("array index out of bounds"), ntt_results[0]))[i];
        int64_t t2 = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD(((a2 - a1)), (NTT_P1)) + NTT_P1)), (NTT_P1));
        t2 = mulmod_i64_i64_i64(t2, p1_mod_p2_inv, NTT_P1);
        int64_t x12_mod = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD((a1), (MOD)) + mulmod_i64_i64_i64(p1_mod_MOD, FLOW_CHECKED_MOD((t2), (MOD)), MOD))), (MOD));
        int64_t x12_mod_p3 = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD((a1), (NTT_P2)) + mulmod_i64_i64_i64(FLOW_CHECKED_MOD((NTT_P0), (NTT_P2)), t2, NTT_P2))), (NTT_P2));
        if (x12_mod_p3 < 0) {
            x12_mod_p3 = (x12_mod_p3 + NTT_P2);
        }
        int64_t t3 = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD(((a3 - x12_mod_p3)), (NTT_P2)) + NTT_P2)), (NTT_P2));
        t3 = mulmod_i64_i64_i64(t3, p12_mod_p3_inv, NTT_P2);
        res[i] = FLOW_CHECKED_MOD(((x12_mod + mulmod_i64_i64_i64(p12_mod_MOD, FLOW_CHECKED_MOD((t3), (MOD)), MOD))), (MOD));
        if (res[i] < 0) {
            res[i] = (res[i] + MOD);
        }
        i = (i + 1);
    }
    free(((void*)((((unsigned)(0) < 3) ? ntt_results[0] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(0), 3), flow_fault_handler("array index out of bounds"), ntt_results[0])))));
    free(((void*)((((unsigned)(1) < 3) ? ntt_results[1] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(1), 3), flow_fault_handler("array index out of bounds"), ntt_results[0])))));
    free(((void*)((((unsigned)(2) < 3) ? ntt_results[2] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(2), 3), flow_fault_handler("array index out of bounds"), ntt_results[0])))));
    return res;
}

int64_t* series_inverse_ptr_i64_i32(int64_t* f, int32_t n_terms) {
    if (n_terms <= 0) {
        return ((int64_t*)(NULL));
    }
    int64_t f0 = FLOW_CHECKED_MOD((f[0]), (MOD));
    if (f0 < 0) {
        f0 = (f0 + MOD);
    }
    int64_t g0 = modinv_i64_i64(f0, MOD);
    int64_t* g = (int64_t*)(((int64_t*)(calloc(((int64_t)(n_terms)), 8))));
    g[0] = g0;
    int32_t m = 1;
    while (m < n_terms) {
        int32_t m2 = (m * 2);
        if (m2 > n_terms) {
            m2 = n_terms;
        }
        int64_t* fg = (int64_t*)(conv_mod_ptr_i64_i32_ptr_i64_i32_i32(f, m2, g, m, m2));
        int32_t i = 0;
        while (i < m2) {
            fg[i] = FLOW_CHECKED_MOD(((-fg[i])), (MOD));
            if (fg[i] < 0) {
                fg[i] = (fg[i] + MOD);
            }
            i = (i + 1);
        }
        fg[0] = FLOW_CHECKED_MOD(((fg[0] + 2)), (MOD));
        int64_t* g_new = (int64_t*)(conv_mod_ptr_i64_i32_ptr_i64_i32_i32(g, m, fg, m2, m2));
        int32_t ii = 0;
        while (ii < m2) {
            g[ii] = g_new[ii];
            ii = (ii + 1);
        }
        free(((void*)(fg)));
        free(((void*)(g_new)));
        m = m2;
    }
    return g;
}

void init_crt(void) {
    p1_mod_p2_inv = modinv_i64_i64(FLOW_CHECKED_MOD((NTT_P0), (NTT_P1)), NTT_P1);
    int64_t p12_mod_p3 = mulmod_i64_i64_i64(FLOW_CHECKED_MOD((NTT_P0), (NTT_P2)), FLOW_CHECKED_MOD((NTT_P1), (NTT_P2)), NTT_P2);
    p12_mod_p3_inv = modinv_i64_i64(p12_mod_p3, NTT_P2);
    p1_mod_MOD = FLOW_CHECKED_MOD((NTT_P0), (MOD));
    p12_mod_MOD = mulmod_i64_i64_i64(FLOW_CHECKED_MOD((NTT_P0), (MOD)), FLOW_CHECKED_MOD((NTT_P1), (MOD)), MOD);
}

int32_t main(void) {
    init_crt();
    int64_t* fib = (int64_t*)(((int64_t*)(calloc(((int64_t)((N + 1))), 8))));
    fib[1] = 1;
    if (N >= 2) {
        fib[2] = 1;
    }
    int32_t i = 3;
    while (i <= N) {
        int64_t x = (fib[(i - 1)] + fib[(i - 2)]);
        if (x >= MOD) {
            x = (x - MOD);
        }
        fib[i] = x;
        i = (i + 1);
    }
    int64_t* s = (int64_t*)(((int64_t*)(calloc(((int64_t)((N + 1))), 8))));
    int32_t d = 1;
    while (d <= N) {
        int64_t val = fib[d];
        if ((d & 1) == 0) {
            val = (MOD - val);
        }
        int32_t k = d;
        while (k <= N) {
            int64_t x = (s[k] + val);
            if (x >= MOD) {
                x = (x - MOD);
            }
            s[k] = x;
            k = (k + d);
        }
        d = (d + 1);
    }
    int64_t* f = (int64_t*)(((int64_t*)(calloc(((int64_t)((N + 1))), 8))));
    f[0] = 1;
    int32_t ii = 1;
    while (ii <= N) {
        f[ii] = FLOW_CHECKED_MOD(((MOD - s[ii])), (MOD));
        if (f[ii] < 0) {
            f[ii] = (f[ii] + MOD);
        }
        ii = (ii + 1);
    }
    int64_t* t = (int64_t*)(series_inverse_ptr_i64_i32(f, (N + 1)));
    int64_t result = FLOW_CHECKED_MOD((t[N]), (MOD));
    if (result < 0) {
        result = (result + MOD);
    }
    free(((void*)(fib)));
    free(((void*)(s)));
    free(((void*)(f)));
    free(((void*)(t)));
    printf("%lld\n", result);
    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) -> ()
  func.func private @malloc(i64) -> !llvm.ptr
  func.func private @realloc(!llvm.ptr, i64) -> !llvm.ptr

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