Problem 696

Mahjong: w(10^8, 10^8, 30) mod 1e9+7. Split by suit: a hand is t triples + one pair, and the pair's suit is forced (only that suit holds a tile count = 2 mod 3), so w(n, s, t) = s * [x^t] B(x) * A(x)^(s-1), where a_t(n) / b_t(n) count one-suit multisets forming exactly t triples without / with the pair. Counting multisets once despite ambiguous decompositions (3 chows = 3 pungs, and pair-shift trades like 22 345 345 = 234 234 55) is done with a subset-construction DP: track the set of reachable (pending chows, pair used, triples) states per multiset, so decomposability is judged deterministically. data/p696_tables.txt holds a_t(n), b_t(n) mod 1e9+7 for n = 401..444 from that DP (t = 0..30; 62 rows). Both sequences are polynomial in n of degree <= t+1 there (checked by extrapolating to n = 600 and n = 1000 against the direct DP), so Lagrange interpolation gives n = 10^8. Verified: w(4,1,1)=20, w(9,1,4)=13259, w(9,3,4)=5237550, w(1000,1000,5) = 107662178 mod 1e9+7.

Answer436944244
Output436944244
StatusPASS
Native helperno
Runtime0 ms
Peak memory1136 KB
Time complexityO(n^2) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^2)O(n * sum)
Space complexityO(n^2)O(sum)
ApproachFlow solutionSubset sum DP
VerdictUnknown

Flow source

# Project Euler 696
# Mahjong: w(10^8, 10^8, 30) mod 1e9+7.
#
# Split by suit: a hand is t triples + one pair, and the pair's suit is
# forced (only that suit holds a tile count = 2 mod 3), so
#     w(n, s, t) = s * [x^t] B(x) * A(x)^(s-1),
# where a_t(n) / b_t(n) count one-suit multisets forming exactly t triples
# without / with the pair.  Counting multisets once despite ambiguous
# decompositions (3 chows = 3 pungs, and pair-shift trades like
# 22 345 345 = 234 234 55) is done with a subset-construction DP: track the
# set of reachable (pending chows, pair used, triples) states per multiset,
# so decomposability is judged deterministically.
#
# data/p696_tables.txt holds a_t(n), b_t(n) mod 1e9+7 for n = 401..444 from
# that DP (t = 0..30; 62 rows).  Both sequences are polynomial in n of
# degree <= t+1 there (checked by extrapolating to n = 600 and n = 1000
# against the direct DP), so Lagrange interpolation gives n = 10^8.
# Verified: w(4,1,1)=20, w(9,1,4)=13259, w(9,3,4)=5237550,
# w(1000,1000,5) = 107662178 mod 1e9+7.

extern {
    function fopen(path: string, mode: string) -> ptr<void>
    function fgetc(f: ptr<void>) -> i32
    function fclose(f: ptr<void>) -> i32
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
}

const MOD: i64 = 1000000007
const NPTS: i64 = 44        # samples at n = 401..444
const TMAX: i64 = 30
const BIGN: i64 = 100000000
const SUITS: i64 = 100000000

function powmod(base: i64, exp: i64) -> i64 {
    let mut result: i64 = 1
    let mut b: i64 = base % MOD
    let mut e: i64 = exp
    while e > 0 {
        if (e & 1) == 1 {
            result = result * b % MOD
        }
        b = b * b % MOD
        e = e >> 1
    }
    return result
}

# Lagrange interpolation at X from points (401+i, ys[i]), i = 0..NPTS-1
function lagrange(ys: ptr<i64>, X: i64) -> i64 {
    let mut res: i64 = 0
    let mut i: i64 = 0
    while i < NPTS {
        let mut num: i64 = 1
        let mut den: i64 = 1
        let mut j: i64 = 0
        while j < NPTS {
            if j != i {
                num = num * ((X - (401 + j)) % MOD) % MOD
                let mut d: i64 = (i - j) % MOD
                if d < 0 {
                    d = d + MOD
                }
                den = den * d % MOD
            }
            j = j + 1
        }
        res = (res + ys[i] * num % MOD * powmod(den, MOD - 2)) % MOD
        i = i + 1
    }
    return res
}

# multiply degree-<=TMAX polynomials mod x^(TMAX+1)
function pmul(u: ptr<i64>, v: ptr<i64>, out: ptr<i64>) -> void {
    let mut i: i64 = 0
    while i <= TMAX {
        out[i] = 0
        i = i + 1
    }
    i = 0
    while i <= TMAX {
        if u[i] != 0 {
            let mut j: i64 = 0
            while i + j <= TMAX {
                out[i + j] = (out[i + j] + u[i] * v[j]) % MOD
                j = j + 1
            }
        }
        i = i + 1
    }
}

function main() -> i32 {
    let f: ptr<void> = fopen("data/p696_tables.txt", "r")
    if f == 0 {
        printf("failed to read data/p696_tables.txt\n")
        return 1
    }
    let tab: ptr<i64> = calloc(62 * NPTS, 8)
    let mut idx: i64 = 0
    let mut cur: i64 = 0
    let mut have: i64 = 0
    let mut c: i32 = fgetc(f)
    while c >= 0 {
        if c >= 48 && c <= 57 {
            cur = cur * 10 + ((c - 48) as i64)
            have = 1
        } else {
            if have == 1 {
                tab[idx] = cur
                idx = idx + 1
                cur = 0
                have = 0
            }
        }
        c = fgetc(f)
    }
    if have == 1 {
        tab[idx] = cur
        idx = idx + 1
    }
    fclose(f)

    # interpolate a_t(BIGN), b_t(BIGN)
    let A: ptr<i64> = calloc(TMAX + 1, 8)
    let B: ptr<i64> = calloc(TMAX + 1, 8)
    let mut t: i64 = 0
    while t <= TMAX {
        A[t] = lagrange(tab + t * NPTS, BIGN)
        B[t] = lagrange(tab + (31 + t) * NPTS, BIGN)
        t = t + 1
    }

    # res = A(x)^(SUITS-1) mod x^31, then * B(x); answer = SUITS * res[TMAX]
    let res: ptr<i64> = calloc(TMAX + 1, 8)
    let base: ptr<i64> = calloc(TMAX + 1, 8)
    let tmp: ptr<i64> = calloc(TMAX + 1, 8)
    res[0] = 1
    let mut i: i64 = 0
    while i <= TMAX {
        base[i] = A[i]
        i = i + 1
    }
    let mut e: i64 = SUITS - 1
    while e > 0 {
        if (e & 1) == 1 {
            pmul(res, base, tmp)
            i = 0
            while i <= TMAX {
                res[i] = tmp[i]
                i = i + 1
            }
        }
        e = e >> 1
        if e > 0 {
            pmul(base, base, tmp)
            i = 0
            while i <= TMAX {
                base[i] = tmp[i]
                i = i + 1
            }
        }
    }
    pmul(res, B, tmp)
    let ans: i64 = SUITS % MOD * tmp[TMAX] % MOD
    printf("%lld\n", ans)

    free(tab)
    free(A)
    free(B)
    free(res)
    free(base)
    free(tmp)
    return 0
}

Generated C

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

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

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

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

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

#include <math.h>

void* _ui_state = NULL;

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

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

int64_t powmod_i64_i64(int64_t base, int64_t exp);
int64_t lagrange_ptr_i64_i64(int64_t* ys, int64_t X);
void pmul_ptr_i64_ptr_i64_ptr_i64(int64_t* u, int64_t* v, int64_t* out);
int32_t main(void);

static const int64_t MOD = 1000000007;
static const int64_t NPTS = 44;
static const int64_t TMAX = 30;
static const int64_t BIGN = 100000000;
static const int64_t SUITS = 100000000;






int64_t powmod_i64_i64(int64_t base, int64_t exp) {
    int64_t result = 1;
    int64_t b = FLOW_CHECKED_MOD((base), (MOD));
    int64_t e = exp;
    while (e > 0) {
        if ((e & 1) == 1) {
            result = FLOW_CHECKED_MOD(((result * b)), (MOD));
        }
        b = FLOW_CHECKED_MOD(((b * b)), (MOD));
        e = FLOW_CHECKED_SHR((e), (1));
    }
    return result;
}

int64_t lagrange_ptr_i64_i64(int64_t* ys, int64_t X) {
    int64_t res = 0;
    int64_t i = 0;
    while (i < NPTS) {
        int64_t num = 1;
        int64_t den = 1;
        int64_t j = 0;
        while (j < NPTS) {
            if (j != i) {
                num = FLOW_CHECKED_MOD(((num * FLOW_CHECKED_MOD(((X - (401 + j))), (MOD)))), (MOD));
                int64_t d = FLOW_CHECKED_MOD(((i - j)), (MOD));
                if (d < 0) {
                    d = (d + MOD);
                }
                den = FLOW_CHECKED_MOD(((den * d)), (MOD));
            }
            j = (j + 1);
        }
        res = FLOW_CHECKED_MOD(((res + (FLOW_CHECKED_MOD(((ys[i] * num)), (MOD)) * powmod_i64_i64(den, (MOD - 2))))), (MOD));
        i = (i + 1);
    }
    return res;
}

void pmul_ptr_i64_ptr_i64_ptr_i64(int64_t* u, int64_t* v, int64_t* out) {
    int64_t i = 0;
    while (i <= TMAX) {
        out[i] = 0;
        i = (i + 1);
    }
    i = 0;
    while (i <= TMAX) {
        if (u[i] != 0) {
            int64_t j = 0;
            while ((i + j) <= TMAX) {
                out[(i + j)] = FLOW_CHECKED_MOD(((out[(i + j)] + (u[i] * v[j]))), (MOD));
                j = (j + 1);
            }
        }
        i = (i + 1);
    }
}

int32_t main(void) {
    void* f = (void*)(fopen("data/p696_tables.txt", "r"));
    if (f == 0) {
        printf("failed to read data/p696_tables.txt\n");
        return 1;
    }
    int64_t* tab = (int64_t*)(calloc((62 * NPTS), 8));
    int64_t idx = 0;
    int64_t cur = 0;
    int64_t have = 0;
    int32_t c = fgetc(f);
    while (c >= 0) {
        if ((c >= 48 && c <= 57)) {
            cur = ((cur * 10) + ((int64_t)((c - 48))));
            have = 1;
        } else {
            if (have == 1) {
                tab[idx] = cur;
                idx = (idx + 1);
                cur = 0;
                have = 0;
            }
        }
        c = fgetc(f);
    }
    if (have == 1) {
        tab[idx] = cur;
        idx = (idx + 1);
    }
    fclose(f);
    int64_t* A = (int64_t*)(calloc((TMAX + 1), 8));
    int64_t* B = (int64_t*)(calloc((TMAX + 1), 8));
    int64_t t = 0;
    while (t <= TMAX) {
        A[t] = lagrange_ptr_i64_i64((tab + (t * NPTS)), BIGN);
        B[t] = lagrange_ptr_i64_i64((tab + ((31 + t) * NPTS)), BIGN);
        t = (t + 1);
    }
    int64_t* res = (int64_t*)(calloc((TMAX + 1), 8));
    int64_t* base = (int64_t*)(calloc((TMAX + 1), 8));
    int64_t* tmp = (int64_t*)(calloc((TMAX + 1), 8));
    res[0] = 1;
    int64_t i = 0;
    while (i <= TMAX) {
        base[i] = A[i];
        i = (i + 1);
    }
    int64_t e = (SUITS - 1);
    while (e > 0) {
        if ((e & 1) == 1) {
            pmul_ptr_i64_ptr_i64_ptr_i64(res, base, tmp);
            i = 0;
            while (i <= TMAX) {
                res[i] = tmp[i];
                i = (i + 1);
            }
        }
        e = FLOW_CHECKED_SHR((e), (1));
        if (e > 0) {
            pmul_ptr_i64_ptr_i64_ptr_i64(base, base, tmp);
            i = 0;
            while (i <= TMAX) {
                base[i] = tmp[i];
                i = (i + 1);
            }
        }
    }
    pmul_ptr_i64_ptr_i64_ptr_i64(res, B, tmp);
    int64_t ans = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD((SUITS), (MOD)) * tmp[TMAX])), (MOD));
    printf("%lld\n", ans);
    free(tab);
    free(A);
    free(B);
    free(res);
    free(base);
    free(tmp);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("data/p696_tables.txt\00") {addr_space = 0 : i32} : !llvm.array<21 x i8>
  llvm.mlir.global internal constant @str_1("r\00") {addr_space = 0 : i32} : !llvm.array<2 x i8>
  llvm.mlir.global internal constant @str_2("failed to read data/p696_tables.txt\n\00") {addr_space = 0 : i32} : !llvm.array<37 x i8>
  llvm.mlir.global internal constant @str_3("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
  func.func private @fopen(!llvm.ptr, !llvm.ptr) -> !llvm.ptr
  func.func private @fgetc(!llvm.ptr) -> i32
  func.func private @fclose(!llvm.ptr) -> i32
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  // Constant: MOD
  llvm.mlir.global internal constant @MOD(1000000007 : i64) : i64
  // Constant: NPTS
  llvm.mlir.global internal constant @NPTS(44 : i64) : i64
  // Constant: TMAX
  llvm.mlir.global internal constant @TMAX(30 : i64) : i64
  // Constant: BIGN
  llvm.mlir.global internal constant @BIGN(100000000 : i64) : i64
  // Constant: SUITS
  llvm.mlir.global internal constant @SUITS(100000000 : i64) : i64
  func.func @powmod(%arg0: i64, %arg1: i64) -> i64 {
    %0 = arith.constant 1 : i32
    %1 = arith.extsi %0 : i32 to i64
    %2 = llvm.mlir.constant(1 : i64) : i64
    %3 = llvm.alloca %2 x i64 : (i64) -> !llvm.ptr
    llvm.store %1, %3 : i64, !llvm.ptr
    %4 = llvm.mlir.addressof @MOD : !llvm.ptr
    %5 = llvm.load %4 : !llvm.ptr -> i64
    %6 = arith.remsi %arg0, %5 : i64
    %7 = llvm.mlir.constant(1 : i64) : i64
    %8 = llvm.alloca %7 x i64 : (i64) -> !llvm.ptr
    llvm.store %6, %8 : i64, !llvm.ptr
    %9 = llvm.mlir.constant(1 : i64) : i64
    %10 = llvm.alloca %9 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %10 : i64, !llvm.ptr
    cf.br ^bb0
    ^bb0:
    %11 = llvm.load %10 : !llvm.ptr -> i64
    %12 = arith.constant 0 : i32
    %14 = arith.extsi %12 : i32 to i64
    %13 = arith.cmpi sgt, %11, %14 : i64
    cf.cond_br %13, ^bb1, ^bb2
    ^bb1:
      %15 = llvm.load %10 : !llvm.ptr -> i64
      %16 = arith.constant 1 : i32
      %18 = arith.extsi %16 : i32 to i64
      %17 = arith.andi %15, %18 : i64
      %19 = arith.constant 1 : i32
      %21 = arith.extsi %19 : i32 to i64
      %20 = arith.cmpi eq, %17, %21 : i64
      cf.cond_br %20, ^bb3, ^bb4
      ^bb3:
        %22 = llvm.load %3 : !llvm.ptr -> i64
        %23 = llvm.load %8 : !llvm.ptr -> i64
        %24 = arith.muli %22, %23 : i64
        %25 = llvm.mlir.addressof @MOD : !llvm.ptr
        %26 = llvm.load %25 : !llvm.ptr -> i64
        %27 = arith.remsi %24, %26 : i64
        llvm.store %27, %3 : i64, !llvm.ptr
        cf.br ^bb5
      ^bb4:
        cf.br ^bb5
      ^bb5:
      %28 = llvm.load %8 : !llvm.ptr -> i64
      %29 = llvm.load %8 : !llvm.ptr -> i64
      %30 = arith.muli %28, %29 : i64
      %31 = llvm.mlir.addressof @MOD : !llvm.ptr
      %32 = llvm.load %31 : !llvm.ptr -> i64
      %33 = arith.remsi %30, %32 : i64
      llvm.store %33, %8 : i64, !llvm.ptr
      %34 = llvm.load %10 : !llvm.ptr -> i64
      %35 = arith.constant 1 : i32
      %37 = arith.extsi %35 : i32 to i64
      %36 = arith.shrsi %34, %37 : i64
      llvm.store %36, %10 : i64, !llvm.ptr
      cf.br ^bb0
    ^bb2:
    %38 = llvm.load %3 : !llvm.ptr -> i64
    func.return %38 : i64
  }
  func.func @lagrange(%arg0: !llvm.ptr, %arg1: i64) -> i64 {
    %39 = arith.constant 0 : i32
    %40 = arith.extsi %39 : i32 to i64
    %41 = llvm.mlir.constant(1 : i64) : i64
    %42 = llvm.alloca %41 x i64 : (i64) -> !llvm.ptr
    llvm.store %40, %42 : i64, !llvm.ptr
    %43 = arith.constant 0 : i32
    %44 = arith.extsi %43 : i32 to i64
    %45 = llvm.mlir.constant(1 : i64) : i64
    %46 = llvm.alloca %45 x i64 : (i64) -> !llvm.ptr
    llvm.store %44, %46 : i64, !llvm.ptr
    cf.br ^bb6
    ^bb6:
    %47 = llvm.load %46 : !llvm.ptr -> i64
    %48 = llvm.mlir.addressof @NPTS : !llvm.ptr
    %49 = llvm.load %48 : !llvm.ptr -> i64
    %50 = arith.cmpi slt, %47, %49 : i64
    cf.cond_br %50, ^bb7, ^bb8
    ^bb7:
      %51 = arith.constant 1 : i32
      %52 = arith.extsi %51 : i32 to i64
      %53 = llvm.mlir.constant(1 : i64) : i64
      %54 = llvm.alloca %53 x i64 : (i64) -> !llvm.ptr
      llvm.store %52, %54 : i64, !llvm.ptr
      %55 = arith.constant 1 : i32
      %56 = arith.extsi %55 : i32 to i64
      %57 = llvm.mlir.constant(1 : i64) : i64
      %58 = llvm.alloca %57 x i64 : (i64) -> !llvm.ptr
      llvm.store %56, %58 : i64, !llvm.ptr
      %59 = arith.constant 0 : i32
      %60 = arith.extsi %59 : i32 to i64
      %61 = llvm.mlir.constant(1 : i64) : i64
      %62 = llvm.alloca %61 x i64 : (i64) -> !llvm.ptr
      llvm.store %60, %62 : i64, !llvm.ptr
      cf.br ^bb9
      ^bb9:
      %63 = llvm.load %62 : !llvm.ptr -> i64
      %64 = llvm.mlir.addressof @NPTS : !llvm.ptr
      %65 = llvm.load %64 : !llvm.ptr -> i64
      %66 = arith.cmpi slt, %63, %65 : i64
      cf.cond_br %66, ^bb10, ^bb11
      ^bb10:
        %67 = llvm.load %62 : !llvm.ptr -> i64
        %68 = llvm.load %46 : !llvm.ptr -> i64
        %69 = arith.cmpi ne, %67, %68 : i64
        cf.cond_br %69, ^bb12, ^bb13
        ^bb12:
          %70 = llvm.load %54 : !llvm.ptr -> i64
          %71 = arith.constant 401 : i32
          %72 = llvm.load %62 : !llvm.ptr -> i64
          %74 = arith.extsi %71 : i32 to i64
          %73 = arith.addi %74, %72 : i64
          %75 = arith.subi %arg1, %73 : i64
          %76 = llvm.mlir.addressof @MOD : !llvm.ptr
          %77 = llvm.load %76 : !llvm.ptr -> i64
          %78 = arith.remsi %75, %77 : i64
          %79 = arith.muli %70, %78 : i64
          %80 = llvm.mlir.addressof @MOD : !llvm.ptr
          %81 = llvm.load %80 : !llvm.ptr -> i64
          %82 = arith.remsi %79, %81 : i64
          llvm.store %82, %54 : i64, !llvm.ptr
          %83 = llvm.load %46 : !llvm.ptr -> i64
          %84 = llvm.load %62 : !llvm.ptr -> i64
          %85 = arith.subi %83, %84 : i64
          %86 = llvm.mlir.addressof @MOD : !llvm.ptr
          %87 = llvm.load %86 : !llvm.ptr -> i64
          %88 = arith.remsi %85, %87 : i64
          %89 = llvm.mlir.constant(1 : i64) : i64
          %90 = llvm.alloca %89 x i64 : (i64) -> !llvm.ptr
          llvm.store %88, %90 : i64, !llvm.ptr
          %91 = llvm.load %90 : !llvm.ptr -> i64
          %92 = arith.constant 0 : i32
          %94 = arith.extsi %92 : i32 to i64
          %93 = arith.cmpi slt, %91, %94 : i64
          cf.cond_br %93, ^bb15, ^bb16
          ^bb15:
            %95 = llvm.load %90 : !llvm.ptr -> i64
            %96 = llvm.mlir.addressof @MOD : !llvm.ptr
            %97 = llvm.load %96 : !llvm.ptr -> i64
            %98 = arith.addi %95, %97 : i64
            llvm.store %98, %90 : i64, !llvm.ptr
            cf.br ^bb17
          ^bb16:
            cf.br ^bb17
          ^bb17:
          %99 = llvm.load %58 : !llvm.ptr -> i64
          %100 = llvm.load %90 : !llvm.ptr -> i64
          %101 = arith.muli %99, %100 : i64
          %102 = llvm.mlir.addressof @MOD : !llvm.ptr
          %103 = llvm.load %102 : !llvm.ptr -> i64
          %104 = arith.remsi %101, %103 : i64
          llvm.store %104, %58 : i64, !llvm.ptr
          cf.br ^bb14
        ^bb13:
          cf.br ^bb14
        ^bb14:
        %105 = llvm.load %62 : !llvm.ptr -> i64
        %106 = arith.constant 1 : i32
        %108 = arith.extsi %106 : i32 to i64
        %107 = arith.addi %105, %108 : i64
        llvm.store %107, %62 : i64, !llvm.ptr
        cf.br ^bb9
      ^bb11:
      %109 = llvm.load %42 : !llvm.ptr -> i64
      %111 = llvm.load %46 : !llvm.ptr -> i64
      %112 = llvm.getelementptr %arg0[%111] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %110 = llvm.load %112 : !llvm.ptr -> i64
      %113 = llvm.load %54 : !llvm.ptr -> i64
      %114 = arith.muli %110, %113 : i64
      %115 = llvm.mlir.addressof @MOD : !llvm.ptr
      %116 = llvm.load %115 : !llvm.ptr -> i64
      %117 = arith.remsi %114, %116 : i64
      %119 = llvm.load %58 : !llvm.ptr -> i64
      %120 = llvm.mlir.addressof @MOD : !llvm.ptr
      %121 = llvm.load %120 : !llvm.ptr -> i64
      %122 = arith.constant 2 : i32
      %124 = arith.extsi %122 : i32 to i64
      %123 = arith.subi %121, %124 : i64
      %118 = func.call @powmod(%119, %123) : (i64, i64) -> i64
      %125 = arith.muli %117, %118 : i64
      %126 = arith.addi %109, %125 : i64
      %127 = llvm.mlir.addressof @MOD : !llvm.ptr
      %128 = llvm.load %127 : !llvm.ptr -> i64
      %129 = arith.remsi %126, %128 : i64
      llvm.store %129, %42 : i64, !llvm.ptr
      %130 = llvm.load %46 : !llvm.ptr -> i64
      %131 = arith.constant 1 : i32
      %133 = arith.extsi %131 : i32 to i64
      %132 = arith.addi %130, %133 : i64
      llvm.store %132, %46 : i64, !llvm.ptr
      cf.br ^bb6
    ^bb8:
    %134 = llvm.load %42 : !llvm.ptr -> i64
    func.return %134 : i64
  }
  func.func @pmul(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> () {
    %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 ^bb18
    ^bb18:
    %139 = llvm.load %138 : !llvm.ptr -> i64
    %140 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %141 = llvm.load %140 : !llvm.ptr -> i64
    %142 = arith.cmpi sle, %139, %141 : i64
    cf.cond_br %142, ^bb19, ^bb20
    ^bb19:
      %143 = arith.constant 0 : i32
      %144 = llvm.load %138 : !llvm.ptr -> i64
      %145 = arith.extsi %143 : i32 to i64
      %146 = llvm.getelementptr %arg2[%144] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %145, %146 : i64, !llvm.ptr
      %147 = llvm.load %138 : !llvm.ptr -> i64
      %148 = arith.constant 1 : i32
      %150 = arith.extsi %148 : i32 to i64
      %149 = arith.addi %147, %150 : i64
      llvm.store %149, %138 : i64, !llvm.ptr
      cf.br ^bb18
    ^bb20:
    %151 = arith.constant 0 : i32
    %152 = arith.extsi %151 : i32 to i64
    llvm.store %152, %138 : i64, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %153 = llvm.load %138 : !llvm.ptr -> i64
    %154 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %155 = llvm.load %154 : !llvm.ptr -> i64
    %156 = arith.cmpi sle, %153, %155 : i64
    cf.cond_br %156, ^bb22, ^bb23
    ^bb22:
      %158 = llvm.load %138 : !llvm.ptr -> i64
      %159 = llvm.getelementptr %arg0[%158] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %157 = llvm.load %159 : !llvm.ptr -> i64
      %160 = arith.constant 0 : i32
      %162 = arith.extsi %160 : i32 to i64
      %161 = arith.cmpi ne, %157, %162 : i64
      cf.cond_br %161, ^bb24, ^bb25
      ^bb24:
        %163 = arith.constant 0 : i32
        %164 = arith.extsi %163 : i32 to i64
        %165 = llvm.mlir.constant(1 : i64) : i64
        %166 = llvm.alloca %165 x i64 : (i64) -> !llvm.ptr
        llvm.store %164, %166 : i64, !llvm.ptr
        cf.br ^bb27
        ^bb27:
        %167 = llvm.load %138 : !llvm.ptr -> i64
        %168 = llvm.load %166 : !llvm.ptr -> i64
        %169 = arith.addi %167, %168 : i64
        %170 = llvm.mlir.addressof @TMAX : !llvm.ptr
        %171 = llvm.load %170 : !llvm.ptr -> i64
        %172 = arith.cmpi sle, %169, %171 : i64
        cf.cond_br %172, ^bb28, ^bb29
        ^bb28:
          %174 = llvm.load %138 : !llvm.ptr -> i64
          %175 = llvm.load %166 : !llvm.ptr -> i64
          %176 = arith.addi %174, %175 : i64
          %177 = llvm.getelementptr %arg2[%176] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %173 = llvm.load %177 : !llvm.ptr -> i64
          %179 = llvm.load %138 : !llvm.ptr -> i64
          %180 = llvm.getelementptr %arg0[%179] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %178 = llvm.load %180 : !llvm.ptr -> i64
          %182 = llvm.load %166 : !llvm.ptr -> i64
          %183 = llvm.getelementptr %arg1[%182] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %181 = llvm.load %183 : !llvm.ptr -> i64
          %184 = arith.muli %178, %181 : i64
          %185 = arith.addi %173, %184 : i64
          %186 = llvm.mlir.addressof @MOD : !llvm.ptr
          %187 = llvm.load %186 : !llvm.ptr -> i64
          %188 = arith.remsi %185, %187 : i64
          %189 = llvm.load %138 : !llvm.ptr -> i64
          %190 = llvm.load %166 : !llvm.ptr -> i64
          %191 = arith.addi %189, %190 : i64
          %192 = llvm.getelementptr %arg2[%191] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %188, %192 : i64, !llvm.ptr
          %193 = llvm.load %166 : !llvm.ptr -> i64
          %194 = arith.constant 1 : i32
          %196 = arith.extsi %194 : i32 to i64
          %195 = arith.addi %193, %196 : i64
          llvm.store %195, %166 : i64, !llvm.ptr
          cf.br ^bb27
        ^bb29:
        cf.br ^bb26
      ^bb25:
        cf.br ^bb26
      ^bb26:
      %197 = llvm.load %138 : !llvm.ptr -> i64
      %198 = arith.constant 1 : i32
      %200 = arith.extsi %198 : i32 to i64
      %199 = arith.addi %197, %200 : i64
      llvm.store %199, %138 : i64, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    func.return
  }
  func.func @main() -> i32 {
    %202 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %203 = llvm.mlir.addressof @str_1 : !llvm.ptr
    %201 = func.call @fopen(%202, %203) : (!llvm.ptr, !llvm.ptr) -> !llvm.ptr
    %204 = arith.constant 0 : i32
    %206 = llvm.inttoptr %204 : i32 to !llvm.ptr
    %205 = llvm.icmp "eq" %201, %206 : !llvm.ptr
    cf.cond_br %205, ^bb30, ^bb31
    ^bb30:
      %207 = llvm.mlir.addressof @str_2 : !llvm.ptr
      %208 = llvm.call @printf(%207) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr) -> i32
      %209 = arith.constant 1 : i32
      func.return %209 : i32
    ^bb31:
      cf.br ^bb32
    ^bb32:
    %211 = arith.constant 62 : i32
    %212 = llvm.mlir.addressof @NPTS : !llvm.ptr
    %213 = llvm.load %212 : !llvm.ptr -> i64
    %215 = arith.extsi %211 : i32 to i64
    %214 = arith.muli %215, %213 : i64
    %216 = arith.constant 8 : i32
    %217 = arith.extsi %216 : i32 to i64
    %210 = func.call @calloc(%214, %217) : (i64, i64) -> !llvm.ptr
    %218 = arith.constant 0 : i32
    %219 = arith.extsi %218 : i32 to i64
    %220 = llvm.mlir.constant(1 : i64) : i64
    %221 = llvm.alloca %220 x i64 : (i64) -> !llvm.ptr
    llvm.store %219, %221 : i64, !llvm.ptr
    %222 = arith.constant 0 : i32
    %223 = arith.extsi %222 : i32 to i64
    %224 = llvm.mlir.constant(1 : i64) : i64
    %225 = llvm.alloca %224 x i64 : (i64) -> !llvm.ptr
    llvm.store %223, %225 : i64, !llvm.ptr
    %226 = arith.constant 0 : i32
    %227 = arith.extsi %226 : i32 to i64
    %228 = llvm.mlir.constant(1 : i64) : i64
    %229 = llvm.alloca %228 x i64 : (i64) -> !llvm.ptr
    llvm.store %227, %229 : i64, !llvm.ptr
    %230 = func.call @fgetc(%201) : (!llvm.ptr) -> i32
    %231 = llvm.mlir.constant(1 : i64) : i64
    %232 = llvm.alloca %231 x i32 : (i64) -> !llvm.ptr
    llvm.store %230, %232 : i32, !llvm.ptr
    cf.br ^bb33
    ^bb33:
    %233 = llvm.load %232 : !llvm.ptr -> i32
    %234 = arith.constant 0 : i32
    %235 = arith.cmpi sge, %233, %234 : i32
    cf.cond_br %235, ^bb34, ^bb35
    ^bb34:
      %236 = llvm.load %232 : !llvm.ptr -> i32
      %237 = arith.constant 48 : i32
      %238 = arith.cmpi sge, %236, %237 : i32
      %239 = scf.if %238 -> (i1) {
        %240 = llvm.load %232 : !llvm.ptr -> i32
        %241 = arith.constant 57 : i32
        %242 = arith.cmpi sle, %240, %241 : i32
        scf.yield %242 : i1
      } else {
        %243 = arith.constant false
        scf.yield %243 : i1
      }
      cf.cond_br %239, ^bb36, ^bb37
      ^bb36:
        %244 = llvm.load %225 : !llvm.ptr -> i64
        %245 = arith.constant 10 : i32
        %247 = arith.extsi %245 : i32 to i64
        %246 = arith.muli %244, %247 : i64
        %248 = llvm.load %232 : !llvm.ptr -> i32
        %249 = arith.constant 48 : i32
        %250 = arith.subi %248, %249 : i32
        %251 = arith.extsi %250 : i32 to i64
        %252 = arith.addi %246, %251 : i64
        llvm.store %252, %225 : i64, !llvm.ptr
        %253 = arith.constant 1 : i32
        %254 = arith.extsi %253 : i32 to i64
        llvm.store %254, %229 : i64, !llvm.ptr
        cf.br ^bb38
      ^bb37:
        %255 = llvm.load %229 : !llvm.ptr -> i64
        %256 = arith.constant 1 : i32
        %258 = arith.extsi %256 : i32 to i64
        %257 = arith.cmpi eq, %255, %258 : i64
        cf.cond_br %257, ^bb39, ^bb40
        ^bb39:
          %259 = llvm.load %225 : !llvm.ptr -> i64
          %260 = llvm.load %221 : !llvm.ptr -> i64
          %261 = llvm.getelementptr %210[%260] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %259, %261 : i64, !llvm.ptr
          %262 = llvm.load %221 : !llvm.ptr -> i64
          %263 = arith.constant 1 : i32
          %265 = arith.extsi %263 : i32 to i64
          %264 = arith.addi %262, %265 : i64
          llvm.store %264, %221 : i64, !llvm.ptr
          %266 = arith.constant 0 : i32
          %267 = arith.extsi %266 : i32 to i64
          llvm.store %267, %225 : i64, !llvm.ptr
          %268 = arith.constant 0 : i32
          %269 = arith.extsi %268 : i32 to i64
          llvm.store %269, %229 : i64, !llvm.ptr
          cf.br ^bb41
        ^bb40:
          cf.br ^bb41
        ^bb41:
        cf.br ^bb38
      ^bb38:
      %270 = func.call @fgetc(%201) : (!llvm.ptr) -> i32
      llvm.store %270, %232 : i32, !llvm.ptr
      cf.br ^bb33
    ^bb35:
    %271 = llvm.load %229 : !llvm.ptr -> i64
    %272 = arith.constant 1 : i32
    %274 = arith.extsi %272 : i32 to i64
    %273 = arith.cmpi eq, %271, %274 : i64
    cf.cond_br %273, ^bb42, ^bb43
    ^bb42:
      %275 = llvm.load %225 : !llvm.ptr -> i64
      %276 = llvm.load %221 : !llvm.ptr -> i64
      %277 = llvm.getelementptr %210[%276] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %275, %277 : i64, !llvm.ptr
      %278 = llvm.load %221 : !llvm.ptr -> i64
      %279 = arith.constant 1 : i32
      %281 = arith.extsi %279 : i32 to i64
      %280 = arith.addi %278, %281 : i64
      llvm.store %280, %221 : i64, !llvm.ptr
      cf.br ^bb44
    ^bb43:
      cf.br ^bb44
    ^bb44:
    %282 = func.call @fclose(%201) : (!llvm.ptr) -> i32
    %284 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %285 = llvm.load %284 : !llvm.ptr -> i64
    %286 = arith.constant 1 : i32
    %288 = arith.extsi %286 : i32 to i64
    %287 = arith.addi %285, %288 : i64
    %289 = arith.constant 8 : i32
    %290 = arith.extsi %289 : i32 to i64
    %283 = func.call @calloc(%287, %290) : (i64, i64) -> !llvm.ptr
    %292 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %293 = llvm.load %292 : !llvm.ptr -> i64
    %294 = arith.constant 1 : i32
    %296 = arith.extsi %294 : i32 to i64
    %295 = arith.addi %293, %296 : i64
    %297 = arith.constant 8 : i32
    %298 = arith.extsi %297 : i32 to i64
    %291 = func.call @calloc(%295, %298) : (i64, i64) -> !llvm.ptr
    %299 = arith.constant 0 : i32
    %300 = arith.extsi %299 : i32 to i64
    %301 = llvm.mlir.constant(1 : i64) : i64
    %302 = llvm.alloca %301 x i64 : (i64) -> !llvm.ptr
    llvm.store %300, %302 : i64, !llvm.ptr
    cf.br ^bb45
    ^bb45:
    %303 = llvm.load %302 : !llvm.ptr -> i64
    %304 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %305 = llvm.load %304 : !llvm.ptr -> i64
    %306 = arith.cmpi sle, %303, %305 : i64
    cf.cond_br %306, ^bb46, ^bb47
    ^bb46:
      # String concatenation: !llvm.ptr + i64
      %309 = llvm.mlir.addressof @BIGN : !llvm.ptr
      %310 = llvm.load %309 : !llvm.ptr -> i64
      %307 = func.call @lagrange(%308, %310) : (!llvm.ptr, i64) -> i64
      %311 = llvm.load %302 : !llvm.ptr -> i64
      %312 = llvm.getelementptr %283[%311] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %307, %312 : i64, !llvm.ptr
      # String concatenation: !llvm.ptr + i64
      %315 = llvm.mlir.addressof @BIGN : !llvm.ptr
      %316 = llvm.load %315 : !llvm.ptr -> i64
      %313 = func.call @lagrange(%314, %316) : (!llvm.ptr, i64) -> i64
      %317 = llvm.load %302 : !llvm.ptr -> i64
      %318 = llvm.getelementptr %291[%317] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %313, %318 : i64, !llvm.ptr
      %319 = llvm.load %302 : !llvm.ptr -> i64
      %320 = arith.constant 1 : i32
      %322 = arith.extsi %320 : i32 to i64
      %321 = arith.addi %319, %322 : i64
      llvm.store %321, %302 : i64, !llvm.ptr
      cf.br ^bb45
    ^bb47:
    %324 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %325 = llvm.load %324 : !llvm.ptr -> i64
    %326 = arith.constant 1 : i32
    %328 = arith.extsi %326 : i32 to i64
    %327 = arith.addi %325, %328 : i64
    %329 = arith.constant 8 : i32
    %330 = arith.extsi %329 : i32 to i64
    %323 = func.call @calloc(%327, %330) : (i64, i64) -> !llvm.ptr
    %332 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %333 = llvm.load %332 : !llvm.ptr -> i64
    %334 = arith.constant 1 : i32
    %336 = arith.extsi %334 : i32 to i64
    %335 = arith.addi %333, %336 : i64
    %337 = arith.constant 8 : i32
    %338 = arith.extsi %337 : i32 to i64
    %331 = func.call @calloc(%335, %338) : (i64, i64) -> !llvm.ptr
    %340 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %341 = llvm.load %340 : !llvm.ptr -> i64
    %342 = arith.constant 1 : i32
    %344 = arith.extsi %342 : i32 to i64
    %343 = arith.addi %341, %344 : i64
    %345 = arith.constant 8 : i32
    %346 = arith.extsi %345 : i32 to i64
    %339 = func.call @calloc(%343, %346) : (i64, i64) -> !llvm.ptr
    %347 = arith.constant 1 : i32
    %348 = arith.constant 0 : i32
    %349 = arith.extsi %347 : i32 to i64
    %350 = arith.extsi %348 : i32 to i64
    %351 = llvm.getelementptr %323[%350] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %349, %351 : i64, !llvm.ptr
    %352 = arith.constant 0 : i32
    %353 = arith.extsi %352 : i32 to i64
    %354 = llvm.mlir.constant(1 : i64) : i64
    %355 = llvm.alloca %354 x i64 : (i64) -> !llvm.ptr
    llvm.store %353, %355 : i64, !llvm.ptr
    cf.br ^bb48
    ^bb48:
    %356 = llvm.load %355 : !llvm.ptr -> i64
    %357 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %358 = llvm.load %357 : !llvm.ptr -> i64
    %359 = arith.cmpi sle, %356, %358 : i64
    cf.cond_br %359, ^bb49, ^bb50
    ^bb49:
      %361 = llvm.load %355 : !llvm.ptr -> i64
      %362 = llvm.getelementptr %283[%361] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %360 = llvm.load %362 : !llvm.ptr -> i64
      %363 = llvm.load %355 : !llvm.ptr -> i64
      %364 = llvm.getelementptr %331[%363] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %360, %364 : i64, !llvm.ptr
      %365 = llvm.load %355 : !llvm.ptr -> i64
      %366 = arith.constant 1 : i32
      %368 = arith.extsi %366 : i32 to i64
      %367 = arith.addi %365, %368 : i64
      llvm.store %367, %355 : i64, !llvm.ptr
      cf.br ^bb48
    ^bb50:
    %369 = llvm.mlir.addressof @SUITS : !llvm.ptr
    %370 = llvm.load %369 : !llvm.ptr -> i64
    %371 = arith.constant 1 : i32
    %373 = arith.extsi %371 : i32 to i64
    %372 = arith.subi %370, %373 : i64
    %374 = llvm.mlir.constant(1 : i64) : i64
    %375 = llvm.alloca %374 x i64 : (i64) -> !llvm.ptr
    llvm.store %372, %375 : i64, !llvm.ptr
    cf.br ^bb51
    ^bb51:
    %376 = llvm.load %375 : !llvm.ptr -> i64
    %377 = arith.constant 0 : i32
    %379 = arith.extsi %377 : i32 to i64
    %378 = arith.cmpi sgt, %376, %379 : i64
    cf.cond_br %378, ^bb52, ^bb53
    ^bb52:
      %380 = llvm.load %375 : !llvm.ptr -> i64
      %381 = arith.constant 1 : i32
      %383 = arith.extsi %381 : i32 to i64
      %382 = arith.andi %380, %383 : i64
      %384 = arith.constant 1 : i32
      %386 = arith.extsi %384 : i32 to i64
      %385 = arith.cmpi eq, %382, %386 : i64
      cf.cond_br %385, ^bb54, ^bb55
      ^bb54:
        func.call @pmul(%323, %331, %339) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
        %388 = arith.constant 0 : i32
        %389 = arith.extsi %388 : i32 to i64
        llvm.store %389, %355 : i64, !llvm.ptr
        cf.br ^bb57
        ^bb57:
        %390 = llvm.load %355 : !llvm.ptr -> i64
        %391 = llvm.mlir.addressof @TMAX : !llvm.ptr
        %392 = llvm.load %391 : !llvm.ptr -> i64
        %393 = arith.cmpi sle, %390, %392 : i64
        cf.cond_br %393, ^bb58, ^bb59
        ^bb58:
          %395 = llvm.load %355 : !llvm.ptr -> i64
          %396 = llvm.getelementptr %339[%395] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %394 = llvm.load %396 : !llvm.ptr -> i64
          %397 = llvm.load %355 : !llvm.ptr -> i64
          %398 = llvm.getelementptr %323[%397] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %394, %398 : i64, !llvm.ptr
          %399 = llvm.load %355 : !llvm.ptr -> i64
          %400 = arith.constant 1 : i32
          %402 = arith.extsi %400 : i32 to i64
          %401 = arith.addi %399, %402 : i64
          llvm.store %401, %355 : i64, !llvm.ptr
          cf.br ^bb57
        ^bb59:
        cf.br ^bb56
      ^bb55:
        cf.br ^bb56
      ^bb56:
      %403 = llvm.load %375 : !llvm.ptr -> i64
      %404 = arith.constant 1 : i32
      %406 = arith.extsi %404 : i32 to i64
      %405 = arith.shrsi %403, %406 : i64
      llvm.store %405, %375 : i64, !llvm.ptr
      %407 = llvm.load %375 : !llvm.ptr -> i64
      %408 = arith.constant 0 : i32
      %410 = arith.extsi %408 : i32 to i64
      %409 = arith.cmpi sgt, %407, %410 : i64
      cf.cond_br %409, ^bb60, ^bb61
      ^bb60:
        func.call @pmul(%331, %331, %339) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
        %412 = arith.constant 0 : i32
        %413 = arith.extsi %412 : i32 to i64
        llvm.store %413, %355 : i64, !llvm.ptr
        cf.br ^bb63
        ^bb63:
        %414 = llvm.load %355 : !llvm.ptr -> i64
        %415 = llvm.mlir.addressof @TMAX : !llvm.ptr
        %416 = llvm.load %415 : !llvm.ptr -> i64
        %417 = arith.cmpi sle, %414, %416 : i64
        cf.cond_br %417, ^bb64, ^bb65
        ^bb64:
          %419 = llvm.load %355 : !llvm.ptr -> i64
          %420 = llvm.getelementptr %339[%419] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %418 = llvm.load %420 : !llvm.ptr -> i64
          %421 = llvm.load %355 : !llvm.ptr -> i64
          %422 = llvm.getelementptr %331[%421] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %418, %422 : i64, !llvm.ptr
          %423 = llvm.load %355 : !llvm.ptr -> i64
          %424 = arith.constant 1 : i32
          %426 = arith.extsi %424 : i32 to i64
          %425 = arith.addi %423, %426 : i64
          llvm.store %425, %355 : i64, !llvm.ptr
          cf.br ^bb63
        ^bb65:
        cf.br ^bb62
      ^bb61:
        cf.br ^bb62
      ^bb62:
      cf.br ^bb51
    ^bb53:
    func.call @pmul(%323, %291, %339) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
    %428 = llvm.mlir.addressof @SUITS : !llvm.ptr
    %429 = llvm.load %428 : !llvm.ptr -> i64
    %430 = llvm.mlir.addressof @MOD : !llvm.ptr
    %431 = llvm.load %430 : !llvm.ptr -> i64
    %432 = arith.remsi %429, %431 : i64
    %434 = llvm.mlir.addressof @TMAX : !llvm.ptr
    %435 = llvm.load %434 : !llvm.ptr -> i64
    %436 = llvm.getelementptr %339[%435] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %433 = llvm.load %436 : !llvm.ptr -> i64
    %437 = arith.muli %432, %433 : i64
    %438 = llvm.mlir.addressof @MOD : !llvm.ptr
    %439 = llvm.load %438 : !llvm.ptr -> i64
    %440 = arith.remsi %437, %439 : i64
    %441 = llvm.mlir.addressof @str_3 : !llvm.ptr
    %442 = llvm.call @printf(%441, %440) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    func.call @free(%210) : (!llvm.ptr) -> ()
    func.call @free(%283) : (!llvm.ptr) -> ()
    func.call @free(%291) : (!llvm.ptr) -> ()
    func.call @free(%323) : (!llvm.ptr) -> ()
    func.call @free(%331) : (!llvm.ptr) -> ()
    func.call @free(%339) : (!llvm.ptr) -> ()
    %449 = arith.constant 0 : i32
    func.return %449 : i32
  }
}