Problem 801

Sum of f(p) for primes p in [10^16, 10^16 + 10^6], mod 993353399. Pure Flow port of the native C solver. Uses i128 for mulmod/powmod.

Answer638129754
Output638129754
StatusPASS
Native helperno
Runtime2170 ms
Peak memory2560 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 or enumeration
VerdictSuboptimal

Flow source

# Project Euler 801: x^y = y^x (mod p).
# Sum of f(p) for primes p in [10^16, 10^16 + 10^6], mod 993353399.
# Pure Flow port of the native C solver. Uses i128 for mulmod/powmod.

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

const MOD: i64 = 993353399

# 64-bit modular multiply via i128.
function mulmod(a: i64, b: i64, m: i64) -> i64 {
    return ((a as i128) * (b as i128) % (m as i128)) as i64
}

function powmod(a0: i64, e0: i64, m: i64) -> i64 {
    let mut r: i64 = 1 % m
    let mut a: i64 = a0 % m
    let mut e: i64 = e0
    while e != 0 {
        if e % 2 == 1 {
            r = mulmod(r, a, m)
        }
        a = mulmod(a, a, m)
        e = e / 2
    }
    return r
}

# Deterministic Miller-Rabin for 64-bit.
function is_prime_64(n: i64) -> i32 {
    if n < 2 {
        return 0
    }
    # small primes trial
    let sp: array<i64, 12> = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
    let mut i: i64 = 0
    while i < 12 {
        if n == sp[i] {
            return 1
        }
        if n % sp[i] == 0 {
            return 0
        }
        i = i + 1
    }
    let mut d: i64 = n - 1
    let mut s: i64 = 0
    while d % 2 == 0 {
        d = d / 2
        s = s + 1
    }
    let bases: array<i64, 7> = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]
    let mut bi: i64 = 0
    while bi < 7 {
        let a: i64 = bases[bi]
        if a % n == 0 {
            bi = bi + 1
        } else {
            let mut x: i64 = powmod(a, d, n)
            if x == 1 || x == n - 1 {
                bi = bi + 1
            } else {
                let mut comp: i32 = 1
                let mut j: i64 = 0
                while j < s - 1 {
                    x = mulmod(x, x, n)
                    if x == n - 1 {
                        comp = 0
                        j = s
                    }
                    j = j + 1
                }
                if comp != 0 {
                    return 0
                }
                bi = bi + 1
            }
        }
    }
    return 1
}

function gcd_u64(a0: i64, b0: i64) -> i64 {
    let mut a: i64 = a0
    let mut b: i64 = b0
    while b != 0 {
        let t: i64 = a % b
        a = b
        b = t
    }
    return a
}

let mut rng_state: i64 = -7046029254386353131

function rand64() -> i64 {
    let mut x: i64 = rng_state
    x = x ^ (x >> 12)
    x = x ^ (x << 25)
    x = x ^ (x >> 27)
    rng_state = x
    return x * 2685821657736338717
}

function pollard_rho(n: i64) -> i64 {
    if n % 2 == 0 {
        return 2
    }
    if n % 3 == 0 {
        return 3
    }
    while true {
        let c: i64 = rand64() % (n - 1) + 1
        let mut x: i64 = rand64() % (n - 2) + 2
        let mut y: i64 = x
        let mut d: i64 = 1
        while d == 1 {
            x = (mulmod(x, x, n) + c) % n
            y = (mulmod(y, y, n) + c) % n
            y = (mulmod(y, y, n) + c) % n
            let mut diff: i64 = x - y
            if diff < 0 {
                diff = -diff
            }
            d = gcd_u64(diff, n)
        }
        if d != n {
            return d
        }
    }
    return 0
}

# Factorize n into prime/exp arrays. Returns count.
function factorize(n0: i64, fp: ptr<i64>, ep: ptr<i64>) -> i64 {
    let mut outn: i64 = 0
    let mut n: i64 = n0
    if n <= 1 {
        return 0
    }
    let mut p: i64 = 2
    while p * p <= n && p <= 10000 {
        if n % p == 0 {
            let mut e: i64 = 0
            while n % p == 0 {
                n = n / p
                e = e + 1
            }
            fp[outn] = p
            ep[outn] = e
            outn = outn + 1
        }
        p = p + 1
    }
    if n == 1 {
        return outn
    }
    if is_prime_64(n) != 0 {
        fp[outn] = n
        ep[outn] = 1
        outn = outn + 1
        return outn
    }
    # Pollard-Rho with explicit stack
    let stack: ptr<i64> = calloc(64, 8) as ptr<i64>
    let mut sp: i64 = 0
    stack[sp] = n
    sp = sp + 1
    while sp > 0 {
        sp = sp - 1
        let m: i64 = stack[sp]
        if m == 1 {
        } else {
            if is_prime_64(m) != 0 {
                let mut found: i32 = 0
                let mut i: i64 = 0
                while i < outn {
                    if fp[i] == m {
                        ep[i] = ep[i] + 1
                        found = 1
                        i = outn
                    }
                    i = i + 1
                }
                if found == 0 {
                    fp[outn] = m
                    ep[outn] = 1
                    outn = outn + 1
                }
            } else {
                let d: i64 = pollard_rho(m)
                stack[sp] = d
                sp = sp + 1
                stack[sp] = m / d
                sp = sp + 1
            }
        }
    }
    free(stack)
    return outn
}

# powmod for small modulus (fits in 32 bits).
function powmod_small(a0: i64, e0: i64, m: i64) -> i64 {
    let mut r: i64 = 1 % m
    let mut a: i64 = a0 % m
    if a < 0 {
        a = a + m
    }
    let mut e: i64 = e0
    while e > 0 {
        if e % 2 == 1 {
            r = r * a % m
        }
        a = a * a % m
        e = e / 2
    }
    return r
}

# g(q^e) mod.
function g_prime_power_mod(q: i64, e: i64, modv: i64) -> i64 {
    let qm: i64 = q % modv
    let mut s: i64 = 0
    let mut t: i64 = 1
    while t <= e {
        let expv: i64 = 3 * e - t - 2
        let term: i64 = powmod_small(qm, expv, modv)
        s = (s + (t * t) % modv * term) % modv
        t = t + 1
    }
    let qm1: i64 = (q - 1) % modv
    let term1: i64 = powmod_small(qm1, 3, modv) * s % modv
    let inner: i64 = (e * (q - 1) + q) % modv
    let term2: i64 = powmod_small(qm, 2 * e - 2, modv) * powmod_small(inner, 2, modv) % modv
    return (term1 + term2) % modv
}

function g_from_factorization(fp: ptr<i64>, ep: ptr<i64>, nf: i64, modv: i64) -> i64 {
    let mut g: i64 = 1 % modv
    let mut i: i64 = 0
    while i < nf {
        g = g * g_prime_power_mod(fp[i], ep[i], modv) % modv
        i = i + 1
    }
    return g
}

function f_of_prime(p: i64, modv: i64) -> i64 {
    let m: i64 = p - 1
    let fp: ptr<i64> = calloc(64, 8) as ptr<i64>
    let ep: ptr<i64> = calloc(64, 8) as ptr<i64>
    let nf: i64 = factorize(m, fp, ep)
    let g: i64 = g_from_factorization(fp, ep, nf, modv)
    free(fp)
    free(ep)
    let mm: i64 = m % modv
    return (mm * mm + g) % modv
}

function main() -> i32 {
    let modv: i64 = MOD
    let lo: i64 = 10000000000000000
    let hi: i64 = lo + 1000000
    let length: i64 = hi - lo + 1

    let is_comp: ptr<i8> = calloc(length, 1) as ptr<i8>

    # sieve small primes up to 200000
    let limit: i64 = 200000
    let sieve: ptr<i8> = calloc(limit + 1, 1) as ptr<i8>
    let primes: ptr<i64> = calloc(20000, 8) as ptr<i64>
    let mut pc: i64 = 0
    let mut pp: i64 = 2
    while pp <= limit {
        if sieve[pp] == 0 {
            primes[pc] = pp
            pc = pc + 1
            let mut j: i64 = pp * pp
            while j <= limit {
                sieve[j] = 1
                j = j + pp
            }
        }
        pp = pp + 1
    }
    free(sieve)

    let mut i: i64 = 0
    while i < pc {
        let q: i64 = primes[i]
        let mut offset: i64 = (q - (lo % q)) % q
        let mut j: i64 = offset
        while j < length {
            is_comp[j] = 1
            j = j + q
        }
        if lo <= q && q <= hi {
            is_comp[q - lo] = 0
        }
        i = i + 1
    }
    free(primes)

    let mut total: i64 = 0
    let mut j: i64 = 0
    while j < length {
        if is_comp[j] == 0 {
            let n: i64 = lo + j
            if is_prime_64(n) != 0 {
                total = (total + f_of_prime(n, modv)) % modv
            }
        }
        j = j + 1
    }

    free(is_comp)
    printf("%lld\n", total)
    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 mulmod_i64_i64_i64(int64_t a, int64_t b, int64_t m);
int64_t powmod_i64_i64_i64(int64_t a0, int64_t e0, int64_t m);
int32_t is_prime_64_i64(int64_t n);
int64_t gcd_u64_i64_i64(int64_t a0, int64_t b0);
int64_t rand64(void);
int64_t pollard_rho_i64(int64_t n);
int64_t factorize_i64_ptr_i64_ptr_i64(int64_t n0, int64_t* fp, int64_t* ep);
int64_t powmod_small_i64_i64_i64(int64_t a0, int64_t e0, int64_t m);
int64_t g_prime_power_mod_i64_i64_i64(int64_t q, int64_t e, int64_t modv);
int64_t g_from_factorization_ptr_i64_ptr_i64_i64_i64(int64_t* fp, int64_t* ep, int64_t nf, int64_t modv);
int64_t f_of_prime_i64_i64(int64_t p, int64_t modv);
int32_t main(void);

static const int64_t MOD = 993353399;

/* Module statics */
static int64_t rng_state = (-7046029254386353131);



int64_t mulmod_i64_i64_i64(int64_t a, int64_t b, int64_t m) {
    return ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(a)) * ((__int128)(b)))), (((__int128)(m))))));
}

int64_t powmod_i64_i64_i64(int64_t a0, int64_t e0, int64_t m) {
    int64_t r = FLOW_CHECKED_MOD((1), (m));
    int64_t a = FLOW_CHECKED_MOD((a0), (m));
    int64_t e = e0;
    while (e != 0) {
        if (FLOW_CHECKED_MOD((e), (2)) == 1) {
            r = mulmod_i64_i64_i64(r, a, m);
        }
        a = mulmod_i64_i64_i64(a, a, m);
        e = FLOW_CHECKED_DIV((e), (2));
    }
    return r;
}

int32_t is_prime_64_i64(int64_t n) {
    if (n < 2) {
        return 0;
    }
    int64_t sp[12] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
    int64_t i = 0;
    while (i < 12) {
        if (n == (((unsigned)(i) < 12) ? sp[i] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(i), 12), flow_fault_handler("array index out of bounds"), sp[0]))) {
            return 1;
        }
        if (FLOW_CHECKED_MOD((n), ((((unsigned)(i) < 12) ? sp[i] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(i), 12), flow_fault_handler("array index out of bounds"), sp[0])))) == 0) {
            return 0;
        }
        i = (i + 1);
    }
    int64_t d = (n - 1);
    int64_t s = 0;
    while (FLOW_CHECKED_MOD((d), (2)) == 0) {
        d = FLOW_CHECKED_DIV((d), (2));
        s = (s + 1);
    }
    int64_t bases[7] = { 2, 325, 9375, 28178, 450775, 9780504, 1795265022 };
    int64_t bi = 0;
    while (bi < 7) {
        int64_t a = (((unsigned)(bi) < 7) ? bases[bi] : (fprintf(stderr, "array index %d out of bounds (size %d)\n", (int)(bi), 7), flow_fault_handler("array index out of bounds"), bases[0]));
        if (FLOW_CHECKED_MOD((a), (n)) == 0) {
            bi = (bi + 1);
        } else {
            int64_t x = powmod_i64_i64_i64(a, d, n);
            if ((x == 1 || x == (n - 1))) {
                bi = (bi + 1);
            } else {
                int32_t comp = 1;
                int64_t j = 0;
                while (j < (s - 1)) {
                    x = mulmod_i64_i64_i64(x, x, n);
                    if (x == (n - 1)) {
                        comp = 0;
                        j = s;
                    }
                    j = (j + 1);
                }
                if (comp != 0) {
                    return 0;
                }
                bi = (bi + 1);
            }
        }
    }
    return 1;
}

int64_t gcd_u64_i64_i64(int64_t a0, int64_t b0) {
    int64_t a = a0;
    int64_t b = b0;
    while (b != 0) {
        int64_t t = FLOW_CHECKED_MOD((a), (b));
        a = b;
        b = t;
    }
    return a;
}

int64_t rand64(void) {
    int64_t x = rng_state;
    x = (x ^ FLOW_CHECKED_SHR((x), (12)));
    x = (x ^ FLOW_CHECKED_SHL((x), (25)));
    x = (x ^ FLOW_CHECKED_SHR((x), (27)));
    rng_state = x;
    return (x * 2685821657736338717);
}

int64_t pollard_rho_i64(int64_t n) {
    if (FLOW_CHECKED_MOD((n), (2)) == 0) {
        return 2;
    }
    if (FLOW_CHECKED_MOD((n), (3)) == 0) {
        return 3;
    }
    while (1) {
        int64_t c = (FLOW_CHECKED_MOD((rand64()), ((n - 1))) + 1);
        int64_t x = (FLOW_CHECKED_MOD((rand64()), ((n - 2))) + 2);
        int64_t y = x;
        int64_t d = 1;
        while (d == 1) {
            x = FLOW_CHECKED_MOD(((mulmod_i64_i64_i64(x, x, n) + c)), (n));
            y = FLOW_CHECKED_MOD(((mulmod_i64_i64_i64(y, y, n) + c)), (n));
            y = FLOW_CHECKED_MOD(((mulmod_i64_i64_i64(y, y, n) + c)), (n));
            int64_t diff = (x - y);
            if (diff < 0) {
                diff = (-diff);
            }
            d = gcd_u64_i64_i64(diff, n);
        }
        if (d != n) {
            return d;
        }
    }
    return 0;
}

int64_t factorize_i64_ptr_i64_ptr_i64(int64_t n0, int64_t* fp, int64_t* ep) {
    int64_t outn = 0;
    int64_t n = n0;
    if (n <= 1) {
        return 0;
    }
    int64_t p = 2;
    while (((p * p) <= n && p <= 10000)) {
        if (FLOW_CHECKED_MOD((n), (p)) == 0) {
            int64_t e = 0;
            while (FLOW_CHECKED_MOD((n), (p)) == 0) {
                n = FLOW_CHECKED_DIV((n), (p));
                e = (e + 1);
            }
            fp[outn] = p;
            ep[outn] = e;
            outn = (outn + 1);
        }
        p = (p + 1);
    }
    if (n == 1) {
        return outn;
    }
    if (is_prime_64_i64(n) != 0) {
        fp[outn] = n;
        ep[outn] = 1;
        outn = (outn + 1);
        return outn;
    }
    int64_t* stack = (int64_t*)(((int64_t*)(calloc(64, 8))));
    int64_t sp = 0;
    stack[sp] = n;
    sp = (sp + 1);
    while (sp > 0) {
        sp = (sp - 1);
        int64_t m = stack[sp];
        if (m == 1) {
        } else {
            if (is_prime_64_i64(m) != 0) {
                int32_t found = 0;
                int64_t i = 0;
                while (i < outn) {
                    if (fp[i] == m) {
                        ep[i] = (ep[i] + 1);
                        found = 1;
                        i = outn;
                    }
                    i = (i + 1);
                }
                if (found == 0) {
                    fp[outn] = m;
                    ep[outn] = 1;
                    outn = (outn + 1);
                }
            } else {
                int64_t d = pollard_rho_i64(m);
                stack[sp] = d;
                sp = (sp + 1);
                stack[sp] = FLOW_CHECKED_DIV((m), (d));
                sp = (sp + 1);
            }
        }
    }
    free(stack);
    return outn;
}

int64_t powmod_small_i64_i64_i64(int64_t a0, int64_t e0, int64_t m) {
    int64_t r = FLOW_CHECKED_MOD((1), (m));
    int64_t a = FLOW_CHECKED_MOD((a0), (m));
    if (a < 0) {
        a = (a + m);
    }
    int64_t e = e0;
    while (e > 0) {
        if (FLOW_CHECKED_MOD((e), (2)) == 1) {
            r = FLOW_CHECKED_MOD(((r * a)), (m));
        }
        a = FLOW_CHECKED_MOD(((a * a)), (m));
        e = FLOW_CHECKED_DIV((e), (2));
    }
    return r;
}

int64_t g_prime_power_mod_i64_i64_i64(int64_t q, int64_t e, int64_t modv) {
    int64_t qm = FLOW_CHECKED_MOD((q), (modv));
    int64_t s = 0;
    int64_t t = 1;
    while (t <= e) {
        int64_t expv = (((3 * e) - t) - 2);
        int64_t term = powmod_small_i64_i64_i64(qm, expv, modv);
        s = FLOW_CHECKED_MOD(((s + (FLOW_CHECKED_MOD(((t * t)), (modv)) * term))), (modv));
        t = (t + 1);
    }
    int64_t qm1 = FLOW_CHECKED_MOD(((q - 1)), (modv));
    int64_t term1 = FLOW_CHECKED_MOD(((powmod_small_i64_i64_i64(qm1, 3, modv) * s)), (modv));
    int64_t inner = FLOW_CHECKED_MOD((((e * (q - 1)) + q)), (modv));
    int64_t term2 = FLOW_CHECKED_MOD(((powmod_small_i64_i64_i64(qm, ((2 * e) - 2), modv) * powmod_small_i64_i64_i64(inner, 2, modv))), (modv));
    return FLOW_CHECKED_MOD(((term1 + term2)), (modv));
}

int64_t g_from_factorization_ptr_i64_ptr_i64_i64_i64(int64_t* fp, int64_t* ep, int64_t nf, int64_t modv) {
    int64_t g = FLOW_CHECKED_MOD((1), (modv));
    int64_t i = 0;
    while (i < nf) {
        g = FLOW_CHECKED_MOD(((g * g_prime_power_mod_i64_i64_i64(fp[i], ep[i], modv))), (modv));
        i = (i + 1);
    }
    return g;
}

int64_t f_of_prime_i64_i64(int64_t p, int64_t modv) {
    int64_t m = (p - 1);
    int64_t* fp = (int64_t*)(((int64_t*)(calloc(64, 8))));
    int64_t* ep = (int64_t*)(((int64_t*)(calloc(64, 8))));
    int64_t nf = factorize_i64_ptr_i64_ptr_i64(m, fp, ep);
    int64_t g = g_from_factorization_ptr_i64_ptr_i64_i64_i64(fp, ep, nf, modv);
    free(fp);
    free(ep);
    int64_t mm = FLOW_CHECKED_MOD((m), (modv));
    return FLOW_CHECKED_MOD((((mm * mm) + g)), (modv));
}

int32_t main(void) {
    int64_t modv = MOD;
    int64_t lo = 10000000000000000;
    int64_t hi = (lo + 1000000);
    int64_t length = ((hi - lo) + 1);
    int8_t* is_comp = (int8_t*)(((int8_t*)(calloc(length, 1))));
    int64_t limit = 200000;
    int8_t* sieve = (int8_t*)(((int8_t*)(calloc((limit + 1), 1))));
    int64_t* primes = (int64_t*)(((int64_t*)(calloc(20000, 8))));
    int64_t pc = 0;
    int64_t pp = 2;
    while (pp <= limit) {
        if (sieve[pp] == 0) {
            primes[pc] = pp;
            pc = (pc + 1);
            int64_t j = (pp * pp);
            while (j <= limit) {
                sieve[j] = 1;
                j = (j + pp);
            }
        }
        pp = (pp + 1);
    }
    free(sieve);
    int64_t i = 0;
    while (i < pc) {
        int64_t q = primes[i];
        int64_t offset = FLOW_CHECKED_MOD(((q - FLOW_CHECKED_MOD((lo), (q)))), (q));
        int64_t j = offset;
        while (j < length) {
            is_comp[j] = 1;
            j = (j + q);
        }
        if ((lo <= q && q <= hi)) {
            is_comp[(q - lo)] = 0;
        }
        i = (i + 1);
    }
    free(primes);
    int64_t total = 0;
    int64_t j = 0;
    while (j < length) {
        if (is_comp[j] == 0) {
            int64_t n = (lo + j);
            if (is_prime_64_i64(n) != 0) {
                total = FLOW_CHECKED_MOD(((total + f_of_prime_i64_i64(n, modv))), (modv));
            }
        }
        j = (j + 1);
    }
    free(is_comp);
    printf("%lld\n", total);
    return 0;
}

Generated MLIR

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