Problem 876

Pure Flow port. Sum_{k=1}^{18} F(6^k, 10^k).

Answer457019806569269
Output457019806569269
StatusPASS
Native helperno
Runtime110 ms
Peak memory8960 KB
Time complexityO(n^2) (estimated)
Space complexityO(1) (estimated)

Performance comparison

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

Flow source

# Project Euler 876: Triplet Tricks.
# Pure Flow port. Sum_{k=1}^{18} F(6^k, 10^k).

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

function euclid_subtraction_steps(m_in: i64, n_in: i64) -> i64 {
    let mut m: i64 = m_in
    let mut n: i64 = n_in
    let mut steps: i64 = 0
    while n != 0 {
        let q: i64 = m / n
        steps = steps + q
        let t: i64 = m - q * n
        m = n
        n = t
    }
    return steps
}

# Heapsort parallel arrays cs[i128] and ss[i64] by cs ascending.
function heapsort_entries(cs: ptr<i128>, ss: ptr<i64>, cnt: i64) -> void {
    let n: i64 = cnt
    # build max-heap
    let mut start: i64 = n / 2 - 1
    while start >= 0 {
        let mut root: i64 = start
        while 2 * root + 1 < n {
            let child: i64 = 2 * root + 1
            let mut swap_idx: i64 = root
            if cs[swap_idx] < cs[child] {
                swap_idx = child
            }
            if child + 1 < n && cs[swap_idx] < cs[child + 1] {
                swap_idx = child + 1
            }
            if swap_idx == root {
                break
            }
            let tc: i128 = cs[root]
            cs[root] = cs[swap_idx]
            cs[swap_idx] = tc
            let ts: i64 = ss[root]
            ss[root] = ss[swap_idx]
            ss[swap_idx] = ts
            root = swap_idx
        }
        start = start - 1
    }
    # extract
    let mut end: i64 = n - 1
    while end > 0 {
        let tc: i128 = cs[0]
        cs[0] = cs[end]
        cs[end] = tc
        let ts: i64 = ss[0]
        ss[0] = ss[end]
        ss[end] = ts
        let mut root: i64 = 0
        while 2 * root + 1 < end {
            let child: i64 = 2 * root + 1
            let mut swap_idx: i64 = root
            if cs[swap_idx] < cs[child] {
                swap_idx = child
            }
            if child + 1 < end && cs[swap_idx] < cs[child + 1] {
                swap_idx = child + 1
            }
            if swap_idx == root {
                break
            }
            let tc2: i128 = cs[root]
            cs[root] = cs[swap_idx]
            cs[swap_idx] = tc2
            let ts2: i64 = ss[root]
            ss[root] = ss[swap_idx]
            ss[swap_idx] = ts2
            root = swap_idx
        }
        end = end - 1
    }
}

function compute_F_for_powers(k: i64) -> i64 {
    let mut a: i64 = 1
    let mut b: i64 = 1
    let mut i: i64 = 0
    while i < k {
        a = a * 6
        b = b * 10
        i = i + 1
    }

    let p2: ptr<i64> = malloc(32 * 8)
    let p3: ptr<i64> = malloc(32 * 8)
    let p5: ptr<i64> = malloc(32 * 8)
    p2[0] = 1
    p3[0] = 1
    p5[0] = 1
    i = 0
    while i < k {
        p2[i + 1] = p2[i] * 2
        p3[i + 1] = p3[i] * 3
        p5[i + 1] = p5[i] * 5
        i = i + 1
    }

    let na: i64 = (k + 1) * (k + 1)
    let div_a: ptr<i64> = malloc(400 * 8)
    let ua: ptr<i64> = malloc(400 * 8)
    let mut ia: i64 = 0
    i = 0
    while i <= k {
        let mut j: i64 = 0
        while j <= k {
            div_a[ia] = p2[i] * p3[j]
            ua[ia] = a / div_a[ia]
            ia = ia + 1
            j = j + 1
        }
        i = i + 1
    }

    let nb: i64 = (k + 1) * (k + 1)
    let div_b: ptr<i64> = malloc(400 * 8)
    let vb: ptr<i64> = malloc(400 * 8)
    let mut ib: i64 = 0
    i = 0
    while i <= k {
        let mut j: i64 = 0
        while j <= k {
            div_b[ib] = p2[i] * p5[j]
            vb[ib] = b / div_b[ib]
            ib = ib + 1
            j = j + 1
        }
        i = i + 1
    }

    let max_entries: i64 = na * nb * 2
    let cs: ptr<i128> = malloc(max_entries * 16)
    let ss: ptr<i64> = malloc(max_entries * 8)
    let mut cnt: i64 = 0

    i = 0
    while i < na {
        let x: i64 = div_a[i]
        let u: i64 = ua[i]
        let mut j: i64 = 0
        while j < nb {
            let y: i64 = div_b[j]
            let v: i64 = vb[j]
            let s: i64 = euclid_subtraction_steps(x, y)

            let c1: i128 = ((x + y) as i128) * ((u + v) as i128)
            cs[cnt] = c1
            ss[cnt] = s
            cnt = cnt + 1

            let c2: i128 = ((x - y) as i128) * ((u - v) as i128)
            if c2 > 0 {
                let s2: i64 = s - 1
                if s2 > 0 {
                    cs[cnt] = c2
                    ss[cnt] = s2
                    cnt = cnt + 1
                }
            }
            j = j + 1
        }
        i = i + 1
    }

    heapsort_entries(cs, ss, cnt)

    let mut sum: i64 = 0
    let mut prev_c: i128 = 0
    let mut best_s: i64 = 0
    let mut have: bool = false
    i = 0
    while i < cnt {
        if have && cs[i] == prev_c {
            if ss[i] < best_s {
                best_s = ss[i]
            }
        } else {
            if have {
                sum = sum + best_s
            }
            prev_c = cs[i]
            best_s = ss[i]
            have = true
        }
        i = i + 1
    }
    if have {
        sum = sum + best_s
    }

    free(p2)
    free(p3)
    free(p5)
    free(div_a)
    free(ua)
    free(div_b)
    free(vb)
    free(cs)
    free(ss)
    return sum
}

function main() -> i32 {
    let mut total: i64 = 0
    let mut k: i64 = 1
    while k <= 18 {
        total = total + compute_F_for_powers(k)
        k = k + 1
    }
    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 euclid_subtraction_steps_i64_i64(int64_t m_in, int64_t n_in);
void heapsort_entries_ptr_i128_ptr_i64_i64(__int128* cs, int64_t* ss, int64_t cnt);
int64_t compute_F_for_powers_i64(int64_t k);
int32_t main(void);



int64_t euclid_subtraction_steps_i64_i64(int64_t m_in, int64_t n_in) {
    int64_t m = m_in;
    int64_t n = n_in;
    int64_t steps = 0;
    while (n != 0) {
        int64_t q = FLOW_CHECKED_DIV((m), (n));
        steps = (steps + q);
        int64_t t = (m - (q * n));
        m = n;
        n = t;
    }
    return steps;
}

void heapsort_entries_ptr_i128_ptr_i64_i64(__int128* cs, int64_t* ss, int64_t cnt) {
    int64_t n = cnt;
    int64_t start = (FLOW_CHECKED_DIV((n), (2)) - 1);
    while (start >= 0) {
        int64_t root = start;
        while (((2 * root) + 1) < n) {
            int64_t child = ((2 * root) + 1);
            int64_t swap_idx = root;
            if (cs[swap_idx] < cs[child]) {
                swap_idx = child;
            }
            if (((child + 1) < n && cs[swap_idx] < cs[(child + 1)])) {
                swap_idx = (child + 1);
            }
            if (swap_idx == root) {
                break;
            }
            __int128 tc = cs[root];
            cs[root] = cs[swap_idx];
            cs[swap_idx] = tc;
            int64_t ts = ss[root];
            ss[root] = ss[swap_idx];
            ss[swap_idx] = ts;
            root = swap_idx;
        }
        start = (start - 1);
    }
    int64_t end = (n - 1);
    while (end > 0) {
        __int128 tc = cs[0];
        cs[0] = cs[end];
        cs[end] = tc;
        int64_t ts = ss[0];
        ss[0] = ss[end];
        ss[end] = ts;
        int64_t root = 0;
        while (((2 * root) + 1) < end) {
            int64_t child = ((2 * root) + 1);
            int64_t swap_idx = root;
            if (cs[swap_idx] < cs[child]) {
                swap_idx = child;
            }
            if (((child + 1) < end && cs[swap_idx] < cs[(child + 1)])) {
                swap_idx = (child + 1);
            }
            if (swap_idx == root) {
                break;
            }
            __int128 tc2 = cs[root];
            cs[root] = cs[swap_idx];
            cs[swap_idx] = tc2;
            int64_t ts2 = ss[root];
            ss[root] = ss[swap_idx];
            ss[swap_idx] = ts2;
            root = swap_idx;
        }
        end = (end - 1);
    }
}

int64_t compute_F_for_powers_i64(int64_t k) {
    int64_t a = 1;
    int64_t b = 1;
    int64_t i = 0;
    while (i < k) {
        a = (a * 6);
        b = (b * 10);
        i = (i + 1);
    }
    int64_t* p2 = (int64_t*)(malloc((32 * 8)));
    int64_t* p3 = (int64_t*)(malloc((32 * 8)));
    int64_t* p5 = (int64_t*)(malloc((32 * 8)));
    p2[0] = 1;
    p3[0] = 1;
    p5[0] = 1;
    i = 0;
    while (i < k) {
        p2[(i + 1)] = (p2[i] * 2);
        p3[(i + 1)] = (p3[i] * 3);
        p5[(i + 1)] = (p5[i] * 5);
        i = (i + 1);
    }
    int64_t na = ((k + 1) * (k + 1));
    int64_t* div_a = (int64_t*)(malloc((400 * 8)));
    int64_t* ua = (int64_t*)(malloc((400 * 8)));
    int64_t ia = 0;
    i = 0;
    while (i <= k) {
        int64_t j = 0;
        while (j <= k) {
            div_a[ia] = (p2[i] * p3[j]);
            ua[ia] = FLOW_CHECKED_DIV((a), (div_a[ia]));
            ia = (ia + 1);
            j = (j + 1);
        }
        i = (i + 1);
    }
    int64_t nb = ((k + 1) * (k + 1));
    int64_t* div_b = (int64_t*)(malloc((400 * 8)));
    int64_t* vb = (int64_t*)(malloc((400 * 8)));
    int64_t ib = 0;
    i = 0;
    while (i <= k) {
        int64_t j = 0;
        while (j <= k) {
            div_b[ib] = (p2[i] * p5[j]);
            vb[ib] = FLOW_CHECKED_DIV((b), (div_b[ib]));
            ib = (ib + 1);
            j = (j + 1);
        }
        i = (i + 1);
    }
    int64_t max_entries = ((na * nb) * 2);
    __int128* cs = (__int128*)(malloc((max_entries * 16)));
    int64_t* ss = (int64_t*)(malloc((max_entries * 8)));
    int64_t cnt = 0;
    i = 0;
    while (i < na) {
        int64_t x = div_a[i];
        int64_t u = ua[i];
        int64_t j = 0;
        while (j < nb) {
            int64_t y = div_b[j];
            int64_t v = vb[j];
            int64_t s = euclid_subtraction_steps_i64_i64(x, y);
            __int128 c1 = (((__int128)((x + y))) * ((__int128)((u + v))));
            cs[cnt] = c1;
            ss[cnt] = s;
            cnt = (cnt + 1);
            __int128 c2 = (((__int128)((x - y))) * ((__int128)((u - v))));
            if (c2 > 0) {
                int64_t s2 = (s - 1);
                if (s2 > 0) {
                    cs[cnt] = c2;
                    ss[cnt] = s2;
                    cnt = (cnt + 1);
                }
            }
            j = (j + 1);
        }
        i = (i + 1);
    }
    heapsort_entries_ptr_i128_ptr_i64_i64(cs, ss, cnt);
    int64_t sum = 0;
    __int128 prev_c = 0;
    int64_t best_s = 0;
    bool have = 0;
    i = 0;
    while (i < cnt) {
        if ((have && cs[i] == prev_c)) {
            if (ss[i] < best_s) {
                best_s = ss[i];
            }
        } else {
            if (have) {
                sum = (sum + best_s);
            }
            prev_c = cs[i];
            best_s = ss[i];
            have = 1;
        }
        i = (i + 1);
    }
    if (have) {
        sum = (sum + best_s);
    }
    free(p2);
    free(p3);
    free(p5);
    free(div_a);
    free(ua);
    free(div_b);
    free(vb);
    free(cs);
    free(ss);
    return sum;
}

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