Problem 995

S(p) product over primes < 20000, computed with f64 log10 DP. Ported from the pure f64 log10 C version (no GMP/MPFR needed).

Answer2.21322e536280
Output2.21322e536280
StatusPASS
Native helperno
Runtime1280 ms
Peak memory5568 KB
Time complexityO(n^3) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^3)?
Space complexityO(n^2)?
ApproachFlow solutionNot curated
VerdictUnknown

Flow source

# Project Euler 995
# S(p) product over primes < 20000, computed with f64 log10 DP.
# Ported from the pure f64 log10 C version (no GMP/MPFR needed).

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
    function printf(fmt: ptr<i8>, ...) -> i32
    function log10(x: f64) -> f64
    function pow(x: f64, y: f64) -> f64
    function floor(x: f64) -> f64
}

const LIMIT: i32 = 20000
const PRIME_SEARCH_LIMIT: i32 = 2000000

let mut is_prime_arr: ptr<i8> = 0 as ptr<i8>
let mut primes: ptr<i32> = 0 as ptr<i32>
let mut num_primes: i32 = 0
let mut dlog_table: ptr<i32> = 0 as ptr<i32>
let mut s_log_cache: ptr<f64> = 0 as ptr<f64>

function init_globals() -> void {
    s_log_cache = calloc(LIMIT as i64, 8)
    let mut i: i32 = 0
    while i < LIMIT {
        s_log_cache[i] = -1.0
        i = i + 1
    }
}

function sieve(n: i32) -> void {
    is_prime_arr = calloc((n + 1) as i64, 1)
    let mut i: i32 = 0
    while i <= n {
        is_prime_arr[i] = 1
        i = i + 1
    }
    is_prime_arr[0] = 0
    is_prime_arr[1] = 0
    let mut ii: i32 = 2
    while (ii as i64) * (ii as i64) <= (n as i64) {
        if is_prime_arr[ii] == 1 {
            let mut j: i64 = (ii as i64) * (ii as i64)
            while j <= (n as i64) {
                is_prime_arr[j as i32] = 0
                j = j + (ii as i64)
            }
        }
        ii = ii + 1
    }
    primes = calloc(((n / 8 + 1000) as i64), 4)
    num_primes = 0
    let mut k: i32 = 2
    while k <= n {
        if is_prime_arr[k] == 1 {
            primes[num_primes] = k
            num_primes = num_primes + 1
        }
        k = k + 1
    }
}

function factorize(n: i32, out_p: ptr<i32>, out_e: ptr<i32>) -> i32 {
    let mut count: i32 = 0
    let mut t: i32 = n
    let mut i: i32 = 0
    while i < num_primes {
        let p: i32 = primes[i]
        if (p as i64) * (p as i64) > (t as i64) {
            break
        }
        if t % p == 0 {
            let mut e: i32 = 0
            while t % p == 0 {
                t = t / p
                e = e + 1
            }
            out_p[count] = p
            out_e[count] = e
            count = count + 1
        }
        i = i + 1
    }
    if t > 1 {
        out_p[count] = t
        out_e[count] = 1
        count = count + 1
    }
    return count
}

function divisors_from_factors(fac_p: ptr<i32>, fac_e: ptr<i32>, nf: i32, divs: ptr<i32>) -> i32 {
    let mut ndivs: i32 = 1
    divs[0] = 1
    let mut i: i32 = 0
    while i < nf {
        let p: i32 = fac_p[i]
        let e: i32 = fac_e[i]
        let old_ndivs: i32 = ndivs
        let mut power: i32 = 1
        let mut j: i32 = 0
        while j < e {
            power = power * p
            let mut k: i32 = 0
            while k < old_ndivs {
                divs[ndivs] = divs[k] * power
                ndivs = ndivs + 1
                k = k + 1
            }
            j = j + 1
        }
        i = i + 1
    }
    # Insertion sort
    let mut i2: i32 = 1
    while i2 < ndivs {
        let key: i32 = divs[i2]
        let mut j2: i32 = i2 - 1
        while j2 >= 0 {
            if divs[j2] > key {
                divs[j2 + 1] = divs[j2]
                j2 = j2 - 1
            } else {
                break
            }
        }
        divs[j2 + 1] = key
        i2 = i2 + 1
    }
    return ndivs
}

function gcd_int(a: i32, b: i32) -> i32 {
    let mut x: i32 = a
    let mut y: i32 = b
    while y != 0 {
        let t: i32 = x % y
        x = y
        y = t
    }
    return x
}

function primitive_root(p: i32, fac_p: ptr<i32>, nf: i32) -> i32 {
    if p == 2 {
        return 1
    }
    let m: i32 = p - 1
    let mut g: i32 = 2
    while g < p {
        let mut ok: i32 = 1
        let mut i: i32 = 0
        while i < nf {
            let q: i32 = fac_p[i]
            let mut base: i64 = g as i64
            let mut expv: i64 = (m / q) as i64
            let mut result: i64 = 1
            let modv: i64 = p as i64
            while expv > 0 {
                if (expv & 1) == 1 {
                    result = (result * base) % modv
                }
                base = (base * base) % modv
                expv = expv >> 1
            }
            if result == 1 {
                ok = 0
                break
            }
            i = i + 1
        }
        if ok == 1 {
            return g
        }
        g = g + 1
    }
    return -1
}

function build_dlog_table(p: i32, root: i32) -> void {
    dlog_table = calloc(p as i64, 4)
    let mut i: i32 = 0
    while i < p {
        dlog_table[i] = -1
        i = i + 1
    }
    let mut x: i64 = 1
    let m: i32 = p - 1
    let mut k: i32 = 0
    while k < m {
        dlog_table[x as i32] = k
        x = (x * (root as i64)) % (p as i64)
        k = k + 1
    }
}

function bsearch_divs(divs: ptr<i32>, ndivs: i32, val: i32) -> i32 {
    let mut lo: i32 = 0
    let mut hi: i32 = ndivs - 1
    while lo <= hi {
        let mid: i32 = (lo + hi) / 2
        if divs[mid] == val {
            return mid
        }
        if divs[mid] < val {
            lo = mid + 1
        } else {
            hi = mid - 1
        }
    }
    return -1
}

function S_for_prime_log(p: i32) -> f64 {
    if s_log_cache[p] >= 0.0 {
        return s_log_cache[p]
    }
    if p == 2 {
        s_log_cache[p] = 0.0
        return 0.0
    }
    let m: i32 = p - 1
    let fac_p: ptr<i32> = calloc(32, 4)
    let fac_e: ptr<i32> = calloc(32, 4)
    let nf: i32 = factorize(m, fac_p, fac_e)
    let divs: ptr<i32> = calloc(1024, 4)
    let ndivs: i32 = divisors_from_factors(fac_p, fac_e, nf, divs)
    let root: i32 = primitive_root(p, fac_p, nf)
    build_dlog_table(p, root)
    # For each proper divisor c of m, find least rational prime q with gcd(dlog[q%p], m) == c
    let needed: i32 = ndivs - 1
    let least_prime_for_c: ptr<i32> = calloc(ndivs as i64, 4)
    let mut i: i32 = 0
    while i < ndivs {
        least_prime_for_c[i] = -1
        i = i + 1
    }
    let mut found: i32 = 0
    let mut qi: i32 = 0
    while qi < num_primes {
        if found >= needed {
            break
        }
        let q: i32 = primes[qi]
        if q == p {
            qi = qi + 1
            continue
        }
        let r: i32 = q % p
        let dl: i32 = dlog_table[r]
        let c: i32 = gcd_int(dl, m)
        if c >= m {
            qi = qi + 1
            continue
        }
        let idx: i32 = bsearch_divs(divs, ndivs, c)
        if idx >= 0 {
            if least_prime_for_c[idx] < 0 {
                least_prime_for_c[idx] = q
                found = found + 1
            }
        }
        qi = qi + 1
    }
    # best_q as flat array: best_q_data[Mi * ndivs + di]
    let best_q_data: ptr<i32> = calloc((ndivs as i64) * (ndivs as i64), 4)
    let mut Mi: i32 = 0
    while Mi < ndivs {
        let mut di_init: i32 = 0
        while di_init < ndivs {
            best_q_data[Mi * ndivs + di_init] = -1
            di_init = di_init + 1
        }
        let M: i32 = divs[Mi]
        if M == 1 {
            Mi = Mi + 1
            continue
        }
        let mut ci: i32 = 0
        while ci < ndivs {
            if least_prime_for_c[ci] < 0 {
                ci = ci + 1
                continue
            }
            let c2: i32 = divs[ci]
            let d: i32 = gcd_int(c2, M)
            if d >= M {
                ci = ci + 1
                continue
            }
            let di2: i32 = bsearch_divs(divs, ndivs, d)
            if di2 >= 0 {
                let cur: i32 = best_q_data[Mi * ndivs + di2]
                let lpc: i32 = least_prime_for_c[ci]
                if cur < 0 {
                    best_q_data[Mi * ndivs + di2] = lpc
                } else {
                    if lpc < cur {
                        best_q_data[Mi * ndivs + di2] = lpc
                    }
                }
            }
            ci = ci + 1
        }
        Mi = Mi + 1
    }
    # DP using log10
    let dp_log: ptr<f64> = calloc(ndivs as i64, 8)
    let dp_set: ptr<i32> = calloc(ndivs as i64, 4)
    dp_log[0] = 0.0
    dp_set[0] = 1
    let mut hi: i32 = 0
    while hi < ndivs {
        if dp_set[hi] == 0 {
            hi = hi + 1
            continue
        }
        let h: i32 = divs[hi]
        let M2: i32 = m / h
        if M2 == 1 {
            hi = hi + 1
            continue
        }
        let Mi2: i32 = bsearch_divs(divs, ndivs, M2)
        if Mi2 < 0 {
            hi = hi + 1
            continue
        }
        let mut Li: i32 = 0
        while Li < ndivs {
            let L: i32 = divs[Li]
            if L <= 1 {
                Li = Li + 1
                continue
            }
            if M2 % L != 0 {
                Li = Li + 1
                continue
            }
            let next_h: i32 = h * L
            let nhi: i32 = bsearch_divs(divs, ndivs, next_h)
            if nhi < 0 {
                Li = Li + 1
                continue
            }
            let d3: i32 = M2 / L
            let di3: i32 = bsearch_divs(divs, ndivs, d3)
            if di3 < 0 {
                Li = Li + 1
                continue
            }
            let q2: i32 = best_q_data[Mi2 * ndivs + di3]
            if q2 < 0 {
                Li = Li + 1
                continue
            }
            let candidate_log: f64 = dp_log[hi] + ((L - 1) as f64) * log10(q2 as f64)
            if dp_set[nhi] == 0 {
                dp_log[nhi] = candidate_log
                dp_set[nhi] = 1
            } else {
                if candidate_log < dp_log[nhi] {
                    dp_log[nhi] = candidate_log
                }
            }
            Li = Li + 1
        }
        hi = hi + 1
    }
    let mi: i32 = ndivs - 1
    s_log_cache[p] = dp_log[mi]
    free(best_q_data as ptr<void>)
    free(dp_log as ptr<void>)
    free(dp_set as ptr<void>)
    free(least_prime_for_c as ptr<void>)
    free(dlog_table as ptr<void>)
    free(divs as ptr<void>)
    free(fac_p as ptr<void>)
    free(fac_e as ptr<void>)
    return s_log_cache[p]
}

function main() -> i32 {
    init_globals()
    sieve(PRIME_SEARCH_LIMIT)
    let mut total_log: f64 = 0.0
    let mut i: i32 = 0
    while i < num_primes {
        let p: i32 = primes[i]
        if p >= LIMIT {
            break
        }
        total_log = total_log + S_for_prime_log(p)
        i = i + 1
    }
    let exponent: i32 = floor(total_log) as i32
    let mantissa_log: f64 = total_log - (exponent as f64)
    let mantissa: f64 = pow(10.0, mantissa_log)
    printf("%.5fe%d\n", mantissa, exponent)
    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; }

void init_globals(void);
void sieve_i32(int32_t n);
int32_t factorize_i32_ptr_i32_ptr_i32(int32_t n, int32_t* out_p, int32_t* out_e);
int32_t divisors_from_factors_ptr_i32_ptr_i32_i32_ptr_i32(int32_t* fac_p, int32_t* fac_e, int32_t nf, int32_t* divs);
int32_t gcd_int_i32_i32(int32_t a, int32_t b);
int32_t primitive_root_i32_ptr_i32_i32(int32_t p, int32_t* fac_p, int32_t nf);
void build_dlog_table_i32_i32(int32_t p, int32_t root);
int32_t bsearch_divs_ptr_i32_i32_i32(int32_t* divs, int32_t ndivs, int32_t val);
double S_for_prime_log_i32(int32_t p);
int32_t main(void);

static const int32_t LIMIT = 20000;
static const int32_t PRIME_SEARCH_LIMIT = 2000000;

/* Module statics */
static int8_t* is_prime_arr = ((int8_t*)(0));
static int32_t* primes = ((int32_t*)(0));
static int32_t num_primes = 0;
static int32_t* dlog_table = ((int32_t*)(0));
static double* s_log_cache = ((double*)(0));







void init_globals(void) {
    s_log_cache = calloc(((int64_t)(LIMIT)), 8);
    int32_t i = 0;
    while (i < LIMIT) {
        s_log_cache[i] = (-1.0);
        i = (i + 1);
    }
}

void sieve_i32(int32_t n) {
    is_prime_arr = calloc(((int64_t)((n + 1))), 1);
    int32_t i = 0;
    while (i <= n) {
        is_prime_arr[i] = 1;
        i = (i + 1);
    }
    is_prime_arr[0] = 0;
    is_prime_arr[1] = 0;
    int32_t ii = 2;
    while ((((int64_t)(ii)) * ((int64_t)(ii))) <= ((int64_t)(n))) {
        if (is_prime_arr[ii] == 1) {
            int64_t j = (((int64_t)(ii)) * ((int64_t)(ii)));
            while (j <= ((int64_t)(n))) {
                is_prime_arr[((int32_t)(j))] = 0;
                j = (j + ((int64_t)(ii)));
            }
        }
        ii = (ii + 1);
    }
    primes = calloc(((int64_t)((FLOW_CHECKED_DIV((n), (8)) + 1000))), 4);
    num_primes = 0;
    int32_t k = 2;
    while (k <= n) {
        if (is_prime_arr[k] == 1) {
            primes[num_primes] = k;
            num_primes = (num_primes + 1);
        }
        k = (k + 1);
    }
}

int32_t factorize_i32_ptr_i32_ptr_i32(int32_t n, int32_t* out_p, int32_t* out_e) {
    int32_t count = 0;
    int32_t t = n;
    int32_t i = 0;
    while (i < num_primes) {
        int32_t p = primes[i];
        if ((((int64_t)(p)) * ((int64_t)(p))) > ((int64_t)(t))) {
            break;
        }
        if (FLOW_CHECKED_MOD((t), (p)) == 0) {
            int32_t e = 0;
            while (FLOW_CHECKED_MOD((t), (p)) == 0) {
                t = FLOW_CHECKED_DIV((t), (p));
                e = (e + 1);
            }
            out_p[count] = p;
            out_e[count] = e;
            count = (count + 1);
        }
        i = (i + 1);
    }
    if (t > 1) {
        out_p[count] = t;
        out_e[count] = 1;
        count = (count + 1);
    }
    return count;
}

int32_t divisors_from_factors_ptr_i32_ptr_i32_i32_ptr_i32(int32_t* fac_p, int32_t* fac_e, int32_t nf, int32_t* divs) {
    int32_t ndivs = 1;
    divs[0] = 1;
    int32_t i = 0;
    while (i < nf) {
        int32_t p = fac_p[i];
        int32_t e = fac_e[i];
        int32_t old_ndivs = ndivs;
        int32_t power = 1;
        int32_t j = 0;
        while (j < e) {
            power = (power * p);
            int32_t k = 0;
            while (k < old_ndivs) {
                divs[ndivs] = (divs[k] * power);
                ndivs = (ndivs + 1);
                k = (k + 1);
            }
            j = (j + 1);
        }
        i = (i + 1);
    }
    int32_t i2 = 1;
    while (i2 < ndivs) {
        int32_t key = divs[i2];
        int32_t j2 = (i2 - 1);
        while (j2 >= 0) {
            if (divs[j2] > key) {
                divs[(j2 + 1)] = divs[j2];
                j2 = (j2 - 1);
            } else {
                break;
            }
        }
        divs[(j2 + 1)] = key;
        i2 = (i2 + 1);
    }
    return ndivs;
}

int32_t gcd_int_i32_i32(int32_t a, int32_t b) {
    int32_t x = a;
    int32_t y = b;
    while (y != 0) {
        int32_t t = FLOW_CHECKED_MOD((x), (y));
        x = y;
        y = t;
    }
    return x;
}

int32_t primitive_root_i32_ptr_i32_i32(int32_t p, int32_t* fac_p, int32_t nf) {
    if (p == 2) {
        return 1;
    }
    int32_t m = (p - 1);
    int32_t g = 2;
    while (g < p) {
        int32_t ok = 1;
        int32_t i = 0;
        while (i < nf) {
            int32_t q = fac_p[i];
            int64_t base = ((int64_t)(g));
            int64_t expv = ((int64_t)(FLOW_CHECKED_DIV((m), (q))));
            int64_t result = 1;
            int64_t modv = ((int64_t)(p));
            while (expv > 0) {
                if ((expv & 1) == 1) {
                    result = FLOW_CHECKED_MOD(((result * base)), (modv));
                }
                base = FLOW_CHECKED_MOD(((base * base)), (modv));
                expv = FLOW_CHECKED_SHR((expv), (1));
            }
            if (result == 1) {
                ok = 0;
                break;
            }
            i = (i + 1);
        }
        if (ok == 1) {
            return g;
        }
        g = (g + 1);
    }
    return (-1);
}

void build_dlog_table_i32_i32(int32_t p, int32_t root) {
    dlog_table = calloc(((int64_t)(p)), 4);
    int32_t i = 0;
    while (i < p) {
        dlog_table[i] = (-1);
        i = (i + 1);
    }
    int64_t x = 1;
    int32_t m = (p - 1);
    int32_t k = 0;
    while (k < m) {
        dlog_table[((int32_t)(x))] = k;
        x = FLOW_CHECKED_MOD(((x * ((int64_t)(root)))), (((int64_t)(p))));
        k = (k + 1);
    }
}

int32_t bsearch_divs_ptr_i32_i32_i32(int32_t* divs, int32_t ndivs, int32_t val) {
    int32_t lo = 0;
    int32_t hi = (ndivs - 1);
    while (lo <= hi) {
        int32_t mid = FLOW_CHECKED_DIV(((lo + hi)), (2));
        if (divs[mid] == val) {
            return mid;
        }
        if (divs[mid] < val) {
            lo = (mid + 1);
        } else {
            hi = (mid - 1);
        }
    }
    return (-1);
}

double S_for_prime_log_i32(int32_t p) {
    if (s_log_cache[p] >= 0.0) {
        return s_log_cache[p];
    }
    if (p == 2) {
        s_log_cache[p] = 0.0;
        return 0.0;
    }
    int32_t m = (p - 1);
    int32_t* fac_p = (int32_t*)(calloc(32, 4));
    int32_t* fac_e = (int32_t*)(calloc(32, 4));
    int32_t nf = factorize_i32_ptr_i32_ptr_i32(m, fac_p, fac_e);
    int32_t* divs = (int32_t*)(calloc(1024, 4));
    int32_t ndivs = divisors_from_factors_ptr_i32_ptr_i32_i32_ptr_i32(fac_p, fac_e, nf, divs);
    int32_t root = primitive_root_i32_ptr_i32_i32(p, fac_p, nf);
    build_dlog_table_i32_i32(p, root);
    int32_t needed = (ndivs - 1);
    int32_t* least_prime_for_c = (int32_t*)(calloc(((int64_t)(ndivs)), 4));
    int32_t i = 0;
    while (i < ndivs) {
        least_prime_for_c[i] = (-1);
        i = (i + 1);
    }
    int32_t found = 0;
    int32_t qi = 0;
    while (qi < num_primes) {
        if (found >= needed) {
            break;
        }
        int32_t q = primes[qi];
        if (q == p) {
            qi = (qi + 1);
            continue;
        }
        int32_t r = FLOW_CHECKED_MOD((q), (p));
        int32_t dl = dlog_table[r];
        int32_t c = gcd_int_i32_i32(dl, m);
        if (c >= m) {
            qi = (qi + 1);
            continue;
        }
        int32_t idx = bsearch_divs_ptr_i32_i32_i32(divs, ndivs, c);
        if (idx >= 0) {
            if (least_prime_for_c[idx] < 0) {
                least_prime_for_c[idx] = q;
                found = (found + 1);
            }
        }
        qi = (qi + 1);
    }
    int32_t* best_q_data = (int32_t*)(calloc((((int64_t)(ndivs)) * ((int64_t)(ndivs))), 4));
    int32_t Mi = 0;
    while (Mi < ndivs) {
        int32_t di_init = 0;
        while (di_init < ndivs) {
            best_q_data[((Mi * ndivs) + di_init)] = (-1);
            di_init = (di_init + 1);
        }
        int32_t M = divs[Mi];
        if (M == 1) {
            Mi = (Mi + 1);
            continue;
        }
        int32_t ci = 0;
        while (ci < ndivs) {
            if (least_prime_for_c[ci] < 0) {
                ci = (ci + 1);
                continue;
            }
            int32_t c2 = divs[ci];
            int32_t d = gcd_int_i32_i32(c2, M);
            if (d >= M) {
                ci = (ci + 1);
                continue;
            }
            int32_t di2 = bsearch_divs_ptr_i32_i32_i32(divs, ndivs, d);
            if (di2 >= 0) {
                int32_t cur = best_q_data[((Mi * ndivs) + di2)];
                int32_t lpc = least_prime_for_c[ci];
                if (cur < 0) {
                    best_q_data[((Mi * ndivs) + di2)] = lpc;
                } else {
                    if (lpc < cur) {
                        best_q_data[((Mi * ndivs) + di2)] = lpc;
                    }
                }
            }
            ci = (ci + 1);
        }
        Mi = (Mi + 1);
    }
    double* dp_log = (double*)(calloc(((int64_t)(ndivs)), 8));
    int32_t* dp_set = (int32_t*)(calloc(((int64_t)(ndivs)), 4));
    dp_log[0] = 0.0;
    dp_set[0] = 1;
    int32_t hi = 0;
    while (hi < ndivs) {
        if (dp_set[hi] == 0) {
            hi = (hi + 1);
            continue;
        }
        int32_t h = divs[hi];
        int32_t M2 = FLOW_CHECKED_DIV((m), (h));
        if (M2 == 1) {
            hi = (hi + 1);
            continue;
        }
        int32_t Mi2 = bsearch_divs_ptr_i32_i32_i32(divs, ndivs, M2);
        if (Mi2 < 0) {
            hi = (hi + 1);
            continue;
        }
        int32_t Li = 0;
        while (Li < ndivs) {
            int32_t L = divs[Li];
            if (L <= 1) {
                Li = (Li + 1);
                continue;
            }
            if (FLOW_CHECKED_MOD((M2), (L)) != 0) {
                Li = (Li + 1);
                continue;
            }
            int32_t next_h = (h * L);
            int32_t nhi = bsearch_divs_ptr_i32_i32_i32(divs, ndivs, next_h);
            if (nhi < 0) {
                Li = (Li + 1);
                continue;
            }
            int32_t d3 = FLOW_CHECKED_DIV((M2), (L));
            int32_t di3 = bsearch_divs_ptr_i32_i32_i32(divs, ndivs, d3);
            if (di3 < 0) {
                Li = (Li + 1);
                continue;
            }
            int32_t q2 = best_q_data[((Mi2 * ndivs) + di3)];
            if (q2 < 0) {
                Li = (Li + 1);
                continue;
            }
            double candidate_log = (dp_log[hi] + (((double)((L - 1))) * log10(((double)(q2)))));
            if (dp_set[nhi] == 0) {
                dp_log[nhi] = candidate_log;
                dp_set[nhi] = 1;
            } else {
                if (candidate_log < dp_log[nhi]) {
                    dp_log[nhi] = candidate_log;
                }
            }
            Li = (Li + 1);
        }
        hi = (hi + 1);
    }
    int32_t mi = (ndivs - 1);
    s_log_cache[p] = dp_log[mi];
    free(((void*)(best_q_data)));
    free(((void*)(dp_log)));
    free(((void*)(dp_set)));
    free(((void*)(least_prime_for_c)));
    free(((void*)(dlog_table)));
    free(((void*)(divs)));
    free(((void*)(fac_p)));
    free(((void*)(fac_e)));
    return s_log_cache[p];
}

int32_t main(void) {
    init_globals();
    sieve_i32(PRIME_SEARCH_LIMIT);
    double total_log = 0.0;
    int32_t i = 0;
    while (i < num_primes) {
        int32_t p = primes[i];
        if (p >= LIMIT) {
            break;
        }
        total_log = (total_log + S_for_prime_log_i32(p));
        i = (i + 1);
    }
    int32_t exponent = ((int32_t)(floor(total_log)));
    double mantissa_log = (total_log - ((double)(exponent)));
    double mantissa = pow(10.0, mantissa_log);
    printf("%.5fe%d\n", mantissa, exponent);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%.5fe%d\n\00") {addr_space = 0 : i32} : !llvm.array<9 x i8>
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()

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