// File: /workspace/github_c_makefile_star2_O1/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 $0x88, %rsp
movq %rsi, %rbx
movq %rdi, %r12
movb 0x1451ad(%rip), %cl     # 0x152c08
testb %cl, %cl
jne 0xda65
xorpd %xmm2, %xmm2
jmp 0xda6d
movsd 0x1015b3(%rip), %xmm2   # 0x10f020
ucomisd %xmm2, %xmm0
jae 0xdd02
movb 0x144faa(%rip), %bpl    # 0x152a28
testb %bpl, %bpl
jne 0xda89
xorpd %xmm2, %xmm2
jmp 0xda91
movsd 0x101597(%rip), %xmm2   # 0x10f028
ucomisd %xmm0, %xmm2
jae 0xdd02
movapd 0x10531d(%rip), %xmm2   # 0x112dc0
xorpd %xmm1, %xmm2
maxsd %xmm1, %xmm2
movapd %xmm2, 0x20(%rsp)
movapd %xmm2, %xmm1
addsd %xmm0, %xmm1
movapd %xmm1, 0x10(%rsp)
subsd %xmm2, %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x96c0
cvttsd2si %xmm0, %rax
movapd 0x20(%rsp), %xmm0
ucomisd 0x10154f(%rip), %xmm0   # 0x10f030
jae 0xdd4e
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
movapd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jae 0xdd6a
movsd 0x8(%rsp), %xmm0
callq 0x95f0
cvttsd2si %xmm0, %r15
movapd 0x10(%rsp), %xmm0
callq 0x96c0
movapd 0x10(%rsp), %xmm1
movsd 0x8(%rsp), %xmm2
cvttsd2si %xmm0, %rdi
cvtsi2sd %rdi, %xmm3
movapd %xmm3, %xmm4
subsd %xmm2, %xmm4
xorps %xmm0, %xmm0
cvtsi2sd %r15, %xmm0
movapd %xmm2, %xmm5
subsd %xmm0, %xmm5
subsd %xmm1, %xmm3
movapd %xmm1, %xmm6
subsd %xmm0, %xmm6
movzbl %bpl, %ebp
shlq $0x3f, %rbp
movl $0x1, %esi
xorl %r9d, %r9d
xorpd %xmm7, %xmm7
movl $0x1, %r10d
movl $0x1, %r13d
xorps %xmm9, %xmm9
cvtsi2sd %r15, %xmm9
xorps %xmm8, %xmm8
cvtsi2sd %r13, %xmm8
movapd %xmm9, %xmm0
divsd %xmm8, %xmm0
ucomisd %xmm2, %xmm0
jb 0xdb9c
ucomisd %xmm0, %xmm1
jae 0xdbbd
ucomisd %xmm7, %xmm5
jne 0xdba4
jnp 0xdbbd
ucomisd %xmm7, %xmm6
setnp %al
sete %cl
andb %al, %cl
cmpl $0x65, %r9d
setge %al
orb %cl, %al
cmpb $0x1, %al
jne 0xdbeb
movq %r13, %rcx
xorq %rbp, %rcx
movq %r15, %rdx
xorq $0x1, %rdx
xorl %eax, %eax
orq %rcx, %rdx
movl $0x0, %ecx
cmovneq %r15, %rcx
movq %r13, %rdx
cmoveq %rsi, %rdx
movq %rcx, (%r12)
movq %rdx, (%rbx)
jmp 0xdcf8
incl %r9d
movapd %xmm4, %xmm0
divsd %xmm5, %xmm0
movsd %xmm3, 0x20(%rsp)
movsd %xmm4, 0x68(%rsp)
movsd %xmm5, 0x60(%rsp)
movapd %xmm6, 0x70(%rsp)
movq %rdi, 0x48(%rsp)
movq %rbx, %r14
movl %r9d, %ebx
movq %r10, 0x50(%rsp)
movsd %xmm8, 0x58(%rsp)
movsd %xmm9, 0x40(%rsp)
callq 0x95f0
cvttsd2si %xmm0, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
movsd %xmm0, 0x38(%rsp)
movsd 0x20(%rsp), %xmm0
divsd 0x70(%rsp), %xmm0
callq 0x96c0
movl %ebx, %r9d
movq %r14, %rbx
xorpd %xmm7, %xmm7
movl $0x1, %esi
movsd 0x8(%rsp), %xmm2
cvttsd2si %xmm0, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
minsd 0x38(%rsp), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x48(%rsp), %xmm1
movsd 0x40(%rsp), %xmm3
mulsd %xmm0, %xmm3
addsd %xmm1, %xmm3
cvttsd2si %xmm3, %rcx
xorps %xmm1, %xmm1
cvtsi2sdq 0x50(%rsp), %xmm1
movq %r15, %rdi
movsd 0x58(%rsp), %xmm3
mulsd %xmm0, %xmm3
addsd %xmm1, %xmm3
movq %r13, %r10
cvttsd2si %xmm3, %r13
movapd %xmm0, %xmm1
movapd 0x70(%rsp), %xmm4
mulsd %xmm4, %xmm1
movsd 0x20(%rsp), %xmm5
subsd %xmm1, %xmm5
movsd 0x60(%rsp), %xmm3
mulsd %xmm3, %xmm0
movsd 0x68(%rsp), %xmm1
subsd %xmm0, %xmm1
movb $0x1, %al
movq %rcx, %r15
movapd %xmm1, %xmm6
movapd 0x10(%rsp), %xmm1
testb %al, %al
jne 0xdb74
jmp 0xdd3c
movl 0x144d20(%rip), %edx    # 0x152a28
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
movq %rax, (%r12)
movq $0x1, (%rbx)
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorpd %xmm1, %xmm1
ucomisd 0x8(%rsp), %xmm1
movapd 0x10(%rsp), %xmm0
jbe 0xdd31
ucomisd %xmm0, %xmm1
ja 0xdd73
xorl %eax, %eax
jmp 0xdd31
testq %rax, %rax
jns 0xdd31
movapd %xmm1, %xmm0
callq 0x95f0
cvttsd2si %xmm0, %rax
jmp 0xdd31