Problem 894
Spiral of Circles: Newton solve for (s, theta) then compute total curvilinear triangle area.
View problem on Project Euler
Performance comparison
| Metric | Our solution | Best known |
| Time complexity | O(n^2) | O(n^2) |
| Space complexity | O(1) | O(n^2) |
| Approach | Flow solution | Bottom-up DP |
| Verdict | Optimal |
Flow source
# Project Euler 894
# Spiral of Circles: Newton solve for (s, theta) then compute total curvilinear triangle area.
extern {
function pow(x: f64, y: f64) -> f64
function cos(x: f64) -> f64
function acos(x: f64) -> f64
function sqrt(x: f64) -> f64
function fabs(x: f64) -> f64
}
const PI: f64 = 3.14159265358979323846
struct F2 {
f1: f64
f2: f64
}
function clampd(x: f64, lo: f64, hi: f64) -> f64 {
if x < lo { return lo }
if x > hi { return hi }
return x
}
function fmax_f64(a: f64, b: f64) -> f64 {
if a > b { return a }
return b
}
function is_finite(x: f64) -> bool {
return x == x && (x - x) == 0.0
}
function h_func(s: f64, theta: f64, n: i32) -> f64 {
let sn: f64 = pow(s, n as f64)
let num: f64 = 1.0 + sn * sn - 2.0 * sn * cos((n as f64) * theta)
let den: f64 = (1.0 + sn) * (1.0 + sn)
return num / den
}
function f_func(s: f64, theta: f64) -> F2 {
let h1: f64 = h_func(s, theta, 1)
return F2 { f1: h1 - h_func(s, theta, 7), f2: h1 - h_func(s, theta, 8) }
}
function objective(s: f64, theta: f64) -> f64 {
let r: F2 = f_func(s, theta)
return r.f1 * r.f1 + r.f2 * r.f2
}
function find_initial_guess() -> F2 {
let mut best_s: f64 = 0.9
let mut best_t: f64 = 0.8
let mut best_val: f64 = 1e300
let mut s: f64 = 0.75
while s <= 0.99 + 1e-12 {
let mut theta: f64 = 0.05
while theta <= PI - 0.05 + 1e-12 {
let val: f64 = objective(s, theta)
if val < best_val {
best_val = val
best_s = s
best_t = theta
}
theta = theta + 0.01
}
s = s + 0.002
}
return F2 { f1: best_s, f2: best_t }
}
function newton_solve(s0: f64, t0: f64) -> F2 {
let mut s: f64 = s0
let mut theta: f64 = t0
for iter in 0..60 {
let r: F2 = f_func(s, theta)
if fmax_f64(fabs(r.f1), fabs(r.f2)) < 1e-15 {
return F2 { f1: s, f2: theta }
}
let ds: f64 = 1e-8
let dt: f64 = 1e-8
let rsp: F2 = f_func(s + ds, theta)
let rsm: F2 = f_func(s - ds, theta)
let rtp: F2 = f_func(s, theta + dt)
let rtm: F2 = f_func(s, theta - dt)
let a: f64 = (rsp.f1 - rsm.f1) / (2.0 * ds)
let b: f64 = (rtp.f1 - rtm.f1) / (2.0 * dt)
let c: f64 = (rsp.f2 - rsm.f2) / (2.0 * ds)
let d: f64 = (rtp.f2 - rtm.f2) / (2.0 * dt)
let det: f64 = a * d - b * c
if det == 0.0 || !is_finite(det) {
s = s * 0.999
theta = theta * 0.999
continue
}
let delta_s: f64 = (d * r.f1 - b * r.f2) / det
let delta_t: f64 = (-c * r.f1 + a * r.f2) / det
let cur_obj: f64 = r.f1 * r.f1 + r.f2 * r.f2
let mut step: f64 = 1.0
let mut improved: bool = false
for ls in 0..40 {
let ns: f64 = s - step * delta_s
let nt: f64 = theta - step * delta_t
if !(0.0 < ns && ns < 1.0 && 0.0 < nt && nt < PI) {
step = step * 0.5
continue
}
let nobj: f64 = objective(ns, nt)
if nobj < cur_obj {
s = ns
theta = nt
improved = true
break
}
step = step * 0.5
}
if !improved { break }
}
return F2 { f1: s, f2: theta }
}
function curvilinear_triangle_area(r1: f64, r2: f64, r3: f64) -> f64 {
let a: f64 = r2 + r3
let b: f64 = r1 + r3
let c: f64 = r1 + r2
let p: f64 = 0.5 * (a + b + c)
let mut tri_sq: f64 = p * (p - a) * (p - b) * (p - c)
if tri_sq < 0.0 { tri_sq = 0.0 }
let tri_area: f64 = sqrt(tri_sq)
let cos1: f64 = (b * b + c * c - a * a) / (2.0 * b * c)
let cos2: f64 = (a * a + c * c - b * b) / (2.0 * a * c)
let cos3: f64 = (a * a + b * b - c * c) / (2.0 * a * b)
let ang1: f64 = acos(clampd(cos1, -1.0, 1.0))
let ang2: f64 = acos(clampd(cos2, -1.0, 1.0))
let ang3: f64 = acos(clampd(cos3, -1.0, 1.0))
let sectors: f64 = 0.5 * (r1 * r1 * ang1 + r2 * r2 * ang2 + r3 * r3 * ang3)
return tri_area - sectors
}
function main() -> i32 {
let init: F2 = find_initial_guess()
let sol: F2 = newton_solve(init.f1, init.f2)
let s: f64 = sol.f1
let theta: f64 = sol.f2
let s7: f64 = pow(s, 7.0)
let s8: f64 = s7 * s
let a0: f64 = curvilinear_triangle_area(1.0, s, s8)
let b0: f64 = curvilinear_triangle_area(1.0, s7, s8)
let total: f64 = (a0 + b0) / (1.0 - s * s)
printf("%.10f\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; }
typedef struct F2 F2;
struct F2 {
double f1;
double f2;
};
double acos(double x);
double clampd_f64_f64_f64(double x, double lo, double hi);
double fmax_f64_f64_f64(double a, double b);
bool is_finite_f64(double x);
double h_func_f64_f64_i32(double s, double theta, int32_t n);
F2 f_func_f64_f64(double s, double theta);
double objective_f64_f64(double s, double theta);
F2 find_initial_guess(void);
F2 newton_solve_f64_f64(double s0, double t0);
double curvilinear_triangle_area_f64_f64_f64(double r1, double r2, double r3);
int32_t main(void);
static const double PI = 3.14159265358979323846;
double clampd_f64_f64_f64(double x, double lo, double hi) {
if (x < lo) {
return lo;
}
if (x > hi) {
return hi;
}
return x;
}
double fmax_f64_f64_f64(double a, double b) {
if (a > b) {
return a;
}
return b;
}
bool is_finite_f64(double x) {
return (x == x && (x - x) == 0.0);
}
double h_func_f64_f64_i32(double s, double theta, int32_t n) {
double sn = pow(s, ((double)(n)));
double num = ((1.0 + (sn * sn)) - ((2.0 * sn) * cos((((double)(n)) * theta))));
double den = ((1.0 + sn) * (1.0 + sn));
return (num / den);
}
F2 f_func_f64_f64(double s, double theta) {
double h1 = h_func_f64_f64_i32(s, theta, 1);
return (F2){ .f1 = (h1 - h_func_f64_f64_i32(s, theta, 7)), .f2 = (h1 - h_func_f64_f64_i32(s, theta, 8)) };
}
double objective_f64_f64(double s, double theta) {
F2 r = f_func_f64_f64(s, theta);
return ((r.f1 * r.f1) + (r.f2 * r.f2));
}
F2 find_initial_guess(void) {
double best_s = 0.9;
double best_t = 0.8;
double best_val = 1e300;
double s = 0.75;
while (s <= (0.99 + 1e-12)) {
double theta = 0.05;
while (theta <= ((PI - 0.05) + 1e-12)) {
double val = objective_f64_f64(s, theta);
if (val < best_val) {
best_val = val;
best_s = s;
best_t = theta;
}
theta = (theta + 0.01);
}
s = (s + 0.002);
}
return (F2){ .f1 = best_s, .f2 = best_t };
}
F2 newton_solve_f64_f64(double s0, double t0) {
double s = s0;
double theta = t0;
int32_t __flow_step_1 = 1;
for (int32_t iter = 0; (0 <= 60) ? iter < 60 : iter > 60; iter += (0 <= 60) ? 1 : -1) {
F2 r = f_func_f64_f64(s, theta);
if (fmax_f64_f64_f64(fabs(r.f1), fabs(r.f2)) < 1e-15) {
return (F2){ .f1 = s, .f2 = theta };
}
double ds = 1e-8;
double dt = 1e-8;
F2 rsp = f_func_f64_f64((s + ds), theta);
F2 rsm = f_func_f64_f64((s - ds), theta);
F2 rtp = f_func_f64_f64(s, (theta + dt));
F2 rtm = f_func_f64_f64(s, (theta - dt));
double a = ((rsp.f1 - rsm.f1) / (2.0 * ds));
double b = ((rtp.f1 - rtm.f1) / (2.0 * dt));
double c = ((rsp.f2 - rsm.f2) / (2.0 * ds));
double d = ((rtp.f2 - rtm.f2) / (2.0 * dt));
double det = ((a * d) - (b * c));
if ((det == 0.0 || (!(is_finite_f64(det))))) {
s = (s * 0.999);
theta = (theta * 0.999);
continue;
}
double delta_s = (((d * r.f1) - (b * r.f2)) / det);
double delta_t = ((((-c) * r.f1) + (a * r.f2)) / det);
double cur_obj = ((r.f1 * r.f1) + (r.f2 * r.f2));
double step = 1.0;
bool improved = 0;
int32_t __flow_step_2 = 1;
for (int32_t ls = 0; (0 <= 40) ? ls < 40 : ls > 40; ls += (0 <= 40) ? 1 : -1) {
double ns = (s - (step * delta_s));
double nt = (theta - (step * delta_t));
if ((!((((0.0 < ns && ns < 1.0) && 0.0 < nt) && nt < PI)))) {
step = (step * 0.5);
continue;
}
double nobj = objective_f64_f64(ns, nt);
if (nobj < cur_obj) {
s = ns;
theta = nt;
improved = 1;
break;
}
step = (step * 0.5);
}
if ((!(improved))) {
break;
}
}
return (F2){ .f1 = s, .f2 = theta };
}
double curvilinear_triangle_area_f64_f64_f64(double r1, double r2, double r3) {
double a = (r2 + r3);
double b = (r1 + r3);
double c = (r1 + r2);
double p = (0.5 * ((a + b) + c));
double tri_sq = (((p * (p - a)) * (p - b)) * (p - c));
if (tri_sq < 0.0) {
tri_sq = 0.0;
}
double tri_area = sqrt(tri_sq);
double cos1 = ((((b * b) + (c * c)) - (a * a)) / ((2.0 * b) * c));
double cos2 = ((((a * a) + (c * c)) - (b * b)) / ((2.0 * a) * c));
double cos3 = ((((a * a) + (b * b)) - (c * c)) / ((2.0 * a) * b));
double ang1 = acos(clampd_f64_f64_f64(cos1, (-1.0), 1.0));
double ang2 = acos(clampd_f64_f64_f64(cos2, (-1.0), 1.0));
double ang3 = acos(clampd_f64_f64_f64(cos3, (-1.0), 1.0));
double sectors = (0.5 * ((((r1 * r1) * ang1) + ((r2 * r2) * ang2)) + ((r3 * r3) * ang3)));
return (tri_area - sectors);
}
int32_t main(void) {
F2 init = find_initial_guess();
F2 sol = newton_solve_f64_f64(init.f1, init.f2);
double s = sol.f1;
double theta = sol.f2;
double s7 = pow(s, 7.0);
double s8 = (s7 * s);
double a0 = curvilinear_triangle_area_f64_f64_f64(1.0, s, s8);
double b0 = curvilinear_triangle_area_f64_f64_f64(1.0, s7, s8);
double total = ((a0 + b0) / (1.0 - (s * s)));
printf("%.10f\n", total);
return 0;
}
Generated MLIR
module {
llvm.func @printf(!llvm.ptr, ...) -> i32
llvm.mlir.global internal constant @str_0("%.10f\n\00") {addr_space = 0 : i32} : !llvm.array<7 x i8>
func.func private @pow(f64, f64) -> f64
func.func private @cos(f64) -> f64
func.func private @acos(f64) -> f64
func.func private @sqrt(f64) -> f64
func.func private @fabs(f64) -> f64
// Constant: PI
llvm.mlir.global internal constant @PI(3.14159265358979323846 : f64) : f64
// Struct: F2
// Fields:
// f1: f64
// f2: f64
func.func @clampd(%arg0: f64, %arg1: f64, %arg2: f64) -> f64 {
%0 = arith.cmpf olt, %arg0, %arg1 : f64
cf.cond_br %0, ^bb0, ^bb1
^bb0:
func.return %arg1 : f64
^bb1:
cf.br ^bb2
^bb2:
%1 = arith.cmpf ogt, %arg0, %arg2 : f64
cf.cond_br %1, ^bb3, ^bb4
^bb3:
func.return %arg2 : f64
^bb4:
cf.br ^bb5
^bb5:
func.return %arg0 : f64
}
func.func @fmax_f64(%arg0: f64, %arg1: f64) -> f64 {
%2 = arith.cmpf ogt, %arg0, %arg1 : f64
cf.cond_br %2, ^bb6, ^bb7
^bb6:
func.return %arg0 : f64
^bb7:
cf.br ^bb8
^bb8:
func.return %arg1 : f64
}
func.func @is_finite(%arg0: f64) -> i1 {
%3 = arith.cmpf oeq, %arg0, %arg0 : f64
%4 = scf.if %3 -> (i1) {
%5 = arith.subf %arg0, %arg0 : f64
%6 = arith.constant 0.0 : f32
%8 = arith.extf %6 : f32 to f64
%7 = arith.cmpf oeq, %5, %8 : f64
scf.yield %7 : i1
} else {
%9 = arith.constant false
scf.yield %9 : i1
}
func.return %4 : i1
}
func.func @h_func(%arg0: f64, %arg1: f64, %arg2: i32) -> f64 {
%11 = arith.sitofp %arg2 : i32 to f64
%10 = func.call @pow(%arg0, %11) : (f64, f64) -> f64
%12 = arith.constant 1.0 : f32
%13 = arith.mulf %10, %10 : f64
%15 = arith.extf %12 : f32 to f64
%14 = arith.addf %15, %13 : f64
%16 = arith.constant 2.0 : f32
%18 = arith.extf %16 : f32 to f64
%17 = arith.mulf %18, %10 : f64
%19 = arith.sitofp %arg2 : i32 to f64
%20 = arith.mulf %19, %arg1 : f64
%21 = math.cos %20 : f64
%22 = arith.mulf %17, %21 : f64
%23 = arith.subf %14, %22 : f64
%24 = arith.constant 1.0 : f32
%26 = arith.extf %24 : f32 to f64
%25 = arith.addf %26, %10 : f64
%27 = arith.constant 1.0 : f32
%29 = arith.extf %27 : f32 to f64
%28 = arith.addf %29, %10 : f64
%30 = arith.mulf %25, %28 : f64
%31 = arith.divf %23, %30 : f64
func.return %31 : f64
}
func.func @f_func(%arg0: f64, %arg1: f64) -> !llvm.struct<(f64, f64)> {
%33 = arith.constant 1 : i32
%32 = func.call @h_func(%arg0, %arg1, %33) : (f64, f64, i32) -> f64
%34 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%36 = arith.constant 7 : i32
%35 = func.call @h_func(%arg0, %arg1, %36) : (f64, f64, i32) -> f64
%37 = arith.subf %32, %35 : f64
%38 = llvm.insertvalue %37, %34[0] : !llvm.struct<(f64, f64)>
%40 = arith.constant 8 : i32
%39 = func.call @h_func(%arg0, %arg1, %40) : (f64, f64, i32) -> f64
%41 = arith.subf %32, %39 : f64
%42 = llvm.insertvalue %41, %38[1] : !llvm.struct<(f64, f64)>
%43 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%44 = llvm.extractvalue %42[0] : !llvm.struct<(f64, f64)>
%45 = llvm.insertvalue %44, %43[0] : !llvm.struct<(f64, f64)>
%46 = llvm.extractvalue %42[1] : !llvm.struct<(f64, f64)>
%47 = llvm.insertvalue %46, %45[1] : !llvm.struct<(f64, f64)>
%48 = llvm.mlir.constant(1 : i64) : i64
%49 = llvm.alloca %48 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %47, %49 : !llvm.struct<(f64, f64)>, !llvm.ptr
%50 = llvm.load %49 : !llvm.ptr -> !llvm.struct<(f64, f64)>
func.return %50 : !llvm.struct<(f64, f64)>
}
func.func @objective(%arg0: f64, %arg1: f64) -> f64 {
%51 = func.call @f_func(%arg0, %arg1) : (f64, f64) -> !llvm.struct<(f64, f64)>
%52 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%53 = llvm.extractvalue %51[0] : !llvm.struct<(f64, f64)>
%54 = llvm.insertvalue %53, %52[0] : !llvm.struct<(f64, f64)>
%55 = llvm.extractvalue %51[1] : !llvm.struct<(f64, f64)>
%56 = llvm.insertvalue %55, %54[1] : !llvm.struct<(f64, f64)>
%57 = llvm.mlir.constant(1 : i64) : i64
%58 = llvm.alloca %57 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %56, %58 : !llvm.struct<(f64, f64)>, !llvm.ptr
%59 = llvm.load %58 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%60 = llvm.mlir.constant(1 : i64) : i64
%61 = llvm.alloca %60 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %59, %61 : !llvm.struct<(f64, f64)>, !llvm.ptr
%62 = llvm.load %61 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%63 = llvm.getelementptr %61[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%64 = llvm.load %63 : !llvm.ptr -> f64
%65 = llvm.load %61 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%66 = llvm.getelementptr %61[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%67 = llvm.load %66 : !llvm.ptr -> f64
%68 = arith.mulf %64, %67 : f64
%69 = llvm.load %61 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%70 = llvm.getelementptr %61[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%71 = llvm.load %70 : !llvm.ptr -> f64
%72 = llvm.load %61 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%73 = llvm.getelementptr %61[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%74 = llvm.load %73 : !llvm.ptr -> f64
%75 = arith.mulf %71, %74 : f64
%76 = arith.addf %68, %75 : f64
func.return %76 : f64
}
func.func @find_initial_guess() -> !llvm.struct<(f64, f64)> {
%77 = arith.constant 0.9 : f32
%78 = arith.extf %77 : f32 to f64
%79 = llvm.mlir.constant(1 : i64) : i64
%80 = llvm.alloca %79 x f64 : (i64) -> !llvm.ptr
llvm.store %78, %80 : f64, !llvm.ptr
%81 = arith.constant 0.8 : f32
%82 = arith.extf %81 : f32 to f64
%83 = llvm.mlir.constant(1 : i64) : i64
%84 = llvm.alloca %83 x f64 : (i64) -> !llvm.ptr
llvm.store %82, %84 : f64, !llvm.ptr
%85 = arith.constant 1000000000000000052504760255204420248704468581108159154915854115511802457988908195786371375080447864043704443832883878176942523235360430575644792184786706982848387200926575803737830233794788090059368953234970799945081119038967640880074652742780142494579258788820056842838115669472196386865459400540160 : f32
%86 = arith.extf %85 : f32 to f64
%87 = llvm.mlir.constant(1 : i64) : i64
%88 = llvm.alloca %87 x f64 : (i64) -> !llvm.ptr
llvm.store %86, %88 : f64, !llvm.ptr
%89 = arith.constant 0.75 : f32
%90 = arith.extf %89 : f32 to f64
%91 = llvm.mlir.constant(1 : i64) : i64
%92 = llvm.alloca %91 x f64 : (i64) -> !llvm.ptr
llvm.store %90, %92 : f64, !llvm.ptr
cf.br ^bb9
^bb9:
%93 = llvm.load %92 : !llvm.ptr -> f64
%94 = arith.constant 0.99 : f32
%95 = arith.constant 0 : f32
%96 = arith.addf %94, %95 : f32
%98 = arith.extf %96 : f32 to f64
%97 = arith.cmpf ole, %93, %98 : f64
cf.cond_br %97, ^bb10, ^bb11
^bb10:
%99 = arith.constant 0.05 : f32
%100 = arith.extf %99 : f32 to f64
%101 = llvm.mlir.constant(1 : i64) : i64
%102 = llvm.alloca %101 x f64 : (i64) -> !llvm.ptr
llvm.store %100, %102 : f64, !llvm.ptr
cf.br ^bb12
^bb12:
%103 = llvm.load %102 : !llvm.ptr -> f64
%104 = llvm.mlir.addressof @PI : !llvm.ptr
%105 = llvm.load %104 : !llvm.ptr -> f64
%106 = arith.constant 0.05 : f32
%108 = arith.extf %106 : f32 to f64
%107 = arith.subf %105, %108 : f64
%109 = arith.constant 0 : f32
%111 = arith.extf %109 : f32 to f64
%110 = arith.addf %107, %111 : f64
%112 = arith.cmpf ole, %103, %110 : f64
cf.cond_br %112, ^bb13, ^bb14
^bb13:
%114 = llvm.load %92 : !llvm.ptr -> f64
%115 = llvm.load %102 : !llvm.ptr -> f64
%113 = func.call @objective(%114, %115) : (f64, f64) -> f64
%116 = llvm.load %88 : !llvm.ptr -> f64
%117 = arith.cmpf olt, %113, %116 : f64
cf.cond_br %117, ^bb15, ^bb16
^bb15:
llvm.store %113, %88 : f64, !llvm.ptr
%118 = llvm.load %92 : !llvm.ptr -> f64
llvm.store %118, %80 : f64, !llvm.ptr
%119 = llvm.load %102 : !llvm.ptr -> f64
llvm.store %119, %84 : f64, !llvm.ptr
cf.br ^bb17
^bb16:
cf.br ^bb17
^bb17:
%120 = llvm.load %102 : !llvm.ptr -> f64
%121 = arith.constant 0.01 : f32
%123 = arith.extf %121 : f32 to f64
%122 = arith.addf %120, %123 : f64
llvm.store %122, %102 : f64, !llvm.ptr
cf.br ^bb12
^bb14:
%124 = llvm.load %92 : !llvm.ptr -> f64
%125 = arith.constant 0.002 : f32
%127 = arith.extf %125 : f32 to f64
%126 = arith.addf %124, %127 : f64
llvm.store %126, %92 : f64, !llvm.ptr
cf.br ^bb9
^bb11:
%128 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%129 = llvm.load %80 : !llvm.ptr -> f64
%130 = llvm.insertvalue %129, %128[0] : !llvm.struct<(f64, f64)>
%131 = llvm.load %84 : !llvm.ptr -> f64
%132 = llvm.insertvalue %131, %130[1] : !llvm.struct<(f64, f64)>
%133 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%134 = llvm.extractvalue %132[0] : !llvm.struct<(f64, f64)>
%135 = llvm.insertvalue %134, %133[0] : !llvm.struct<(f64, f64)>
%136 = llvm.extractvalue %132[1] : !llvm.struct<(f64, f64)>
%137 = llvm.insertvalue %136, %135[1] : !llvm.struct<(f64, f64)>
%138 = llvm.mlir.constant(1 : i64) : i64
%139 = llvm.alloca %138 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %137, %139 : !llvm.struct<(f64, f64)>, !llvm.ptr
%140 = llvm.load %139 : !llvm.ptr -> !llvm.struct<(f64, f64)>
func.return %140 : !llvm.struct<(f64, f64)>
}
func.func @newton_solve(%arg0: f64, %arg1: f64) -> !llvm.struct<(f64, f64)> {
%141 = llvm.mlir.constant(1 : i64) : i64
%142 = llvm.alloca %141 x f64 : (i64) -> !llvm.ptr
llvm.store %arg0, %142 : f64, !llvm.ptr
%143 = llvm.mlir.constant(1 : i64) : i64
%144 = llvm.alloca %143 x f64 : (i64) -> !llvm.ptr
llvm.store %arg1, %144 : f64, !llvm.ptr
%145 = arith.constant 0 : i32
%146 = arith.constant 60 : i32
%147 = arith.index_cast %145 : i32 to index
%148 = arith.index_cast %146 : i32 to index
%150 = arith.constant 1 : index
%151 = arith.constant -1 : index
%152 = arith.cmpi sle, %147, %148 : index
%149 = arith.select %152, %150, %151 : index
cf.br ^bb18(%147 : index)
^bb18(%153: index):
%154 = arith.cmpi slt, %153, %148 : index
%155 = arith.cmpi sgt, %153, %148 : index
%156 = arith.select %152, %154, %155 : i1
cf.cond_br %156, ^bb19(%153 : index), ^bb20(%153 : index)
^bb19(%157: index):
%159 = llvm.load %144 : !llvm.ptr -> f64
%160 = llvm.load %142 : !llvm.ptr -> f64
%158 = func.call @f_func(%160, %159) : (f64, f64) -> !llvm.struct<(f64, f64)>
%161 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%162 = llvm.extractvalue %158[0] : !llvm.struct<(f64, f64)>
%163 = llvm.insertvalue %162, %161[0] : !llvm.struct<(f64, f64)>
%164 = llvm.extractvalue %158[1] : !llvm.struct<(f64, f64)>
%165 = llvm.insertvalue %164, %163[1] : !llvm.struct<(f64, f64)>
%166 = llvm.mlir.constant(1 : i64) : i64
%167 = llvm.alloca %166 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %165, %167 : !llvm.struct<(f64, f64)>, !llvm.ptr
%168 = llvm.load %167 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%169 = llvm.mlir.constant(1 : i64) : i64
%170 = llvm.alloca %169 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %168, %170 : !llvm.struct<(f64, f64)>, !llvm.ptr
%172 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%173 = llvm.getelementptr %170[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%174 = llvm.load %173 : !llvm.ptr -> f64
%175 = math.absf %174 : f64
%176 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%177 = llvm.getelementptr %170[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%178 = llvm.load %177 : !llvm.ptr -> f64
%179 = math.absf %178 : f64
%171 = func.call @fmax_f64(%175, %179) : (f64, f64) -> f64
%180 = arith.constant 0 : f32
%182 = arith.extf %180 : f32 to f64
%181 = arith.cmpf olt, %171, %182 : f64
cf.cond_br %181, ^bb21, ^bb22
^bb21:
%183 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%184 = llvm.load %142 : !llvm.ptr -> f64
%185 = llvm.insertvalue %184, %183[0] : !llvm.struct<(f64, f64)>
%186 = llvm.load %144 : !llvm.ptr -> f64
%187 = llvm.insertvalue %186, %185[1] : !llvm.struct<(f64, f64)>
%188 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%189 = llvm.extractvalue %187[0] : !llvm.struct<(f64, f64)>
%190 = llvm.insertvalue %189, %188[0] : !llvm.struct<(f64, f64)>
%191 = llvm.extractvalue %187[1] : !llvm.struct<(f64, f64)>
%192 = llvm.insertvalue %191, %190[1] : !llvm.struct<(f64, f64)>
%193 = llvm.mlir.constant(1 : i64) : i64
%194 = llvm.alloca %193 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %192, %194 : !llvm.struct<(f64, f64)>, !llvm.ptr
%195 = llvm.load %194 : !llvm.ptr -> !llvm.struct<(f64, f64)>
func.return %195 : !llvm.struct<(f64, f64)>
^bb22:
cf.br ^bb23
^bb23:
%196 = arith.constant 0.00000001 : f32
%197 = arith.extf %196 : f32 to f64
%198 = arith.constant 0.00000001 : f32
%199 = arith.extf %198 : f32 to f64
%201 = llvm.load %144 : !llvm.ptr -> f64
%202 = llvm.load %142 : !llvm.ptr -> f64
%203 = arith.addf %202, %197 : f64
%200 = func.call @f_func(%203, %201) : (f64, f64) -> !llvm.struct<(f64, f64)>
%204 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%205 = llvm.extractvalue %200[0] : !llvm.struct<(f64, f64)>
%206 = llvm.insertvalue %205, %204[0] : !llvm.struct<(f64, f64)>
%207 = llvm.extractvalue %200[1] : !llvm.struct<(f64, f64)>
%208 = llvm.insertvalue %207, %206[1] : !llvm.struct<(f64, f64)>
%209 = llvm.mlir.constant(1 : i64) : i64
%210 = llvm.alloca %209 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %208, %210 : !llvm.struct<(f64, f64)>, !llvm.ptr
%211 = llvm.load %210 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%212 = llvm.mlir.constant(1 : i64) : i64
%213 = llvm.alloca %212 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %211, %213 : !llvm.struct<(f64, f64)>, !llvm.ptr
%215 = llvm.load %144 : !llvm.ptr -> f64
%216 = llvm.load %142 : !llvm.ptr -> f64
%217 = arith.subf %216, %197 : f64
%214 = func.call @f_func(%217, %215) : (f64, f64) -> !llvm.struct<(f64, f64)>
%218 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%219 = llvm.extractvalue %214[0] : !llvm.struct<(f64, f64)>
%220 = llvm.insertvalue %219, %218[0] : !llvm.struct<(f64, f64)>
%221 = llvm.extractvalue %214[1] : !llvm.struct<(f64, f64)>
%222 = llvm.insertvalue %221, %220[1] : !llvm.struct<(f64, f64)>
%223 = llvm.mlir.constant(1 : i64) : i64
%224 = llvm.alloca %223 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %222, %224 : !llvm.struct<(f64, f64)>, !llvm.ptr
%225 = llvm.load %224 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%226 = llvm.mlir.constant(1 : i64) : i64
%227 = llvm.alloca %226 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %225, %227 : !llvm.struct<(f64, f64)>, !llvm.ptr
%229 = llvm.load %144 : !llvm.ptr -> f64
%230 = arith.addf %229, %199 : f64
%231 = llvm.load %142 : !llvm.ptr -> f64
%228 = func.call @f_func(%231, %230) : (f64, f64) -> !llvm.struct<(f64, f64)>
%232 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%233 = llvm.extractvalue %228[0] : !llvm.struct<(f64, f64)>
%234 = llvm.insertvalue %233, %232[0] : !llvm.struct<(f64, f64)>
%235 = llvm.extractvalue %228[1] : !llvm.struct<(f64, f64)>
%236 = llvm.insertvalue %235, %234[1] : !llvm.struct<(f64, f64)>
%237 = llvm.mlir.constant(1 : i64) : i64
%238 = llvm.alloca %237 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %236, %238 : !llvm.struct<(f64, f64)>, !llvm.ptr
%239 = llvm.load %238 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%240 = llvm.mlir.constant(1 : i64) : i64
%241 = llvm.alloca %240 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %239, %241 : !llvm.struct<(f64, f64)>, !llvm.ptr
%243 = llvm.load %144 : !llvm.ptr -> f64
%244 = arith.subf %243, %199 : f64
%245 = llvm.load %142 : !llvm.ptr -> f64
%242 = func.call @f_func(%245, %244) : (f64, f64) -> !llvm.struct<(f64, f64)>
%246 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%247 = llvm.extractvalue %242[0] : !llvm.struct<(f64, f64)>
%248 = llvm.insertvalue %247, %246[0] : !llvm.struct<(f64, f64)>
%249 = llvm.extractvalue %242[1] : !llvm.struct<(f64, f64)>
%250 = llvm.insertvalue %249, %248[1] : !llvm.struct<(f64, f64)>
%251 = llvm.mlir.constant(1 : i64) : i64
%252 = llvm.alloca %251 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %250, %252 : !llvm.struct<(f64, f64)>, !llvm.ptr
%253 = llvm.load %252 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%254 = llvm.mlir.constant(1 : i64) : i64
%255 = llvm.alloca %254 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %253, %255 : !llvm.struct<(f64, f64)>, !llvm.ptr
%256 = llvm.load %213 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%257 = llvm.getelementptr %213[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%258 = llvm.load %257 : !llvm.ptr -> f64
%259 = llvm.load %227 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%260 = llvm.getelementptr %227[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%261 = llvm.load %260 : !llvm.ptr -> f64
%262 = arith.subf %258, %261 : f64
%263 = arith.constant 2.0 : f32
%265 = arith.extf %263 : f32 to f64
%264 = arith.mulf %265, %197 : f64
%266 = arith.divf %262, %264 : f64
%267 = llvm.load %241 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%268 = llvm.getelementptr %241[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%269 = llvm.load %268 : !llvm.ptr -> f64
%270 = llvm.load %255 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%271 = llvm.getelementptr %255[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%272 = llvm.load %271 : !llvm.ptr -> f64
%273 = arith.subf %269, %272 : f64
%274 = arith.constant 2.0 : f32
%276 = arith.extf %274 : f32 to f64
%275 = arith.mulf %276, %199 : f64
%277 = arith.divf %273, %275 : f64
%278 = llvm.load %213 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%279 = llvm.getelementptr %213[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%280 = llvm.load %279 : !llvm.ptr -> f64
%281 = llvm.load %227 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%282 = llvm.getelementptr %227[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%283 = llvm.load %282 : !llvm.ptr -> f64
%284 = arith.subf %280, %283 : f64
%285 = arith.constant 2.0 : f32
%287 = arith.extf %285 : f32 to f64
%286 = arith.mulf %287, %197 : f64
%288 = arith.divf %284, %286 : f64
%289 = llvm.load %241 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%290 = llvm.getelementptr %241[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%291 = llvm.load %290 : !llvm.ptr -> f64
%292 = llvm.load %255 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%293 = llvm.getelementptr %255[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%294 = llvm.load %293 : !llvm.ptr -> f64
%295 = arith.subf %291, %294 : f64
%296 = arith.constant 2.0 : f32
%298 = arith.extf %296 : f32 to f64
%297 = arith.mulf %298, %199 : f64
%299 = arith.divf %295, %297 : f64
%300 = arith.mulf %266, %299 : f64
%301 = arith.mulf %277, %288 : f64
%302 = arith.subf %300, %301 : f64
%303 = arith.constant 0.0 : f32
%305 = arith.extf %303 : f32 to f64
%304 = arith.cmpf oeq, %302, %305 : f64
%306 = scf.if %304 -> (i1) {
%307 = arith.constant true
scf.yield %307 : i1
} else {
%308 = func.call @is_finite(%302) : (f64) -> i1
%310 = arith.constant 1 : i1
%309 = arith.xori %308, %310 : i1
scf.yield %309 : i1
}
cf.cond_br %306, ^bb24, ^bb25
^bb24:
%312 = llvm.load %142 : !llvm.ptr -> f64
%313 = arith.constant 0.999 : f32
%315 = arith.extf %313 : f32 to f64
%314 = arith.mulf %312, %315 : f64
llvm.store %314, %142 : f64, !llvm.ptr
%316 = llvm.load %144 : !llvm.ptr -> f64
%317 = arith.constant 0.999 : f32
%319 = arith.extf %317 : f32 to f64
%318 = arith.mulf %316, %319 : f64
llvm.store %318, %144 : f64, !llvm.ptr
%320 = arith.addi %157, %149 : index
cf.br ^bb18(%320 : index)
^bb25:
cf.br ^bb26
^bb26:
%321 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%322 = llvm.getelementptr %170[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%323 = llvm.load %322 : !llvm.ptr -> f64
%324 = arith.mulf %299, %323 : f64
%325 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%326 = llvm.getelementptr %170[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%327 = llvm.load %326 : !llvm.ptr -> f64
%328 = arith.mulf %277, %327 : f64
%329 = arith.subf %324, %328 : f64
%330 = arith.divf %329, %302 : f64
%331 = arith.negf %288 : f64
%332 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%333 = llvm.getelementptr %170[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%334 = llvm.load %333 : !llvm.ptr -> f64
%335 = arith.mulf %331, %334 : f64
%336 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%337 = llvm.getelementptr %170[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%338 = llvm.load %337 : !llvm.ptr -> f64
%339 = arith.mulf %266, %338 : f64
%340 = arith.addf %335, %339 : f64
%341 = arith.divf %340, %302 : f64
%342 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%343 = llvm.getelementptr %170[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%344 = llvm.load %343 : !llvm.ptr -> f64
%345 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%346 = llvm.getelementptr %170[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%347 = llvm.load %346 : !llvm.ptr -> f64
%348 = arith.mulf %344, %347 : f64
%349 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%350 = llvm.getelementptr %170[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%351 = llvm.load %350 : !llvm.ptr -> f64
%352 = llvm.load %170 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%353 = llvm.getelementptr %170[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%354 = llvm.load %353 : !llvm.ptr -> f64
%355 = arith.mulf %351, %354 : f64
%356 = arith.addf %348, %355 : f64
%357 = arith.constant 1.0 : f32
%358 = arith.extf %357 : f32 to f64
%359 = llvm.mlir.constant(1 : i64) : i64
%360 = llvm.alloca %359 x f64 : (i64) -> !llvm.ptr
llvm.store %358, %360 : f64, !llvm.ptr
%361 = arith.constant 0 : i1
%362 = llvm.mlir.constant(1 : i64) : i64
%363 = llvm.alloca %362 x i1 : (i64) -> !llvm.ptr
llvm.store %361, %363 : i1, !llvm.ptr
%364 = arith.constant 0 : i32
%365 = arith.constant 40 : i32
%366 = arith.index_cast %364 : i32 to index
%367 = arith.index_cast %365 : i32 to index
%369 = arith.constant 1 : index
%370 = arith.constant -1 : index
%371 = arith.cmpi sle, %366, %367 : index
%368 = arith.select %371, %369, %370 : index
cf.br ^bb27(%366 : index)
^bb27(%372: index):
%373 = arith.cmpi slt, %372, %367 : index
%374 = arith.cmpi sgt, %372, %367 : index
%375 = arith.select %371, %373, %374 : i1
cf.cond_br %375, ^bb28(%372 : index), ^bb29(%372 : index)
^bb28(%376: index):
%377 = llvm.load %142 : !llvm.ptr -> f64
%378 = llvm.load %360 : !llvm.ptr -> f64
%379 = arith.mulf %378, %330 : f64
%380 = arith.subf %377, %379 : f64
%381 = llvm.load %144 : !llvm.ptr -> f64
%382 = llvm.load %360 : !llvm.ptr -> f64
%383 = arith.mulf %382, %341 : f64
%384 = arith.subf %381, %383 : f64
%385 = arith.constant 0.0 : f32
%387 = arith.extf %385 : f32 to f64
%386 = arith.cmpf olt, %387, %380 : f64
%388 = scf.if %386 -> (i1) {
%389 = arith.constant 1.0 : f32
%391 = arith.extf %389 : f32 to f64
%390 = arith.cmpf olt, %380, %391 : f64
scf.yield %390 : i1
} else {
%392 = arith.constant false
scf.yield %392 : i1
}
%393 = scf.if %388 -> (i1) {
%394 = arith.constant 0.0 : f32
%396 = arith.extf %394 : f32 to f64
%395 = arith.cmpf olt, %396, %384 : f64
scf.yield %395 : i1
} else {
%397 = arith.constant false
scf.yield %397 : i1
}
%398 = scf.if %393 -> (i1) {
%399 = llvm.mlir.addressof @PI : !llvm.ptr
%400 = llvm.load %399 : !llvm.ptr -> f64
%401 = arith.cmpf olt, %384, %400 : f64
scf.yield %401 : i1
} else {
%402 = arith.constant false
scf.yield %402 : i1
}
%404 = arith.constant 1 : i1
%403 = arith.xori %398, %404 : i1
cf.cond_br %403, ^bb30, ^bb31
^bb30:
%406 = llvm.load %360 : !llvm.ptr -> f64
%407 = arith.constant 0.5 : f32
%409 = arith.extf %407 : f32 to f64
%408 = arith.mulf %406, %409 : f64
llvm.store %408, %360 : f64, !llvm.ptr
%410 = arith.addi %376, %368 : index
cf.br ^bb27(%410 : index)
^bb31:
cf.br ^bb32
^bb32:
%411 = func.call @objective(%380, %384) : (f64, f64) -> f64
%412 = arith.cmpf olt, %411, %356 : f64
cf.cond_br %412, ^bb33, ^bb34
^bb33:
llvm.store %380, %142 : f64, !llvm.ptr
llvm.store %384, %144 : f64, !llvm.ptr
%413 = arith.constant 1 : i1
llvm.store %413, %363 : i1, !llvm.ptr
cf.br ^bb29(%376 : index)
^bb34:
cf.br ^bb35
^bb35:
%414 = llvm.load %360 : !llvm.ptr -> f64
%415 = arith.constant 0.5 : f32
%417 = arith.extf %415 : f32 to f64
%416 = arith.mulf %414, %417 : f64
llvm.store %416, %360 : f64, !llvm.ptr
%418 = arith.addi %376, %368 : index
cf.br ^bb27(%418 : index)
^bb29(%419: index):
%420 = llvm.load %363 : !llvm.ptr -> i1
%422 = arith.constant 1 : i1
%421 = arith.xori %420, %422 : i1
cf.cond_br %421, ^bb36, ^bb37
^bb36:
cf.br ^bb20(%157 : index)
^bb37:
cf.br ^bb38
^bb38:
%424 = arith.addi %157, %149 : index
cf.br ^bb18(%424 : index)
^bb20(%425: index):
%426 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%427 = llvm.load %142 : !llvm.ptr -> f64
%428 = llvm.insertvalue %427, %426[0] : !llvm.struct<(f64, f64)>
%429 = llvm.load %144 : !llvm.ptr -> f64
%430 = llvm.insertvalue %429, %428[1] : !llvm.struct<(f64, f64)>
%431 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%432 = llvm.extractvalue %430[0] : !llvm.struct<(f64, f64)>
%433 = llvm.insertvalue %432, %431[0] : !llvm.struct<(f64, f64)>
%434 = llvm.extractvalue %430[1] : !llvm.struct<(f64, f64)>
%435 = llvm.insertvalue %434, %433[1] : !llvm.struct<(f64, f64)>
%436 = llvm.mlir.constant(1 : i64) : i64
%437 = llvm.alloca %436 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %435, %437 : !llvm.struct<(f64, f64)>, !llvm.ptr
%438 = llvm.load %437 : !llvm.ptr -> !llvm.struct<(f64, f64)>
func.return %438 : !llvm.struct<(f64, f64)>
}
func.func @curvilinear_triangle_area(%arg0: f64, %arg1: f64, %arg2: f64) -> f64 {
%439 = arith.addf %arg1, %arg2 : f64
%440 = arith.addf %arg0, %arg2 : f64
%441 = arith.addf %arg0, %arg1 : f64
%442 = arith.constant 0.5 : f32
%443 = arith.addf %439, %440 : f64
%444 = arith.addf %443, %441 : f64
%446 = arith.extf %442 : f32 to f64
%445 = arith.mulf %446, %444 : f64
%447 = arith.subf %445, %439 : f64
%448 = arith.mulf %445, %447 : f64
%449 = arith.subf %445, %440 : f64
%450 = arith.mulf %448, %449 : f64
%451 = arith.subf %445, %441 : f64
%452 = arith.mulf %450, %451 : f64
%453 = llvm.mlir.constant(1 : i64) : i64
%454 = llvm.alloca %453 x f64 : (i64) -> !llvm.ptr
llvm.store %452, %454 : f64, !llvm.ptr
%455 = llvm.load %454 : !llvm.ptr -> f64
%456 = arith.constant 0.0 : f32
%458 = arith.extf %456 : f32 to f64
%457 = arith.cmpf olt, %455, %458 : f64
cf.cond_br %457, ^bb39, ^bb40
^bb39:
%459 = arith.constant 0.0 : f32
%460 = arith.extf %459 : f32 to f64
llvm.store %460, %454 : f64, !llvm.ptr
cf.br ^bb41
^bb40:
cf.br ^bb41
^bb41:
%461 = llvm.load %454 : !llvm.ptr -> f64
%462 = math.sqrt %461 : f64
%463 = arith.mulf %440, %440 : f64
%464 = arith.mulf %441, %441 : f64
%465 = arith.addf %463, %464 : f64
%466 = arith.mulf %439, %439 : f64
%467 = arith.subf %465, %466 : f64
%468 = arith.constant 2.0 : f32
%470 = arith.extf %468 : f32 to f64
%469 = arith.mulf %470, %440 : f64
%471 = arith.mulf %469, %441 : f64
%472 = arith.divf %467, %471 : f64
%473 = arith.mulf %439, %439 : f64
%474 = arith.mulf %441, %441 : f64
%475 = arith.addf %473, %474 : f64
%476 = arith.mulf %440, %440 : f64
%477 = arith.subf %475, %476 : f64
%478 = arith.constant 2.0 : f32
%480 = arith.extf %478 : f32 to f64
%479 = arith.mulf %480, %439 : f64
%481 = arith.mulf %479, %441 : f64
%482 = arith.divf %477, %481 : f64
%483 = arith.mulf %439, %439 : f64
%484 = arith.mulf %440, %440 : f64
%485 = arith.addf %483, %484 : f64
%486 = arith.mulf %441, %441 : f64
%487 = arith.subf %485, %486 : f64
%488 = arith.constant 2.0 : f32
%490 = arith.extf %488 : f32 to f64
%489 = arith.mulf %490, %439 : f64
%491 = arith.mulf %489, %440 : f64
%492 = arith.divf %487, %491 : f64
%495 = arith.constant 1.0 : f32
%496 = arith.negf %495 : f32
%497 = arith.constant 1.0 : f32
%498 = arith.extf %496 : f32 to f64
%499 = arith.extf %497 : f32 to f64
%494 = func.call @clampd(%472, %498, %499) : (f64, f64, f64) -> f64
%493 = func.call @acos(%494) : (f64) -> f64
%502 = arith.constant 1.0 : f32
%503 = arith.negf %502 : f32
%504 = arith.constant 1.0 : f32
%505 = arith.extf %503 : f32 to f64
%506 = arith.extf %504 : f32 to f64
%501 = func.call @clampd(%482, %505, %506) : (f64, f64, f64) -> f64
%500 = func.call @acos(%501) : (f64) -> f64
%509 = arith.constant 1.0 : f32
%510 = arith.negf %509 : f32
%511 = arith.constant 1.0 : f32
%512 = arith.extf %510 : f32 to f64
%513 = arith.extf %511 : f32 to f64
%508 = func.call @clampd(%492, %512, %513) : (f64, f64, f64) -> f64
%507 = func.call @acos(%508) : (f64) -> f64
%514 = arith.constant 0.5 : f32
%515 = arith.mulf %arg0, %arg0 : f64
%516 = arith.mulf %515, %493 : f64
%517 = arith.mulf %arg1, %arg1 : f64
%518 = arith.mulf %517, %500 : f64
%519 = arith.addf %516, %518 : f64
%520 = arith.mulf %arg2, %arg2 : f64
%521 = arith.mulf %520, %507 : f64
%522 = arith.addf %519, %521 : f64
%524 = arith.extf %514 : f32 to f64
%523 = arith.mulf %524, %522 : f64
%525 = arith.subf %462, %523 : f64
func.return %525 : f64
}
func.func @main() -> i32 {
%526 = func.call @find_initial_guess() : () -> !llvm.struct<(f64, f64)>
%527 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%528 = llvm.extractvalue %526[0] : !llvm.struct<(f64, f64)>
%529 = llvm.insertvalue %528, %527[0] : !llvm.struct<(f64, f64)>
%530 = llvm.extractvalue %526[1] : !llvm.struct<(f64, f64)>
%531 = llvm.insertvalue %530, %529[1] : !llvm.struct<(f64, f64)>
%532 = llvm.mlir.constant(1 : i64) : i64
%533 = llvm.alloca %532 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %531, %533 : !llvm.struct<(f64, f64)>, !llvm.ptr
%534 = llvm.load %533 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%535 = llvm.mlir.constant(1 : i64) : i64
%536 = llvm.alloca %535 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %534, %536 : !llvm.struct<(f64, f64)>, !llvm.ptr
%538 = llvm.load %536 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%539 = llvm.getelementptr %536[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%540 = llvm.load %539 : !llvm.ptr -> f64
%541 = llvm.load %536 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%542 = llvm.getelementptr %536[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%543 = llvm.load %542 : !llvm.ptr -> f64
%537 = func.call @newton_solve(%543, %540) : (f64, f64) -> !llvm.struct<(f64, f64)>
%544 = llvm.mlir.undef : !llvm.struct<(f64, f64)>
%545 = llvm.extractvalue %537[0] : !llvm.struct<(f64, f64)>
%546 = llvm.insertvalue %545, %544[0] : !llvm.struct<(f64, f64)>
%547 = llvm.extractvalue %537[1] : !llvm.struct<(f64, f64)>
%548 = llvm.insertvalue %547, %546[1] : !llvm.struct<(f64, f64)>
%549 = llvm.mlir.constant(1 : i64) : i64
%550 = llvm.alloca %549 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %548, %550 : !llvm.struct<(f64, f64)>, !llvm.ptr
%551 = llvm.load %550 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%552 = llvm.mlir.constant(1 : i64) : i64
%553 = llvm.alloca %552 x !llvm.struct<(f64, f64)> : (i64) -> !llvm.ptr
llvm.store %551, %553 : !llvm.struct<(f64, f64)>, !llvm.ptr
%554 = llvm.load %553 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%555 = llvm.getelementptr %553[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%556 = llvm.load %555 : !llvm.ptr -> f64
%557 = llvm.load %553 : !llvm.ptr -> !llvm.struct<(f64, f64)>
%558 = llvm.getelementptr %553[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(f64, f64)>
%559 = llvm.load %558 : !llvm.ptr -> f64
%561 = arith.constant 7.0 : f32
%562 = arith.extf %561 : f32 to f64
%560 = func.call @pow(%556, %562) : (f64, f64) -> f64
%563 = arith.mulf %560, %556 : f64
%565 = arith.constant 1.0 : f32
%566 = arith.extf %565 : f32 to f64
%564 = func.call @curvilinear_triangle_area(%566, %556, %563) : (f64, f64, f64) -> f64
%568 = arith.constant 1.0 : f32
%569 = arith.extf %568 : f32 to f64
%567 = func.call @curvilinear_triangle_area(%569, %560, %563) : (f64, f64, f64) -> f64
%570 = arith.addf %564, %567 : f64
%571 = arith.constant 1.0 : f32
%572 = arith.mulf %556, %556 : f64
%574 = arith.extf %571 : f32 to f64
%573 = arith.subf %574, %572 : f64
%575 = arith.divf %570, %573 : f64
%576 = llvm.mlir.addressof @str_0 : !llvm.ptr
%577 = llvm.call @printf(%576, %575) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, f64) -> i32
%578 = arith.constant 0 : i32
func.return %578 : i32
}
}