#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 */
int /*<<< orphan*/ ERANGE;
double HUGE_VAL;
int /*<<< orphan*/ errno;
double modf(double, double *);
double tan(double arg) {
  double sign, temp, e, x, xsq;
  int flag, i;
  flag = 0;
  sign = 1.;
  if (arg < 0.) {
    arg = -arg;
    sign = -1.;
  }
  arg = arg * 1.27323954473516;
  x = modf(arg, (double *)&e);
  i = e;
  switch (i % 4) {
  case 1:
    x = 1. - x;
    flag = 1;
    break;
  case 2:
    sign = -sign;
    flag = 1;
    break;
  case 3:
    x = 1. - x;
    sign = -sign;
    break;
  case 0:
    break;
  }
  xsq = x * x;
  temp = ((((0.338663864267717e-4 * xsq + 0.342255438724100e-1) * xsq +
            -0.155068565348327e+2) *
               xsq +
           0.105597090171495e+4) *
              xsq +
          -0.130682026475483e+5) *
         x;
  temp = temp /
         (((1.0 * xsq + -0.155503316403171e+3) * xsq + 0.476575136291648e+4) *
              xsq +
          -0.166389523894712e+5);
  if (flag == 1) {
    if (temp == 0.) {
      errno = ERANGE;
      if (sign > 0)
        return (HUGE_VAL);
      return (-HUGE_VAL);
    }
    temp = 1. / temp;
  }
  return (sign * temp);
}


x86 assembly (clang, -O0):
<tan>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
movsd  %xmm0,-0x10(%rbp)
movl   $0x0,-0x3c(%rbp)
movsd  0xed4(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
jbe    116d <tan+0x5d>
movsd  -0x10(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  0xea0(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  0xe96(%rip),%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  -0x10(%rbp),%xmm0
lea    -0x28(%rbp),%rdi
call   1030 <modf@plt>
movsd  %xmm0,-0x30(%rbp)
cvttsd2si -0x28(%rbp),%eax
mov    %eax,-0x40(%rbp)
mov    -0x40(%rbp),%eax
mov    %eax,%edx
add    $0x3,%edx
test   %eax,%eax
mov    %eax,%ecx
cmovs  %edx,%ecx
and    $0xfffffffc,%ecx
sub    %ecx,%eax
mov    %eax,%ecx
mov    %rcx,-0x48(%rbp)
sub    $0x3,%eax
ja     125d <tan+0x14d>
mov    -0x48(%rbp),%rax
lea    0xe8c(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
movsd  0xe23(%rip),%xmm0
subsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movl   $0x1,-0x3c(%rbp)
jmp    125d <tan+0x14d>
movsd  -0x18(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x18(%rbp)
movl   $0x1,-0x3c(%rbp)
jmp    125d <tan+0x14d>
movsd  0xdd8(%rip),%xmm0
subsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x18(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    125d <tan+0x14d>
jmp    125d <tan+0x14d>
movsd  -0x30(%rbp),%xmm0
mulsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x38(%rbp),%xmm0
movsd  0xdcf(%rip),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xdcb(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  -0x38(%rbp),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xda6(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  -0x38(%rbp),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xd89(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  -0x38(%rbp),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xd6c(%rip),%xmm1
addsd  %xmm1,%xmm0
mulsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  -0x38(%rbp),%xmm1
movsd  0xd44(%rip),%xmm2
addsd  %xmm2,%xmm1
movsd  -0x38(%rbp),%xmm2
mulsd  %xmm2,%xmm1
movsd  0xd27(%rip),%xmm2
addsd  %xmm2,%xmm1
movsd  -0x38(%rbp),%xmm2
mulsd  %xmm2,%xmm1
movsd  0xd0a(%rip),%xmm2
addsd  %xmm2,%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
cmpl   $0x1,-0x3c(%rbp)
jne    13b4 <tan+0x2a4>
movsd  -0x20(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    13a2 <tan+0x292>
jp     13a2 <tan+0x292>
mov    0x2c9c(%rip),%rax
mov    (%rax),%ecx
mov    0x2c83(%rip),%rax
mov    %ecx,(%rax)
movsd  -0x18(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    1376 <tan+0x266>
mov    0x2c80(%rip),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    13c3 <tan+0x2b3>
mov    0x2c6b(%rip),%rax
movsd  (%rax),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    13c3 <tan+0x2b3>
movsd  0xc56(%rip),%xmm0
divsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x18(%rbp),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<tan>:
sub    $0x18,%rsp
xorpd  %xmm1,%xmm1
xor    %eax,%eax
ucomisd %xmm0,%xmm1
seta   %al
lea    0xee8(%rip),%rcx
jbe    1132 <tan+0x22>
xorpd  0xece(%rip),%xmm0
movsd  (%rcx,%rax,8),%xmm1
movapd %xmm1,(%rsp)
mulsd  0xedc(%rip),%xmm0
lea    0x10(%rsp),%rdi
call   1030 <modf@plt>
cvttsd2si 0x10(%rsp),%eax
lea    0x3(%rax),%ecx
test   %eax,%eax
cmovns %eax,%ecx
and    $0xfffffffc,%ecx
sub    %ecx,%eax
cmp    $0x3,%eax
je     1184 <tan+0x74>
cmp    $0x2,%eax
je     11a5 <tan+0x95>
cmp    $0x1,%eax
jne    11b6 <tan+0xa6>
movsd  0xeb0(%rip),%xmm1
subsd  %xmm0,%xmm1
mov    $0x1,%al
movapd %xmm1,%xmm0
jmp    11b8 <tan+0xa8>
movsd  0xe9c(%rip),%xmm1
subsd  %xmm0,%xmm1
movapd (%rsp),%xmm3
xorpd  0xe63(%rip),%xmm3
xor    %eax,%eax
movapd %xmm1,%xmm0
jmp    11bd <tan+0xad>
movapd (%rsp),%xmm3
xorpd  0xe4e(%rip),%xmm3
mov    $0x1,%al
jmp    11bd <tan+0xad>
xor    %eax,%eax
movapd (%rsp),%xmm3
movapd %xmm0,%xmm2
mulsd  %xmm0,%xmm2
movsd  0xe63(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe5f(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe5b(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe57(%rip),%xmm1
mulsd  %xmm2,%xmm1
addsd  0xe53(%rip),%xmm1
mulsd  %xmm0,%xmm1
movsd  0xe4f(%rip),%xmm0
addsd  %xmm2,%xmm0
mulsd  %xmm2,%xmm0
addsd  0xe47(%rip),%xmm0
mulsd  %xmm2,%xmm0
addsd  0xe43(%rip),%xmm0
divsd  %xmm0,%xmm1
test   %al,%al
je     1276 <tan+0x166>
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm1
jne    1266 <tan+0x156>
jp     1266 <tan+0x156>
mov    0x2da0(%rip),%rax
mov    (%rax),%eax
mov    0x2d87(%rip),%rcx
mov    %eax,(%rcx)
ucomisd %xmm0,%xmm3
mov    0x2d92(%rip),%rax
movsd  (%rax),%xmm3
ja     127a <tan+0x16a>
xorpd  0xd9c(%rip),%xmm3
jmp    127a <tan+0x16a>
movsd  0xdba(%rip),%xmm0
divsd  %xmm1,%xmm0
movapd %xmm0,%xmm1
mulsd  %xmm1,%xmm3
movapd %xmm3,%xmm0
add    $0x18,%rsp
ret

LLVM IR (-O0):
@ERANGE = global i32 0
@errno = global i32 0
@HUGE_VAL = global double 0.000000e+00
define double @tan(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca double
%9 = alloca i32
%10 = alloca i32
store double %0, double* %3
store i32 0, i32* %9
store double 1.000000e+00, double* %4
%11 = load double, double* %3
%12 = fcmp olt double %11, 0.000000e+00
br i1 %12, label %13, label %16
13: ; preds = %1
%14 = load double, double* %3
%15 = fneg double %14
store double %15, double* %3
store double -1.000000e+00, double* %4
br label %16
16: ; preds = %13, %1
%17 = load double, double* %3
%18 = fmul double %17, 0x3FF45F306DC9C877
store double %18, double* %3
%19 = load double, double* %3
%20 = call double @modf(double %19, double* %6)
store double %20, double* %7
%21 = load double, double* %6
%22 = fptosi double %21 to i32
store i32 %22, i32* %10
%23 = load i32, i32* %10
%24 = srem i32 %23, 4
switch i32 %24, label %37 [
i32 1, label %25
i32 2, label %28
i32 3, label %31
i32 0, label %36
]
25: ; preds = %16
%26 = load double, double* %7
%27 = fsub double 1.000000e+00, %26
store double %27, double* %7
store i32 1, i32* %9
br label %37
28: ; preds = %16
%29 = load double, double* %4
%30 = fneg double %29
store double %30, double* %4
store i32 1, i32* %9
br label %37
31: ; preds = %16
%32 = load double, double* %7
%33 = fsub double 1.000000e+00, %32
store double %33, double* %7
%34 = load double, double* %4
%35 = fneg double %34
store double %35, double* %4
br label %37
36: ; preds = %16
br label %37
37: ; preds = %16, %36, %31, %28, %25
%38 = load double, double* %7
%39 = load double, double* %7
%40 = fmul double %38, %39
store double %40, double* %8
%41 = load double, double* %8
%42 = call double @llvm.fmuladd.f64(double 0x3F01C1782D55FF44, double %41, double 0x3FA18602AF3D5848)
%43 = load double, double* %8
%44 = call double @llvm.fmuladd.f64(double %42, double %43, double 0xC02F0382B321BD9C)
%45 = load double, double* %8
%46 = call double @llvm.fmuladd.f64(double %44, double %45, double 0x40907FE2340F255D)
%47 = load double, double* %8
%48 = call double @llvm.fmuladd.f64(double %46, double %47, double 0xC0C98619F05AD848)
%49 = load double, double* %7
%50 = fmul double %48, %49
store double %50, double* %5
%51 = load double, double* %5
%52 = load double, double* %8
%53 = call double @llvm.fmuladd.f64(double 1.000000e+00, double %52, double 0xC063701B2B00651D)
%54 = load double, double* %8
%55 = call double @llvm.fmuladd.f64(double %53, double %54, double 0x40B29DC05951F1B5)
%56 = load double, double* %8
%57 = call double @llvm.fmuladd.f64(double %55, double %56, double 0xC0D03FBCF3F2F7F7)
%58 = fdiv double %51, %57
store double %58, double* %5
%59 = load i32, i32* %9
%60 = icmp eq i32 %59, 1
br i1 %60, label %61, label %76
61: ; preds = %37
%62 = load double, double* %5
%63 = fcmp oeq double %62, 0.000000e+00
br i1 %63, label %64, label %73
64: ; preds = %61
%65 = load i32, i32* @ERANGE
store i32 %65, i32* @errno
%66 = load double, double* %4
%67 = fcmp ogt double %66, 0.000000e+00
br i1 %67, label %68, label %70
68: ; preds = %64
%69 = load double, double* @HUGE_VAL
store double %69, double* %2
br label %80
70: ; preds = %64
%71 = load double, double* @HUGE_VAL
%72 = fneg double %71
store double %72, double* %2
br label %80
73: ; preds = %61
%74 = load double, double* %5
%75 = fdiv double 1.000000e+00, %74
store double %75, double* %5
br label %76
76: ; preds = %73, %37
%77 = load double, double* %4
%78 = load double, double* %5
%79 = fmul double %77, %78
store double %79, double* %2
br label %80
80: ; preds = %76, %70, %68
%81 = load double, double* %2
ret double %81
}

LLVM IR (-O2):
@ERANGE = global i32 0
@errno = global i32 0
@HUGE_VAL = global double 0.000000e+00
define double @tan(double %0) {
%2 = alloca double
%3 = bitcast double* %2 to i8*
%4 = fcmp olt double %0, 0.000000e+00
%5 = fneg double %0
%6 = select i1 %4, double -1.000000e+00, double 1.000000e+00
%7 = select i1 %4, double %5, double %0
%8 = fmul double %7, 0x3FF45F306DC9C877
%9 = call double @modf(double %8, double* %2)
%10 = load double, double* %2
%11 = fptosi double %10 to i32
%12 = srem i32 %11, 4
switch i32 %12, label %20 [
i32 1, label %13
i32 2, label %15
i32 3, label %17
]
13: ; preds = %1
%14 = fsub double 1.000000e+00, %9
br label %20
15: ; preds = %1
%16 = fneg double %6
br label %20
17: ; preds = %1
%18 = fsub double 1.000000e+00, %9
%19 = fneg double %6
br label %20
20: ; preds = %1, %17, %15, %13
%21 = phi double [ %6, %1 ], [ %19, %17 ], [ %16, %15 ], [ %6, %13 ]
%22 = phi double [ %9, %1 ], [ %18, %17 ], [ %9, %15 ], [ %14, %13 ]
%23 = phi i1 [ false, %1 ], [ false, %17 ], [ true, %15 ], [ true, %13 ]
%24 = fmul double %22, %22
%25 = tail call double @llvm.fmuladd.f64(double %24, double 0x3F01C1782D55FF44, double 0x3FA18602AF3D5848)
%26 = tail call double @llvm.fmuladd.f64(double %25, double %24, double 0xC02F0382B321BD9C)
%27 = tail call double @llvm.fmuladd.f64(double %26, double %24, double 0x40907FE2340F255D)
%28 = tail call double @llvm.fmuladd.f64(double %27, double %24, double 0xC0C98619F05AD848)
%29 = fmul double %22, %28
%30 = fadd double %24, 0xC063701B2B00651D
%31 = tail call double @llvm.fmuladd.f64(double %30, double %24, double 0x40B29DC05951F1B5)
%32 = tail call double @llvm.fmuladd.f64(double %31, double %24, double 0xC0D03FBCF3F2F7F7)
%33 = fdiv double %29, %32
br i1 %23, label %34, label %44
34: ; preds = %20
%35 = fcmp oeq double %33, 0.000000e+00
br i1 %35, label %36, label %42
36: ; preds = %34
%37 = load i32, i32* @ERANGE
store i32 %37, i32* @errno
%38 = fcmp ogt double %21, 0.000000e+00
%39 = load double, double* @HUGE_VAL
br i1 %38, label %47, label %40
40: ; preds = %36
%41 = fneg double %39
br label %47
42: ; preds = %34
%43 = fdiv double 1.000000e+00, %33
br label %44
44: ; preds = %42, %20
%45 = phi double [ %43, %42 ], [ %33, %20 ]
%46 = fmul double %21, %45
br label %47
47: ; preds = %36, %44, %40
%48 = phi double [ %41, %40 ], [ %46, %44 ], [ %39, %36 ]
ret double %48
}