Problem 468

Smooth Divisors of Binomial Coefficients — segment tree over prime powers.

Answer852950321
Output852950321
StatusPASS
Native helperno
Runtime8100 ms
Peak memory169920 KB
Time complexityO(n^2) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^2)O(n log log n)
Space complexityO(n^2)O(n)
ApproachFlow solutionSieve of Eratosthenes
VerdictSuboptimal

Flow source

# Project Euler 468
# Smooth Divisors of Binomial Coefficients — segment tree over prime powers.

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

const N: i64 = 11111111
const MOD: i64 = 1000000993

let mut G_spf: ptr<i32> = null
let mut G_primes: ptr<i32> = null
let mut G_pidx: ptr<i32> = null
let mut G_w: ptr<i32> = null
let mut G_prod: ptr<i64> = null
let mut G_seg: ptr<i64> = null
let mut G_inv: ptr<i64> = null
let mut G_npc: i64 = 0
let mut G_base: i64 = 1

function modpow(base0: i64, exp0: i64, mod: i64) -> i64 {
    let mut r: i64 = 1
    let mut b: i64 = base0 % mod
    let mut e: i64 = exp0
    while e > 0 {
        if (e & 1) == 1 {
            r = ((r 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 mul_leaf(i: i64, factor: i64) -> void {
    let mut pos: i64 = G_base + i
    G_prod[pos] = (G_prod[pos] * factor) % MOD
    G_seg[pos] = ((G_w[i] as i64) * G_prod[pos]) % MOD
    pos = pos / 2
    while pos > 0 {
        let l: i64 = pos * 2
        G_prod[pos] = (G_prod[l] * G_prod[l + 1]) % MOD
        G_seg[pos] = (G_seg[l] + G_prod[l] * G_seg[l + 1]) % MOD
        pos = pos / 2
    }
}

function apply_factor(x0: i64, sign: i64) -> void {
    let mut x: i64 = x0
    while x > 1 {
        let p: i64 = G_spf[x] as i64
        let mut cnt: i64 = 0
        while x % p == 0 {
            x = x / p
            cnt = cnt + 1
        }
        let mut factor: i64 = modpow(p, cnt, MOD)
        if sign < 0 {
            if G_inv[p] == 0 {
                G_inv[p] = modpow(p, MOD - 2, MOD)
            }
            factor = modpow(G_inv[p], cnt, MOD)
        }
        mul_leaf(G_pidx[p] as i64, factor)
    }
}

function main() -> i32 {
    G_spf = calloc(N + 1, 4)
    G_primes = calloc(N / 5 + 16, 4)
    G_pidx = calloc(N + 1, 4)
    G_inv = calloc(N + 1, 8)
    if G_spf == null || G_primes == null || G_pidx == null || G_inv == null { return 1 }

    let mut i: i64 = 0
    while i <= N {
        G_pidx[i] = -1
        i = i + 1
    }

    i = 2
    while i <= N {
        if G_spf[i] == 0 {
            G_spf[i] = i as i32
            G_primes[G_npc] = i as i32
            G_npc = G_npc + 1
        }
        let mut j: i64 = 0
        while j < G_npc {
            let p: i64 = G_primes[j] as i64
            let v: i64 = i * p
            if v > N { break }
            G_spf[v] = p as i32
            if i % p == 0 { break }
            j = j + 1
        }
        i = i + 1
    }

    G_w = calloc(G_npc, 4)
    i = 0
    while i + 1 < G_npc {
        G_w[i] = G_primes[i + 1] - G_primes[i]
        G_pidx[G_primes[i] as i64] = i as i32
        i = i + 1
    }
    G_w[G_npc - 1] = (N - (G_primes[G_npc - 1] as i64) + 1) as i32
    G_pidx[G_primes[G_npc - 1] as i64] = (G_npc - 1) as i32

    while G_base < G_npc {
        G_base = G_base * 2
    }
    G_prod = calloc(2 * G_base, 8)
    G_seg = calloc(2 * G_base, 8)
    if G_w == null || G_prod == null || G_seg == null { return 1 }

    i = 0
    while i < 2 * G_base {
        G_prod[i] = 1
        G_seg[i] = 0
        i = i + 1
    }
    i = 0
    while i < G_npc {
        G_seg[G_base + i] = (G_w[i] as i64) % MOD
        i = i + 1
    }
    i = G_base - 1
    while i >= 1 {
        let l: i64 = i * 2
        G_prod[i] = (G_prod[l] * G_prod[l + 1]) % MOD
        G_seg[i] = (G_seg[l] + G_prod[l] * G_seg[l + 1]) % MOD
        i = i - 1
    }

    let mut total: i64 = 0
    let mid: i64 = N / 2
    let even: i64 = 1 - (N % 2)
    let mut r: i64 = 0
    while r <= mid {
        let h: i64 = (1 + G_seg[1]) % MOD
        if even == 1 && r == mid {
            total = (total + h) % MOD
            break
        }
        total = (total + 2 * h) % MOD
        apply_factor(N - r, 1)
        apply_factor(r + 1, -1)
        r = r + 1
    }

    printf("%lld\n", total)
    free(G_seg)
    free(G_prod)
    free(G_w)
    free(G_inv)
    free(G_pidx)
    free(G_primes)
    free(G_spf)
    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);
void mul_leaf_i64_i64(int64_t i, int64_t factor);
void apply_factor_i64_i64(int64_t x0, int64_t sign);
int32_t main(void);

static const int64_t N = 11111111;
static const int64_t MOD = 1000000993;

/* Module statics */
static int32_t* G_spf = NULL;
static int32_t* G_primes = NULL;
static int32_t* G_pidx = NULL;
static int32_t* G_w = NULL;
static int64_t* G_prod = NULL;
static int64_t* G_seg = NULL;
static int64_t* G_inv = NULL;
static int64_t G_npc = 0;
static int64_t G_base = 1;



int64_t modpow_i64_i64_i64(int64_t base0, int64_t exp0, int64_t mod) {
    int64_t r = 1;
    int64_t b = FLOW_CHECKED_MOD((base0), (mod));
    int64_t e = exp0;
    while (e > 0) {
        if ((e & 1) == 1) {
            r = ((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;
}

void mul_leaf_i64_i64(int64_t i, int64_t factor) {
    int64_t pos = (G_base + i);
    G_prod[pos] = FLOW_CHECKED_MOD(((G_prod[pos] * factor)), (MOD));
    G_seg[pos] = FLOW_CHECKED_MOD(((((int64_t)(G_w[i])) * G_prod[pos])), (MOD));
    pos = FLOW_CHECKED_DIV((pos), (2));
    while (pos > 0) {
        int64_t l = (pos * 2);
        G_prod[pos] = FLOW_CHECKED_MOD(((G_prod[l] * G_prod[(l + 1)])), (MOD));
        G_seg[pos] = FLOW_CHECKED_MOD(((G_seg[l] + (G_prod[l] * G_seg[(l + 1)]))), (MOD));
        pos = FLOW_CHECKED_DIV((pos), (2));
    }
}

void apply_factor_i64_i64(int64_t x0, int64_t sign) {
    int64_t x = x0;
    while (x > 1) {
        int64_t p = ((int64_t)(G_spf[x]));
        int64_t cnt = 0;
        while (FLOW_CHECKED_MOD((x), (p)) == 0) {
            x = FLOW_CHECKED_DIV((x), (p));
            cnt = (cnt + 1);
        }
        int64_t factor = modpow_i64_i64_i64(p, cnt, MOD);
        if (sign < 0) {
            if (G_inv[p] == 0) {
                G_inv[p] = modpow_i64_i64_i64(p, (MOD - 2), MOD);
            }
            factor = modpow_i64_i64_i64(G_inv[p], cnt, MOD);
        }
        mul_leaf_i64_i64(((int64_t)(G_pidx[p])), factor);
    }
}

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