// File: /workspace/github_c_makefile_star2_O0/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:
subq $0xd8, %rsp
movsd %xmm0, 0xc8(%rsp)
movsd %xmm1, 0xc0(%rsp)
movq %rdi, 0xb8(%rsp)
movq %rsi, 0xb0(%rsp)
movl $0x0, 0x44(%rsp)
movsd 0xc8(%rsp), %xmm0
cvtsi2sdq 0x209215(%rip), %xmm1 # 0x21a738
ucomisd %xmm1, %xmm0
jae 0x11541
movsd 0xc8(%rsp), %xmm1
cvtsi2sdq 0x20901d(%rip), %xmm0 # 0x21a558
ucomisd %xmm1, %xmm0
jb 0x1159b
movsd 0xc8(%rsp), %xmm0
cvtsi2sdq 0x209005(%rip), %xmm1 # 0x21a558
ucomisd %xmm1, %xmm0
jbe 0x1156d
movq 0x2091d8(%rip), %rcx    # 0x21a738
movq 0xb8(%rsp), %rax
movq %rcx, (%rax)
jmp 0x1157f
movq 0x208fe4(%rip), %rcx    # 0x21a558
movq 0xb8(%rsp), %rax
movq %rcx, (%rax)
movq 0xb0(%rsp), %rax
movq $0x1, (%rax)
movb $0x1, 0xd7(%rsp)
jmp 0x11a69
xorps %xmm0, %xmm0
ucomisd 0xc0(%rsp), %xmm0
jbe 0x115d2
movsd 0xc0(%rsp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movsd %xmm0, 0xc0(%rsp)
movsd 0xc8(%rsp), %xmm0
subsd 0xc0(%rsp), %xmm0
movsd %xmm0, 0xa8(%rsp)
movsd 0xc8(%rsp), %xmm0
addsd 0xc0(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
movsd 0xa8(%rsp), %xmm0
callq 0x96c0
cvttsd2si %xmm0, %rax
movq %rax, 0x98(%rsp)
movsd 0xc0(%rsp), %xmm0
movsd 0x1d0334(%rip), %xmm1   # 0x1e1968
ucomisd %xmm1, %xmm0
jb 0x116b6
xorps %xmm0, %xmm0
ucomisd 0xa8(%rsp), %xmm0
jbe 0x11687
xorps %xmm0, %xmm0
ucomisd 0xa0(%rsp), %xmm0
jbe 0x11676
movsd 0xa0(%rsp), %xmm0
callq 0x95f0
cvttsd2si %xmm0, %rcx
movq 0xb8(%rsp), %rax
movq %rcx, (%rax)
jmp 0x11685
movq 0xb8(%rsp), %rax
movq $0x0, (%rax)
jmp 0x1169a
movq 0x98(%rsp), %rcx
movq 0xb8(%rsp), %rax
movq %rcx, (%rax)
movq 0xb0(%rsp), %rax
movq $0x1, (%rax)
movb $0x1, 0xd7(%rsp)
jmp 0x11a69
movsd 0xa0(%rsp), %xmm0
cvtsi2sdq 0x98(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jb 0x11729
cmpq $0x0, 0x98(%rsp)
jl 0x116ef
movq 0x98(%rsp), %rcx
movq 0xb8(%rsp), %rax
movq %rcx, (%rax)
jmp 0x1170d
movsd 0xa0(%rsp), %xmm0
callq 0x95f0
cvttsd2si %xmm0, %rcx
movq 0xb8(%rsp), %rax
movq %rcx, (%rax)
movq 0xb0(%rsp), %rax
movq $0x1, (%rax)
movb $0x1, 0xd7(%rsp)
jmp 0x11a69
movsd 0xa8(%rsp), %xmm0
callq 0x95f0
cvttsd2si %xmm0, %rax
movq %rax, 0x90(%rsp)
movsd 0xa0(%rsp), %xmm0
callq 0x96c0
cvttsd2si %xmm0, %rax
movq %rax, 0x88(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x80(%rsp)
movq $0x1, 0x78(%rsp)
movq 0x88(%rsp), %rax
movq %rax, 0x70(%rsp)
movq $0x1, 0x68(%rsp)
cvtsi2sdq 0x88(%rsp), %xmm0
subsd 0xa8(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0xa8(%rsp), %xmm0
cvtsi2sdq 0x90(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x58(%rsp)
cvtsi2sdq 0x88(%rsp), %xmm0
subsd 0xa0(%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0xa0(%rsp), %xmm0
cvtsi2sdq 0x90(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
cvtsi2sdq 0x80(%rsp), %xmm0
cvtsi2sdq 0x78(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0xa8(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x1183f
movsd 0x10(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jae 0x1186c
movsd 0x58(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x11852
jp 0x11852
jmp 0x1186c
movsd 0x48(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x11865
jp 0x11865
jmp 0x1186c
cmpl $0x64, 0x44(%rsp)
jle 0x118d5
movq 0x78(%rsp), %rax
cmpq 0x208ce0(%rip), %rax    # 0x21a558
jne 0x118a5
cmpq $0x1, 0x80(%rsp)
jne 0x118a5
movq 0xb8(%rsp), %rax
movq $0x0, (%rax)
movq 0xb0(%rsp), %rax
movq $0x1, (%rax)
jmp 0x118c8
movq 0x80(%rsp), %rcx
movq 0xb8(%rsp), %rax
movq %rcx, (%rax)
movq 0x78(%rsp), %rcx
movq 0xb0(%rsp), %rax
movq %rcx, (%rax)
movb $0x1, 0xd7(%rsp)
jmp 0x11a69
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
movsd 0x60(%rsp), %xmm0
divsd 0x58(%rsp), %xmm0
callq 0x95f0
cvttsd2si %xmm0, %rax
cvtsi2sd %rax, %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x50(%rsp), %xmm0
divsd 0x48(%rsp), %xmm0
callq 0x96c0
cvttsd2si %xmm0, %rax
cvtsi2sd %rax, %xmm0
movsd %xmm0, (%rsp)
movsd (%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1193d
movsd (%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movq 0x70(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0x68(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0x68(%rsp)
movsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x50(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
cvtsi2sdq 0x38(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
cvtsi2sdq 0x80(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, 0x80(%rsp)
cvtsi2sdq 0x30(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
cvtsi2sdq 0x78(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, 0x78(%rsp)
movsd 0x18(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
movsd 0x48(%rsp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x28(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
movsd 0x20(%rsp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
jmp 0x117fa
movb 0xd7(%rsp), %al
andb $0x1, %al
addq $0xd8, %rsp
retq
nopw (%rax,%rax)