#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 */
double fabs(double);
double frexp(double x, int *exp) {
  union dblhex {
    double d;
    unsigned short s[4];
  };
  union dblhex split;
  if (x == 0.0) {
    exp = 0;
    return (0.0);
  }
  split.d = x;
  *exp = (((split.s[0] >> 8) & 0x007f) - 64) * 4;
  split.s[0] = split.s[0] & 0x80ff;
  split.s[0] = split.s[0] | 0x4000;
  while ((fabs(split.d) < 0.5) && (split.d != 0)) {
    split.d = split.d * 2;
    *exp = (*exp) - 1;
  }
  return (split.d);
}


x86 assembly (clang, -O0):
<frexp>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x10(%rbp)
mov    %rdi,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    113a <frexp+0x3a>
jp     113a <frexp+0x3a>
movq   $0x0,-0x18(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11f2 <frexp+0xf2>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movzwl -0x20(%rbp),%ecx
sar    $0x8,%ecx
and    $0x7f,%ecx
sub    $0x40,%ecx
shl    $0x2,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,(%rax)
movzwl -0x20(%rbp),%eax
and    $0x80ff,%eax
mov    %ax,-0x20(%rbp)
movzwl -0x20(%rbp),%eax
or     $0x4000,%eax
mov    %ax,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm1
movaps 0xe90(%rip),%xmm0
pand   %xmm0,%xmm1
xor    %eax,%eax
movsd  0xe72(%rip),%xmm0
ucomisd %xmm1,%xmm0
mov    %al,-0x21(%rbp)
jbe    11b2 <frexp+0xb2>
movsd  -0x20(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
setne  %al
setp   %cl
or     %cl,%al
mov    %al,-0x21(%rbp)
mov    -0x21(%rbp),%al
test   $0x1,%al
jne    11c2 <frexp+0xc2>
jmp    11e8 <frexp+0xe8>
movsd  0xe3e(%rip),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0x18(%rbp),%rax
mov    (%rax),%ecx
sub    $0x1,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,(%rax)
jmp    1174 <frexp+0x74>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<frexp>:
movapd %xmm0,%xmm1
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm1
jne    1111 <frexp+0x11>
jp     1111 <frexp+0x11>
ret
movq   %xmm1,%rcx
mov    %ecx,%eax
shr    $0x6,%eax
and    $0x1fc,%eax
add    $0xffffff00,%eax
mov    %eax,(%rdi)
and    $0xffffffffffff80ff,%rcx
or     $0x4000,%rcx
movq   %rcx,%xmm0
movdqa 0xebe(%rip),%xmm2
pand   %xmm0,%xmm2
movsd  0xec2(%rip),%xmm1
ucomisd %xmm2,%xmm1
jbe    1110 <frexp+0x10>
xorpd  %xmm2,%xmm2
ucomisd %xmm2,%xmm0
jne    1160 <frexp+0x60>
jnp    1110 <frexp+0x10>
movapd 0xe98(%rip),%xmm3
nopl   0x0(%rax,%rax,1)
addsd  %xmm0,%xmm0
add    $0xffffffff,%eax
movapd %xmm0,%xmm4
andpd  %xmm3,%xmm4
ucomisd %xmm4,%xmm1
jbe    118d <frexp+0x8d>
ucomisd %xmm2,%xmm0
jne    1170 <frexp+0x70>
jp     1170 <frexp+0x70>
mov    %eax,(%rdi)
ret

LLVM IR (-O0):
%union.dblhex = type { double }
define double @frexp(double %0, i32* %1) {
%3 = alloca double
%4 = alloca double
%5 = alloca i32*
%6 = alloca %union.dblhex
store double %0, double* %4
store i32* %1, i32** %5
%7 = load double, double* %4
%8 = fcmp oeq double %7, 0.000000e+00
br i1 %8, label %9, label %10
9: ; preds = %2
store i32* null, i32** %5
store double 0.000000e+00, double* %3
br label %61
10: ; preds = %2
%11 = load double, double* %4
%12 = bitcast %union.dblhex* %6 to double*
store double %11, double* %12
%13 = bitcast %union.dblhex* %6 to [4 x i16]*
%14 = getelementptr inbounds [4 x i16], [4 x i16]* %13, i64 0, i64 0
%15 = load i16, i16* %14
%16 = zext i16 %15 to i32
%17 = ashr i32 %16, 8
%18 = and i32 %17, 127
%19 = sub nsw i32 %18, 64
%20 = mul nsw i32 %19, 4
%21 = load i32*, i32** %5
store i32 %20, i32* %21
%22 = bitcast %union.dblhex* %6 to [4 x i16]*
%23 = getelementptr inbounds [4 x i16], [4 x i16]* %22, i64 0, i64 0
%24 = load i16, i16* %23
%25 = zext i16 %24 to i32
%26 = and i32 %25, 33023
%27 = trunc i32 %26 to i16
%28 = bitcast %union.dblhex* %6 to [4 x i16]*
%29 = getelementptr inbounds [4 x i16], [4 x i16]* %28, i64 0, i64 0
store i16 %27, i16* %29
%30 = bitcast %union.dblhex* %6 to [4 x i16]*
%31 = getelementptr inbounds [4 x i16], [4 x i16]* %30, i64 0, i64 0
%32 = load i16, i16* %31
%33 = zext i16 %32 to i32
%34 = or i32 %33, 16384
%35 = trunc i32 %34 to i16
%36 = bitcast %union.dblhex* %6 to [4 x i16]*
%37 = getelementptr inbounds [4 x i16], [4 x i16]* %36, i64 0, i64 0
store i16 %35, i16* %37
br label %38
38: ; preds = %49, %10
%39 = bitcast %union.dblhex* %6 to double*
%40 = load double, double* %39
%41 = call double @llvm.fabs.f64(double %40)
%42 = fcmp olt double %41, 5.000000e-01
br i1 %42, label %43, label %47
43: ; preds = %38
%44 = bitcast %union.dblhex* %6 to double*
%45 = load double, double* %44
%46 = fcmp une double %45, 0.000000e+00
br label %47
47: ; preds = %43, %38
%48 = phi i1 [ false, %38 ], [ %46, %43 ]
br i1 %48, label %49, label %58
49: ; preds = %47
%50 = bitcast %union.dblhex* %6 to double*
%51 = load double, double* %50
%52 = fmul double %51, 2.000000e+00
%53 = bitcast %union.dblhex* %6 to double*
store double %52, double* %53
%54 = load i32*, i32** %5
%55 = load i32, i32* %54
%56 = sub nsw i32 %55, 1
%57 = load i32*, i32** %5
store i32 %56, i32* %57
br label %38
58: ; preds = %47
%59 = bitcast %union.dblhex* %6 to double*
%60 = load double, double* %59
store double %60, double* %3
br label %61
61: ; preds = %58, %9
%62 = load double, double* %3
ret double %62
}

LLVM IR (-O2):
define double @frexp(double %0, i32* nocapture %1) {
%3 = fcmp oeq double %0, 0.000000e+00
br i1 %3, label %27, label %4
4: ; preds = %2
%5 = bitcast double %0 to i64
%6 = trunc i64 %5 to i32
%7 = lshr i32 %6, 6
%8 = and i32 %7, 508
%9 = add nsw i32 %8, -256
store i32 %9, i32* %1
%10 = and i64 %5, -32513
%11 = or i64 %10, 16384
%12 = bitcast i64 %11 to double
%13 = tail call double @llvm.fabs.f64(double %12)
%14 = fcmp olt double %13, 5.000000e-01
%15 = fcmp une double %12, 0.000000e+00
%16 = and i1 %14, %15
br i1 %16, label %17, label %27
17: ; preds = %4, %17
%18 = phi i32 [ %21, %17 ], [ %9, %4 ]
%19 = phi double [ %20, %17 ], [ %12, %4 ]
%20 = fmul double %19, 2.000000e+00
%21 = add nsw i32 %18, -1
%22 = tail call double @llvm.fabs.f64(double %20)
%23 = fcmp olt double %22, 5.000000e-01
%24 = fcmp une double %20, 0.000000e+00
%25 = select i1 %23, i1 %24, i1 false
br i1 %25, label %17, label %26
26: ; preds = %17
store i32 %21, i32* %1
br label %27
27: ; preds = %4, %26, %2
%28 = phi double [ 0.000000e+00, %2 ], [ %20, %26 ], [ %12, %4 ]
ret double %28
}