Problem 533

Minimum Values of the Carmichael Function — L(2*10^7) mod 10^9.

Answer789453601
Output789453601
StatusPASS
Native helperno
Runtime450 ms
Peak memory167152 KB
Time complexityO(n^3) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^3)O(n log n)
Space complexityO(n^2)O(n)
ApproachFlow solutionModular DP or matrix exponentiation
VerdictSuboptimal

Flow source

# Project Euler 533
# Minimum Values of the Carmichael Function — L(2*10^7) mod 10^9.

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

const MOD: i64 = 1000000000
const TARGET: i64 = 20000000

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

function is_odd_prime(x: i64, isp: ptr<i8>) -> i32 {
    if x == 2 { return 1 }
    if x < 2 || (x & 1) == 0 { return 0 }
    return isp[x / 2] as i32
}

function factorize(n0: i64, pf: ptr<i64>, pe: ptr<i32>, out_n: ptr<i32>) -> void {
    let mut n: i64 = n0
    let mut cnt: i32 = 0
    if (n & 1) == 0 {
        let mut e: i32 = 0
        while (n & 1) == 0 {
            n = n / 2
            e = e + 1
        }
        pf[cnt] = 2
        pe[cnt] = e
        cnt = cnt + 1
    }
    let mut p: i64 = 3
    while p * p <= n {
        if n % p == 0 {
            let mut e2: i32 = 0
            while n % p == 0 {
                n = n / p
                e2 = e2 + 1
            }
            pf[cnt] = p
            pe[cnt] = e2
            cnt = cnt + 1
        }
        p = p + 2
    }
    if n > 1 {
        pf[cnt] = n
        pe[cnt] = 1
        cnt = cnt + 1
    }
    out_n[0] = cnt
}

function N_mod(m: i64, isp: ptr<i8>) -> i64 {
    let pf: ptr<i64> = calloc(32, 8)
    let pe: ptr<i32> = calloc(32, 4)
    let fc: ptr<i32> = calloc(1, 4)
    let divs: ptr<i64> = calloc(4096, 8)
    if pf == null || pe == null || fc == null || divs == null { return 0 }
    factorize(m, pf, pe, fc)
    let nf: i32 = fc[0]
    let mut nd: i64 = 1
    divs[0] = 1
    let mut fi: i32 = 0
    while fi < nf {
        let p: i64 = pf[fi]
        let e: i32 = pe[fi]
        let base: i64 = nd
        let mut pe2: i64 = 1
        let mut ei: i32 = 0
        while ei < e {
            pe2 = pe2 * p
            let mut j: i64 = 0
            while j < base {
                divs[nd] = divs[j] * pe2
                nd = nd + 1
                j = j + 1
            }
            ei = ei + 1
        }
        fi = fi + 1
    }
    let mut e2: i64 = 1
    if (m & 1) == 0 {
        let mut v2: i64 = 0
        let mut t: i64 = m
        while (t & 1) == 0 {
            t = t / 2
            v2 = v2 + 1
        }
        e2 = v2 + 2
    }
    let mut res: i64 = modpow(2, e2, MOD)
    let mut di: i64 = 0
    while di < nd {
        let d: i64 = divs[di]
        let p2: i64 = d + 1
        if p2 != 2 && (p2 & 1) == 1 && is_odd_prime(p2, isp) == 1 {
            let mut t2: i64 = m / d
            let mut e3: i64 = 1
            while t2 % p2 == 0 {
                t2 = t2 / p2
                e3 = e3 + 1
            }
            res = ((res as i128) * (modpow(p2, e3, MOD) as i128) % (MOD as i128)) as i64
        }
        di = di + 1
    }
    free(pf); free(pe); free(fc); free(divs)
    return res
}

function main() -> i32 {
    let limit: i64 = TARGET - 1
    let size: i64 = limit + 1
    let isp: ptr<i8> = calloc((limit + 2) / 2 + 1, 1)
    let score: ptr<f64> = calloc(size, 8)
    if isp == null || score == null { return 1 }
    let mut p: i64 = 3
    let r: i64 = 4472  # isqrt(limit+1) approx
    isp[0] = 0
    let mut idx: i64 = 1
    while idx < (limit + 2) / 2 + 1 {
        isp[idx] = 1
        idx = idx + 1
    }
    p = 3
    while p <= r {
        if isp[p / 2] == 1 {
            let mut j: i64 = p * p
            while j <= limit + 1 {
                if (j & 1) == 1 { isp[j / 2] = 0 }
                j = j + 2 * p
            }
        }
        p = p + 2
    }
    let ln2: f64 = log(2.0)
    let mut i: i64 = 2
    while i <= limit {
        score[i] = score[i] + ln2
        i = i + 2
    }
    let mut pow2: i64 = 2
    while pow2 <= limit {
        i = pow2
        while i <= limit {
            score[i] = score[i] + ln2
            i = i + pow2
        }
        pow2 = pow2 << 1
    }
    idx = 1
    while idx < (limit + 2) / 2 + 1 {
        if isp[idx] == 1 {
            let p2: i64 = 2 * idx + 1
            let lnp: f64 = log(p2 as f64)
            let mut step: i64 = p2 - 1
            while step <= limit {
                i = step
                while i <= limit {
                    score[i] = score[i] + lnp
                    i = i + step
                }
                step = step * p2
            }
        }
        idx = idx + 1
    }
    let mut best_m: i64 = 1
    let mut best_s: f64 = score[1]
    i = 2
    while i <= limit {
        if score[i] > best_s {
            best_s = score[i]
            best_m = i
        }
        i = i + 1
    }
    let ans: i64 = (N_mod(best_m, isp) + 1) % MOD
    printf("%lld\n", ans)
    free(isp); free(score)
    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 mod);
int32_t is_odd_prime_i64_ptr_i8(int64_t x, int8_t* isp);
void factorize_i64_ptr_i64_ptr_i32_ptr_i32(int64_t n0, int64_t* pf, int32_t* pe, int32_t* out_n);
int64_t N_mod_i64_ptr_i8(int64_t m, int8_t* isp);
int32_t main(void);

static const int64_t MOD = 1000000000;
static const int64_t TARGET = 20000000;




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

int32_t is_odd_prime_i64_ptr_i8(int64_t x, int8_t* isp) {
    if (x == 2) {
        return 1;
    }
    if ((x < 2 || (x & 1) == 0)) {
        return 0;
    }
    return ((int32_t)(isp[FLOW_CHECKED_DIV((x), (2))]));
}

void factorize_i64_ptr_i64_ptr_i32_ptr_i32(int64_t n0, int64_t* pf, int32_t* pe, int32_t* out_n) {
    int64_t n = n0;
    int32_t cnt = 0;
    if ((n & 1) == 0) {
        int32_t e = 0;
        while ((n & 1) == 0) {
            n = FLOW_CHECKED_DIV((n), (2));
            e = (e + 1);
        }
        pf[cnt] = 2;
        pe[cnt] = e;
        cnt = (cnt + 1);
    }
    int64_t p = 3;
    while ((p * p) <= n) {
        if (FLOW_CHECKED_MOD((n), (p)) == 0) {
            int32_t e2 = 0;
            while (FLOW_CHECKED_MOD((n), (p)) == 0) {
                n = FLOW_CHECKED_DIV((n), (p));
                e2 = (e2 + 1);
            }
            pf[cnt] = p;
            pe[cnt] = e2;
            cnt = (cnt + 1);
        }
        p = (p + 2);
    }
    if (n > 1) {
        pf[cnt] = n;
        pe[cnt] = 1;
        cnt = (cnt + 1);
    }
    out_n[0] = cnt;
}

int64_t N_mod_i64_ptr_i8(int64_t m, int8_t* isp) {
    int64_t* pf = (int64_t*)(calloc(32, 8));
    int32_t* pe = (int32_t*)(calloc(32, 4));
    int32_t* fc = (int32_t*)(calloc(1, 4));
    int64_t* divs = (int64_t*)(calloc(4096, 8));
    if ((((pf == NULL || pe == NULL) || fc == NULL) || divs == NULL)) {
        return 0;
    }
    factorize_i64_ptr_i64_ptr_i32_ptr_i32(m, pf, pe, fc);
    int32_t nf = fc[0];
    int64_t nd = 1;
    divs[0] = 1;
    int32_t fi = 0;
    while (fi < nf) {
        int64_t p = pf[fi];
        int32_t e = pe[fi];
        int64_t base = nd;
        int64_t pe2 = 1;
        int32_t ei = 0;
        while (ei < e) {
            pe2 = (pe2 * p);
            int64_t j = 0;
            while (j < base) {
                divs[nd] = (divs[j] * pe2);
                nd = (nd + 1);
                j = (j + 1);
            }
            ei = (ei + 1);
        }
        fi = (fi + 1);
    }
    int64_t e2 = 1;
    if ((m & 1) == 0) {
        int64_t v2 = 0;
        int64_t t = m;
        while ((t & 1) == 0) {
            t = FLOW_CHECKED_DIV((t), (2));
            v2 = (v2 + 1);
        }
        e2 = (v2 + 2);
    }
    int64_t res = modpow_i64_i64_i64(2, e2, MOD);
    int64_t di = 0;
    while (di < nd) {
        int64_t d = divs[di];
        int64_t p2 = (d + 1);
        if (((p2 != 2 && (p2 & 1) == 1) && is_odd_prime_i64_ptr_i8(p2, isp) == 1)) {
            int64_t t2 = FLOW_CHECKED_DIV((m), (d));
            int64_t e3 = 1;
            while (FLOW_CHECKED_MOD((t2), (p2)) == 0) {
                t2 = FLOW_CHECKED_DIV((t2), (p2));
                e3 = (e3 + 1);
            }
            res = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(res)) * ((__int128)(modpow_i64_i64_i64(p2, e3, MOD))))), (((__int128)(MOD))))));
        }
        di = (di + 1);
    }
    free(pf);
    free(pe);
    free(fc);
    free(divs);
    return res;
}

int32_t main(void) {
    int64_t limit = (TARGET - 1);
    int64_t size = (limit + 1);
    int8_t* isp = (int8_t*)(calloc((FLOW_CHECKED_DIV(((limit + 2)), (2)) + 1), 1));
    double* score = (double*)(calloc(size, 8));
    if ((isp == NULL || score == NULL)) {
        return 1;
    }
    int64_t p = 3;
    int64_t r = 4472;
    isp[0] = 0;
    int64_t idx = 1;
    while (idx < (FLOW_CHECKED_DIV(((limit + 2)), (2)) + 1)) {
        isp[idx] = 1;
        idx = (idx + 1);
    }
    p = 3;
    while (p <= r) {
        if (isp[FLOW_CHECKED_DIV((p), (2))] == 1) {
            int64_t j = (p * p);
            while (j <= (limit + 1)) {
                if ((j & 1) == 1) {
                    isp[FLOW_CHECKED_DIV((j), (2))] = 0;
                }
                j = (j + (2 * p));
            }
        }
        p = (p + 2);
    }
    double ln2 = log(2.0);
    int64_t i = 2;
    while (i <= limit) {
        score[i] = (score[i] + ln2);
        i = (i + 2);
    }
    int64_t pow2 = 2;
    while (pow2 <= limit) {
        i = pow2;
        while (i <= limit) {
            score[i] = (score[i] + ln2);
            i = (i + pow2);
        }
        pow2 = FLOW_CHECKED_SHL((pow2), (1));
    }
    idx = 1;
    while (idx < (FLOW_CHECKED_DIV(((limit + 2)), (2)) + 1)) {
        if (isp[idx] == 1) {
            int64_t p2 = ((2 * idx) + 1);
            double lnp = log(((double)(p2)));
            int64_t step = (p2 - 1);
            while (step <= limit) {
                i = step;
                while (i <= limit) {
                    score[i] = (score[i] + lnp);
                    i = (i + step);
                }
                step = (step * p2);
            }
        }
        idx = (idx + 1);
    }
    int64_t best_m = 1;
    double best_s = score[1];
    i = 2;
    while (i <= limit) {
        if (score[i] > best_s) {
            best_s = score[i];
            best_m = i;
        }
        i = (i + 1);
    }
    int64_t ans = FLOW_CHECKED_MOD(((N_mod_i64_ptr_i8(best_m, isp) + 1)), (MOD));
    printf("%lld\n", ans);
    free(isp);
    free(score);
    return 0;
}

Generated MLIR

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