Problem 324
f(10^10000) mod 100000007 via Berlekamp-Massey + Kitamasa on a(m)=f(2m).
View problem on Project Euler
Performance comparison
| Metric | Our solution | Best known |
| Time complexity | O(n^2) | ? |
| Space complexity | O(n^2) | ? |
| Approach | Flow solution | Not curated |
| Verdict | Unknown |
Flow source
# Project Euler 324
# f(10^10000) mod 100000007 via Berlekamp-Massey + Kitamasa on a(m)=f(2m).
extern {
function calloc(n: i64, size: i64) -> ptr<void>
function free(p: ptr<void>) -> void
}
function mul_poly(p: ptr<i64>, q: ptr<i64>, rec: ptr<i64>, k: i64, mod: i64, out: ptr<i64>) -> i32 {
let tmp: ptr<i64> = calloc(2 * k, 8)
for i in 0..k {
let pi: i64 = p[i]
if pi != 0 {
for j in 0..k {
let qj: i64 = q[j]
if qj != 0 {
tmp[i + j] = (tmp[i + j] + pi * qj) % mod
}
}
}
}
let mut d: i64 = 2 * k - 2
while d >= k {
let val: i64 = tmp[d]
if val != 0 {
for t in 1..k + 1 {
tmp[d - t] = (tmp[d - t] + val * rec[t - 1]) % mod
}
}
d = d - 1
}
for i in 0..k {
out[i] = tmp[i]
}
free(tmp)
return 0
}
function big_halve(digits: ptr<i8>, n: i64) -> i64 {
# divide decimal digit array (MSB at 0) by 2; return old LSB parity
let mut rem: i64 = 0
for i in 0..n {
let cur: i64 = rem * 10 + (digits[i] as i64)
digits[i] = (cur / 2) as i8
rem = cur % 2
}
return rem
}
function big_is_zero(digits: ptr<i8>, n: i64) -> i64 {
let mut i: i64 = 0
while i < n {
if digits[i] != 0 { return 0 }
i = i + 1
}
return 1
}
function main() -> i32 {
let mod: i64 = 100000007
let k: i64 = 19
let rec: ptr<i64> = calloc(k, 8)
let init: ptr<i64> = calloc(k, 8)
# recurrence for a(m)=f(2m)
rec[0] = 675; rec[1] = 99926536; rec[2] = 3221189; rec[3] = 27416735; rec[4] = 25908201
rec[5] = 28897274; rec[6] = 23056067; rec[7] = 28479264; rec[8] = 4524104; rec[9] = 95475903
rec[10] = 71520743; rec[11] = 76943940; rec[12] = 71102733; rec[13] = 74091806; rec[14] = 72583272
rec[15] = 96778818; rec[16] = 73471; rec[17] = 99999332; rec[18] = 1
init[0] = 1; init[1] = 229; init[2] = 117805; init[3] = 64647289; init[4] = 69563725
init[5] = 96149360; init[6] = 40041351; init[7] = 13625499; init[8] = 49444743; init[9] = 7047816
init[10] = 63444149; init[11] = 71774943; init[12] = 18904145; init[13] = 72062; init[14] = 58262981
init[15] = 68125412; init[16] = 64015488; init[17] = 12253197; init[18] = 9101639
# exponent m = 5 * 10^9999 as decimal digits
let nd: i64 = 10000
let digits: ptr<i8> = calloc(nd, 1)
digits[0] = 5
# rest already 0 => 5 followed by 9999 zeros = 5*10^9999
let res: ptr<i64> = calloc(k, 8)
let base: ptr<i64> = calloc(k, 8)
let tmp: ptr<i64> = calloc(k, 8)
res[0] = 1
base[1] = 1
while big_is_zero(digits, nd) == 0 {
# skip leading zeros length shrink optional
let odd: i64 = big_halve(digits, nd)
if odd == 1 {
mul_poly(res, base, rec, k, mod, tmp)
for i in 0..k { res[i] = tmp[i] }
}
if big_is_zero(digits, nd) == 0 {
mul_poly(base, base, rec, k, mod, tmp)
for j in 0..k { base[j] = tmp[j] }
}
}
let mut ans: i64 = 0
for i in 0..k {
ans = (ans + res[i] * init[i]) % mod
}
printf("%lld\n", ans)
free(rec); free(init); free(digits); free(res); free(base); free(tmp)
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 mul_poly_ptr_i64_ptr_i64_ptr_i64_i64_i64_ptr_i64(int64_t* p, int64_t* q, int64_t* rec, int64_t k, int64_t mod, int64_t* out);
int64_t big_halve_ptr_i8_i64(int8_t* digits, int64_t n);
int64_t big_is_zero_ptr_i8_i64(int8_t* digits, int64_t n);
int32_t main(void);
int32_t mul_poly_ptr_i64_ptr_i64_ptr_i64_i64_i64_ptr_i64(int64_t* p, int64_t* q, int64_t* rec, int64_t k, int64_t mod, int64_t* out) {
int64_t* tmp = (int64_t*)(calloc((2 * k), 8));
int32_t __flow_step_1 = 1;
for (int32_t i = 0; (0 <= k) ? i < k : i > k; i += (0 <= k) ? 1 : -1) {
int64_t pi = p[i];
if (pi != 0) {
int32_t __flow_step_2 = 1;
for (int32_t j = 0; (0 <= k) ? j < k : j > k; j += (0 <= k) ? 1 : -1) {
int64_t qj = q[j];
if (qj != 0) {
tmp[(i + j)] = FLOW_CHECKED_MOD(((tmp[(i + j)] + (pi * qj))), (mod));
}
}
}
}
int64_t d = ((2 * k) - 2);
while (d >= k) {
int64_t val = tmp[d];
if (val != 0) {
int32_t __flow_step_3 = 1;
for (int32_t t = 1; (1 <= (k + 1)) ? t < (k + 1) : t > (k + 1); t += (1 <= (k + 1)) ? 1 : -1) {
tmp[(d - t)] = FLOW_CHECKED_MOD(((tmp[(d - t)] + (val * rec[(t - 1)]))), (mod));
}
}
d = (d - 1);
}
int32_t __flow_step_4 = 1;
for (int32_t i = 0; (0 <= k) ? i < k : i > k; i += (0 <= k) ? 1 : -1) {
out[i] = tmp[i];
}
free(tmp);
return 0;
}
int64_t big_halve_ptr_i8_i64(int8_t* digits, int64_t n) {
int64_t rem = 0;
int32_t __flow_step_5 = 1;
for (int32_t i = 0; (0 <= n) ? i < n : i > n; i += (0 <= n) ? 1 : -1) {
int64_t cur = ((rem * 10) + ((int64_t)(digits[i])));
digits[i] = ((int8_t)(FLOW_CHECKED_DIV((cur), (2))));
rem = FLOW_CHECKED_MOD((cur), (2));
}
return rem;
}
int64_t big_is_zero_ptr_i8_i64(int8_t* digits, int64_t n) {
int64_t i = 0;
while (i < n) {
if (digits[i] != 0) {
return 0;
}
i = (i + 1);
}
return 1;
}
int32_t main(void) {
int64_t mod = 100000007;
int64_t k = 19;
int64_t* rec = (int64_t*)(calloc(k, 8));
int64_t* init = (int64_t*)(calloc(k, 8));
rec[0] = 675;
rec[1] = 99926536;
rec[2] = 3221189;
rec[3] = 27416735;
rec[4] = 25908201;
rec[5] = 28897274;
rec[6] = 23056067;
rec[7] = 28479264;
rec[8] = 4524104;
rec[9] = 95475903;
rec[10] = 71520743;
rec[11] = 76943940;
rec[12] = 71102733;
rec[13] = 74091806;
rec[14] = 72583272;
rec[15] = 96778818;
rec[16] = 73471;
rec[17] = 99999332;
rec[18] = 1;
init[0] = 1;
init[1] = 229;
init[2] = 117805;
init[3] = 64647289;
init[4] = 69563725;
init[5] = 96149360;
init[6] = 40041351;
init[7] = 13625499;
init[8] = 49444743;
init[9] = 7047816;
init[10] = 63444149;
init[11] = 71774943;
init[12] = 18904145;
init[13] = 72062;
init[14] = 58262981;
init[15] = 68125412;
init[16] = 64015488;
init[17] = 12253197;
init[18] = 9101639;
int64_t nd = 10000;
int8_t* digits = (int8_t*)(calloc(nd, 1));
digits[0] = 5;
int64_t* res = (int64_t*)(calloc(k, 8));
int64_t* base = (int64_t*)(calloc(k, 8));
int64_t* tmp = (int64_t*)(calloc(k, 8));
res[0] = 1;
base[1] = 1;
while (big_is_zero_ptr_i8_i64(digits, nd) == 0) {
int64_t odd = big_halve_ptr_i8_i64(digits, nd);
if (odd == 1) {
mul_poly_ptr_i64_ptr_i64_ptr_i64_i64_i64_ptr_i64(res, base, rec, k, mod, tmp);
int32_t __flow_step_6 = 1;
for (int32_t i = 0; (0 <= k) ? i < k : i > k; i += (0 <= k) ? 1 : -1) {
res[i] = tmp[i];
}
}
if (big_is_zero_ptr_i8_i64(digits, nd) == 0) {
mul_poly_ptr_i64_ptr_i64_ptr_i64_i64_i64_ptr_i64(base, base, rec, k, mod, tmp);
int32_t __flow_step_7 = 1;
for (int32_t j = 0; (0 <= k) ? j < k : j > k; j += (0 <= k) ? 1 : -1) {
base[j] = tmp[j];
}
}
}
int64_t ans = 0;
int32_t __flow_step_8 = 1;
for (int32_t i = 0; (0 <= k) ? i < k : i > k; i += (0 <= k) ? 1 : -1) {
ans = FLOW_CHECKED_MOD(((ans + (res[i] * init[i]))), (mod));
}
printf("%lld\n", ans);
free(rec);
free(init);
free(digits);
free(res);
free(base);
free(tmp);
return 0;
}
Generated MLIR
module {
llvm.func @printf(!llvm.ptr, ...) -> i32
llvm.mlir.global internal constant @str_0("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
func.func private @calloc(i64, i64) -> !llvm.ptr
func.func private @free(!llvm.ptr) -> ()
func.func @mul_poly(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: i64, %arg4: i64, %arg5: !llvm.ptr) -> i32 {
%1 = arith.constant 2 : i32
%3 = arith.extsi %1 : i32 to i64
%2 = arith.muli %3, %arg3 : i64
%4 = arith.constant 8 : i32
%5 = arith.extsi %4 : i32 to i64
%0 = func.call @calloc(%2, %5) : (i64, i64) -> !llvm.ptr
%6 = arith.constant 0 : i32
%7 = arith.index_cast %6 : i32 to index
%8 = arith.index_cast %arg3 : i32 to index
%10 = arith.constant 1 : index
%11 = arith.constant -1 : index
%12 = arith.cmpi sle, %7, %8 : index
%9 = arith.select %12, %10, %11 : index
cf.br ^bb0(%7 : index)
^bb0(%13: index):
%14 = arith.cmpi slt, %13, %8 : index
%15 = arith.cmpi sgt, %13, %8 : index
%16 = arith.select %12, %14, %15 : i1
cf.cond_br %16, ^bb1(%13 : index), ^bb2(%13 : index)
^bb1(%17: index):
%19 = arith.index_cast %17 : index to i64
%20 = llvm.getelementptr %arg0[%19] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%18 = llvm.load %20 : !llvm.ptr -> i64
%21 = arith.constant 0 : i32
%23 = arith.extsi %21 : i32 to i64
%22 = arith.cmpi ne, %18, %23 : i64
cf.cond_br %22, ^bb3, ^bb4
^bb3:
%24 = arith.constant 0 : i32
%25 = arith.index_cast %24 : i32 to index
%26 = arith.index_cast %arg3 : i32 to index
%28 = arith.constant 1 : index
%29 = arith.constant -1 : index
%30 = arith.cmpi sle, %25, %26 : index
%27 = arith.select %30, %28, %29 : index
cf.br ^bb6(%25 : index)
^bb6(%31: index):
%32 = arith.cmpi slt, %31, %26 : index
%33 = arith.cmpi sgt, %31, %26 : index
%34 = arith.select %30, %32, %33 : i1
cf.cond_br %34, ^bb7(%31 : index), ^bb8(%31 : index)
^bb7(%35: index):
%37 = arith.index_cast %35 : index to i64
%38 = llvm.getelementptr %arg1[%37] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%36 = llvm.load %38 : !llvm.ptr -> i64
%39 = arith.constant 0 : i32
%41 = arith.extsi %39 : i32 to i64
%40 = arith.cmpi ne, %36, %41 : i64
cf.cond_br %40, ^bb9, ^bb10
^bb9:
%43 = arith.addi %17, %35 : index
%44 = arith.index_cast %43 : index to i64
%45 = llvm.getelementptr %0[%44] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%42 = llvm.load %45 : !llvm.ptr -> i64
%46 = arith.muli %18, %36 : i64
%47 = arith.addi %42, %46 : i64
%48 = arith.remsi %47, %arg4 : i64
%49 = arith.addi %17, %35 : index
%50 = arith.index_cast %49 : index to i64
%51 = llvm.getelementptr %0[%50] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %48, %51 : i64, !llvm.ptr
cf.br ^bb11
^bb10:
cf.br ^bb11
^bb11:
%52 = arith.addi %35, %27 : index
cf.br ^bb6(%52 : index)
^bb8(%53: index):
cf.br ^bb5
^bb4:
cf.br ^bb5
^bb5:
%54 = arith.addi %17, %9 : index
cf.br ^bb0(%54 : index)
^bb2(%55: index):
%56 = arith.constant 2 : i32
%58 = arith.extsi %56 : i32 to i64
%57 = arith.muli %58, %arg3 : i64
%59 = arith.constant 2 : i32
%61 = arith.extsi %59 : i32 to i64
%60 = arith.subi %57, %61 : i64
%62 = llvm.mlir.constant(1 : i64) : i64
%63 = llvm.alloca %62 x i64 : (i64) -> !llvm.ptr
llvm.store %60, %63 : i64, !llvm.ptr
cf.br ^bb12
^bb12:
%64 = llvm.load %63 : !llvm.ptr -> i64
%65 = arith.cmpi sge, %64, %arg3 : i64
cf.cond_br %65, ^bb13, ^bb14
^bb13:
%67 = llvm.load %63 : !llvm.ptr -> i64
%68 = llvm.getelementptr %0[%67] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%66 = llvm.load %68 : !llvm.ptr -> i64
%69 = arith.constant 0 : i32
%71 = arith.extsi %69 : i32 to i64
%70 = arith.cmpi ne, %66, %71 : i64
cf.cond_br %70, ^bb15, ^bb16
^bb15:
%72 = arith.constant 1 : i32
%73 = arith.constant 1 : i32
%75 = arith.extsi %73 : i32 to i64
%74 = arith.addi %arg3, %75 : i64
%76 = arith.index_cast %72 : i32 to index
%77 = arith.index_cast %74 : i32 to index
%79 = arith.constant 1 : index
%80 = arith.constant -1 : index
%81 = arith.cmpi sle, %76, %77 : index
%78 = arith.select %81, %79, %80 : index
cf.br ^bb18(%76 : index)
^bb18(%82: index):
%83 = arith.cmpi slt, %82, %77 : index
%84 = arith.cmpi sgt, %82, %77 : index
%85 = arith.select %81, %83, %84 : i1
cf.cond_br %85, ^bb19(%82 : index), ^bb20(%82 : index)
^bb19(%86: index):
%88 = llvm.load %63 : !llvm.ptr -> i64
%90 = arith.trunci %88 : i64 to i32
%91 = arith.index_cast %86 : index to i32
%89 = arith.subi %90, %91 : i32
%92 = arith.extsi %89 : i32 to i64
%93 = llvm.getelementptr %0[%92] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%87 = llvm.load %93 : !llvm.ptr -> i64
%95 = arith.constant 1 : i32
%97 = arith.index_cast %86 : index to i32
%96 = arith.subi %97, %95 : i32
%98 = arith.extsi %96 : i32 to i64
%99 = llvm.getelementptr %arg2[%98] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%94 = llvm.load %99 : !llvm.ptr -> i64
%100 = arith.muli %66, %94 : i64
%101 = arith.addi %87, %100 : i64
%102 = arith.remsi %101, %arg4 : i64
%103 = llvm.load %63 : !llvm.ptr -> i64
%105 = arith.trunci %103 : i64 to i32
%106 = arith.index_cast %86 : index to i32
%104 = arith.subi %105, %106 : i32
%107 = arith.extsi %104 : i32 to i64
%108 = llvm.getelementptr %0[%107] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %102, %108 : i64, !llvm.ptr
%109 = arith.addi %86, %78 : index
cf.br ^bb18(%109 : index)
^bb20(%110: index):
cf.br ^bb17
^bb16:
cf.br ^bb17
^bb17:
%111 = llvm.load %63 : !llvm.ptr -> i64
%112 = arith.constant 1 : i32
%114 = arith.extsi %112 : i32 to i64
%113 = arith.subi %111, %114 : i64
llvm.store %113, %63 : i64, !llvm.ptr
cf.br ^bb12
^bb14:
%115 = arith.constant 0 : i32
%116 = arith.index_cast %115 : i32 to index
%117 = arith.index_cast %arg3 : i32 to index
%119 = arith.constant 1 : index
%120 = arith.constant -1 : index
%121 = arith.cmpi sle, %116, %117 : index
%118 = arith.select %121, %119, %120 : index
cf.br ^bb21(%116 : index)
^bb21(%122: index):
%123 = arith.cmpi slt, %122, %117 : index
%124 = arith.cmpi sgt, %122, %117 : index
%125 = arith.select %121, %123, %124 : i1
cf.cond_br %125, ^bb22(%122 : index), ^bb23(%122 : index)
^bb22(%126: index):
%128 = arith.index_cast %126 : index to i64
%129 = llvm.getelementptr %0[%128] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%127 = llvm.load %129 : !llvm.ptr -> i64
%130 = arith.index_cast %126 : index to i64
%131 = llvm.getelementptr %arg5[%130] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %127, %131 : i64, !llvm.ptr
%132 = arith.addi %126, %118 : index
cf.br ^bb21(%132 : index)
^bb23(%133: index):
func.call @free(%0) : (!llvm.ptr) -> ()
%135 = arith.constant 0 : i32
func.return %135 : i32
}
func.func @big_halve(%arg0: !llvm.ptr, %arg1: i64) -> i64 {
%136 = arith.constant 0 : i32
%137 = arith.extsi %136 : i32 to i64
%138 = llvm.mlir.constant(1 : i64) : i64
%139 = llvm.alloca %138 x i64 : (i64) -> !llvm.ptr
llvm.store %137, %139 : i64, !llvm.ptr
%140 = arith.constant 0 : i32
%141 = arith.index_cast %140 : i32 to index
%142 = arith.index_cast %arg1 : i32 to index
%144 = arith.constant 1 : index
%145 = arith.constant -1 : index
%146 = arith.cmpi sle, %141, %142 : index
%143 = arith.select %146, %144, %145 : index
cf.br ^bb24(%141 : index)
^bb24(%147: index):
%148 = arith.cmpi slt, %147, %142 : index
%149 = arith.cmpi sgt, %147, %142 : index
%150 = arith.select %146, %148, %149 : i1
cf.cond_br %150, ^bb25(%147 : index), ^bb26(%147 : index)
^bb25(%151: index):
%152 = llvm.load %139 : !llvm.ptr -> i64
%153 = arith.constant 10 : i32
%155 = arith.extsi %153 : i32 to i64
%154 = arith.muli %152, %155 : i64
%157 = arith.index_cast %151 : index to i64
%158 = llvm.getelementptr %arg0[%157] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%156 = llvm.load %158 : !llvm.ptr -> i8
%159 = arith.extsi %156 : i8 to i64
%160 = arith.addi %154, %159 : i64
%161 = arith.constant 2 : i32
%163 = arith.extsi %161 : i32 to i64
%162 = arith.divsi %160, %163 : i64
%164 = arith.trunci %162 : i64 to i8
%165 = arith.index_cast %151 : index to i64
%166 = llvm.getelementptr %arg0[%165] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %164, %166 : i8, !llvm.ptr
%167 = arith.constant 2 : i32
%169 = arith.extsi %167 : i32 to i64
%168 = arith.remsi %160, %169 : i64
llvm.store %168, %139 : i64, !llvm.ptr
%170 = arith.addi %151, %143 : index
cf.br ^bb24(%170 : index)
^bb26(%171: index):
%172 = llvm.load %139 : !llvm.ptr -> i64
func.return %172 : i64
}
func.func @big_is_zero(%arg0: !llvm.ptr, %arg1: i64) -> i64 {
%173 = arith.constant 0 : i32
%174 = arith.extsi %173 : i32 to i64
%175 = llvm.mlir.constant(1 : i64) : i64
%176 = llvm.alloca %175 x i64 : (i64) -> !llvm.ptr
llvm.store %174, %176 : i64, !llvm.ptr
cf.br ^bb27
^bb27:
%177 = llvm.load %176 : !llvm.ptr -> i64
%178 = arith.cmpi slt, %177, %arg1 : i64
cf.cond_br %178, ^bb28, ^bb29
^bb28:
%180 = llvm.load %176 : !llvm.ptr -> i64
%181 = llvm.getelementptr %arg0[%180] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%179 = llvm.load %181 : !llvm.ptr -> i8
%182 = arith.constant 0 : i32
%184 = arith.extsi %179 : i8 to i32
%183 = arith.cmpi ne, %184, %182 : i32
cf.cond_br %183, ^bb30, ^bb31
^bb30:
%185 = arith.constant 0 : i32
%186 = arith.extsi %185 : i32 to i64
func.return %186 : i64
^bb31:
cf.br ^bb32
^bb32:
%187 = llvm.load %176 : !llvm.ptr -> i64
%188 = arith.constant 1 : i32
%190 = arith.extsi %188 : i32 to i64
%189 = arith.addi %187, %190 : i64
llvm.store %189, %176 : i64, !llvm.ptr
cf.br ^bb27
^bb29:
%191 = arith.constant 1 : i32
%192 = arith.extsi %191 : i32 to i64
func.return %192 : i64
}
func.func @main() -> i32 {
%193 = arith.constant 100000007 : i32
%194 = arith.extsi %193 : i32 to i64
%195 = arith.constant 19 : i32
%196 = arith.extsi %195 : i32 to i64
%198 = arith.constant 8 : i32
%199 = arith.extsi %198 : i32 to i64
%197 = func.call @calloc(%196, %199) : (i64, i64) -> !llvm.ptr
%201 = arith.constant 8 : i32
%202 = arith.extsi %201 : i32 to i64
%200 = func.call @calloc(%196, %202) : (i64, i64) -> !llvm.ptr
%203 = arith.constant 675 : i32
%204 = arith.constant 0 : i32
%205 = arith.extsi %203 : i32 to i64
%206 = arith.extsi %204 : i32 to i64
%207 = llvm.getelementptr %197[%206] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %205, %207 : i64, !llvm.ptr
%208 = arith.constant 99926536 : i32
%209 = arith.constant 1 : i32
%210 = arith.extsi %208 : i32 to i64
%211 = arith.extsi %209 : i32 to i64
%212 = llvm.getelementptr %197[%211] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %210, %212 : i64, !llvm.ptr
%213 = arith.constant 3221189 : i32
%214 = arith.constant 2 : i32
%215 = arith.extsi %213 : i32 to i64
%216 = arith.extsi %214 : i32 to i64
%217 = llvm.getelementptr %197[%216] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %215, %217 : i64, !llvm.ptr
%218 = arith.constant 27416735 : i32
%219 = arith.constant 3 : i32
%220 = arith.extsi %218 : i32 to i64
%221 = arith.extsi %219 : i32 to i64
%222 = llvm.getelementptr %197[%221] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %220, %222 : i64, !llvm.ptr
%223 = arith.constant 25908201 : i32
%224 = arith.constant 4 : i32
%225 = arith.extsi %223 : i32 to i64
%226 = arith.extsi %224 : i32 to i64
%227 = llvm.getelementptr %197[%226] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %225, %227 : i64, !llvm.ptr
%228 = arith.constant 28897274 : i32
%229 = arith.constant 5 : i32
%230 = arith.extsi %228 : i32 to i64
%231 = arith.extsi %229 : i32 to i64
%232 = llvm.getelementptr %197[%231] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %230, %232 : i64, !llvm.ptr
%233 = arith.constant 23056067 : i32
%234 = arith.constant 6 : i32
%235 = arith.extsi %233 : i32 to i64
%236 = arith.extsi %234 : i32 to i64
%237 = llvm.getelementptr %197[%236] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %235, %237 : i64, !llvm.ptr
%238 = arith.constant 28479264 : i32
%239 = arith.constant 7 : i32
%240 = arith.extsi %238 : i32 to i64
%241 = arith.extsi %239 : i32 to i64
%242 = llvm.getelementptr %197[%241] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %240, %242 : i64, !llvm.ptr
%243 = arith.constant 4524104 : i32
%244 = arith.constant 8 : i32
%245 = arith.extsi %243 : i32 to i64
%246 = arith.extsi %244 : i32 to i64
%247 = llvm.getelementptr %197[%246] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %245, %247 : i64, !llvm.ptr
%248 = arith.constant 95475903 : i32
%249 = arith.constant 9 : i32
%250 = arith.extsi %248 : i32 to i64
%251 = arith.extsi %249 : i32 to i64
%252 = llvm.getelementptr %197[%251] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %250, %252 : i64, !llvm.ptr
%253 = arith.constant 71520743 : i32
%254 = arith.constant 10 : i32
%255 = arith.extsi %253 : i32 to i64
%256 = arith.extsi %254 : i32 to i64
%257 = llvm.getelementptr %197[%256] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %255, %257 : i64, !llvm.ptr
%258 = arith.constant 76943940 : i32
%259 = arith.constant 11 : i32
%260 = arith.extsi %258 : i32 to i64
%261 = arith.extsi %259 : i32 to i64
%262 = llvm.getelementptr %197[%261] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %260, %262 : i64, !llvm.ptr
%263 = arith.constant 71102733 : i32
%264 = arith.constant 12 : i32
%265 = arith.extsi %263 : i32 to i64
%266 = arith.extsi %264 : i32 to i64
%267 = llvm.getelementptr %197[%266] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %265, %267 : i64, !llvm.ptr
%268 = arith.constant 74091806 : i32
%269 = arith.constant 13 : i32
%270 = arith.extsi %268 : i32 to i64
%271 = arith.extsi %269 : i32 to i64
%272 = llvm.getelementptr %197[%271] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %270, %272 : i64, !llvm.ptr
%273 = arith.constant 72583272 : i32
%274 = arith.constant 14 : i32
%275 = arith.extsi %273 : i32 to i64
%276 = arith.extsi %274 : i32 to i64
%277 = llvm.getelementptr %197[%276] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %275, %277 : i64, !llvm.ptr
%278 = arith.constant 96778818 : i32
%279 = arith.constant 15 : i32
%280 = arith.extsi %278 : i32 to i64
%281 = arith.extsi %279 : i32 to i64
%282 = llvm.getelementptr %197[%281] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %280, %282 : i64, !llvm.ptr
%283 = arith.constant 73471 : i32
%284 = arith.constant 16 : i32
%285 = arith.extsi %283 : i32 to i64
%286 = arith.extsi %284 : i32 to i64
%287 = llvm.getelementptr %197[%286] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %285, %287 : i64, !llvm.ptr
%288 = arith.constant 99999332 : i32
%289 = arith.constant 17 : i32
%290 = arith.extsi %288 : i32 to i64
%291 = arith.extsi %289 : i32 to i64
%292 = llvm.getelementptr %197[%291] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %290, %292 : i64, !llvm.ptr
%293 = arith.constant 1 : i32
%294 = arith.constant 18 : i32
%295 = arith.extsi %293 : i32 to i64
%296 = arith.extsi %294 : i32 to i64
%297 = llvm.getelementptr %197[%296] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %295, %297 : i64, !llvm.ptr
%298 = arith.constant 1 : i32
%299 = arith.constant 0 : i32
%300 = arith.extsi %298 : i32 to i64
%301 = arith.extsi %299 : i32 to i64
%302 = llvm.getelementptr %200[%301] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %300, %302 : i64, !llvm.ptr
%303 = arith.constant 229 : i32
%304 = arith.constant 1 : i32
%305 = arith.extsi %303 : i32 to i64
%306 = arith.extsi %304 : i32 to i64
%307 = llvm.getelementptr %200[%306] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %305, %307 : i64, !llvm.ptr
%308 = arith.constant 117805 : i32
%309 = arith.constant 2 : i32
%310 = arith.extsi %308 : i32 to i64
%311 = arith.extsi %309 : i32 to i64
%312 = llvm.getelementptr %200[%311] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %310, %312 : i64, !llvm.ptr
%313 = arith.constant 64647289 : i32
%314 = arith.constant 3 : i32
%315 = arith.extsi %313 : i32 to i64
%316 = arith.extsi %314 : i32 to i64
%317 = llvm.getelementptr %200[%316] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %315, %317 : i64, !llvm.ptr
%318 = arith.constant 69563725 : i32
%319 = arith.constant 4 : i32
%320 = arith.extsi %318 : i32 to i64
%321 = arith.extsi %319 : i32 to i64
%322 = llvm.getelementptr %200[%321] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %320, %322 : i64, !llvm.ptr
%323 = arith.constant 96149360 : i32
%324 = arith.constant 5 : i32
%325 = arith.extsi %323 : i32 to i64
%326 = arith.extsi %324 : i32 to i64
%327 = llvm.getelementptr %200[%326] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %325, %327 : i64, !llvm.ptr
%328 = arith.constant 40041351 : i32
%329 = arith.constant 6 : i32
%330 = arith.extsi %328 : i32 to i64
%331 = arith.extsi %329 : i32 to i64
%332 = llvm.getelementptr %200[%331] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %330, %332 : i64, !llvm.ptr
%333 = arith.constant 13625499 : i32
%334 = arith.constant 7 : i32
%335 = arith.extsi %333 : i32 to i64
%336 = arith.extsi %334 : i32 to i64
%337 = llvm.getelementptr %200[%336] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %335, %337 : i64, !llvm.ptr
%338 = arith.constant 49444743 : i32
%339 = arith.constant 8 : i32
%340 = arith.extsi %338 : i32 to i64
%341 = arith.extsi %339 : i32 to i64
%342 = llvm.getelementptr %200[%341] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %340, %342 : i64, !llvm.ptr
%343 = arith.constant 7047816 : i32
%344 = arith.constant 9 : i32
%345 = arith.extsi %343 : i32 to i64
%346 = arith.extsi %344 : i32 to i64
%347 = llvm.getelementptr %200[%346] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %345, %347 : i64, !llvm.ptr
%348 = arith.constant 63444149 : i32
%349 = arith.constant 10 : i32
%350 = arith.extsi %348 : i32 to i64
%351 = arith.extsi %349 : i32 to i64
%352 = llvm.getelementptr %200[%351] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %350, %352 : i64, !llvm.ptr
%353 = arith.constant 71774943 : i32
%354 = arith.constant 11 : i32
%355 = arith.extsi %353 : i32 to i64
%356 = arith.extsi %354 : i32 to i64
%357 = llvm.getelementptr %200[%356] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %355, %357 : i64, !llvm.ptr
%358 = arith.constant 18904145 : i32
%359 = arith.constant 12 : i32
%360 = arith.extsi %358 : i32 to i64
%361 = arith.extsi %359 : i32 to i64
%362 = llvm.getelementptr %200[%361] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %360, %362 : i64, !llvm.ptr
%363 = arith.constant 72062 : i32
%364 = arith.constant 13 : i32
%365 = arith.extsi %363 : i32 to i64
%366 = arith.extsi %364 : i32 to i64
%367 = llvm.getelementptr %200[%366] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %365, %367 : i64, !llvm.ptr
%368 = arith.constant 58262981 : i32
%369 = arith.constant 14 : i32
%370 = arith.extsi %368 : i32 to i64
%371 = arith.extsi %369 : i32 to i64
%372 = llvm.getelementptr %200[%371] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %370, %372 : i64, !llvm.ptr
%373 = arith.constant 68125412 : i32
%374 = arith.constant 15 : i32
%375 = arith.extsi %373 : i32 to i64
%376 = arith.extsi %374 : i32 to i64
%377 = llvm.getelementptr %200[%376] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %375, %377 : i64, !llvm.ptr
%378 = arith.constant 64015488 : i32
%379 = arith.constant 16 : i32
%380 = arith.extsi %378 : i32 to i64
%381 = arith.extsi %379 : i32 to i64
%382 = llvm.getelementptr %200[%381] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %380, %382 : i64, !llvm.ptr
%383 = arith.constant 12253197 : i32
%384 = arith.constant 17 : i32
%385 = arith.extsi %383 : i32 to i64
%386 = arith.extsi %384 : i32 to i64
%387 = llvm.getelementptr %200[%386] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %385, %387 : i64, !llvm.ptr
%388 = arith.constant 9101639 : i32
%389 = arith.constant 18 : i32
%390 = arith.extsi %388 : i32 to i64
%391 = arith.extsi %389 : i32 to i64
%392 = llvm.getelementptr %200[%391] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %390, %392 : i64, !llvm.ptr
%393 = arith.constant 10000 : i32
%394 = arith.extsi %393 : i32 to i64
%396 = arith.constant 1 : i32
%397 = arith.extsi %396 : i32 to i64
%395 = func.call @calloc(%394, %397) : (i64, i64) -> !llvm.ptr
%398 = arith.constant 5 : i32
%399 = arith.constant 0 : i32
%400 = arith.trunci %398 : i32 to i8
%401 = arith.extsi %399 : i32 to i64
%402 = llvm.getelementptr %395[%401] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %400, %402 : i8, !llvm.ptr
%404 = arith.constant 8 : i32
%405 = arith.extsi %404 : i32 to i64
%403 = func.call @calloc(%196, %405) : (i64, i64) -> !llvm.ptr
%407 = arith.constant 8 : i32
%408 = arith.extsi %407 : i32 to i64
%406 = func.call @calloc(%196, %408) : (i64, i64) -> !llvm.ptr
%410 = arith.constant 8 : i32
%411 = arith.extsi %410 : i32 to i64
%409 = func.call @calloc(%196, %411) : (i64, i64) -> !llvm.ptr
%412 = arith.constant 1 : i32
%413 = arith.constant 0 : i32
%414 = arith.extsi %412 : i32 to i64
%415 = arith.extsi %413 : i32 to i64
%416 = llvm.getelementptr %403[%415] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %414, %416 : i64, !llvm.ptr
%417 = arith.constant 1 : i32
%418 = arith.constant 1 : i32
%419 = arith.extsi %417 : i32 to i64
%420 = arith.extsi %418 : i32 to i64
%421 = llvm.getelementptr %406[%420] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %419, %421 : i64, !llvm.ptr
cf.br ^bb33
^bb33:
%422 = func.call @big_is_zero(%395, %394) : (!llvm.ptr, i64) -> i64
%423 = arith.constant 0 : i32
%425 = arith.extsi %423 : i32 to i64
%424 = arith.cmpi eq, %422, %425 : i64
cf.cond_br %424, ^bb34, ^bb35
^bb34:
%426 = func.call @big_halve(%395, %394) : (!llvm.ptr, i64) -> i64
%427 = arith.constant 1 : i32
%429 = arith.extsi %427 : i32 to i64
%428 = arith.cmpi eq, %426, %429 : i64
cf.cond_br %428, ^bb36, ^bb37
^bb36:
%430 = func.call @mul_poly(%403, %406, %197, %196, %194, %409) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, i64, i64, !llvm.ptr) -> i32
%431 = arith.constant 0 : i32
%432 = arith.index_cast %431 : i32 to index
%433 = arith.index_cast %196 : i32 to index
%435 = arith.constant 1 : index
%436 = arith.constant -1 : index
%437 = arith.cmpi sle, %432, %433 : index
%434 = arith.select %437, %435, %436 : index
cf.br ^bb39(%432 : index)
^bb39(%438: index):
%439 = arith.cmpi slt, %438, %433 : index
%440 = arith.cmpi sgt, %438, %433 : index
%441 = arith.select %437, %439, %440 : i1
cf.cond_br %441, ^bb40(%438 : index), ^bb41(%438 : index)
^bb40(%442: index):
%444 = arith.index_cast %442 : index to i64
%445 = llvm.getelementptr %409[%444] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%443 = llvm.load %445 : !llvm.ptr -> i64
%446 = arith.index_cast %442 : index to i64
%447 = llvm.getelementptr %403[%446] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %443, %447 : i64, !llvm.ptr
%448 = arith.addi %442, %434 : index
cf.br ^bb39(%448 : index)
^bb41(%449: index):
cf.br ^bb38
^bb37:
cf.br ^bb38
^bb38:
%450 = func.call @big_is_zero(%395, %394) : (!llvm.ptr, i64) -> i64
%451 = arith.constant 0 : i32
%453 = arith.extsi %451 : i32 to i64
%452 = arith.cmpi eq, %450, %453 : i64
cf.cond_br %452, ^bb42, ^bb43
^bb42:
%454 = func.call @mul_poly(%406, %406, %197, %196, %194, %409) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, i64, i64, !llvm.ptr) -> i32
%455 = arith.constant 0 : i32
%456 = arith.index_cast %455 : i32 to index
%457 = arith.index_cast %196 : i32 to index
%459 = arith.constant 1 : index
%460 = arith.constant -1 : index
%461 = arith.cmpi sle, %456, %457 : index
%458 = arith.select %461, %459, %460 : index
cf.br ^bb45(%456 : index)
^bb45(%462: index):
%463 = arith.cmpi slt, %462, %457 : index
%464 = arith.cmpi sgt, %462, %457 : index
%465 = arith.select %461, %463, %464 : i1
cf.cond_br %465, ^bb46(%462 : index), ^bb47(%462 : index)
^bb46(%466: index):
%468 = arith.index_cast %466 : index to i64
%469 = llvm.getelementptr %409[%468] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%467 = llvm.load %469 : !llvm.ptr -> i64
%470 = arith.index_cast %466 : index to i64
%471 = llvm.getelementptr %406[%470] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %467, %471 : i64, !llvm.ptr
%472 = arith.addi %466, %458 : index
cf.br ^bb45(%472 : index)
^bb47(%473: index):
cf.br ^bb44
^bb43:
cf.br ^bb44
^bb44:
cf.br ^bb33
^bb35:
%474 = arith.constant 0 : i32
%475 = arith.extsi %474 : i32 to i64
%476 = llvm.mlir.constant(1 : i64) : i64
%477 = llvm.alloca %476 x i64 : (i64) -> !llvm.ptr
llvm.store %475, %477 : i64, !llvm.ptr
%478 = arith.constant 0 : i32
%479 = arith.index_cast %478 : i32 to index
%480 = arith.index_cast %196 : i32 to index
%482 = arith.constant 1 : index
%483 = arith.constant -1 : index
%484 = arith.cmpi sle, %479, %480 : index
%481 = arith.select %484, %482, %483 : index
cf.br ^bb48(%479 : index)
^bb48(%485: index):
%486 = arith.cmpi slt, %485, %480 : index
%487 = arith.cmpi sgt, %485, %480 : index
%488 = arith.select %484, %486, %487 : i1
cf.cond_br %488, ^bb49(%485 : index), ^bb50(%485 : index)
^bb49(%489: index):
%490 = llvm.load %477 : !llvm.ptr -> i64
%492 = arith.index_cast %489 : index to i64
%493 = llvm.getelementptr %403[%492] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%491 = llvm.load %493 : !llvm.ptr -> i64
%495 = arith.index_cast %489 : index to i64
%496 = llvm.getelementptr %200[%495] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%494 = llvm.load %496 : !llvm.ptr -> i64
%497 = arith.muli %491, %494 : i64
%498 = arith.addi %490, %497 : i64
%499 = arith.remsi %498, %194 : i64
llvm.store %499, %477 : i64, !llvm.ptr
%500 = arith.addi %489, %481 : index
cf.br ^bb48(%500 : index)
^bb50(%501: index):
%502 = llvm.mlir.addressof @str_0 : !llvm.ptr
%503 = llvm.load %477 : !llvm.ptr -> i64
%504 = llvm.call @printf(%502, %503) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
func.call @free(%197) : (!llvm.ptr) -> ()
func.call @free(%200) : (!llvm.ptr) -> ()
func.call @free(%395) : (!llvm.ptr) -> ()
func.call @free(%403) : (!llvm.ptr) -> ()
func.call @free(%406) : (!llvm.ptr) -> ()
func.call @free(%409) : (!llvm.ptr) -> ()
%511 = arith.constant 0 : i32
func.return %511 : i32
}
}