Problem 958

Euclid's Labour: meet-in-the-middle search on the Stern-Brocot tree.

Answer367554579311
Output367554579311
StatusPASS
Native helperno
Runtime30 ms
Peak memory1088 KB
Time complexityO(2^n) (estimated)
Space complexityO(1) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(2^n)O(log n)
Space complexityO(1)O(log n)
ApproachFlow solutionStern-Brocot or binary representation
VerdictSuboptimal

Flow source

# Project Euler 958
# Euclid's Labour: meet-in-the-middle search on the Stern-Brocot tree.

let mut g_n: i64 = 0
let mut g_steps: i64 = 0
let mut g_split_depth: i64 = 0
let mut g_best_steps: i64 = 0
let mut g_best_value: i64 = 0
let mut g_local_a: i64 = 0
let mut g_local_b: i64 = 0
let mut g_norm: i64 = 0
let mut g_inv_result: i64 = 0

function mod_inverse(value0: i64, modulus: i64) -> i32 {
    let mut value: i64 = ((value0 % modulus) + modulus) % modulus
    let mut old_r: i128 = modulus as i128
    let mut r: i128 = value as i128
    let mut old_s: i128 = 0 as i128
    let mut s: i128 = 1 as i128
    while r != 0 as i128 {
        let q: i128 = old_r / r
        let tmp: i128 = old_r - q * r
        old_r = r
        r = tmp
        let tmp2: i128 = old_s - q * s
        old_s = s
        s = tmp2
    }
    if old_r != 1 as i128 {
        return 0
    }
    let mm: i128 = modulus as i128
    g_inv_result = (((old_s % mm) + mm) % mm) as i64
    return 1
}

function check(candidate_a: i64, candidate_b: i64, current_depth: i64) -> void {
    if candidate_a < 0 || candidate_b < 0 {
        return
    }
    if candidate_a * candidate_a + candidate_b * candidate_b > g_norm {
        return
    }

    let mut x: i64 = candidate_a
    let mut y: i64 = candidate_b
    let mut vx: i64 = g_local_a
    let mut vy: i64 = g_local_b

    if (g_steps & 1) != 0 {
        if (vx & 1) != 0 || (y & 1) != 0 {
            return
        }
        x = x - y / 2
        vy = vy + vx / 2
        if (vy & 1) != 0 || (x & 1) != 0 {
            return
        }
        x = x / 2
        y = y / 2
        vx = vx / 2
        vy = vy / 2
    }

    if x * vx + y * vy != g_n {
        return
    }

    let remaining_steps: i64 = g_steps - g_split_depth
    let mut used_steps: i64 = 0
    while used_steps <= remaining_steps && x != 0 && y != 0 {
        if x > y {
            let t: i64 = x
            x = y
            y = t
            let t2: i64 = vx
            vx = vy
            vy = t2
        }
        y = y - x
        vx = vx + vy
        used_steps = used_steps + 1
    }

    if used_steps > remaining_steps {
        return
    }

    let residue: i64 = (((vx + vy - g_n) % g_n + g_n) % g_n)
    if mod_inverse(residue, g_n) == 0 {
        return
    }
    let inv_residue: i64 = g_inv_result

    let total_steps: i64 = current_depth + used_steps
    let nn: i64 = g_n
    let mut value: i64 = residue
    if nn - residue < value {
        value = nn - residue
    }
    if inv_residue < value {
        value = inv_residue
    }
    if nn - inv_residue < value {
        value = nn - inv_residue
    }

    if total_steps < g_best_steps {
        g_best_steps = total_steps
        g_best_value = value
    } else {
        if total_steps == g_best_steps && value < g_best_value {
            g_best_steps = total_steps
            g_best_value = value
        }
    }
}

function consider(basis_a0: i64, basis_b0: i64, coeff_a0: i64, coeff_b0: i64, current_depth: i64) -> void {
    let mut basis_a: i64 = basis_a0
    let mut basis_b: i64 = basis_b0
    let mut coeff_a: i64 = coeff_a0
    let mut coeff_b: i64 = coeff_b0

    if basis_a > basis_b {
        let t: i64 = basis_a
        basis_a = basis_b
        basis_b = t
        let t2: i64 = coeff_a
        coeff_a = coeff_b
        coeff_b = t2
    }

    if coeff_b < 0 {
        return
    }
    if coeff_a < 0 {
        let shift: i64 = (0 - coeff_a + basis_b - 1) / basis_b
        coeff_a = coeff_a + shift * basis_b
        coeff_b = coeff_b - shift * basis_a
        if coeff_b < 0 {
            return
        }
    }

    if basis_a * coeff_a + basis_b * coeff_b != g_n {
        return
    }

    if current_depth == g_split_depth {
        let mut local_a: i64 = basis_a
        let mut local_b: i64 = basis_b
        let mut local_ca: i64 = coeff_a
        let mut local_cb: i64 = coeff_b

        if (g_steps & 1) != 0 {
            local_a = local_a * 2
            local_b = local_b * 2
            local_ca = local_ca * 2
            local_cb = local_cb * 2
            local_b = local_b - local_a / 2
            local_ca = local_ca + local_cb / 2
            if local_a * local_ca + local_b * local_cb != 4 * g_n {
                return
            }
        }

        let norm: i64 = local_a * local_a + local_b * local_b
        if norm < g_n {
            return
        }

        let cross: i64 = local_ca * local_b - local_cb * local_a
        let shift: i64 = cross / norm
        local_ca = local_ca - shift * local_b
        local_cb = local_cb + shift * local_a

        let cross2: i64 = cross - shift * norm
        if cross2 < 0 {
            local_ca = local_ca + local_b
            local_cb = local_cb - local_a
        }

        g_local_a = local_a
        g_local_b = local_b
        g_norm = norm

        check(local_ca, local_cb, current_depth)
        check(local_ca - local_b, local_cb + local_a, current_depth)
        return
    }

    let mut x: i64 = basis_a
    let mut y: i64 = basis_b
    let mut i: i64 = current_depth
    while i < g_steps / 2 {
        if x > y {
            let t: i64 = x
            x = y
            y = t
        }
        x = x + y
        let t: i64 = x
        x = y
        y = t
        i = i + 1
    }
    if x > y {
        let t: i64 = x
        x = y
        y = t
    }

    if (g_steps & 1) != 0 {
        if 5 * y * y / 4 + x * y + x * x < g_n {
            return
        }
    } else {
        if x * x + y * y < g_n {
            return
        }
    }

    consider(basis_b, basis_a + basis_b, coeff_b - coeff_a, coeff_a, current_depth + 1)
    if basis_a > 0 && basis_a < basis_b {
        consider(basis_a, basis_a + basis_b, coeff_a - coeff_b, coeff_b, current_depth + 1)
    }
}

function f(n: i64) -> i64 {
    g_n = n
    let mut steps: i64 = 0
    while true {
        g_steps = steps
        g_split_depth = (steps + 1) / 2
        g_best_steps = steps
        g_best_value = n + 1

        consider(0, 1, 0, n, 0)

        if g_best_value <= n {
            return g_best_value
        }
        steps = steps + 1
    }
    return 0
}

function main() -> i32 {
    printf("%lld\n", f(1000000000000 + 39))
    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; }

int32_t mod_inverse_i64_i64(int64_t value0, int64_t modulus);
void check_i64_i64_i64(int64_t candidate_a, int64_t candidate_b, int64_t current_depth);
void consider_i64_i64_i64_i64_i64(int64_t basis_a0, int64_t basis_b0, int64_t coeff_a0, int64_t coeff_b0, int64_t current_depth);
int64_t f_i64(int64_t n);
int32_t main(void);

/* Module statics */
static int64_t g_n = 0;
static int64_t g_steps = 0;
static int64_t g_split_depth = 0;
static int64_t g_best_steps = 0;
static int64_t g_best_value = 0;
static int64_t g_local_a = 0;
static int64_t g_local_b = 0;
static int64_t g_norm = 0;
static int64_t g_inv_result = 0;

int32_t mod_inverse_i64_i64(int64_t value0, int64_t modulus) {
    int64_t value = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD((value0), (modulus)) + modulus)), (modulus));
    __int128 old_r = ((__int128)(modulus));
    __int128 r = ((__int128)(value));
    __int128 old_s = ((__int128)(0));
    __int128 s = ((__int128)(1));
    while (r != ((__int128)(0))) {
        __int128 q = FLOW_CHECKED_DIV((old_r), (r));
        __int128 tmp = (old_r - (q * r));
        old_r = r;
        r = tmp;
        __int128 tmp2 = (old_s - (q * s));
        old_s = s;
        s = tmp2;
    }
    if (old_r != ((__int128)(1))) {
        return 0;
    }
    __int128 mm = ((__int128)(modulus));
    g_inv_result = ((int64_t)(FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD((old_s), (mm)) + mm)), (mm))));
    return 1;
}

void check_i64_i64_i64(int64_t candidate_a, int64_t candidate_b, int64_t current_depth) {
    if ((candidate_a < 0 || candidate_b < 0)) {
        return;
    }
    if (((candidate_a * candidate_a) + (candidate_b * candidate_b)) > g_norm) {
        return;
    }
    int64_t x = candidate_a;
    int64_t y = candidate_b;
    int64_t vx = g_local_a;
    int64_t vy = g_local_b;
    if ((g_steps & 1) != 0) {
        if (((vx & 1) != 0 || (y & 1) != 0)) {
            return;
        }
        x = (x - FLOW_CHECKED_DIV((y), (2)));
        vy = (vy + FLOW_CHECKED_DIV((vx), (2)));
        if (((vy & 1) != 0 || (x & 1) != 0)) {
            return;
        }
        x = FLOW_CHECKED_DIV((x), (2));
        y = FLOW_CHECKED_DIV((y), (2));
        vx = FLOW_CHECKED_DIV((vx), (2));
        vy = FLOW_CHECKED_DIV((vy), (2));
    }
    if (((x * vx) + (y * vy)) != g_n) {
        return;
    }
    int64_t remaining_steps = (g_steps - g_split_depth);
    int64_t used_steps = 0;
    while (((used_steps <= remaining_steps && x != 0) && y != 0)) {
        if (x > y) {
            int64_t t = x;
            x = y;
            y = t;
            int64_t t2 = vx;
            vx = vy;
            vy = t2;
        }
        y = (y - x);
        vx = (vx + vy);
        used_steps = (used_steps + 1);
    }
    if (used_steps > remaining_steps) {
        return;
    }
    int64_t residue = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD((((vx + vy) - g_n)), (g_n)) + g_n)), (g_n));
    if (mod_inverse_i64_i64(residue, g_n) == 0) {
        return;
    }
    int64_t inv_residue = g_inv_result;
    int64_t total_steps = (current_depth + used_steps);
    int64_t nn = g_n;
    int64_t value = residue;
    if ((nn - residue) < value) {
        value = (nn - residue);
    }
    if (inv_residue < value) {
        value = inv_residue;
    }
    if ((nn - inv_residue) < value) {
        value = (nn - inv_residue);
    }
    if (total_steps < g_best_steps) {
        g_best_steps = total_steps;
        g_best_value = value;
    } else {
        if ((total_steps == g_best_steps && value < g_best_value)) {
            g_best_steps = total_steps;
            g_best_value = value;
        }
    }
}

void consider_i64_i64_i64_i64_i64(int64_t basis_a0, int64_t basis_b0, int64_t coeff_a0, int64_t coeff_b0, int64_t current_depth) {
    int64_t basis_a = basis_a0;
    int64_t basis_b = basis_b0;
    int64_t coeff_a = coeff_a0;
    int64_t coeff_b = coeff_b0;
    if (basis_a > basis_b) {
        int64_t t = basis_a;
        basis_a = basis_b;
        basis_b = t;
        int64_t t2 = coeff_a;
        coeff_a = coeff_b;
        coeff_b = t2;
    }
    if (coeff_b < 0) {
        return;
    }
    if (coeff_a < 0) {
        int64_t shift = FLOW_CHECKED_DIV(((((0 - coeff_a) + basis_b) - 1)), (basis_b));
        coeff_a = (coeff_a + (shift * basis_b));
        coeff_b = (coeff_b - (shift * basis_a));
        if (coeff_b < 0) {
            return;
        }
    }
    if (((basis_a * coeff_a) + (basis_b * coeff_b)) != g_n) {
        return;
    }
    if (current_depth == g_split_depth) {
        int64_t local_a = basis_a;
        int64_t local_b = basis_b;
        int64_t local_ca = coeff_a;
        int64_t local_cb = coeff_b;
        if ((g_steps & 1) != 0) {
            local_a = (local_a * 2);
            local_b = (local_b * 2);
            local_ca = (local_ca * 2);
            local_cb = (local_cb * 2);
            local_b = (local_b - FLOW_CHECKED_DIV((local_a), (2)));
            local_ca = (local_ca + FLOW_CHECKED_DIV((local_cb), (2)));
            if (((local_a * local_ca) + (local_b * local_cb)) != (4 * g_n)) {
                return;
            }
        }
        int64_t norm = ((local_a * local_a) + (local_b * local_b));
        if (norm < g_n) {
            return;
        }
        int64_t cross = ((local_ca * local_b) - (local_cb * local_a));
        int64_t shift = FLOW_CHECKED_DIV((cross), (norm));
        local_ca = (local_ca - (shift * local_b));
        local_cb = (local_cb + (shift * local_a));
        int64_t cross2 = (cross - (shift * norm));
        if (cross2 < 0) {
            local_ca = (local_ca + local_b);
            local_cb = (local_cb - local_a);
        }
        g_local_a = local_a;
        g_local_b = local_b;
        g_norm = norm;
        check_i64_i64_i64(local_ca, local_cb, current_depth);
        check_i64_i64_i64((local_ca - local_b), (local_cb + local_a), current_depth);
        return;
    }
    int64_t x = basis_a;
    int64_t y = basis_b;
    int64_t i = current_depth;
    while (i < FLOW_CHECKED_DIV((g_steps), (2))) {
        if (x > y) {
            int64_t t = x;
            x = y;
            y = t;
        }
        x = (x + y);
        int64_t t = x;
        x = y;
        y = t;
        i = (i + 1);
    }
    if (x > y) {
        int64_t t = x;
        x = y;
        y = t;
    }
    if ((g_steps & 1) != 0) {
        if (((FLOW_CHECKED_DIV((((5 * y) * y)), (4)) + (x * y)) + (x * x)) < g_n) {
            return;
        }
    } else {
        if (((x * x) + (y * y)) < g_n) {
            return;
        }
    }
    consider_i64_i64_i64_i64_i64(basis_b, (basis_a + basis_b), (coeff_b - coeff_a), coeff_a, (current_depth + 1));
    if ((basis_a > 0 && basis_a < basis_b)) {
        consider_i64_i64_i64_i64_i64(basis_a, (basis_a + basis_b), (coeff_a - coeff_b), coeff_b, (current_depth + 1));
    }
}

int64_t f_i64(int64_t n) {
    g_n = n;
    int64_t steps = 0;
    while (1) {
        g_steps = steps;
        g_split_depth = FLOW_CHECKED_DIV(((steps + 1)), (2));
        g_best_steps = steps;
        g_best_value = (n + 1);
        consider_i64_i64_i64_i64_i64(0, 1, 0, n, 0);
        if (g_best_value <= n) {
            return g_best_value;
        }
        steps = (steps + 1);
    }
    return 0;
}

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