Problem 894

Spiral of Circles: Newton solve for (s, theta) then compute total curvilinear triangle area.

Answer0.7718678168
Output0.7718678168
StatusPASS
Native helperno
Runtime0 ms
Peak memory1072 KB
Time complexityO(n^2) (estimated)
Space complexityO(1) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^2)O(n^2)
Space complexityO(1)O(n^2)
ApproachFlow solutionBottom-up DP
VerdictOptimal

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
  }
}