// File: /workspace/github_c_makefile_star2_O3/BernardTatin[P]s7sh/s7.c
// Function: c_rationalize
static bool c_rationalize(s7_double ux, s7_double error, s7_int *numer, s7_int *denom)
    {
        /*
           (define* (rat ux (err 0.0000001))
           ;; translated from CL code in Canny, Donald, Ressler, "A Rational Rotation Method for Robust Geometric Algorithms"
           (let ((x0 (- ux error))
           (x1 (+ ux error)))
           (let ((i (ceiling x0))
           (i0 (floor x0))
           (i1 (ceiling x1))
           (r 0))
           (if (>= x1 i)
           i
           (do ((p0 i0 (+ p1 (* r p0)))
           (q0 1 (+ q1 (* r q0)))
           (p1 i1 p0)
           (q1 1 q0)
           (e0 (- i1 x0) e1p)
           (e1 (- x0 i0) (- e0p (* r e1p)))
           (e0p (- i1 x1) e1)
           (e1p (- x1 i0) (- e0 (* r e1))))
           ((<= x0 (/ p0 q0) x1)
           (/ p0 q0))
           (set! r (min (floor (/ e0 e1))
           (ceiling (/ e0p e1p)))))))))
           */

        double x0, x1;
        s7_int i, i0, i1, p0, q0, p1, q1;
        double e0, e1, e0p, e1p;
        int32_t tries = 0;
        /* don't use long double: the loop below will hang */

        /* #e1e19 is a killer -- it's bigger than most-positive-fixnum, but if we ceil(ux) below
         *   it turns into most-negative-fixnum.  1e19 is trouble in many places.
         */
        if ((ux >= s7_int_max) || (ux <= s7_int_min)) /* (rationalize most-positive-fixnum) should not return most-negative-fixnum */
        {
            /* can't return false here because that confuses some of the callers! */
            if (ux > s7_int_min) (*numer) = s7_int_max; else (*numer) = s7_int_min;
            (*denom) = 1;
            return(true);
        }

        if (error < 0.0) error = -error;
        x0 = ux - error;
        x1 = ux + error;
        i = (s7_int)ceil(x0);

        if (error >= 1.0) /* aw good grief! */
        {
            if (x0 < 0)
            {
                if (x1 < 0)
                    (*numer) = (s7_int)floor(x1);
                else (*numer) = 0;
            }
            else (*numer) = i;
            (*denom) = 1;
            return(true);
        }

        if (x1 >= i)
        {
            if (i >= 0)
                (*numer) = i;
            else (*numer) = (s7_int)floor(x1);
            (*denom) = 1;
            return(true);
        }

        i0 = (s7_int)floor(x0);
        i1 = (s7_int)ceil(x1);

        p0 = i0;
        q0 = 1;
        p1 = i1;
        q1 = 1;
        e0 = i1 - x0;
        e1 = x0 - i0;
        e0p = i1 - x1;
        e1p = x1 - i0;

        while (true)
        {
            s7_int old_p1, old_q1;
            double old_e0, old_e1, old_e0p, val, r, r1;
            val = (double)p0 / (double)q0;

            if (((x0 <= val) && (val <= x1)) ||
                    (e1 == 0)                    ||
                    (e1p == 0)                   ||
                    (tries > 100))
            {
                if ((q0 == s7_int_min) && (p0 == 1)) /* (rationalize 1.000000004297917e-12) when error is 1e-12 */
                {
                    (*numer) = 0;
                    (*denom) = 1;
                }
                else
                {
                    (*numer) = p0;
                    (*denom) = q0;
                }
                return(true);
            }
            tries++;

            r = (s7_int)floor(e0 / e1);
            r1 = (s7_int)ceil(e0p / e1p);
            if (r1 < r) r = r1;

            /* do handles all step vars in parallel */
            old_p1 = p1;
            p1 = p0;
            old_q1 = q1;
            q1 = q0;
            old_e0 = e0;
            e0 = e1p;
            old_e0p = e0p;
            e0p = e1;
            old_e1 = e1;

            p0 = old_p1 + r * p0;
            q0 = old_q1 + r * q0;
            e1 = old_e0p - r * e1p;
            /* if the error is set too low, we can get e1 = 0 here: (rationalize (/ pi) 1e-17) */
            e1p = old_e0 - r * old_e1;
        }
        return(false);
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rsi, %r14
movq %rdi, %r15
movb 0x13df6d(%rip), %cl     # 0x14ac08
xorpd %xmm3, %xmm3
testb %cl, %cl
jne 0xcca9
xorpd %xmm2, %xmm2
jmp 0xccb1
movsd 0xf936f(%rip), %xmm2    # 0x106020
movb 0x13dd70(%rip), %bpl    # 0x14aa28
testb %bpl, %bpl
je 0xccc5
movsd 0xf9363(%rip), %xmm3    # 0x106028
ucomisd %xmm2, %xmm0
jae 0xcef6
ucomisd %xmm0, %xmm3
jae 0xcef6
movapd 0xfd1cf(%rip), %xmm2    # 0x109eb0
xorpd %xmm1, %xmm2
maxsd %xmm1, %xmm2
movapd %xmm2, 0x30(%rsp)
movapd %xmm2, %xmm1
addsd %xmm0, %xmm1
movapd %xmm1, 0x10(%rsp)
subsd %xmm2, %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x86c0
cvttsd2si %xmm0, %rax
movapd 0x30(%rsp), %xmm0
ucomisd 0xf9311(%rip), %xmm0    # 0x106030
jae 0xcf3d
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
movapd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jae 0xcf5e
movq %r15, 0x40(%rsp)
movq %r14, 0x48(%rsp)
movsd 0x8(%rsp), %xmm0
callq 0x85f0
cvttsd2si %xmm0, %r15
movapd 0x10(%rsp), %xmm0
callq 0x86c0
movsd 0x8(%rsp), %xmm3
cvttsd2si %xmm0, %rbx
cvtsi2sd %rbx, %xmm4
movapd %xmm4, %xmm5
subsd %xmm3, %xmm5
xorps %xmm2, %xmm2
cvtsi2sd %r15, %xmm2
movapd %xmm3, %xmm0
subsd %xmm2, %xmm0
movapd 0x10(%rsp), %xmm1
subsd %xmm1, %xmm4
subsd %xmm2, %xmm1
movl $0x1, %r14d
xorl %r12d, %r12d
xorpd %xmm2, %xmm2
movl $0x1, %r13d
movapd %xmm1, %xmm6
movapd %xmm0, %xmm7
xorps %xmm9, %xmm9
cvtsi2sd %r15, %xmm9
xorps %xmm8, %xmm8
cvtsi2sd %r13, %xmm8
movapd %xmm9, %xmm0
divsd %xmm8, %xmm0
ucomisd %xmm3, %xmm0
jb 0xcde5
movapd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jae 0xcf78
ucomisd %xmm2, %xmm7
jne 0xcdf1
jnp 0xcf78
ucomisd %xmm2, %xmm6
jne 0xcdfd
jnp 0xcf78
cmpl $0x65, %r12d
jae 0xcf78
incl %r12d
movapd %xmm5, %xmm0
divsd %xmm7, %xmm0
movsd %xmm4, 0x30(%rsp)
movsd %xmm5, 0x70(%rsp)
movsd %xmm6, 0x28(%rsp)
movsd %xmm7, 0x68(%rsp)
movsd %xmm8, 0x60(%rsp)
movsd %xmm9, 0x58(%rsp)
callq 0x85f0
cvttsd2si %xmm0, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x30(%rsp), %xmm0
divsd 0x28(%rsp), %xmm0
callq 0x86c0
xorpd %xmm2, %xmm2
movsd 0x8(%rsp), %xmm3
cvttsd2si %xmm0, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
minsd 0x50(%rsp), %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %rbx, %xmm1
movsd 0x58(%rsp), %xmm4
mulsd %xmm0, %xmm4
addsd %xmm1, %xmm4
cvttsd2si %xmm4, %rax
xorps %xmm1, %xmm1
cvtsi2sd %r14, %xmm1
movsd 0x60(%rsp), %xmm4
mulsd %xmm0, %xmm4
addsd %xmm1, %xmm4
movq %r13, %r14
cvttsd2si %xmm4, %r13
movq %r15, %rbx
movapd %xmm0, %xmm1
movsd 0x28(%rsp), %xmm5
mulsd %xmm5, %xmm1
movsd 0x30(%rsp), %xmm4
subsd %xmm1, %xmm4
movsd 0x68(%rsp), %xmm6
mulsd %xmm6, %xmm0
movsd 0x70(%rsp), %xmm1
subsd %xmm0, %xmm1
movapd %xmm4, %xmm0
movapd %xmm6, %xmm4
movq %rax, %r15
jmp 0xcdab
movzbl %bpl, %edx
shlq $0x3f, %rdx
xorps %xmm1, %xmm1
cvtsi2sd %rdx, %xmm1
movabsq $-0x8000000000000000, %rsi # imm = 0x8000000000000000
decq %rsi
xorl %eax, %eax
testb %cl, %cl
cmovneq %rsi, %rax
ucomisd %xmm1, %xmm0
cmovbeq %rdx, %rax
movl $0x1, %ebx
movq %rax, (%r15)
movq %rbx, (%r14)
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movapd 0x10(%rsp), %xmm1
movl $0x1, %ebx
xorpd %xmm0, %xmm0
ucomisd 0x8(%rsp), %xmm0
jbe 0xcf28
ucomisd %xmm1, %xmm0
ja 0xcf68
xorl %eax, %eax
jmp 0xcf28
movl $0x1, %ebx
testq %rax, %rax
jns 0xcf28
movapd %xmm1, %xmm0
callq 0x85f0
cvttsd2si %xmm0, %rax
jmp 0xcf28
movzbl %bpl, %ecx
shlq $0x3f, %rcx
xorq %r13, %rcx
movq %r15, %rdx
xorq $0x1, %rdx
xorl %eax, %eax
orq %rcx, %rdx
cmovneq %r15, %rax
movl $0x1, %ebx
cmovneq %r13, %rbx
movq 0x48(%rsp), %r14
movq 0x40(%rsp), %r15
jmp 0xcf28