Problem 672

H(K) = S((7^K - 1)/11) mod 1117117717, K=10^9. Uses 4x4 matrix exponentiation over base-7 digits of 1/11.

Answer91627537
Output91627537
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(log n)
Space complexityO(1)O(n^2)
ApproachFlow solutionMatrix exponentiation
VerdictSuboptimal

Flow source

# Project Euler 672: One More One
# H(K) = S((7^K - 1)/11) mod 1117117717, K=10^9.
# Uses 4x4 matrix exponentiation over base-7 digits of 1/11.

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

const MOD: i64 = 1117117717

# 4x4 matrix multiply: R = A * B (mod MOD)
function mat_mul(a: ptr<i64>, b: ptr<i64>, r: ptr<i64>) -> void {
    for i in 0..4 {
        for j in 0..4 {
            let mut s: i64 = 0
            for k in 0..4 {
                s = (s + a[i * 4 + k] * b[k * 4 + j]) % MOD
            }
            r[i * 4 + j] = s
        }
    }
}

# 4x4 matrix power: R = M^e (mod MOD)
function mat_pow(m: ptr<i64>, e: i64, r: ptr<i64>) -> void {
    # Initialize r = identity
    for i in 0..4 {
        for j in 0..4 {
            if i == j { r[i * 4 + j] = 1 } else { r[i * 4 + j] = 0 }
        }
    }
    # Copy m to base
    let base: ptr<i64> = calloc(16, 8)
    for i in 0..16 { base[i] = m[i] }
    let mut e_local: i64 = e
    while e_local > 0 {
        if e_local & 1 == 1 {
            let tmp: ptr<i64> = calloc(16, 8)
            mat_mul(r, base, tmp)
            for i in 0..16 { r[i] = tmp[i] }
            free(tmp)
        }
        let tmp2: ptr<i64> = calloc(16, 8)
        mat_mul(base, base, tmp2)
        for i in 0..16 { base[i] = tmp2[i] }
        free(tmp2)
        e_local = e_local >> 1
    }
    free(base)
}

# Matrix-vector multiply: v = M * v (mod MOD), v is length 4
function mat_vec(m: ptr<i64>, v: ptr<i64>, out: ptr<i64>) -> void {
    for i in 0..4 {
        let mut s: i64 = 0
        for k in 0..4 {
            s = (s + m[i * 4 + k] * v[k]) % MOD
        }
        out[i] = s
    }
}

# Build digit matrix for appending base-7 digit r
function digit_matrix(r: i64, out: ptr<i64>) -> void {
    let c1: i64 = (-6 + 7 * r - (r * (r + 1)) / 2) % MOD
    if c1 < 0 { c1 = c1 + MOD }
    let c2: i64
    if r == 6 { c2 = 0 } else { c2 = (6 - r) % MOD }
    if c2 < 0 { c2 = c2 + MOD }

    # Row 0: [7, r, 21, c1]
    out[0] = 7 % MOD
    out[1] = r % MOD
    out[2] = 21 % MOD
    out[3] = c1
    # Row 1: [0, 1, 0, c2]
    out[4] = 0
    out[5] = 1
    out[6] = 0
    out[7] = c2
    # Row 2: [0, 0, 7, r]
    out[8] = 0
    out[9] = 0
    out[10] = 7 % MOD
    out[11] = r % MOD
    # Row 3: [0, 0, 0, 1]
    out[12] = 0
    out[13] = 0
    out[14] = 0
    out[15] = 1
}

function main() -> i32 {
    # Base-7 digits of 1/11 with period 10
    # A = [0,4,3,1,1,6,2,3,5,5]
    # B = A[1:] + A[:1] = [4,3,1,1,6,2,3,5,5,0]
    let B: ptr<i64> = calloc(10, 8)
    B[0] = 4; B[1] = 3; B[2] = 1; B[3] = 1; B[4] = 6
    B[5] = 2; B[6] = 3; B[7] = 5; B[8] = 5; B[9] = 0

    let K: i64 = 1000000000  # 10^9
    let total_digits: i64 = K - 1
    let full_blocks: i64 = total_digits / 10
    let rem: i64 = total_digits % 10

    # Build block matrix M_block = product of digit_matrix(B[i]) for i=0..9
    let M_block: ptr<i64> = calloc(16, 8)
    # Initialize as identity
    for i in 0..4 {
        for j in 0..4 {
            if i == j { M_block[i * 4 + j] = 1 } else { M_block[i * 4 + j] = 0 }
        }
    }
    let dm: ptr<i64> = calloc(16, 8)
    let tmp: ptr<i64> = calloc(16, 8)
    for i in 0..10 {
        digit_matrix(B[i], dm)
        mat_mul(dm, M_block, tmp)
        for j in 0..16 { M_block[j] = tmp[j] }
    }
    free(dm)
    free(tmp)

    # v = [0, 0, 0, 1]
    let v: ptr<i64> = calloc(4, 8)
    v[0] = 0; v[1] = 0; v[2] = 0; v[3] = 1

    # Apply M_block^full_blocks
    if full_blocks > 0 {
        let mp: ptr<i64> = calloc(16, 8)
        mat_pow(M_block, full_blocks, mp)
        let vv: ptr<i64> = calloc(4, 8)
        mat_vec(mp, v, vv)
        for i in 0..4 { v[i] = vv[i] }
        free(vv)
        free(mp)
    }

    # Apply remaining digits
    let dm2: ptr<i64> = calloc(16, 8)
    let vv2: ptr<i64> = calloc(4, 8)
    for i in 0..rem {
        digit_matrix(B[i], dm2)
        mat_vec(dm2, v, vv2)
        for j in 0..4 { v[j] = vv2[j] }
    }
    free(dm2)
    free(vv2)

    let ans: i64 = v[0] % MOD
    if ans < 0 { ans = ans + MOD }
    printf("%lld\n", ans)

    free(v)
    free(M_block)
    free(B)
    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(int64_t* a, int64_t* b, int64_t* r);
void mat_pow_ptr_i64_i64_ptr_i64(int64_t* m, int64_t e, int64_t* r);
void mat_vec_ptr_i64_ptr_i64_ptr_i64(int64_t* m, int64_t* v, int64_t* out);
void digit_matrix_i64_ptr_i64(int64_t r, int64_t* out);
int32_t main(void);

static const int64_t MOD = 1117117717;



void mat_mul_ptr_i64_ptr_i64_ptr_i64(int64_t* a, int64_t* b, int64_t* r) {
    int32_t __flow_step_1 = 1;
    for (int32_t i = 0; (0 <= 4) ? i < 4 : i > 4; i += (0 <= 4) ? 1 : -1) {
        int32_t __flow_step_2 = 1;
        for (int32_t j = 0; (0 <= 4) ? j < 4 : j > 4; j += (0 <= 4) ? 1 : -1) {
            int64_t s = 0;
            int32_t __flow_step_3 = 1;
            for (int32_t k = 0; (0 <= 4) ? k < 4 : k > 4; k += (0 <= 4) ? 1 : -1) {
                s = FLOW_CHECKED_MOD(((s + (a[((i * 4) + k)] * b[((k * 4) + j)]))), (MOD));
            }
            r[((i * 4) + j)] = s;
        }
    }
}

void mat_pow_ptr_i64_i64_ptr_i64(int64_t* m, int64_t e, int64_t* r) {
    int32_t __flow_step_4 = 1;
    for (int32_t i = 0; (0 <= 4) ? i < 4 : i > 4; i += (0 <= 4) ? 1 : -1) {
        int32_t __flow_step_5 = 1;
        for (int32_t j = 0; (0 <= 4) ? j < 4 : j > 4; j += (0 <= 4) ? 1 : -1) {
            if (i == j) {
                r[((i * 4) + j)] = 1;
            } else {
                r[((i * 4) + j)] = 0;
            }
        }
    }
    int64_t* base = (int64_t*)(calloc(16, 8));
    int32_t __flow_step_6 = 1;
    for (int32_t i = 0; (0 <= 16) ? i < 16 : i > 16; i += (0 <= 16) ? 1 : -1) {
        base[i] = m[i];
    }
    int64_t e_local = e;
    while (e_local > 0) {
        if ((e_local & 1 == 1)) {
            int64_t* tmp = (int64_t*)(calloc(16, 8));
            mat_mul_ptr_i64_ptr_i64_ptr_i64(r, base, tmp);
            int32_t __flow_step_7 = 1;
            for (int32_t i = 0; (0 <= 16) ? i < 16 : i > 16; i += (0 <= 16) ? 1 : -1) {
                r[i] = tmp[i];
            }
            free(tmp);
        }
        int64_t* tmp2 = (int64_t*)(calloc(16, 8));
        mat_mul_ptr_i64_ptr_i64_ptr_i64(base, base, tmp2);
        int32_t __flow_step_8 = 1;
        for (int32_t i = 0; (0 <= 16) ? i < 16 : i > 16; i += (0 <= 16) ? 1 : -1) {
            base[i] = tmp2[i];
        }
        free(tmp2);
        e_local = FLOW_CHECKED_SHR((e_local), (1));
    }
    free(base);
}

void mat_vec_ptr_i64_ptr_i64_ptr_i64(int64_t* m, int64_t* v, int64_t* out) {
    int32_t __flow_step_9 = 1;
    for (int32_t i = 0; (0 <= 4) ? i < 4 : i > 4; i += (0 <= 4) ? 1 : -1) {
        int64_t s = 0;
        int32_t __flow_step_10 = 1;
        for (int32_t k = 0; (0 <= 4) ? k < 4 : k > 4; k += (0 <= 4) ? 1 : -1) {
            s = FLOW_CHECKED_MOD(((s + (m[((i * 4) + k)] * v[k]))), (MOD));
        }
        out[i] = s;
    }
}

void digit_matrix_i64_ptr_i64(int64_t r, int64_t* out) {
    int64_t c1 = FLOW_CHECKED_MOD(((((-6) + (7 * r)) - FLOW_CHECKED_DIV(((r * (r + 1))), (2)))), (MOD));
    if (c1 < 0) {
        c1 = (c1 + MOD);
    }
    int64_t c2;
    if (r == 6) {
        c2 = 0;
    } else {
        c2 = FLOW_CHECKED_MOD(((6 - r)), (MOD));
    }
    if (c2 < 0) {
        c2 = (c2 + MOD);
    }
    out[0] = FLOW_CHECKED_MOD((7), (MOD));
    out[1] = FLOW_CHECKED_MOD((r), (MOD));
    out[2] = FLOW_CHECKED_MOD((21), (MOD));
    out[3] = c1;
    out[4] = 0;
    out[5] = 1;
    out[6] = 0;
    out[7] = c2;
    out[8] = 0;
    out[9] = 0;
    out[10] = FLOW_CHECKED_MOD((7), (MOD));
    out[11] = FLOW_CHECKED_MOD((r), (MOD));
    out[12] = 0;
    out[13] = 0;
    out[14] = 0;
    out[15] = 1;
}

int32_t main(void) {
    int64_t* B = (int64_t*)(calloc(10, 8));
    B[0] = 4;
    B[1] = 3;
    B[2] = 1;
    B[3] = 1;
    B[4] = 6;
    B[5] = 2;
    B[6] = 3;
    B[7] = 5;
    B[8] = 5;
    B[9] = 0;
    int64_t K = 1000000000;
    int64_t total_digits = (K - 1);
    int64_t full_blocks = FLOW_CHECKED_DIV((total_digits), (10));
    int64_t rem = FLOW_CHECKED_MOD((total_digits), (10));
    int64_t* M_block = (int64_t*)(calloc(16, 8));
    int32_t __flow_step_11 = 1;
    for (int32_t i = 0; (0 <= 4) ? i < 4 : i > 4; i += (0 <= 4) ? 1 : -1) {
        int32_t __flow_step_12 = 1;
        for (int32_t j = 0; (0 <= 4) ? j < 4 : j > 4; j += (0 <= 4) ? 1 : -1) {
            if (i == j) {
                M_block[((i * 4) + j)] = 1;
            } else {
                M_block[((i * 4) + j)] = 0;
            }
        }
    }
    int64_t* dm = (int64_t*)(calloc(16, 8));
    int64_t* tmp = (int64_t*)(calloc(16, 8));
    int32_t __flow_step_13 = 1;
    for (int32_t i = 0; (0 <= 10) ? i < 10 : i > 10; i += (0 <= 10) ? 1 : -1) {
        digit_matrix_i64_ptr_i64(B[i], dm);
        mat_mul_ptr_i64_ptr_i64_ptr_i64(dm, M_block, tmp);
        int32_t __flow_step_14 = 1;
        for (int32_t j = 0; (0 <= 16) ? j < 16 : j > 16; j += (0 <= 16) ? 1 : -1) {
            M_block[j] = tmp[j];
        }
    }
    free(dm);
    free(tmp);
    int64_t* v = (int64_t*)(calloc(4, 8));
    v[0] = 0;
    v[1] = 0;
    v[2] = 0;
    v[3] = 1;
    if (full_blocks > 0) {
        int64_t* mp = (int64_t*)(calloc(16, 8));
        mat_pow_ptr_i64_i64_ptr_i64(M_block, full_blocks, mp);
        int64_t* vv = (int64_t*)(calloc(4, 8));
        mat_vec_ptr_i64_ptr_i64_ptr_i64(mp, v, vv);
        int32_t __flow_step_15 = 1;
        for (int32_t i = 0; (0 <= 4) ? i < 4 : i > 4; i += (0 <= 4) ? 1 : -1) {
            v[i] = vv[i];
        }
        free(vv);
        free(mp);
    }
    int64_t* dm2 = (int64_t*)(calloc(16, 8));
    int64_t* vv2 = (int64_t*)(calloc(4, 8));
    int32_t __flow_step_16 = 1;
    for (int32_t i = 0; (0 <= rem) ? i < rem : i > rem; i += (0 <= rem) ? 1 : -1) {
        digit_matrix_i64_ptr_i64(B[i], dm2);
        mat_vec_ptr_i64_ptr_i64_ptr_i64(dm2, v, vv2);
        int32_t __flow_step_17 = 1;
        for (int32_t j = 0; (0 <= 4) ? j < 4 : j > 4; j += (0 <= 4) ? 1 : -1) {
            v[j] = vv2[j];
        }
    }
    free(dm2);
    free(vv2);
    int64_t ans = FLOW_CHECKED_MOD((v[0]), (MOD));
    if (ans < 0) {
        ans = (ans + MOD);
    }
    printf("%lld\n", ans);
    free(v);
    free(M_block);
    free(B);
    return 0;
}

Generated MLIR

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