#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 */

/* Variables and functions */
unsigned long long LLONG_MIN;
double fabs(double);
unsigned long long ulp(double x, double y) {
  if (x == 0)
    x = fabs(x);
  if (y == 0)
    y = fabs(y);
  if (x != x && y != y)
    return 0;
  if (x != x)
    return LLONG_MIN;
  if (y != y)
    return LLONG_MIN;
  long long xx = *((unsigned long long *)&x);
  xx = xx < 0 ? LLONG_MIN - xx : xx;
  long long yy = *((unsigned long long *)&y);
  yy = yy < 0 ? LLONG_MIN - yy : yy;
  return xx >= yy ? xx - yy : yy - xx;
}


x86 assembly (clang, -O0):
<ulp>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    113b <ulp+0x3b>
jp     113b <ulp+0x3b>
movsd  -0x10(%rbp),%xmm0
movaps 0xece(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  -0x18(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    1168 <ulp+0x68>
jp     1168 <ulp+0x68>
movsd  -0x18(%rbp),%xmm0
movaps 0xea1(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
ucomisd -0x10(%rbp),%xmm0
jne    1183 <ulp+0x83>
jp     1183 <ulp+0x83>
jmp    11ab <ulp+0xab>
movsd  -0x18(%rbp),%xmm0
ucomisd -0x18(%rbp),%xmm0
jne    119e <ulp+0x9e>
jp     119e <ulp+0x9e>
jmp    11ab <ulp+0xab>
movq   $0x0,-0x8(%rbp)
jmp    12ae <ulp+0x1ae>
movsd  -0x10(%rbp),%xmm0
ucomisd -0x10(%rbp),%xmm0
jne    11c6 <ulp+0xc6>
jp     11c6 <ulp+0xc6>
jmp    11d9 <ulp+0xd9>
mov    0x2e13(%rip),%rax
mov    (%rax),%rax
mov    %rax,-0x8(%rbp)
jmp    12ae <ulp+0x1ae>
movsd  -0x18(%rbp),%xmm0
ucomisd -0x18(%rbp),%xmm0
jne    11f4 <ulp+0xf4>
jp     11f4 <ulp+0xf4>
jmp    1207 <ulp+0x107>
mov    0x2de5(%rip),%rax
mov    (%rax),%rax
mov    %rax,-0x8(%rbp)
jmp    12ae <ulp+0x1ae>
mov    -0x10(%rbp),%rax
mov    %rax,-0x20(%rbp)
cmpq   $0x0,-0x20(%rbp)
jge    1231 <ulp+0x131>
mov    0x2dbf(%rip),%rax
mov    (%rax),%rax
sub    -0x20(%rbp),%rax
mov    %rax,-0x30(%rbp)
jmp    1239 <ulp+0x139>
mov    -0x20(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x28(%rbp)
cmpq   $0x0,-0x28(%rbp)
jge    126b <ulp+0x16b>
mov    0x2d85(%rip),%rax
mov    (%rax),%rax
sub    -0x28(%rbp),%rax
mov    %rax,-0x38(%rbp)
jmp    1273 <ulp+0x173>
mov    -0x28(%rbp),%rax
mov    %rax,-0x38(%rbp)
mov    -0x38(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x20(%rbp),%rax
cmp    -0x28(%rbp),%rax
jl     129a <ulp+0x19a>
mov    -0x20(%rbp),%rax
sub    -0x28(%rbp),%rax
mov    %rax,-0x40(%rbp)
jmp    12a6 <ulp+0x1a6>
mov    -0x28(%rbp),%rax
sub    -0x20(%rbp),%rax
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<ulp>:
movapd 0xef8(%rip),%xmm4
xorpd  %xmm2,%xmm2
movapd %xmm0,%xmm3
cmpeqsd %xmm2,%xmm3
movapd %xmm0,%xmm5
andpd  %xmm3,%xmm5
andpd  %xmm4,%xmm5
andnpd %xmm0,%xmm3
orpd   %xmm5,%xmm3
cmpeqsd %xmm1,%xmm2
movapd %xmm1,%xmm0
andpd  %xmm2,%xmm0
andpd  %xmm4,%xmm0
andnpd %xmm1,%xmm2
orpd   %xmm0,%xmm2
ucomisd %xmm3,%xmm3
jnp    1151 <ulp+0x51>
ucomisd %xmm2,%xmm2
jnp    1151 <ulp+0x51>
xor    %eax,%eax
ret
ucomisd %xmm3,%xmm3
jp     1199 <ulp+0x99>
ucomisd %xmm2,%xmm2
jp     1199 <ulp+0x99>
movq   %xmm3,%rcx
mov    0x2e77(%rip),%rax
mov    (%rax),%rdx
mov    %rdx,%rax
sub    %rcx,%rax
test   %rcx,%rcx
cmovns %rcx,%rax
movq   %xmm2,%rcx
sub    %rcx,%rdx
test   %rcx,%rcx
cmovns %rcx,%rdx
mov    %rax,%rcx
sub    %rdx,%rcx
neg    %rcx
sub    %rdx,%rax
cmovl  %rcx,%rax
ret
mov    0x2e40(%rip),%rax
mov    (%rax),%rax
ret

LLVM IR (-O0):
@LLONG_MIN = global i64 0
define i64 @ulp(double %0, double %1) {
%3 = alloca i64
%4 = alloca double
%5 = alloca double
%6 = alloca i64
%7 = alloca i64
store double %0, double* %4
store double %1, double* %5
%8 = load double, double* %4
%9 = fcmp oeq double %8, 0.000000e+00
br i1 %9, label %10, label %13
10: ; preds = %2
%11 = load double, double* %4
%12 = call double @llvm.fabs.f64(double %11)
store double %12, double* %4
br label %13
13: ; preds = %10, %2
%14 = load double, double* %5
%15 = fcmp oeq double %14, 0.000000e+00
br i1 %15, label %16, label %19
16: ; preds = %13
%17 = load double, double* %5
%18 = call double @llvm.fabs.f64(double %17)
store double %18, double* %5
br label %19
19: ; preds = %16, %13
%20 = load double, double* %4
%21 = load double, double* %4
%22 = fcmp une double %20, %21
br i1 %22, label %23, label %28
23: ; preds = %19
%24 = load double, double* %5
%25 = load double, double* %5
%26 = fcmp une double %24, %25
br i1 %26, label %27, label %28
27: ; preds = %23
store i64 0, i64* %3
br label %78
28: ; preds = %23, %19
%29 = load double, double* %4
%30 = load double, double* %4
%31 = fcmp une double %29, %30
br i1 %31, label %32, label %34
32: ; preds = %28
%33 = load i64, i64* @LLONG_MIN
store i64 %33, i64* %3
br label %78
34: ; preds = %28
%35 = load double, double* %5
%36 = load double, double* %5
%37 = fcmp une double %35, %36
br i1 %37, label %38, label %40
38: ; preds = %34
%39 = load i64, i64* @LLONG_MIN
store i64 %39, i64* %3
br label %78
40: ; preds = %34
%41 = bitcast double* %4 to i64*
%42 = load i64, i64* %41
store i64 %42, i64* %6
%43 = load i64, i64* %6
%44 = icmp slt i64 %43, 0
br i1 %44, label %45, label %49
45: ; preds = %40
%46 = load i64, i64* @LLONG_MIN
%47 = load i64, i64* %6
%48 = sub i64 %46, %47
br label %51
49: ; preds = %40
%50 = load i64, i64* %6
br label %51
51: ; preds = %49, %45
%52 = phi i64 [ %48, %45 ], [ %50, %49 ]
store i64 %52, i64* %6
%53 = bitcast double* %5 to i64*
%54 = load i64, i64* %53
store i64 %54, i64* %7
%55 = load i64, i64* %7
%56 = icmp slt i64 %55, 0
br i1 %56, label %57, label %61
57: ; preds = %51
%58 = load i64, i64* @LLONG_MIN
%59 = load i64, i64* %7
%60 = sub i64 %58, %59
br label %63
61: ; preds = %51
%62 = load i64, i64* %7
br label %63
63: ; preds = %61, %57
%64 = phi i64 [ %60, %57 ], [ %62, %61 ]
store i64 %64, i64* %7
%65 = load i64, i64* %6
%66 = load i64, i64* %7
%67 = icmp sge i64 %65, %66
br i1 %67, label %68, label %72
68: ; preds = %63
%69 = load i64, i64* %6
%70 = load i64, i64* %7
%71 = sub nsw i64 %69, %70
br label %76
72: ; preds = %63
%73 = load i64, i64* %7
%74 = load i64, i64* %6
%75 = sub nsw i64 %73, %74
br label %76
76: ; preds = %72, %68
%77 = phi i64 [ %71, %68 ], [ %75, %72 ]
store i64 %77, i64* %3
br label %78
78: ; preds = %76, %38, %32, %27
%79 = load i64, i64* %3
ret i64 %79
}

LLVM IR (-O2):
@LLONG_MIN = global i64 0
define i64 @ulp(double %0, double %1) {
%3 = fcmp oeq double %0, 0.000000e+00
%4 = tail call double @llvm.fabs.f64(double %0)
%5 = select i1 %3, double %4, double %0
%6 = fcmp oeq double %1, 0.000000e+00
%7 = tail call double @llvm.fabs.f64(double %1)
%8 = select i1 %6, double %7, double %1
%9 = fcmp uno double %5, 0.000000e+00
%10 = fcmp uno double %8, 0.000000e+00
%11 = select i1 %9, i1 %10, i1 false
br i1 %11, label %32, label %12
12: ; preds = %2
br i1 %9, label %13, label %15
13: ; preds = %12
%14 = load i64, i64* @LLONG_MIN
br label %32
15: ; preds = %12
br i1 %10, label %16, label %18
16: ; preds = %15
%17 = load i64, i64* @LLONG_MIN
br label %32
18: ; preds = %15
%19 = bitcast double %5 to i64
%20 = icmp slt i64 %19, 0
%21 = load i64, i64* @LLONG_MIN
%22 = sub i64 %21, %19
%23 = select i1 %20, i64 %22, i64 %19
%24 = bitcast double %8 to i64
%25 = icmp slt i64 %24, 0
%26 = sub i64 %21, %24
%27 = select i1 %25, i64 %26, i64 %24
%28 = icmp slt i64 %23, %27
%29 = sub nsw i64 %23, %27
%30 = sub nsw i64 %27, %23
%31 = select i1 %28, i64 %30, i64 %29
br label %32
32: ; preds = %2, %18, %16, %13
%33 = phi i64 [ %14, %13 ], [ %17, %16 ], [ %31, %18 ], [ 0, %2 ]
ret i64 %33
}