Problem 590

Sets with a Given LCM — HL(50000) mod 1e9 (CRT: 0 mod 512, value mod 5^9).

Answer834171904
Output834171904
StatusPASS
Native helperno
Runtime470 ms
Peak memory150112 KB
Time complexityO(n^2) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

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

Flow source

# Project Euler 590
# Sets with a Given LCM — HL(50000) mod 1e9 (CRT: 0 mod 512, value mod 5^9).

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

const MOD2: i64 = 512
const MOD5: i64 = 1953125
const PHI5: i64 = 1562500

function modpow(base0: i64, exp0: i64, modv: i64) -> i64 {
    let mut result: i64 = 1
    let mut base: i64 = base0 % modv
    let mut exp: i64 = exp0
    while exp > 0 {
        if (exp & 1) != 0 {
            result = ((result as i128) * (base as i128) % (modv as i128)) as i64
        }
        base = ((base as i128) * (base as i128) % (modv as i128)) as i64
        exp = exp >> 1
    }
    return result
}

function modinv_coprime(a0: i64, m: i64) -> i64 {
    let mut a: i64 = a0 % m
    if a < 0 { a = a + m }
    let mut mm: i64 = m
    let mut x0: i64 = 1
    let mut x1: i64 = 0
    while mm != 0 {
        let q: i64 = a / mm
        let na: i64 = mm
        mm = a - q * mm
        a = na
        let nx: i64 = x1
        x1 = x0 - q * x1
        x0 = nx
    }
    let mut inv: i64 = x0 % m
    if inv < 0 { inv = inv + m }
    return inv
}

function sieve(limit: i64, primes: ptr<i64>) -> i64 {
    let s: ptr<i8> = calloc(limit + 1, 1)
    let mut i: i64 = 0
    while i <= limit { s[i] = 1; i = i + 1 }
    s[0] = 0
    s[1] = 0
    i = 2
    while i * i <= limit {
        if s[i] != 0 {
            let mut j: i64 = i * i
            while j <= limit { s[j] = 0; j = j + i }
        }
        i = i + 1
    }
    let mut m: i64 = 0
    i = 2
    while i <= limit {
        if s[i] != 0 { primes[m] = i; m = m + 1 }
        i = i + 1
    }
    free(s)
    return m
}

function max_power_exp(p: i64, n: i64) -> i64 {
    let mut e: i64 = 1
    let mut pp: i64 = p
    while pp * p <= n {
        pp = pp * p
        e = e + 1
    }
    return e
}

# C(n,k) mod 5^9 via stripping factors of 5
function binom_mod5(n: i64, k: i64) -> i64 {
    if k < 0 || k > n { return 0 }
    if k == 0 || k == n { return 1 }
    if k > n - k { k = n - k }
    let mut num: i64 = 1
    let mut den: i64 = 1
    let mut val: i64 = 0
    let mut i: i64 = 1
    while i <= k {
        let mut a: i64 = n - k + i
        let mut b: i64 = i
        while a % 5 == 0 {
            a = a / 5
            val = val + 1
        }
        while b % 5 == 0 {
            b = b / 5
            val = val - 1
        }
        num = ((num as i128) * (a as i128) % (MOD5 as i128)) as i64
        den = ((den as i128) * (b as i128) % (MOD5 as i128)) as i64
        i = i + 1
    }
    if val >= 9 { return 0 }
    let inv: i64 = modinv_coprime(den, MOD5)
    let mut res: i64 = ((num as i128) * (inv as i128) % (MOD5 as i128)) as i64
    let mut p: i64 = 0
    while p < val {
        res = (res * 5) % MOD5
        p = p + 1
    }
    return res
}

function HL_50000() -> i64 {
    let N: i64 = 50000
    let primes: ptr<i64> = calloc(10000, 8)
    let np: i64 = sieve(N, primes)
    let mut r: i64 = 0
    let counts: ptr<i64> = calloc(32, 8)
    let mut i: i64 = 0
    while i < np {
        let ae: i64 = max_power_exp(primes[i], N)
        if ae == 1 {
            r = r + 1
        } else {
            counts[ae] = counts[ae] + 1
        }
        i = i + 1
    }

    let CAP: i64 = 4000003
    let mut keys: ptr<i64> = calloc(CAP, 8)
    let mut vals: ptr<i64> = calloc(CAP, 8)
    let mut used: ptr<i8> = calloc(CAP, 1)
    let mut h: i64 = 1 % CAP
    used[h] = 1
    keys[h] = 1
    vals[h] = 1

    let mut ae: i64 = 2
    while ae < 32 {
        let c: i64 = counts[ae]
        if c > 0 {
            let terms_mul: ptr<i64> = calloc(c + 1, 8)
            let terms_w: ptr<i64> = calloc(c + 1, 8)
            let mut t: i64 = 0
            while t <= c {
                let mul: i64 = (modpow(ae, t, PHI5) * modpow(ae + 1, c - t, PHI5)) % PHI5
                let mut w: i64 = binom_mod5(c, t)
                if (t & 1) != 0 {
                    w = (MOD5 - w) % MOD5
                }
                terms_mul[t] = mul
                terms_w[t] = w
                t = t + 1
            }
            let nkeys: ptr<i64> = calloc(CAP, 8)
            let nvals: ptr<i64> = calloc(CAP, 8)
            let nused: ptr<i8> = calloc(CAP, 1)
            i = 0
            while i < CAP {
                if used[i] != 0 {
                    let x_prev: i64 = keys[i]
                    let w_prev: i64 = vals[i]
                    t = 0
                    while t <= c {
                        let new_x: i64 = (x_prev * terms_mul[t]) % PHI5
                        let add: i64 = ((w_prev as i128) * (terms_w[t] as i128) % (MOD5 as i128)) as i64
                        let mut hh: i64 = new_x % CAP
                        if hh < 0 { hh = -hh }
                        while nused[hh] != 0 && nkeys[hh] != new_x {
                            hh = hh + 1
                            if hh >= CAP { hh = 0 }
                        }
                        if nused[hh] == 0 {
                            nused[hh] = 1
                            nkeys[hh] = new_x
                            nvals[hh] = add
                        } else {
                            nvals[hh] = (nvals[hh] + add) % MOD5
                        }
                        t = t + 1
                    }
                }
                i = i + 1
            }
            free(keys); free(vals); free(used)
            free(terms_mul); free(terms_w)
            keys = nkeys
            vals = nvals
            used = nused
        }
        ae = ae + 1
    }

    let coeffs: ptr<i64> = calloc(r + 1, 8)
    let mut k: i64 = 0
    while k <= r {
        let ck: i64 = binom_mod5(r, k)
        if ((r - k) & 1) == 0 {
            coeffs[k] = ck
        } else {
            coeffs[k] = (MOD5 - ck) % MOD5
        }
        k = k + 1
    }

    let mut total_mod5: i64 = 0
    i = 0
    while i < CAP {
        if used[i] != 0 {
            let w: i64 = vals[i]
            if w != 0 {
                let x_mod: i64 = keys[i]
                let mut p: i64 = modpow(2, x_mod, MOD5)
                let mut acc: i64 = 0
                k = 0
                while k <= r {
                    acc = acc + coeffs[k] * p
                    if (k & 63) == 63 { acc = acc % MOD5 }
                    p = ((p as i128) * (p as i128) % (MOD5 as i128)) as i64
                    k = k + 1
                }
                total_mod5 = (total_mod5 + ((w as i128) * ((acc % MOD5) as i128) % (MOD5 as i128)) as i64) % MOD5
            }
        }
        i = i + 1
    }

    let inv: i64 = modinv_coprime(MOD2, MOD5)
    let tt: i64 = ((total_mod5 as i128) * (inv as i128) % (MOD5 as i128)) as i64
    let ans: i64 = (MOD2 * tt) % 1000000000
    free(primes); free(counts); free(keys); free(vals); free(used); free(coeffs)
    return ans
}

function main() -> i32 {
    printf("%lld\n", HL_50000())
    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 modpow_i64_i64_i64(int64_t base0, int64_t exp0, int64_t modv);
int64_t modinv_coprime_i64_i64(int64_t a0, int64_t m);
int64_t sieve_i64_ptr_i64(int64_t limit, int64_t* primes);
int64_t max_power_exp_i64_i64(int64_t p, int64_t n);
int64_t binom_mod5_i64_i64(int64_t n, int64_t k);
int64_t HL_50000(void);
int32_t main(void);

static const int64_t MOD2 = 512;
static const int64_t MOD5 = 1953125;
static const int64_t PHI5 = 1562500;



int64_t modpow_i64_i64_i64(int64_t base0, int64_t exp0, int64_t modv) {
    int64_t result = 1;
    int64_t base = FLOW_CHECKED_MOD((base0), (modv));
    int64_t exp = exp0;
    while (exp > 0) {
        if ((exp & 1) != 0) {
            result = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(result)) * ((__int128)(base)))), (((__int128)(modv))))));
        }
        base = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(base)) * ((__int128)(base)))), (((__int128)(modv))))));
        exp = FLOW_CHECKED_SHR((exp), (1));
    }
    return result;
}

int64_t modinv_coprime_i64_i64(int64_t a0, int64_t m) {
    int64_t a = FLOW_CHECKED_MOD((a0), (m));
    if (a < 0) {
        a = (a + m);
    }
    int64_t mm = m;
    int64_t x0 = 1;
    int64_t x1 = 0;
    while (mm != 0) {
        int64_t q = FLOW_CHECKED_DIV((a), (mm));
        int64_t na = mm;
        mm = (a - (q * mm));
        a = na;
        int64_t nx = x1;
        x1 = (x0 - (q * x1));
        x0 = nx;
    }
    int64_t inv = FLOW_CHECKED_MOD((x0), (m));
    if (inv < 0) {
        inv = (inv + m);
    }
    return inv;
}

int64_t sieve_i64_ptr_i64(int64_t limit, int64_t* primes) {
    int8_t* s = (int8_t*)(calloc((limit + 1), 1));
    int64_t i = 0;
    while (i <= limit) {
        s[i] = 1;
        i = (i + 1);
    }
    s[0] = 0;
    s[1] = 0;
    i = 2;
    while ((i * i) <= limit) {
        if (s[i] != 0) {
            int64_t j = (i * i);
            while (j <= limit) {
                s[j] = 0;
                j = (j + i);
            }
        }
        i = (i + 1);
    }
    int64_t m = 0;
    i = 2;
    while (i <= limit) {
        if (s[i] != 0) {
            primes[m] = i;
            m = (m + 1);
        }
        i = (i + 1);
    }
    free(s);
    return m;
}

int64_t max_power_exp_i64_i64(int64_t p, int64_t n) {
    int64_t e = 1;
    int64_t pp = p;
    while ((pp * p) <= n) {
        pp = (pp * p);
        e = (e + 1);
    }
    return e;
}

int64_t binom_mod5_i64_i64(int64_t n, int64_t k) {
    if ((k < 0 || k > n)) {
        return 0;
    }
    if ((k == 0 || k == n)) {
        return 1;
    }
    if (k > (n - k)) {
        k = (n - k);
    }
    int64_t num = 1;
    int64_t den = 1;
    int64_t val = 0;
    int64_t i = 1;
    while (i <= k) {
        int64_t a = ((n - k) + i);
        int64_t b = i;
        while (FLOW_CHECKED_MOD((a), (5)) == 0) {
            a = FLOW_CHECKED_DIV((a), (5));
            val = (val + 1);
        }
        while (FLOW_CHECKED_MOD((b), (5)) == 0) {
            b = FLOW_CHECKED_DIV((b), (5));
            val = (val - 1);
        }
        num = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(num)) * ((__int128)(a)))), (((__int128)(MOD5))))));
        den = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(den)) * ((__int128)(b)))), (((__int128)(MOD5))))));
        i = (i + 1);
    }
    if (val >= 9) {
        return 0;
    }
    int64_t inv = modinv_coprime_i64_i64(den, MOD5);
    int64_t res = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(num)) * ((__int128)(inv)))), (((__int128)(MOD5))))));
    int64_t p = 0;
    while (p < val) {
        res = FLOW_CHECKED_MOD(((res * 5)), (MOD5));
        p = (p + 1);
    }
    return res;
}

int64_t HL_50000(void) {
    int64_t N = 50000;
    int64_t* primes = (int64_t*)(calloc(10000, 8));
    int64_t np = sieve_i64_ptr_i64(N, primes);
    int64_t r = 0;
    int64_t* counts = (int64_t*)(calloc(32, 8));
    int64_t i = 0;
    while (i < np) {
        int64_t ae = max_power_exp_i64_i64(primes[i], N);
        if (ae == 1) {
            r = (r + 1);
        } else {
            counts[ae] = (counts[ae] + 1);
        }
        i = (i + 1);
    }
    int64_t CAP = 4000003;
    int64_t* keys = (int64_t*)(calloc(CAP, 8));
    int64_t* vals = (int64_t*)(calloc(CAP, 8));
    int8_t* used = (int8_t*)(calloc(CAP, 1));
    int64_t h = FLOW_CHECKED_MOD((1), (CAP));
    used[h] = 1;
    keys[h] = 1;
    vals[h] = 1;
    int64_t ae = 2;
    while (ae < 32) {
        int64_t c = counts[ae];
        if (c > 0) {
            int64_t* terms_mul = (int64_t*)(calloc((c + 1), 8));
            int64_t* terms_w = (int64_t*)(calloc((c + 1), 8));
            int64_t t = 0;
            while (t <= c) {
                int64_t mul = FLOW_CHECKED_MOD(((modpow_i64_i64_i64(ae, t, PHI5) * modpow_i64_i64_i64((ae + 1), (c - t), PHI5))), (PHI5));
                int64_t w = binom_mod5_i64_i64(c, t);
                if ((t & 1) != 0) {
                    w = FLOW_CHECKED_MOD(((MOD5 - w)), (MOD5));
                }
                terms_mul[t] = mul;
                terms_w[t] = w;
                t = (t + 1);
            }
            int64_t* nkeys = (int64_t*)(calloc(CAP, 8));
            int64_t* nvals = (int64_t*)(calloc(CAP, 8));
            int8_t* nused = (int8_t*)(calloc(CAP, 1));
            i = 0;
            while (i < CAP) {
                if (used[i] != 0) {
                    int64_t x_prev = keys[i];
                    int64_t w_prev = vals[i];
                    t = 0;
                    while (t <= c) {
                        int64_t new_x = FLOW_CHECKED_MOD(((x_prev * terms_mul[t])), (PHI5));
                        int64_t add = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(w_prev)) * ((__int128)(terms_w[t])))), (((__int128)(MOD5))))));
                        int64_t hh = FLOW_CHECKED_MOD((new_x), (CAP));
                        if (hh < 0) {
                            hh = (-hh);
                        }
                        while ((nused[hh] != 0 && nkeys[hh] != new_x)) {
                            hh = (hh + 1);
                            if (hh >= CAP) {
                                hh = 0;
                            }
                        }
                        if (nused[hh] == 0) {
                            nused[hh] = 1;
                            nkeys[hh] = new_x;
                            nvals[hh] = add;
                        } else {
                            nvals[hh] = FLOW_CHECKED_MOD(((nvals[hh] + add)), (MOD5));
                        }
                        t = (t + 1);
                    }
                }
                i = (i + 1);
            }
            free(keys);
            free(vals);
            free(used);
            free(terms_mul);
            free(terms_w);
            keys = nkeys;
            vals = nvals;
            used = nused;
        }
        ae = (ae + 1);
    }
    int64_t* coeffs = (int64_t*)(calloc((r + 1), 8));
    int64_t k = 0;
    while (k <= r) {
        int64_t ck = binom_mod5_i64_i64(r, k);
        if (((r - k) & 1) == 0) {
            coeffs[k] = ck;
        } else {
            coeffs[k] = FLOW_CHECKED_MOD(((MOD5 - ck)), (MOD5));
        }
        k = (k + 1);
    }
    int64_t total_mod5 = 0;
    i = 0;
    while (i < CAP) {
        if (used[i] != 0) {
            int64_t w = vals[i];
            if (w != 0) {
                int64_t x_mod = keys[i];
                int64_t p = modpow_i64_i64_i64(2, x_mod, MOD5);
                int64_t acc = 0;
                k = 0;
                while (k <= r) {
                    acc = (acc + (coeffs[k] * p));
                    if ((k & 63) == 63) {
                        acc = FLOW_CHECKED_MOD((acc), (MOD5));
                    }
                    p = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(p)) * ((__int128)(p)))), (((__int128)(MOD5))))));
                    k = (k + 1);
                }
                total_mod5 = FLOW_CHECKED_MOD(((total_mod5 + ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(w)) * ((__int128)(FLOW_CHECKED_MOD((acc), (MOD5)))))), (((__int128)(MOD5)))))))), (MOD5));
            }
        }
        i = (i + 1);
    }
    int64_t inv = modinv_coprime_i64_i64(MOD2, MOD5);
    int64_t tt = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(total_mod5)) * ((__int128)(inv)))), (((__int128)(MOD5))))));
    int64_t ans = FLOW_CHECKED_MOD(((MOD2 * tt)), (1000000000));
    free(primes);
    free(counts);
    free(keys);
    free(vals);
    free(used);
    free(coeffs);
    return ans;
}

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