#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef unsigned int uint64_t;

/* Variables and functions */
int /*<<< orphan*/ INFINITY;
unsigned int UINT64_MAX;
unsigned int eh_float64_to_uint64(double);
scalar_t__ isinf(double);
scalar_t__ isnan(double);
double nextafter(double, int /*<<< orphan*/);
uint64_t _float64_distance(double l, double r) {
  uint64_t u64a, u64b;
  double tmp;
  if (l == r) {
    return 0;
  }
  if (isnan(l) || isnan(r) || isinf(l) || isinf(r)) {
    return UINT64_MAX;
  }
  if (r > l) {
    tmp = l;
    l = r;
    r = tmp;
  }
  if (nextafter(r, INFINITY) == l) {
    return 1U;
  }
  if (l > 0.0 && r < 0.0) {
    u64a = _float64_distance(l, 0.0);
    u64b = 1U + _float64_distance(r, nextafter(0.0, -INFINITY));
    return u64a + u64b;
  }
  u64a = eh_float64_to_uint64(l);
  u64b = eh_float64_to_uint64(r);
  if (u64b > u64a) {
    do {
      if (&(u64a) != &(u64b)) {
        (u64a) ^= (u64b);
        (u64b) ^= (u64a);
        (u64a) ^= (u64b);
      }
    } while (0);
  }
  return u64a - u64b;
}


x86 assembly (clang, -O0):
<_float64_distance>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
ucomisd -0x18(%rbp),%xmm0
jne    1184 <_float64_distance+0x34>
jp     1184 <_float64_distance+0x34>
movl   $0x0,-0x4(%rbp)
jmp    1305 <_float64_distance+0x1b5>
movsd  -0x10(%rbp),%xmm0
call   1050 <isnan@plt>
cmp    $0x0,%rax
jne    11d4 <_float64_distance+0x84>
movsd  -0x18(%rbp),%xmm0
call   1050 <isnan@plt>
cmp    $0x0,%rax
jne    11d4 <_float64_distance+0x84>
movsd  -0x10(%rbp),%xmm0
call   1070 <isinf@plt>
cmp    $0x0,%rax
jne    11d4 <_float64_distance+0x84>
movsd  -0x18(%rbp),%xmm0
call   1070 <isinf@plt>
cmp    $0x0,%rax
je     11e5 <_float64_distance+0x95>
mov    0x2df5(%rip),%rax
mov    (%rax),%eax
mov    %eax,-0x4(%rbp)
jmp    1305 <_float64_distance+0x1b5>
movsd  -0x18(%rbp),%xmm0
ucomisd -0x10(%rbp),%xmm0
jbe    1213 <_float64_distance+0xc3>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
mov    0x2dc9(%rip),%rax
mov    (%rax),%edi
call   1060 <nextafter@plt>
ucomisd -0x10(%rbp),%xmm0
jne    1243 <_float64_distance+0xf3>
jp     1243 <_float64_distance+0xf3>
movl   $0x1,-0x4(%rbp)
jmp    1305 <_float64_distance+0x1b5>
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    12b1 <_float64_distance+0x161>
xorps  %xmm0,%xmm0
ucomisd -0x18(%rbp),%xmm0
jbe    12b1 <_float64_distance+0x161>
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
call   1040 <_float64_distance@plt>
mov    %eax,-0x1c(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
xor    %edi,%edi
mov    0x2d62(%rip),%rax
sub    (%rax),%edi
xorps  %xmm0,%xmm0
call   1060 <nextafter@plt>
movaps %xmm0,%xmm1
movsd  -0x30(%rbp),%xmm0
call   1040 <_float64_distance@plt>
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
mov    -0x1c(%rbp),%eax
add    -0x20(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    1305 <_float64_distance+0x1b5>
movsd  -0x10(%rbp),%xmm0
call   1030 <eh_float64_to_uint64@plt>
mov    %eax,-0x1c(%rbp)
movsd  -0x18(%rbp),%xmm0
call   1030 <eh_float64_to_uint64@plt>
mov    %eax,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jbe    12fc <_float64_distance+0x1ac>
jmp    12dc <_float64_distance+0x18c>
mov    -0x20(%rbp),%eax
xor    -0x1c(%rbp),%eax
mov    %eax,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
xor    -0x20(%rbp),%eax
mov    %eax,-0x20(%rbp)
mov    -0x20(%rbp),%eax
xor    -0x1c(%rbp),%eax
mov    %eax,-0x1c(%rbp)
jmp    12fc <_float64_distance+0x1ac>
mov    -0x1c(%rbp),%eax
sub    -0x20(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<_float64_distance>:
push   %r14
push   %rbx
sub    $0x18,%rsp
xor    %eax,%eax
ucomisd %xmm1,%xmm0
jne    1161 <_float64_distance+0x11>
jnp    11ae <_float64_distance+0x5e>
movsd  %xmm1,0x8(%rsp)
movsd  %xmm0,(%rsp)
call   1050 <isnan@plt>
test   %rax,%rax
jne    11a5 <_float64_distance+0x55>
movsd  0x8(%rsp),%xmm0
call   1050 <isnan@plt>
test   %rax,%rax
jne    11a5 <_float64_distance+0x55>
movsd  (%rsp),%xmm0
call   1070 <isinf@plt>
test   %rax,%rax
jne    11a5 <_float64_distance+0x55>
movsd  0x8(%rsp),%xmm0
call   1070 <isinf@plt>
test   %rax,%rax
je     11b6 <_float64_distance+0x66>
mov    0x2e24(%rip),%rax
mov    (%rax),%eax
add    $0x18,%rsp
pop    %rbx
pop    %r14
ret
movsd  0x8(%rsp),%xmm2
movapd %xmm2,%xmm1
movsd  (%rsp),%xmm0
maxsd  %xmm0,%xmm1
movsd  %xmm1,0x10(%rsp)
minsd  %xmm2,%xmm0
movsd  %xmm0,(%rsp)
mov    0x2e09(%rip),%rbx
mov    (%rbx),%edi
call   1060 <nextafter@plt>
movsd  0x10(%rsp),%xmm2
movsd  (%rsp),%xmm1
mov    $0x1,%eax
ucomisd %xmm2,%xmm0
jne    11fe <_float64_distance+0xae>
jnp    11ae <_float64_distance+0x5e>
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm2
jbe    1244 <_float64_distance+0xf4>
ucomisd %xmm1,%xmm0
jbe    1244 <_float64_distance+0xf4>
xorpd  %xmm1,%xmm1
movapd %xmm2,%xmm0
call   1040 <_float64_distance@plt>
mov    %eax,%r14d
xor    %edi,%edi
sub    (%rbx),%edi
xorpd  %xmm0,%xmm0
call   1060 <nextafter@plt>
movapd %xmm0,%xmm1
movsd  (%rsp),%xmm0
call   1040 <_float64_distance@plt>
add    %r14d,%eax
add    $0x1,%eax
jmp    11ae <_float64_distance+0x5e>
movapd %xmm2,%xmm0
call   1030 <eh_float64_to_uint64@plt>
mov    %eax,%ebx
movsd  (%rsp),%xmm0
call   1030 <eh_float64_to_uint64@plt>
mov    %eax,%ecx
cmp    %ebx,%eax
mov    %ebx,%eax
cmova  %ecx,%eax
cmova  %ebx,%ecx
sub    %ecx,%eax
jmp    11ae <_float64_distance+0x5e>

LLVM IR (-O0):
@UINT64_MAX = global i32 0
@INFINITY = global i32 0
define i32 @_float64_distance(double %0, double %1) {
%3 = alloca i32
%4 = alloca double
%5 = alloca double
%6 = alloca i32
%7 = alloca i32
%8 = alloca double
store double %0, double* %4
store double %1, double* %5
%9 = load double, double* %4
%10 = load double, double* %5
%11 = fcmp oeq double %9, %10
br i1 %11, label %12, label %13
12: ; preds = %2
store i32 0, i32* %3
br label %88
13: ; preds = %2
%14 = load double, double* %4
%15 = call i64 @isnan(double %14)
%16 = icmp ne i64 %15, 0
br i1 %16, label %29, label %17
17: ; preds = %13
%18 = load double, double* %5
%19 = call i64 @isnan(double %18)
%20 = icmp ne i64 %19, 0
br i1 %20, label %29, label %21
21: ; preds = %17
%22 = load double, double* %4
%23 = call i64 @isinf(double %22)
%24 = icmp ne i64 %23, 0
br i1 %24, label %29, label %25
25: ; preds = %21
%26 = load double, double* %5
%27 = call i64 @isinf(double %26)
%28 = icmp ne i64 %27, 0
br i1 %28, label %29, label %31
29: ; preds = %25, %21, %17, %13
%30 = load i32, i32* @UINT64_MAX
store i32 %30, i32* %3
br label %88
31: ; preds = %25
%32 = load double, double* %5
%33 = load double, double* %4
%34 = fcmp ogt double %32, %33
br i1 %34, label %35, label %39
35: ; preds = %31
%36 = load double, double* %4
store double %36, double* %8
%37 = load double, double* %5
store double %37, double* %4
%38 = load double, double* %8
store double %38, double* %5
br label %39
39: ; preds = %35, %31
%40 = load double, double* %5
%41 = load i32, i32* @INFINITY
%42 = call double @nextafter(double %40, i32 %41)
%43 = load double, double* %4
%44 = fcmp oeq double %42, %43
br i1 %44, label %45, label %46
45: ; preds = %39
store i32 1, i32* %3
br label %88
46: ; preds = %39
%47 = load double, double* %4
%48 = fcmp ogt double %47, 0.000000e+00
br i1 %48, label %49, label %64
49: ; preds = %46
%50 = load double, double* %5
%51 = fcmp olt double %50, 0.000000e+00
br i1 %51, label %52, label %64
52: ; preds = %49
%53 = load double, double* %4
%54 = call i32 @_float64_distance(double %53, double 0.000000e+00)
store i32 %54, i32* %6
%55 = load double, double* %5
%56 = load i32, i32* @INFINITY
%57 = sub nsw i32 0, %56
%58 = call double @nextafter(double 0.000000e+00, i32 %57)
%59 = call i32 @_float64_distance(double %55, double %58)
%60 = add i32 1, %59
store i32 %60, i32* %7
%61 = load i32, i32* %6
%62 = load i32, i32* %7
%63 = add i32 %61, %62
store i32 %63, i32* %3
br label %88
64: ; preds = %49, %46
%65 = load double, double* %4
%66 = call i32 @eh_float64_to_uint64(double %65)
store i32 %66, i32* %6
%67 = load double, double* %5
%68 = call i32 @eh_float64_to_uint64(double %67)
store i32 %68, i32* %7
%69 = load i32, i32* %7
%70 = load i32, i32* %6
%71 = icmp ugt i32 %69, %70
br i1 %71, label %72, label %84
72: ; preds = %64
br label %73
73: ; preds = %72
%74 = load i32, i32* %7
%75 = load i32, i32* %6
%76 = xor i32 %75, %74
store i32 %76, i32* %6
%77 = load i32, i32* %6
%78 = load i32, i32* %7
%79 = xor i32 %78, %77
store i32 %79, i32* %7
%80 = load i32, i32* %7
%81 = load i32, i32* %6
%82 = xor i32 %81, %80
store i32 %82, i32* %6
br label %83
83: ; preds = %73
br label %84
84: ; preds = %83, %64
%85 = load i32, i32* %6
%86 = load i32, i32* %7
%87 = sub i32 %85, %86
store i32 %87, i32* %3
br label %88
88: ; preds = %84, %52, %45, %29, %12
%89 = load i32, i32* %3
ret i32 %89
}

LLVM IR (-O2):
@UINT64_MAX = global i32 0
@INFINITY = global i32 0
define i32 @_float64_distance(double %0, double %1) {
%3 = fcmp oeq double %0, %1
br i1 %3, label %29, label %4
4: ; preds = %2
%5 = tail call i64 @isnan(double %0)
%6 = icmp eq i64 %5, 0
br i1 %6, label %7, label %16
7: ; preds = %4
%8 = tail call i64 @isnan(double %1)
%9 = icmp eq i64 %8, 0
br i1 %9, label %10, label %16
10: ; preds = %7
%11 = tail call i64 @isinf(double %0)
%12 = icmp eq i64 %11, 0
br i1 %12, label %13, label %16
13: ; preds = %10
%14 = tail call i64 @isinf(double %1)
%15 = icmp eq i64 %14, 0
br i1 %15, label %18, label %16
16: ; preds = %13, %10, %7, %4
%17 = load i32, i32* @UINT64_MAX
br label %29
18: ; preds = %13
%19 = fcmp ogt double %1, %0
%20 = select i1 %19, double %1, double %0
%21 = select i1 %19, double %0, double %1
%22 = load i32, i32* @INFINITY
%23 = tail call double @nextafter(double %21, i32 %22)
%24 = fcmp oeq double %23, %20
br i1 %24, label %29, label %25
25: ; preds = %18
%26 = fcmp ogt double %20, 0.000000e+00
%27 = fcmp olt double %21, 0.000000e+00
%28 = and i1 %26, %27
br i1 %28, label %31, label %39
29: ; preds = %16, %39, %2, %18, %31
%30 = phi i32 [ %38, %31 ], [ %17, %16 ], [ %45, %39 ], [ 0, %2 ], [ 1, %18 ]
ret i32 %30
31: ; preds = %25
%32 = tail call i32 @_float64_distance(double %20, double 0.000000e+00)
%33 = load i32, i32* @INFINITY
%34 = sub nsw i32 0, %33
%35 = tail call double @nextafter(double 0.000000e+00, i32 %34)
%36 = tail call i32 @_float64_distance(double %21, double %35)
%37 = add i32 %32, 1
%38 = add i32 %37, %36
br label %29
39: ; preds = %25
%40 = tail call i32 @eh_float64_to_uint64(double %20)
%41 = tail call i32 @eh_float64_to_uint64(double %21)
%42 = icmp ugt i32 %41, %40
%43 = select i1 %42, i32 %41, i32 %40
%44 = select i1 %42, i32 %40, i32 %41
%45 = sub i32 %43, %44
br label %29
}