Problem 382

Last 9 digits of f(10^18) via 12x12 matrix exponentiation.

Answer697003956
Output697003956
StatusPASS
Native helperno
Runtime0 ms
Peak memory1072 KB
Time complexityO(n^3) (estimated)
Space complexityO(1) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^3)O(n)
Space complexityO(1)O(n)
ApproachFlow solutionBig-integer arithmetic
VerdictSuboptimal

Flow source

# Project Euler 382
# Last 9 digits of f(10^18) via 12x12 matrix exponentiation.

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

function mat_mul(A: ptr<i64>, B: ptr<i64>, R: ptr<i64>, mod: i64) -> void {
    let n: i64 = 12
    let mut i: i64 = 0
    while i < n {
        let mut j: i64 = 0
        while j < n {
            let mut s: i64 = 0
            let mut k: i64 = 0
            while k < n {
                let a: i64 = A[i * n + k]
                if a != 0 {
                    s = (s + a * B[k * n + j]) % mod
                }
                k = k + 1
            }
            R[i * n + j] = s
            j = j + 1
        }
        i = i + 1
    }
}

function mat_copy(src: ptr<i64>, dst: ptr<i64>) -> void {
    let mut i: i64 = 0
    while i < 144 {
        dst[i] = src[i]
        i = i + 1
    }
}

function mat_pow(M: ptr<i64>, e0: i64, mod: i64, out: ptr<i64>, tmp: ptr<i64>, base: ptr<i64>) -> void {
    # out = I
    let mut i: i64 = 0
    while i < 144 {
        out[i] = 0
        i = i + 1
    }
    i = 0
    while i < 12 {
        out[i * 12 + i] = 1
        i = i + 1
    }
    mat_copy(M, base)
    let mut e: i64 = e0
    while e > 0 {
        if (e & 1) == 1 {
            mat_mul(base, out, tmp, mod)
            mat_copy(tmp, out)
        }
        mat_mul(base, base, tmp, mod)
        mat_copy(tmp, base)
        e = e >> 1
    }
}

function mat_vec(M: ptr<i64>, v: ptr<i64>, out: ptr<i64>, mod: i64) -> void {
    let mut i: i64 = 0
    while i < 12 {
        let mut s: i64 = 0
        let mut j: i64 = 0
        while j < 12 {
            let c: i64 = M[i * 12 + j]
            if c != 0 {
                s = (s + c * v[j]) % mod
            }
            j = j + 1
        }
        out[i] = s
        i = i + 1
    }
}

function modpow(base0: i64, exp0: i64, mod: i64) -> i64 {
    let mut r: i64 = 1
    let mut b: i64 = base0 % mod
    let mut e: i64 = exp0
    while e > 0 {
        if (e & 1) == 1 { r = (r * b) % mod }
        b = (b * b) % mod
        e = e >> 1
    }
    return r
}

function prefix_sum_b(n: i64, mod: i64, M: ptr<i64>, P: ptr<i64>, tmp: ptr<i64>, base: ptr<i64>,
                      v: ptr<i64>, v2: ptr<i64>) -> i64 {
    if n <= 0 { return 0 }
    let idx: i64 = n - 1
    let b0: i64 = 1
    let b1: i64 = 2
    let b2: i64 = 4
    let b3: i64 = 6
    let b4: i64 = 11
    let b5: i64 = 20
    if idx == 0 { return b0 }
    if idx == 1 { return (b0 + b1) % mod }
    if idx == 2 { return (b0 + b1 + b2) % mod }
    if idx == 3 { return (b0 + b1 + b2 + b3) % mod }
    if idx == 4 { return (b0 + b1 + b2 + b3 + b4) % mod }
    if idx == 5 { return (b0 + b1 + b2 + b3 + b4 + b5) % mod }

    let S5: i64 = (b0 + b1 + b2 + b3 + b4 + b5) % mod
    v[0] = b5
    v[1] = b4
    v[2] = b3
    v[3] = b2
    v[4] = b1
    v[5] = b0
    v[6] = modpow(2, 5, mod)
    v[7] = modpow(2, 4, mod)
    v[8] = modpow(2, 3, mod)
    v[9] = modpow(2, 2, mod)
    v[10] = S5
    v[11] = 1

    mat_pow(M, idx - 5, mod, P, tmp, base)
    mat_vec(P, v, v2, mod)
    return v2[10] % mod
}

function f_n(n: i64, mod: i64, M: ptr<i64>, P: ptr<i64>, tmp: ptr<i64>, base: ptr<i64>,
             v: ptr<i64>, v2: ptr<i64>) -> i64 {
    let bad: i64 = prefix_sum_b(n, mod, M, P, tmp, base, v, v2)
    let pow2: i64 = modpow(2, n, mod)
    let mut ans: i64 = (pow2 - 1 - bad) % mod
    if ans < 0 { ans = ans + mod }
    return ans
}

function main() -> i32 {
    let mod: i64 = 1000000000
    let M: ptr<i64> = calloc(144, 8)
    let P: ptr<i64> = calloc(144, 8)
    let tmp: ptr<i64> = calloc(144, 8)
    let base: ptr<i64> = calloc(144, 8)
    let v: ptr<i64> = calloc(12, 8)
    let v2: ptr<i64> = calloc(12, 8)
    if M == null || P == null || tmp == null || base == null || v == null || v2 == null { return 1 }

    # Build transition matrix
    let mut i: i64 = 0
    while i < 144 {
        M[i] = 0
        i = i + 1
    }
    M[0 * 12 + 2] = 2
    M[0 * 12 + 3] = 1
    M[0 * 12 + 5] = mod - 1
    M[0 * 12 + 9] = 5
    M[0 * 12 + 11] = 1
    M[1 * 12 + 0] = 1
    M[2 * 12 + 1] = 1
    M[3 * 12 + 2] = 1
    M[4 * 12 + 3] = 1
    M[5 * 12 + 4] = 1
    M[6 * 12 + 6] = 2
    M[7 * 12 + 6] = 1
    M[8 * 12 + 7] = 1
    M[9 * 12 + 8] = 1
    M[10 * 12 + 10] = 1
    i = 0
    while i < 12 {
        M[10 * 12 + i] = (M[10 * 12 + i] + M[0 * 12 + i]) % mod
        i = i + 1
    }
    M[11 * 12 + 11] = 1

    let ans: i64 = f_n(1000000000000000000, mod, M, P, tmp, base, v, v2)
    printf("%lld\n", ans)

    free(v2)
    free(v)
    free(base)
    free(tmp)
    free(P)
    free(M)
    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; }

void mat_mul_ptr_i64_ptr_i64_ptr_i64_i64(int64_t* A, int64_t* B, int64_t* R, int64_t mod);
void mat_copy_ptr_i64_ptr_i64(int64_t* src, int64_t* dst);
void mat_pow_ptr_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64(int64_t* M, int64_t e0, int64_t mod, int64_t* out, int64_t* tmp, int64_t* base);
void mat_vec_ptr_i64_ptr_i64_ptr_i64_i64(int64_t* M, int64_t* v, int64_t* out, int64_t mod);
int64_t modpow_i64_i64_i64(int64_t base0, int64_t exp0, int64_t mod);
int64_t prefix_sum_b_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t n, int64_t mod, int64_t* M, int64_t* P, int64_t* tmp, int64_t* base, int64_t* v, int64_t* v2);
int64_t f_n_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t n, int64_t mod, int64_t* M, int64_t* P, int64_t* tmp, int64_t* base, int64_t* v, int64_t* v2);
int32_t main(void);



void mat_mul_ptr_i64_ptr_i64_ptr_i64_i64(int64_t* A, int64_t* B, int64_t* R, int64_t mod) {
    int64_t n = 12;
    int64_t i = 0;
    while (i < n) {
        int64_t j = 0;
        while (j < n) {
            int64_t s = 0;
            int64_t k = 0;
            while (k < n) {
                int64_t a = A[((i * n) + k)];
                if (a != 0) {
                    s = FLOW_CHECKED_MOD(((s + (a * B[((k * n) + j)]))), (mod));
                }
                k = (k + 1);
            }
            R[((i * n) + j)] = s;
            j = (j + 1);
        }
        i = (i + 1);
    }
}

void mat_copy_ptr_i64_ptr_i64(int64_t* src, int64_t* dst) {
    int64_t i = 0;
    while (i < 144) {
        dst[i] = src[i];
        i = (i + 1);
    }
}

void mat_pow_ptr_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64(int64_t* M, int64_t e0, int64_t mod, int64_t* out, int64_t* tmp, int64_t* base) {
    int64_t i = 0;
    while (i < 144) {
        out[i] = 0;
        i = (i + 1);
    }
    i = 0;
    while (i < 12) {
        out[((i * 12) + i)] = 1;
        i = (i + 1);
    }
    mat_copy_ptr_i64_ptr_i64(M, base);
    int64_t e = e0;
    while (e > 0) {
        if ((e & 1) == 1) {
            mat_mul_ptr_i64_ptr_i64_ptr_i64_i64(base, out, tmp, mod);
            mat_copy_ptr_i64_ptr_i64(tmp, out);
        }
        mat_mul_ptr_i64_ptr_i64_ptr_i64_i64(base, base, tmp, mod);
        mat_copy_ptr_i64_ptr_i64(tmp, base);
        e = FLOW_CHECKED_SHR((e), (1));
    }
}

void mat_vec_ptr_i64_ptr_i64_ptr_i64_i64(int64_t* M, int64_t* v, int64_t* out, int64_t mod) {
    int64_t i = 0;
    while (i < 12) {
        int64_t s = 0;
        int64_t j = 0;
        while (j < 12) {
            int64_t c = M[((i * 12) + j)];
            if (c != 0) {
                s = FLOW_CHECKED_MOD(((s + (c * v[j]))), (mod));
            }
            j = (j + 1);
        }
        out[i] = s;
        i = (i + 1);
    }
}

int64_t modpow_i64_i64_i64(int64_t base0, int64_t exp0, int64_t mod) {
    int64_t r = 1;
    int64_t b = FLOW_CHECKED_MOD((base0), (mod));
    int64_t e = exp0;
    while (e > 0) {
        if ((e & 1) == 1) {
            r = FLOW_CHECKED_MOD(((r * b)), (mod));
        }
        b = FLOW_CHECKED_MOD(((b * b)), (mod));
        e = FLOW_CHECKED_SHR((e), (1));
    }
    return r;
}

int64_t prefix_sum_b_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t n, int64_t mod, int64_t* M, int64_t* P, int64_t* tmp, int64_t* base, int64_t* v, int64_t* v2) {
    if (n <= 0) {
        return 0;
    }
    int64_t idx = (n - 1);
    int64_t b0 = 1;
    int64_t b1 = 2;
    int64_t b2 = 4;
    int64_t b3 = 6;
    int64_t b4 = 11;
    int64_t b5 = 20;
    if (idx == 0) {
        return b0;
    }
    if (idx == 1) {
        return FLOW_CHECKED_MOD(((b0 + b1)), (mod));
    }
    if (idx == 2) {
        return FLOW_CHECKED_MOD((((b0 + b1) + b2)), (mod));
    }
    if (idx == 3) {
        return FLOW_CHECKED_MOD(((((b0 + b1) + b2) + b3)), (mod));
    }
    if (idx == 4) {
        return FLOW_CHECKED_MOD((((((b0 + b1) + b2) + b3) + b4)), (mod));
    }
    if (idx == 5) {
        return FLOW_CHECKED_MOD(((((((b0 + b1) + b2) + b3) + b4) + b5)), (mod));
    }
    int64_t S5 = FLOW_CHECKED_MOD(((((((b0 + b1) + b2) + b3) + b4) + b5)), (mod));
    v[0] = b5;
    v[1] = b4;
    v[2] = b3;
    v[3] = b2;
    v[4] = b1;
    v[5] = b0;
    v[6] = modpow_i64_i64_i64(2, 5, mod);
    v[7] = modpow_i64_i64_i64(2, 4, mod);
    v[8] = modpow_i64_i64_i64(2, 3, mod);
    v[9] = modpow_i64_i64_i64(2, 2, mod);
    v[10] = S5;
    v[11] = 1;
    mat_pow_ptr_i64_i64_i64_ptr_i64_ptr_i64_ptr_i64(M, (idx - 5), mod, P, tmp, base);
    mat_vec_ptr_i64_ptr_i64_ptr_i64_i64(P, v, v2, mod);
    return FLOW_CHECKED_MOD((v2[10]), (mod));
}

int64_t f_n_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t n, int64_t mod, int64_t* M, int64_t* P, int64_t* tmp, int64_t* base, int64_t* v, int64_t* v2) {
    int64_t bad = prefix_sum_b_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(n, mod, M, P, tmp, base, v, v2);
    int64_t pow2 = modpow_i64_i64_i64(2, n, mod);
    int64_t ans = FLOW_CHECKED_MOD((((pow2 - 1) - bad)), (mod));
    if (ans < 0) {
        ans = (ans + mod);
    }
    return ans;
}

int32_t main(void) {
    int64_t mod = 1000000000;
    int64_t* M = (int64_t*)(calloc(144, 8));
    int64_t* P = (int64_t*)(calloc(144, 8));
    int64_t* tmp = (int64_t*)(calloc(144, 8));
    int64_t* base = (int64_t*)(calloc(144, 8));
    int64_t* v = (int64_t*)(calloc(12, 8));
    int64_t* v2 = (int64_t*)(calloc(12, 8));
    if ((((((M == NULL || P == NULL) || tmp == NULL) || base == NULL) || v == NULL) || v2 == NULL)) {
        return 1;
    }
    int64_t i = 0;
    while (i < 144) {
        M[i] = 0;
        i = (i + 1);
    }
    M[((0 * 12) + 2)] = 2;
    M[((0 * 12) + 3)] = 1;
    M[((0 * 12) + 5)] = (mod - 1);
    M[((0 * 12) + 9)] = 5;
    M[((0 * 12) + 11)] = 1;
    M[((1 * 12) + 0)] = 1;
    M[((2 * 12) + 1)] = 1;
    M[((3 * 12) + 2)] = 1;
    M[((4 * 12) + 3)] = 1;
    M[((5 * 12) + 4)] = 1;
    M[((6 * 12) + 6)] = 2;
    M[((7 * 12) + 6)] = 1;
    M[((8 * 12) + 7)] = 1;
    M[((9 * 12) + 8)] = 1;
    M[((10 * 12) + 10)] = 1;
    i = 0;
    while (i < 12) {
        M[((10 * 12) + i)] = FLOW_CHECKED_MOD(((M[((10 * 12) + i)] + M[((0 * 12) + i)])), (mod));
        i = (i + 1);
    }
    M[((11 * 12) + 11)] = 1;
    int64_t ans = f_n_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(1000000000000000000, mod, M, P, tmp, base, v, v2);
    printf("%lld\n", ans);
    free(v2);
    free(v);
    free(base);
    free(tmp);
    free(P);
    free(M);
    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 @mat_mul(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: i64) -> () {
    %0 = arith.constant 12 : i32
    %1 = arith.extsi %0 : i32 to i64
    %2 = arith.constant 0 : i32
    %3 = arith.extsi %2 : i32 to i64
    %4 = llvm.mlir.constant(1 : i64) : i64
    %5 = llvm.alloca %4 x i64 : (i64) -> !llvm.ptr
    llvm.store %3, %5 : i64, !llvm.ptr
    cf.br ^bb0
    ^bb0:
    %6 = llvm.load %5 : !llvm.ptr -> i64
    %7 = arith.cmpi slt, %6, %1 : i64
    cf.cond_br %7, ^bb1, ^bb2
    ^bb1:
      %8 = arith.constant 0 : i32
      %9 = arith.extsi %8 : i32 to i64
      %10 = llvm.mlir.constant(1 : i64) : i64
      %11 = llvm.alloca %10 x i64 : (i64) -> !llvm.ptr
      llvm.store %9, %11 : i64, !llvm.ptr
      cf.br ^bb3
      ^bb3:
      %12 = llvm.load %11 : !llvm.ptr -> i64
      %13 = arith.cmpi slt, %12, %1 : i64
      cf.cond_br %13, ^bb4, ^bb5
      ^bb4:
        %14 = arith.constant 0 : i32
        %15 = arith.extsi %14 : i32 to i64
        %16 = llvm.mlir.constant(1 : i64) : i64
        %17 = llvm.alloca %16 x i64 : (i64) -> !llvm.ptr
        llvm.store %15, %17 : i64, !llvm.ptr
        %18 = arith.constant 0 : i32
        %19 = arith.extsi %18 : i32 to i64
        %20 = llvm.mlir.constant(1 : i64) : i64
        %21 = llvm.alloca %20 x i64 : (i64) -> !llvm.ptr
        llvm.store %19, %21 : i64, !llvm.ptr
        cf.br ^bb6
        ^bb6:
        %22 = llvm.load %21 : !llvm.ptr -> i64
        %23 = arith.cmpi slt, %22, %1 : i64
        cf.cond_br %23, ^bb7, ^bb8
        ^bb7:
          %25 = llvm.load %5 : !llvm.ptr -> i64
          %26 = arith.muli %25, %1 : i64
          %27 = llvm.load %21 : !llvm.ptr -> i64
          %28 = arith.addi %26, %27 : i64
          %29 = llvm.getelementptr %arg0[%28] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %24 = llvm.load %29 : !llvm.ptr -> i64
          %30 = arith.constant 0 : i32
          %32 = arith.extsi %30 : i32 to i64
          %31 = arith.cmpi ne, %24, %32 : i64
          cf.cond_br %31, ^bb9, ^bb10
          ^bb9:
            %33 = llvm.load %17 : !llvm.ptr -> i64
            %35 = llvm.load %21 : !llvm.ptr -> i64
            %36 = arith.muli %35, %1 : i64
            %37 = llvm.load %11 : !llvm.ptr -> i64
            %38 = arith.addi %36, %37 : i64
            %39 = llvm.getelementptr %arg1[%38] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %34 = llvm.load %39 : !llvm.ptr -> i64
            %40 = arith.muli %24, %34 : i64
            %41 = arith.addi %33, %40 : i64
            %42 = arith.remsi %41, %arg3 : i64
            llvm.store %42, %17 : i64, !llvm.ptr
            cf.br ^bb11
          ^bb10:
            cf.br ^bb11
          ^bb11:
          %43 = llvm.load %21 : !llvm.ptr -> i64
          %44 = arith.constant 1 : i32
          %46 = arith.extsi %44 : i32 to i64
          %45 = arith.addi %43, %46 : i64
          llvm.store %45, %21 : i64, !llvm.ptr
          cf.br ^bb6
        ^bb8:
        %47 = llvm.load %17 : !llvm.ptr -> i64
        %48 = llvm.load %5 : !llvm.ptr -> i64
        %49 = arith.muli %48, %1 : i64
        %50 = llvm.load %11 : !llvm.ptr -> i64
        %51 = arith.addi %49, %50 : i64
        %52 = llvm.getelementptr %arg2[%51] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %47, %52 : i64, !llvm.ptr
        %53 = llvm.load %11 : !llvm.ptr -> i64
        %54 = arith.constant 1 : i32
        %56 = arith.extsi %54 : i32 to i64
        %55 = arith.addi %53, %56 : i64
        llvm.store %55, %11 : i64, !llvm.ptr
        cf.br ^bb3
      ^bb5:
      %57 = llvm.load %5 : !llvm.ptr -> i64
      %58 = arith.constant 1 : i32
      %60 = arith.extsi %58 : i32 to i64
      %59 = arith.addi %57, %60 : i64
      llvm.store %59, %5 : i64, !llvm.ptr
      cf.br ^bb0
    ^bb2:
    func.return
  }
  func.func @mat_copy(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () {
    %61 = arith.constant 0 : i32
    %62 = arith.extsi %61 : i32 to i64
    %63 = llvm.mlir.constant(1 : i64) : i64
    %64 = llvm.alloca %63 x i64 : (i64) -> !llvm.ptr
    llvm.store %62, %64 : i64, !llvm.ptr
    cf.br ^bb12
    ^bb12:
    %65 = llvm.load %64 : !llvm.ptr -> i64
    %66 = arith.constant 144 : i32
    %68 = arith.extsi %66 : i32 to i64
    %67 = arith.cmpi slt, %65, %68 : i64
    cf.cond_br %67, ^bb13, ^bb14
    ^bb13:
      %70 = llvm.load %64 : !llvm.ptr -> i64
      %71 = llvm.getelementptr %arg0[%70] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %69 = llvm.load %71 : !llvm.ptr -> i64
      %72 = llvm.load %64 : !llvm.ptr -> i64
      %73 = llvm.getelementptr %arg1[%72] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %69, %73 : i64, !llvm.ptr
      %74 = llvm.load %64 : !llvm.ptr -> i64
      %75 = arith.constant 1 : i32
      %77 = arith.extsi %75 : i32 to i64
      %76 = arith.addi %74, %77 : i64
      llvm.store %76, %64 : i64, !llvm.ptr
      cf.br ^bb12
    ^bb14:
    func.return
  }
  func.func @mat_pow(%arg0: !llvm.ptr, %arg1: i64, %arg2: i64, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr) -> () {
    %78 = arith.constant 0 : i32
    %79 = arith.extsi %78 : i32 to i64
    %80 = llvm.mlir.constant(1 : i64) : i64
    %81 = llvm.alloca %80 x i64 : (i64) -> !llvm.ptr
    llvm.store %79, %81 : i64, !llvm.ptr
    cf.br ^bb15
    ^bb15:
    %82 = llvm.load %81 : !llvm.ptr -> i64
    %83 = arith.constant 144 : i32
    %85 = arith.extsi %83 : i32 to i64
    %84 = arith.cmpi slt, %82, %85 : i64
    cf.cond_br %84, ^bb16, ^bb17
    ^bb16:
      %86 = arith.constant 0 : i32
      %87 = llvm.load %81 : !llvm.ptr -> i64
      %88 = arith.extsi %86 : i32 to i64
      %89 = llvm.getelementptr %arg3[%87] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %88, %89 : i64, !llvm.ptr
      %90 = llvm.load %81 : !llvm.ptr -> i64
      %91 = arith.constant 1 : i32
      %93 = arith.extsi %91 : i32 to i64
      %92 = arith.addi %90, %93 : i64
      llvm.store %92, %81 : i64, !llvm.ptr
      cf.br ^bb15
    ^bb17:
    %94 = arith.constant 0 : i32
    %95 = arith.extsi %94 : i32 to i64
    llvm.store %95, %81 : i64, !llvm.ptr
    cf.br ^bb18
    ^bb18:
    %96 = llvm.load %81 : !llvm.ptr -> i64
    %97 = arith.constant 12 : i32
    %99 = arith.extsi %97 : i32 to i64
    %98 = arith.cmpi slt, %96, %99 : i64
    cf.cond_br %98, ^bb19, ^bb20
    ^bb19:
      %100 = arith.constant 1 : i32
      %101 = llvm.load %81 : !llvm.ptr -> i64
      %102 = arith.constant 12 : i32
      %104 = arith.extsi %102 : i32 to i64
      %103 = arith.muli %101, %104 : i64
      %105 = llvm.load %81 : !llvm.ptr -> i64
      %106 = arith.addi %103, %105 : i64
      %107 = arith.extsi %100 : i32 to i64
      %108 = llvm.getelementptr %arg3[%106] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %107, %108 : i64, !llvm.ptr
      %109 = llvm.load %81 : !llvm.ptr -> i64
      %110 = arith.constant 1 : i32
      %112 = arith.extsi %110 : i32 to i64
      %111 = arith.addi %109, %112 : i64
      llvm.store %111, %81 : i64, !llvm.ptr
      cf.br ^bb18
    ^bb20:
    func.call @mat_copy(%arg0, %arg5) : (!llvm.ptr, !llvm.ptr) -> ()
    %114 = llvm.mlir.constant(1 : i64) : i64
    %115 = llvm.alloca %114 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %115 : i64, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %116 = llvm.load %115 : !llvm.ptr -> i64
    %117 = arith.constant 0 : i32
    %119 = arith.extsi %117 : i32 to i64
    %118 = arith.cmpi sgt, %116, %119 : i64
    cf.cond_br %118, ^bb22, ^bb23
    ^bb22:
      %120 = llvm.load %115 : !llvm.ptr -> i64
      %121 = arith.constant 1 : i32
      %123 = arith.extsi %121 : i32 to i64
      %122 = arith.andi %120, %123 : i64
      %124 = arith.constant 1 : i32
      %126 = arith.extsi %124 : i32 to i64
      %125 = arith.cmpi eq, %122, %126 : i64
      cf.cond_br %125, ^bb24, ^bb25
      ^bb24:
        func.call @mat_mul(%arg5, %arg3, %arg4, %arg2) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, i64) -> ()
        func.call @mat_copy(%arg4, %arg3) : (!llvm.ptr, !llvm.ptr) -> ()
        cf.br ^bb26
      ^bb25:
        cf.br ^bb26
      ^bb26:
      func.call @mat_mul(%arg5, %arg5, %arg4, %arg2) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, i64) -> ()
      func.call @mat_copy(%arg4, %arg5) : (!llvm.ptr, !llvm.ptr) -> ()
      %131 = llvm.load %115 : !llvm.ptr -> i64
      %132 = arith.constant 1 : i32
      %134 = arith.extsi %132 : i32 to i64
      %133 = arith.shrsi %131, %134 : i64
      llvm.store %133, %115 : i64, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    func.return
  }
  func.func @mat_vec(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: i64) -> () {
    %135 = arith.constant 0 : i32
    %136 = arith.extsi %135 : i32 to i64
    %137 = llvm.mlir.constant(1 : i64) : i64
    %138 = llvm.alloca %137 x i64 : (i64) -> !llvm.ptr
    llvm.store %136, %138 : i64, !llvm.ptr
    cf.br ^bb27
    ^bb27:
    %139 = llvm.load %138 : !llvm.ptr -> i64
    %140 = arith.constant 12 : i32
    %142 = arith.extsi %140 : i32 to i64
    %141 = arith.cmpi slt, %139, %142 : i64
    cf.cond_br %141, ^bb28, ^bb29
    ^bb28:
      %143 = arith.constant 0 : i32
      %144 = arith.extsi %143 : i32 to i64
      %145 = llvm.mlir.constant(1 : i64) : i64
      %146 = llvm.alloca %145 x i64 : (i64) -> !llvm.ptr
      llvm.store %144, %146 : i64, !llvm.ptr
      %147 = arith.constant 0 : i32
      %148 = arith.extsi %147 : i32 to i64
      %149 = llvm.mlir.constant(1 : i64) : i64
      %150 = llvm.alloca %149 x i64 : (i64) -> !llvm.ptr
      llvm.store %148, %150 : i64, !llvm.ptr
      cf.br ^bb30
      ^bb30:
      %151 = llvm.load %150 : !llvm.ptr -> i64
      %152 = arith.constant 12 : i32
      %154 = arith.extsi %152 : i32 to i64
      %153 = arith.cmpi slt, %151, %154 : i64
      cf.cond_br %153, ^bb31, ^bb32
      ^bb31:
        %156 = llvm.load %138 : !llvm.ptr -> i64
        %157 = arith.constant 12 : i32
        %159 = arith.extsi %157 : i32 to i64
        %158 = arith.muli %156, %159 : i64
        %160 = llvm.load %150 : !llvm.ptr -> i64
        %161 = arith.addi %158, %160 : i64
        %162 = llvm.getelementptr %arg0[%161] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %155 = llvm.load %162 : !llvm.ptr -> i64
        %163 = arith.constant 0 : i32
        %165 = arith.extsi %163 : i32 to i64
        %164 = arith.cmpi ne, %155, %165 : i64
        cf.cond_br %164, ^bb33, ^bb34
        ^bb33:
          %166 = llvm.load %146 : !llvm.ptr -> i64
          %168 = llvm.load %150 : !llvm.ptr -> i64
          %169 = llvm.getelementptr %arg1[%168] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %167 = llvm.load %169 : !llvm.ptr -> i64
          %170 = arith.muli %155, %167 : i64
          %171 = arith.addi %166, %170 : i64
          %172 = arith.remsi %171, %arg3 : i64
          llvm.store %172, %146 : i64, !llvm.ptr
          cf.br ^bb35
        ^bb34:
          cf.br ^bb35
        ^bb35:
        %173 = llvm.load %150 : !llvm.ptr -> i64
        %174 = arith.constant 1 : i32
        %176 = arith.extsi %174 : i32 to i64
        %175 = arith.addi %173, %176 : i64
        llvm.store %175, %150 : i64, !llvm.ptr
        cf.br ^bb30
      ^bb32:
      %177 = llvm.load %146 : !llvm.ptr -> i64
      %178 = llvm.load %138 : !llvm.ptr -> i64
      %179 = llvm.getelementptr %arg2[%178] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %177, %179 : i64, !llvm.ptr
      %180 = llvm.load %138 : !llvm.ptr -> i64
      %181 = arith.constant 1 : i32
      %183 = arith.extsi %181 : i32 to i64
      %182 = arith.addi %180, %183 : i64
      llvm.store %182, %138 : i64, !llvm.ptr
      cf.br ^bb27
    ^bb29:
    func.return
  }
  func.func @modpow(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    %184 = arith.constant 1 : i32
    %185 = arith.extsi %184 : i32 to i64
    %186 = llvm.mlir.constant(1 : i64) : i64
    %187 = llvm.alloca %186 x i64 : (i64) -> !llvm.ptr
    llvm.store %185, %187 : i64, !llvm.ptr
    %188 = arith.remsi %arg0, %arg2 : i64
    %189 = llvm.mlir.constant(1 : i64) : i64
    %190 = llvm.alloca %189 x i64 : (i64) -> !llvm.ptr
    llvm.store %188, %190 : i64, !llvm.ptr
    %191 = llvm.mlir.constant(1 : i64) : i64
    %192 = llvm.alloca %191 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %192 : i64, !llvm.ptr
    cf.br ^bb36
    ^bb36:
    %193 = llvm.load %192 : !llvm.ptr -> i64
    %194 = arith.constant 0 : i32
    %196 = arith.extsi %194 : i32 to i64
    %195 = arith.cmpi sgt, %193, %196 : i64
    cf.cond_br %195, ^bb37, ^bb38
    ^bb37:
      %197 = llvm.load %192 : !llvm.ptr -> i64
      %198 = arith.constant 1 : i32
      %200 = arith.extsi %198 : i32 to i64
      %199 = arith.andi %197, %200 : i64
      %201 = arith.constant 1 : i32
      %203 = arith.extsi %201 : i32 to i64
      %202 = arith.cmpi eq, %199, %203 : i64
      cf.cond_br %202, ^bb39, ^bb40
      ^bb39:
        %204 = llvm.load %187 : !llvm.ptr -> i64
        %205 = llvm.load %190 : !llvm.ptr -> i64
        %206 = arith.muli %204, %205 : i64
        %207 = arith.remsi %206, %arg2 : i64
        llvm.store %207, %187 : i64, !llvm.ptr
        cf.br ^bb41
      ^bb40:
        cf.br ^bb41
      ^bb41:
      %208 = llvm.load %190 : !llvm.ptr -> i64
      %209 = llvm.load %190 : !llvm.ptr -> i64
      %210 = arith.muli %208, %209 : i64
      %211 = arith.remsi %210, %arg2 : i64
      llvm.store %211, %190 : i64, !llvm.ptr
      %212 = llvm.load %192 : !llvm.ptr -> i64
      %213 = arith.constant 1 : i32
      %215 = arith.extsi %213 : i32 to i64
      %214 = arith.shrsi %212, %215 : i64
      llvm.store %214, %192 : i64, !llvm.ptr
      cf.br ^bb36
    ^bb38:
    %216 = llvm.load %187 : !llvm.ptr -> i64
    func.return %216 : i64
  }
  func.func @prefix_sum_b(%arg0: i64, %arg1: i64, %arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr, %arg6: !llvm.ptr, %arg7: !llvm.ptr) -> i64 {
    %217 = arith.constant 0 : i32
    %219 = arith.extsi %217 : i32 to i64
    %218 = arith.cmpi sle, %arg0, %219 : i64
    cf.cond_br %218, ^bb42, ^bb43
    ^bb42:
      %220 = arith.constant 0 : i32
      %221 = arith.extsi %220 : i32 to i64
      func.return %221 : i64
    ^bb43:
      cf.br ^bb44
    ^bb44:
    %222 = arith.constant 1 : i32
    %224 = arith.extsi %222 : i32 to i64
    %223 = arith.subi %arg0, %224 : i64
    %225 = arith.constant 1 : i32
    %226 = arith.extsi %225 : i32 to i64
    %227 = arith.constant 2 : i32
    %228 = arith.extsi %227 : i32 to i64
    %229 = arith.constant 4 : i32
    %230 = arith.extsi %229 : i32 to i64
    %231 = arith.constant 6 : i32
    %232 = arith.extsi %231 : i32 to i64
    %233 = arith.constant 11 : i32
    %234 = arith.extsi %233 : i32 to i64
    %235 = arith.constant 20 : i32
    %236 = arith.extsi %235 : i32 to i64
    %237 = arith.constant 0 : i32
    %239 = arith.extsi %237 : i32 to i64
    %238 = arith.cmpi eq, %223, %239 : i64
    cf.cond_br %238, ^bb45, ^bb46
    ^bb45:
      func.return %226 : i64
    ^bb46:
      cf.br ^bb47
    ^bb47:
    %240 = arith.constant 1 : i32
    %242 = arith.extsi %240 : i32 to i64
    %241 = arith.cmpi eq, %223, %242 : i64
    cf.cond_br %241, ^bb48, ^bb49
    ^bb48:
      %243 = arith.addi %226, %228 : i64
      %244 = arith.remsi %243, %arg1 : i64
      func.return %244 : i64
    ^bb49:
      cf.br ^bb50
    ^bb50:
    %245 = arith.constant 2 : i32
    %247 = arith.extsi %245 : i32 to i64
    %246 = arith.cmpi eq, %223, %247 : i64
    cf.cond_br %246, ^bb51, ^bb52
    ^bb51:
      %248 = arith.addi %226, %228 : i64
      %249 = arith.addi %248, %230 : i64
      %250 = arith.remsi %249, %arg1 : i64
      func.return %250 : i64
    ^bb52:
      cf.br ^bb53
    ^bb53:
    %251 = arith.constant 3 : i32
    %253 = arith.extsi %251 : i32 to i64
    %252 = arith.cmpi eq, %223, %253 : i64
    cf.cond_br %252, ^bb54, ^bb55
    ^bb54:
      %254 = arith.addi %226, %228 : i64
      %255 = arith.addi %254, %230 : i64
      %256 = arith.addi %255, %232 : i64
      %257 = arith.remsi %256, %arg1 : i64
      func.return %257 : i64
    ^bb55:
      cf.br ^bb56
    ^bb56:
    %258 = arith.constant 4 : i32
    %260 = arith.extsi %258 : i32 to i64
    %259 = arith.cmpi eq, %223, %260 : i64
    cf.cond_br %259, ^bb57, ^bb58
    ^bb57:
      %261 = arith.addi %226, %228 : i64
      %262 = arith.addi %261, %230 : i64
      %263 = arith.addi %262, %232 : i64
      %264 = arith.addi %263, %234 : i64
      %265 = arith.remsi %264, %arg1 : i64
      func.return %265 : i64
    ^bb58:
      cf.br ^bb59
    ^bb59:
    %266 = arith.constant 5 : i32
    %268 = arith.extsi %266 : i32 to i64
    %267 = arith.cmpi eq, %223, %268 : i64
    cf.cond_br %267, ^bb60, ^bb61
    ^bb60:
      %269 = arith.addi %226, %228 : i64
      %270 = arith.addi %269, %230 : i64
      %271 = arith.addi %270, %232 : i64
      %272 = arith.addi %271, %234 : i64
      %273 = arith.addi %272, %236 : i64
      %274 = arith.remsi %273, %arg1 : i64
      func.return %274 : i64
    ^bb61:
      cf.br ^bb62
    ^bb62:
    %275 = arith.addi %226, %228 : i64
    %276 = arith.addi %275, %230 : i64
    %277 = arith.addi %276, %232 : i64
    %278 = arith.addi %277, %234 : i64
    %279 = arith.addi %278, %236 : i64
    %280 = arith.remsi %279, %arg1 : i64
    %281 = arith.constant 0 : i32
    %282 = arith.extsi %281 : i32 to i64
    %283 = llvm.getelementptr %arg6[%282] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %236, %283 : i64, !llvm.ptr
    %284 = arith.constant 1 : i32
    %285 = arith.extsi %284 : i32 to i64
    %286 = llvm.getelementptr %arg6[%285] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %234, %286 : i64, !llvm.ptr
    %287 = arith.constant 2 : i32
    %288 = arith.extsi %287 : i32 to i64
    %289 = llvm.getelementptr %arg6[%288] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %232, %289 : i64, !llvm.ptr
    %290 = arith.constant 3 : i32
    %291 = arith.extsi %290 : i32 to i64
    %292 = llvm.getelementptr %arg6[%291] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %230, %292 : i64, !llvm.ptr
    %293 = arith.constant 4 : i32
    %294 = arith.extsi %293 : i32 to i64
    %295 = llvm.getelementptr %arg6[%294] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %228, %295 : i64, !llvm.ptr
    %296 = arith.constant 5 : i32
    %297 = arith.extsi %296 : i32 to i64
    %298 = llvm.getelementptr %arg6[%297] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %226, %298 : i64, !llvm.ptr
    %300 = arith.constant 2 : i32
    %301 = arith.constant 5 : i32
    %302 = arith.extsi %300 : i32 to i64
    %303 = arith.extsi %301 : i32 to i64
    %299 = func.call @modpow(%302, %303, %arg1) : (i64, i64, i64) -> i64
    %304 = arith.constant 6 : i32
    %305 = arith.extsi %304 : i32 to i64
    %306 = llvm.getelementptr %arg6[%305] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %299, %306 : i64, !llvm.ptr
    %308 = arith.constant 2 : i32
    %309 = arith.constant 4 : i32
    %310 = arith.extsi %308 : i32 to i64
    %311 = arith.extsi %309 : i32 to i64
    %307 = func.call @modpow(%310, %311, %arg1) : (i64, i64, i64) -> i64
    %312 = arith.constant 7 : i32
    %313 = arith.extsi %312 : i32 to i64
    %314 = llvm.getelementptr %arg6[%313] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %307, %314 : i64, !llvm.ptr
    %316 = arith.constant 2 : i32
    %317 = arith.constant 3 : i32
    %318 = arith.extsi %316 : i32 to i64
    %319 = arith.extsi %317 : i32 to i64
    %315 = func.call @modpow(%318, %319, %arg1) : (i64, i64, i64) -> i64
    %320 = arith.constant 8 : i32
    %321 = arith.extsi %320 : i32 to i64
    %322 = llvm.getelementptr %arg6[%321] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %315, %322 : i64, !llvm.ptr
    %324 = arith.constant 2 : i32
    %325 = arith.constant 2 : i32
    %326 = arith.extsi %324 : i32 to i64
    %327 = arith.extsi %325 : i32 to i64
    %323 = func.call @modpow(%326, %327, %arg1) : (i64, i64, i64) -> i64
    %328 = arith.constant 9 : i32
    %329 = arith.extsi %328 : i32 to i64
    %330 = llvm.getelementptr %arg6[%329] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %323, %330 : i64, !llvm.ptr
    %331 = arith.constant 10 : i32
    %332 = arith.extsi %331 : i32 to i64
    %333 = llvm.getelementptr %arg6[%332] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %280, %333 : i64, !llvm.ptr
    %334 = arith.constant 1 : i32
    %335 = arith.constant 11 : i32
    %336 = arith.extsi %334 : i32 to i64
    %337 = arith.extsi %335 : i32 to i64
    %338 = llvm.getelementptr %arg6[%337] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %336, %338 : i64, !llvm.ptr
    %340 = arith.constant 5 : i32
    %342 = arith.extsi %340 : i32 to i64
    %341 = arith.subi %223, %342 : i64
    func.call @mat_pow(%arg2, %341, %arg1, %arg3, %arg4, %arg5) : (!llvm.ptr, i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
    func.call @mat_vec(%arg3, %arg6, %arg7, %arg1) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, i64) -> ()
    %345 = arith.constant 10 : i32
    %346 = arith.extsi %345 : i32 to i64
    %347 = llvm.getelementptr %arg7[%346] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %344 = llvm.load %347 : !llvm.ptr -> i64
    %348 = arith.remsi %344, %arg1 : i64
    func.return %348 : i64
  }
  func.func @f_n(%arg0: i64, %arg1: i64, %arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr, %arg6: !llvm.ptr, %arg7: !llvm.ptr) -> i64 {
    %349 = func.call @prefix_sum_b(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7) : (i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %351 = arith.constant 2 : i32
    %352 = arith.extsi %351 : i32 to i64
    %350 = func.call @modpow(%352, %arg0, %arg1) : (i64, i64, i64) -> i64
    %353 = arith.constant 1 : i32
    %355 = arith.extsi %353 : i32 to i64
    %354 = arith.subi %350, %355 : i64
    %356 = arith.subi %354, %349 : i64
    %357 = arith.remsi %356, %arg1 : i64
    %358 = llvm.mlir.constant(1 : i64) : i64
    %359 = llvm.alloca %358 x i64 : (i64) -> !llvm.ptr
    llvm.store %357, %359 : i64, !llvm.ptr
    %360 = llvm.load %359 : !llvm.ptr -> i64
    %361 = arith.constant 0 : i32
    %363 = arith.extsi %361 : i32 to i64
    %362 = arith.cmpi slt, %360, %363 : i64
    cf.cond_br %362, ^bb63, ^bb64
    ^bb63:
      %364 = llvm.load %359 : !llvm.ptr -> i64
      %365 = arith.addi %364, %arg1 : i64
      llvm.store %365, %359 : i64, !llvm.ptr
      cf.br ^bb65
    ^bb64:
      cf.br ^bb65
    ^bb65:
    %366 = llvm.load %359 : !llvm.ptr -> i64
    func.return %366 : i64
  }
  func.func @main() -> i32 {
    %367 = arith.constant 1000000000 : i32
    %368 = arith.extsi %367 : i32 to i64
    %370 = arith.constant 144 : i32
    %371 = arith.constant 8 : i32
    %372 = arith.extsi %370 : i32 to i64
    %373 = arith.extsi %371 : i32 to i64
    %369 = func.call @calloc(%372, %373) : (i64, i64) -> !llvm.ptr
    %375 = arith.constant 144 : i32
    %376 = arith.constant 8 : i32
    %377 = arith.extsi %375 : i32 to i64
    %378 = arith.extsi %376 : i32 to i64
    %374 = func.call @calloc(%377, %378) : (i64, i64) -> !llvm.ptr
    %380 = arith.constant 144 : i32
    %381 = arith.constant 8 : i32
    %382 = arith.extsi %380 : i32 to i64
    %383 = arith.extsi %381 : i32 to i64
    %379 = func.call @calloc(%382, %383) : (i64, i64) -> !llvm.ptr
    %385 = arith.constant 144 : i32
    %386 = arith.constant 8 : i32
    %387 = arith.extsi %385 : i32 to i64
    %388 = arith.extsi %386 : i32 to i64
    %384 = func.call @calloc(%387, %388) : (i64, i64) -> !llvm.ptr
    %390 = arith.constant 12 : i32
    %391 = arith.constant 8 : i32
    %392 = arith.extsi %390 : i32 to i64
    %393 = arith.extsi %391 : i32 to i64
    %389 = func.call @calloc(%392, %393) : (i64, i64) -> !llvm.ptr
    %395 = arith.constant 12 : i32
    %396 = arith.constant 8 : i32
    %397 = arith.extsi %395 : i32 to i64
    %398 = arith.extsi %396 : i32 to i64
    %394 = func.call @calloc(%397, %398) : (i64, i64) -> !llvm.ptr
    %399 = llvm.mlir.zero : !llvm.ptr
    %400 = llvm.icmp "eq" %369, %399 : !llvm.ptr
    %401 = scf.if %400 -> (i1) {
      %402 = arith.constant true
      scf.yield %402 : i1
    } else {
      %403 = llvm.mlir.zero : !llvm.ptr
      %404 = llvm.icmp "eq" %374, %403 : !llvm.ptr
      scf.yield %404 : i1
    }
    %405 = scf.if %401 -> (i1) {
      %406 = arith.constant true
      scf.yield %406 : i1
    } else {
      %407 = llvm.mlir.zero : !llvm.ptr
      %408 = llvm.icmp "eq" %379, %407 : !llvm.ptr
      scf.yield %408 : i1
    }
    %409 = scf.if %405 -> (i1) {
      %410 = arith.constant true
      scf.yield %410 : i1
    } else {
      %411 = llvm.mlir.zero : !llvm.ptr
      %412 = llvm.icmp "eq" %384, %411 : !llvm.ptr
      scf.yield %412 : i1
    }
    %413 = scf.if %409 -> (i1) {
      %414 = arith.constant true
      scf.yield %414 : i1
    } else {
      %415 = llvm.mlir.zero : !llvm.ptr
      %416 = llvm.icmp "eq" %389, %415 : !llvm.ptr
      scf.yield %416 : i1
    }
    %417 = scf.if %413 -> (i1) {
      %418 = arith.constant true
      scf.yield %418 : i1
    } else {
      %419 = llvm.mlir.zero : !llvm.ptr
      %420 = llvm.icmp "eq" %394, %419 : !llvm.ptr
      scf.yield %420 : i1
    }
    cf.cond_br %417, ^bb66, ^bb67
    ^bb66:
      %421 = arith.constant 1 : i32
      func.return %421 : i32
    ^bb67:
      cf.br ^bb68
    ^bb68:
    %422 = arith.constant 0 : i32
    %423 = arith.extsi %422 : i32 to i64
    %424 = llvm.mlir.constant(1 : i64) : i64
    %425 = llvm.alloca %424 x i64 : (i64) -> !llvm.ptr
    llvm.store %423, %425 : i64, !llvm.ptr
    cf.br ^bb69
    ^bb69:
    %426 = llvm.load %425 : !llvm.ptr -> i64
    %427 = arith.constant 144 : i32
    %429 = arith.extsi %427 : i32 to i64
    %428 = arith.cmpi slt, %426, %429 : i64
    cf.cond_br %428, ^bb70, ^bb71
    ^bb70:
      %430 = arith.constant 0 : i32
      %431 = llvm.load %425 : !llvm.ptr -> i64
      %432 = arith.extsi %430 : i32 to i64
      %433 = llvm.getelementptr %369[%431] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %432, %433 : i64, !llvm.ptr
      %434 = llvm.load %425 : !llvm.ptr -> i64
      %435 = arith.constant 1 : i32
      %437 = arith.extsi %435 : i32 to i64
      %436 = arith.addi %434, %437 : i64
      llvm.store %436, %425 : i64, !llvm.ptr
      cf.br ^bb69
    ^bb71:
    %438 = arith.constant 2 : i32
    %439 = arith.constant 0 : i32
    %440 = arith.constant 12 : i32
    %441 = arith.muli %439, %440 : i32
    %442 = arith.constant 2 : i32
    %443 = arith.addi %441, %442 : i32
    %444 = arith.extsi %438 : i32 to i64
    %445 = arith.extsi %443 : i32 to i64
    %446 = llvm.getelementptr %369[%445] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %444, %446 : i64, !llvm.ptr
    %447 = arith.constant 1 : i32
    %448 = arith.constant 0 : i32
    %449 = arith.constant 12 : i32
    %450 = arith.muli %448, %449 : i32
    %451 = arith.constant 3 : i32
    %452 = arith.addi %450, %451 : i32
    %453 = arith.extsi %447 : i32 to i64
    %454 = arith.extsi %452 : i32 to i64
    %455 = llvm.getelementptr %369[%454] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %453, %455 : i64, !llvm.ptr
    %456 = arith.constant 1 : i32
    %458 = arith.extsi %456 : i32 to i64
    %457 = arith.subi %368, %458 : i64
    %459 = arith.constant 0 : i32
    %460 = arith.constant 12 : i32
    %461 = arith.muli %459, %460 : i32
    %462 = arith.constant 5 : i32
    %463 = arith.addi %461, %462 : i32
    %464 = arith.extsi %463 : i32 to i64
    %465 = llvm.getelementptr %369[%464] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %457, %465 : i64, !llvm.ptr
    %466 = arith.constant 5 : i32
    %467 = arith.constant 0 : i32
    %468 = arith.constant 12 : i32
    %469 = arith.muli %467, %468 : i32
    %470 = arith.constant 9 : i32
    %471 = arith.addi %469, %470 : i32
    %472 = arith.extsi %466 : i32 to i64
    %473 = arith.extsi %471 : i32 to i64
    %474 = llvm.getelementptr %369[%473] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %472, %474 : i64, !llvm.ptr
    %475 = arith.constant 1 : i32
    %476 = arith.constant 0 : i32
    %477 = arith.constant 12 : i32
    %478 = arith.muli %476, %477 : i32
    %479 = arith.constant 11 : i32
    %480 = arith.addi %478, %479 : i32
    %481 = arith.extsi %475 : i32 to i64
    %482 = arith.extsi %480 : i32 to i64
    %483 = llvm.getelementptr %369[%482] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %481, %483 : i64, !llvm.ptr
    %484 = arith.constant 1 : i32
    %485 = arith.constant 1 : i32
    %486 = arith.constant 12 : i32
    %487 = arith.muli %485, %486 : i32
    %488 = arith.constant 0 : i32
    %489 = arith.addi %487, %488 : i32
    %490 = arith.extsi %484 : i32 to i64
    %491 = arith.extsi %489 : i32 to i64
    %492 = llvm.getelementptr %369[%491] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %490, %492 : i64, !llvm.ptr
    %493 = arith.constant 1 : i32
    %494 = arith.constant 2 : i32
    %495 = arith.constant 12 : i32
    %496 = arith.muli %494, %495 : i32
    %497 = arith.constant 1 : i32
    %498 = arith.addi %496, %497 : i32
    %499 = arith.extsi %493 : i32 to i64
    %500 = arith.extsi %498 : i32 to i64
    %501 = llvm.getelementptr %369[%500] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %499, %501 : i64, !llvm.ptr
    %502 = arith.constant 1 : i32
    %503 = arith.constant 3 : i32
    %504 = arith.constant 12 : i32
    %505 = arith.muli %503, %504 : i32
    %506 = arith.constant 2 : i32
    %507 = arith.addi %505, %506 : i32
    %508 = arith.extsi %502 : i32 to i64
    %509 = arith.extsi %507 : i32 to i64
    %510 = llvm.getelementptr %369[%509] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %508, %510 : i64, !llvm.ptr
    %511 = arith.constant 1 : i32
    %512 = arith.constant 4 : i32
    %513 = arith.constant 12 : i32
    %514 = arith.muli %512, %513 : i32
    %515 = arith.constant 3 : i32
    %516 = arith.addi %514, %515 : i32
    %517 = arith.extsi %511 : i32 to i64
    %518 = arith.extsi %516 : i32 to i64
    %519 = llvm.getelementptr %369[%518] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %517, %519 : i64, !llvm.ptr
    %520 = arith.constant 1 : i32
    %521 = arith.constant 5 : i32
    %522 = arith.constant 12 : i32
    %523 = arith.muli %521, %522 : i32
    %524 = arith.constant 4 : i32
    %525 = arith.addi %523, %524 : i32
    %526 = arith.extsi %520 : i32 to i64
    %527 = arith.extsi %525 : i32 to i64
    %528 = llvm.getelementptr %369[%527] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %526, %528 : i64, !llvm.ptr
    %529 = arith.constant 2 : i32
    %530 = arith.constant 6 : i32
    %531 = arith.constant 12 : i32
    %532 = arith.muli %530, %531 : i32
    %533 = arith.constant 6 : i32
    %534 = arith.addi %532, %533 : i32
    %535 = arith.extsi %529 : i32 to i64
    %536 = arith.extsi %534 : i32 to i64
    %537 = llvm.getelementptr %369[%536] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %535, %537 : i64, !llvm.ptr
    %538 = arith.constant 1 : i32
    %539 = arith.constant 7 : i32
    %540 = arith.constant 12 : i32
    %541 = arith.muli %539, %540 : i32
    %542 = arith.constant 6 : i32
    %543 = arith.addi %541, %542 : i32
    %544 = arith.extsi %538 : i32 to i64
    %545 = arith.extsi %543 : i32 to i64
    %546 = llvm.getelementptr %369[%545] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %544, %546 : i64, !llvm.ptr
    %547 = arith.constant 1 : i32
    %548 = arith.constant 8 : i32
    %549 = arith.constant 12 : i32
    %550 = arith.muli %548, %549 : i32
    %551 = arith.constant 7 : i32
    %552 = arith.addi %550, %551 : i32
    %553 = arith.extsi %547 : i32 to i64
    %554 = arith.extsi %552 : i32 to i64
    %555 = llvm.getelementptr %369[%554] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %553, %555 : i64, !llvm.ptr
    %556 = arith.constant 1 : i32
    %557 = arith.constant 9 : i32
    %558 = arith.constant 12 : i32
    %559 = arith.muli %557, %558 : i32
    %560 = arith.constant 8 : i32
    %561 = arith.addi %559, %560 : i32
    %562 = arith.extsi %556 : i32 to i64
    %563 = arith.extsi %561 : i32 to i64
    %564 = llvm.getelementptr %369[%563] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %562, %564 : i64, !llvm.ptr
    %565 = arith.constant 1 : i32
    %566 = arith.constant 10 : i32
    %567 = arith.constant 12 : i32
    %568 = arith.muli %566, %567 : i32
    %569 = arith.constant 10 : i32
    %570 = arith.addi %568, %569 : i32
    %571 = arith.extsi %565 : i32 to i64
    %572 = arith.extsi %570 : i32 to i64
    %573 = llvm.getelementptr %369[%572] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %571, %573 : i64, !llvm.ptr
    %574 = arith.constant 0 : i32
    %575 = arith.extsi %574 : i32 to i64
    llvm.store %575, %425 : i64, !llvm.ptr
    cf.br ^bb72
    ^bb72:
    %576 = llvm.load %425 : !llvm.ptr -> i64
    %577 = arith.constant 12 : i32
    %579 = arith.extsi %577 : i32 to i64
    %578 = arith.cmpi slt, %576, %579 : i64
    cf.cond_br %578, ^bb73, ^bb74
    ^bb73:
      %581 = arith.constant 10 : i32
      %582 = arith.constant 12 : i32
      %583 = arith.muli %581, %582 : i32
      %584 = llvm.load %425 : !llvm.ptr -> i64
      %586 = arith.extsi %583 : i32 to i64
      %585 = arith.addi %586, %584 : i64
      %587 = llvm.getelementptr %369[%585] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %580 = llvm.load %587 : !llvm.ptr -> i64
      %589 = arith.constant 0 : i32
      %590 = arith.constant 12 : i32
      %591 = arith.muli %589, %590 : i32
      %592 = llvm.load %425 : !llvm.ptr -> i64
      %594 = arith.extsi %591 : i32 to i64
      %593 = arith.addi %594, %592 : i64
      %595 = llvm.getelementptr %369[%593] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %588 = llvm.load %595 : !llvm.ptr -> i64
      %596 = arith.addi %580, %588 : i64
      %597 = arith.remsi %596, %368 : i64
      %598 = arith.constant 10 : i32
      %599 = arith.constant 12 : i32
      %600 = arith.muli %598, %599 : i32
      %601 = llvm.load %425 : !llvm.ptr -> i64
      %603 = arith.extsi %600 : i32 to i64
      %602 = arith.addi %603, %601 : i64
      %604 = llvm.getelementptr %369[%602] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %597, %604 : i64, !llvm.ptr
      %605 = llvm.load %425 : !llvm.ptr -> i64
      %606 = arith.constant 1 : i32
      %608 = arith.extsi %606 : i32 to i64
      %607 = arith.addi %605, %608 : i64
      llvm.store %607, %425 : i64, !llvm.ptr
      cf.br ^bb72
    ^bb74:
    %609 = arith.constant 1 : i32
    %610 = arith.constant 11 : i32
    %611 = arith.constant 12 : i32
    %612 = arith.muli %610, %611 : i32
    %613 = arith.constant 11 : i32
    %614 = arith.addi %612, %613 : i32
    %615 = arith.extsi %609 : i32 to i64
    %616 = arith.extsi %614 : i32 to i64
    %617 = llvm.getelementptr %369[%616] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %615, %617 : i64, !llvm.ptr
    %619 = arith.constant 999999995705032704 : i32
    %620 = arith.extsi %619 : i32 to i64
    %618 = func.call @f_n(%620, %368, %369, %374, %379, %384, %389, %394) : (i64, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %621 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %622 = llvm.call @printf(%621, %618) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    func.call @free(%394) : (!llvm.ptr) -> ()
    func.call @free(%389) : (!llvm.ptr) -> ()
    func.call @free(%384) : (!llvm.ptr) -> ()
    func.call @free(%379) : (!llvm.ptr) -> ()
    func.call @free(%374) : (!llvm.ptr) -> ()
    func.call @free(%369) : (!llvm.ptr) -> ()
    %629 = arith.constant 0 : i32
    func.return %629 : i32
  }
}