#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 */
scalar_t__ acos(float);
float floats_dot(float const *, float const *, int);
int /*<<< orphan*/ floats_normalize(float *, int, float *);
int /*<<< orphan*/ memcpy(float *, float const *, int);
scalar_t__ sin(float);
void floats_quat_slerp(const float q0[4], const float _q1[4], float r[4],
                       float w) {
  float dot = floats_dot(q0, _q1, 4);
  float q1[4];
  memcpy(q1, _q1, sizeof(float) * 4);
  if (dot < 0) {
    dot = -dot;
    for (int i = 0; i < 4; i++)
      q1[i] *= -1;
  }
  if (dot > 0.95) {
    for (int i = 0; i < 4; i++)
      r[i] = q0[i] * (1 - w) + q1[i] * w;
  } else {
    float angle = (float)acos(dot);
    float w0 = (float)sin(angle * (1 - w)), w1 = (float)sin(angle * w);
    for (int i = 0; i < 4; i++)
      r[i] = q0[i] * w0 + q1[i] * w1;
    floats_normalize(r, 4, r);
  }
}


x86 assembly (clang, -O0):
<floats_quat_slerp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movss  %xmm0,-0x1c(%rbp)
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
mov    $0x4,%edx
call   1070 <floats_dot@plt>
movss  %xmm0,-0x20(%rbp)
lea    -0x30(%rbp),%rdi
mov    -0x10(%rbp),%rsi
mov    $0x10,%edx
call   1050 <memcpy@plt>
xorps  %xmm0,%xmm0
ucomiss -0x20(%rbp),%xmm0
jbe    11f2 <floats_quat_slerp+0xa2>
movss  -0x20(%rbp),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
movss  %xmm0,-0x20(%rbp)
movl   $0x0,-0x34(%rbp)
cmpl   $0x4,-0x34(%rbp)
jge    11ed <floats_quat_slerp+0x9d>
movslq -0x34(%rbp),%rax
movss  0xe39(%rip),%xmm0
mulss  -0x30(%rbp,%rax,4),%xmm0
movss  %xmm0,-0x30(%rbp,%rax,4)
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    11bd <floats_quat_slerp+0x6d>
jmp    11f2 <floats_quat_slerp+0xa2>
movss  -0x20(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  0xdfd(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    126f <floats_quat_slerp+0x11f>
movl   $0x0,-0x38(%rbp)
cmpl   $0x4,-0x38(%rbp)
jge    126a <floats_quat_slerp+0x11a>
mov    -0x8(%rbp),%rax
movslq -0x38(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
movss  0xdd5(%rip),%xmm2
subss  -0x1c(%rbp),%xmm2
movslq -0x38(%rbp),%rax
movss  -0x30(%rbp,%rax,4),%xmm1
mulss  -0x1c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
movslq -0x38(%rbp),%rcx
movss  %xmm0,(%rax,%rcx,4)
mov    -0x38(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x38(%rbp)
jmp    1214 <floats_quat_slerp+0xc4>
jmp    1328 <floats_quat_slerp+0x1d8>
movss  -0x20(%rbp),%xmm0
call   1030 <acos@plt>
cvtsi2ss %rax,%xmm0
movss  %xmm0,-0x3c(%rbp)
movss  -0x3c(%rbp),%xmm0
movss  0xd78(%rip),%xmm1
subss  -0x1c(%rbp),%xmm1
mulss  %xmm1,%xmm0
call   1040 <sin@plt>
cvtsi2ss %rax,%xmm0
movss  %xmm0,-0x40(%rbp)
movss  -0x3c(%rbp),%xmm0
mulss  -0x1c(%rbp),%xmm0
call   1040 <sin@plt>
cvtsi2ss %rax,%xmm0
movss  %xmm0,-0x44(%rbp)
movl   $0x0,-0x48(%rbp)
cmpl   $0x4,-0x48(%rbp)
jge    1316 <floats_quat_slerp+0x1c6>
mov    -0x8(%rbp),%rax
movslq -0x48(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
movss  -0x40(%rbp),%xmm2
movslq -0x48(%rbp),%rax
movss  -0x30(%rbp,%rax,4),%xmm1
mulss  -0x44(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
movslq -0x48(%rbp),%rcx
movss  %xmm0,(%rax,%rcx,4)
mov    -0x48(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x48(%rbp)
jmp    12c8 <floats_quat_slerp+0x178>
mov    -0x18(%rbp),%rdi
mov    -0x18(%rbp),%rdx
mov    $0x4,%esi
call   1060 <floats_normalize@plt>
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<floats_quat_slerp>:
push   %r15
push   %r14
push   %rbx
sub    $0x40,%rsp
movss  %xmm0,0xc(%rsp)
mov    %rdx,%r14
mov    %rsi,%rbx
mov    %rdi,%r15
mov    $0x4,%edx
call   1070 <floats_dot@plt>
movaps %xmm0,0x30(%rsp)
lea    0x10(%rsp),%rdi
mov    %rbx,%rsi
mov    $0x10,%edx
call   1050 <memcpy@plt>
movaps 0x30(%rsp),%xmm0
xorps  %xmm1,%xmm1
ucomiss %xmm0,%xmm1
jbe    11ad <floats_quat_slerp+0x5d>
movaps 0xe63(%rip),%xmm2
movaps 0x10(%rsp),%xmm1
xorps  %xmm2,%xmm1
movaps %xmm1,0x10(%rsp)
xorps  %xmm2,%xmm0
xorps  %xmm1,%xmm1
cvtss2sd %xmm0,%xmm1
ucomisd 0xe54(%rip),%xmm1
jbe    1247 <floats_quat_slerp+0xf7>
movss  0xe4e(%rip),%xmm0
movss  0xc(%rsp),%xmm3
subss  %xmm3,%xmm0
movss  0x10(%rsp),%xmm1
mulss  %xmm3,%xmm1
movss  (%r15),%xmm2
mulss  %xmm0,%xmm2
addss  %xmm1,%xmm2
movss  %xmm2,(%r14)
movss  0x14(%rsp),%xmm1
mulss  %xmm3,%xmm1
movss  0x4(%r15),%xmm2
mulss  %xmm0,%xmm2
addss  %xmm1,%xmm2
movss  %xmm2,0x4(%r14)
movss  0x18(%rsp),%xmm1
mulss  %xmm3,%xmm1
movss  0x8(%r15),%xmm2
mulss  %xmm0,%xmm2
addss  %xmm1,%xmm2
movss  %xmm2,0x8(%r14)
mulss  0x1c(%rsp),%xmm3
mulss  0xc(%r15),%xmm0
addss  %xmm3,%xmm0
movss  %xmm0,0xc(%r14)
jmp    131f <floats_quat_slerp+0x1cf>
call   1030 <acos@plt>
xorps  %xmm1,%xmm1
cvtsi2ss %rax,%xmm1
movss  %xmm1,0x2c(%rsp)
movss  0xdb6(%rip),%xmm0
subss  0xc(%rsp),%xmm0
mulss  %xmm1,%xmm0
call   1040 <sin@plt>
xorps  %xmm0,%xmm0
cvtsi2ss %rax,%xmm0
movss  %xmm0,0x30(%rsp)
movss  0x2c(%rsp),%xmm0
mulss  0xc(%rsp),%xmm0
call   1040 <sin@plt>
xorps  %xmm0,%xmm0
cvtsi2ss %rax,%xmm0
movss  0x10(%rsp),%xmm1
mulss  %xmm0,%xmm1
movss  (%r15),%xmm2
movss  0x30(%rsp),%xmm3
mulss  %xmm3,%xmm2
addss  %xmm1,%xmm2
movss  %xmm2,(%r14)
movss  0x14(%rsp),%xmm1
mulss  %xmm0,%xmm1
movss  0x4(%r15),%xmm2
mulss  %xmm3,%xmm2
addss  %xmm1,%xmm2
movss  %xmm2,0x4(%r14)
movss  0x18(%rsp),%xmm1
mulss  %xmm0,%xmm1
movss  0x8(%r15),%xmm2
mulss  %xmm3,%xmm2
addss  %xmm1,%xmm2
movss  %xmm2,0x8(%r14)
mulss  0x1c(%rsp),%xmm0
movaps %xmm3,%xmm1
mulss  0xc(%r15),%xmm1
addss  %xmm0,%xmm1
movss  %xmm1,0xc(%r14)
mov    %r14,%rdi
mov    $0x4,%esi
mov    %r14,%rdx
call   1060 <floats_normalize@plt>
add    $0x40,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define void @floats_quat_slerp(float* %0, float* %1, float* %2, float %3) {
%5 = alloca float*
%6 = alloca float*
%7 = alloca float*
%8 = alloca float
%9 = alloca float
%10 = alloca [4 x float]
%11 = alloca i32
%12 = alloca i32
%13 = alloca float
%14 = alloca float
%15 = alloca float
%16 = alloca i32
store float* %0, float** %5
store float* %1, float** %6
store float* %2, float** %7
store float %3, float* %8
%17 = load float*, float** %5
%18 = load float*, float** %6
%19 = call float @floats_dot(float* %17, float* %18, i32 4)
store float %19, float* %9
%20 = getelementptr inbounds [4 x float], [4 x float]* %10, i64 0, i64 0
%21 = load float*, float** %6
%22 = call i32 @memcpy(float* %20, float* %21, i32 16)
%23 = load float, float* %9
%24 = fcmp olt float %23, 0.000000e+00
br i1 %24, label %25, label %41
25: ; preds = %4
%26 = load float, float* %9
%27 = fneg float %26
store float %27, float* %9
store i32 0, i32* %11
br label %28
28: ; preds = %37, %25
%29 = load i32, i32* %11
%30 = icmp slt i32 %29, 4
br i1 %30, label %31, label %40
31: ; preds = %28
%32 = load i32, i32* %11
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds [4 x float], [4 x float]* %10, i64 0, i64 %33
%35 = load float, float* %34
%36 = fmul float %35, -1.000000e+00
store float %36, float* %34
br label %37
37: ; preds = %31
%38 = load i32, i32* %11
%39 = add nsw i32 %38, 1
store i32 %39, i32* %11
br label %28
40: ; preds = %28
br label %41
41: ; preds = %40, %4
%42 = load float, float* %9
%43 = fpext float %42 to double
%44 = fcmp ogt double %43, 0x3FEE666666666666
br i1 %44, label %45, label %72
45: ; preds = %41
store i32 0, i32* %12
br label %46
46: ; preds = %68, %45
%47 = load i32, i32* %12
%48 = icmp slt i32 %47, 4
br i1 %48, label %49, label %71
49: ; preds = %46
%50 = load float*, float** %5
%51 = load i32, i32* %12
%52 = sext i32 %51 to i64
%53 = getelementptr inbounds float, float* %50, i64 %52
%54 = load float, float* %53
%55 = load float, float* %8
%56 = fsub float 1.000000e+00, %55
%57 = load i32, i32* %12
%58 = sext i32 %57 to i64
%59 = getelementptr inbounds [4 x float], [4 x float]* %10, i64 0, i64 %58
%60 = load float, float* %59
%61 = load float, float* %8
%62 = fmul float %60, %61
%63 = call float @llvm.fmuladd.f32(float %54, float %56, float %62)
%64 = load float*, float** %7
%65 = load i32, i32* %12
%66 = sext i32 %65 to i64
%67 = getelementptr inbounds float, float* %64, i64 %66
store float %63, float* %67
br label %68
68: ; preds = %49
%69 = load i32, i32* %12
%70 = add nsw i32 %69, 1
store i32 %70, i32* %12
br label %46
71: ; preds = %46
br label %115
72: ; preds = %41
%73 = load float, float* %9
%74 = call i64 @acos(float %73)
%75 = sitofp i64 %74 to float
store float %75, float* %13
%76 = load float, float* %13
%77 = load float, float* %8
%78 = fsub float 1.000000e+00, %77
%79 = fmul float %76, %78
%80 = call i64 @sin(float %79)
%81 = sitofp i64 %80 to float
store float %81, float* %14
%82 = load float, float* %13
%83 = load float, float* %8
%84 = fmul float %82, %83
%85 = call i64 @sin(float %84)
%86 = sitofp i64 %85 to float
store float %86, float* %15
store i32 0, i32* %16
br label %87
87: ; preds = %108, %72
%88 = load i32, i32* %16
%89 = icmp slt i32 %88, 4
br i1 %89, label %90, label %111
90: ; preds = %87
%91 = load float*, float** %5
%92 = load i32, i32* %16
%93 = sext i32 %92 to i64
%94 = getelementptr inbounds float, float* %91, i64 %93
%95 = load float, float* %94
%96 = load float, float* %14
%97 = load i32, i32* %16
%98 = sext i32 %97 to i64
%99 = getelementptr inbounds [4 x float], [4 x float]* %10, i64 0, i64 %98
%100 = load float, float* %99
%101 = load float, float* %15
%102 = fmul float %100, %101
%103 = call float @llvm.fmuladd.f32(float %95, float %96, float %102)
%104 = load float*, float** %7
%105 = load i32, i32* %16
%106 = sext i32 %105 to i64
%107 = getelementptr inbounds float, float* %104, i64 %106
store float %103, float* %107
br label %108
108: ; preds = %90
%109 = load i32, i32* %16
%110 = add nsw i32 %109, 1
store i32 %110, i32* %16
br label %87
111: ; preds = %87
%112 = load float*, float** %7
%113 = load float*, float** %7
%114 = call i32 @floats_normalize(float* %112, i32 4, float* %113)
br label %115
115: ; preds = %111, %71
ret void
}

LLVM IR (-O2):
define void @floats_quat_slerp(float* %0, float* %1, float* %2, float %3) {
%5 = alloca <4 x float>
%6 = tail call float @floats_dot(float* %0, float* %1, i32 4)
%7 = bitcast <4 x float>* %5 to i8*
%8 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 0
%9 = call i32 @memcpy(float* %8, float* %1, i32 16)
%10 = fcmp olt float %6, 0.000000e+00
br i1 %10, label %11, label %15
11: ; preds = %4
%12 = load <4 x float>, <4 x float>* %5
%13 = fneg <4 x float> %12
store <4 x float> %13, <4 x float>* %5
%14 = fneg float %6
br label %15
15: ; preds = %11, %4
%16 = phi float [ %6, %4 ], [ %14, %11 ]
%17 = fpext float %16 to double
%18 = fcmp ogt double %17, 0x3FEE666666666666
br i1 %18, label %19, label %46
19: ; preds = %15
%20 = fsub float 1.000000e+00, %3
%21 = load float, float* %0
%22 = load float, float* %8
%23 = fmul float %22, %3
%24 = call float @llvm.fmuladd.f32(float %21, float %20, float %23)
store float %24, float* %2
%25 = getelementptr inbounds float, float* %0, i64 1
%26 = load float, float* %25
%27 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 1
%28 = load float, float* %27
%29 = fmul float %28, %3
%30 = call float @llvm.fmuladd.f32(float %26, float %20, float %29)
%31 = getelementptr inbounds float, float* %2, i64 1
store float %30, float* %31
%32 = getelementptr inbounds float, float* %0, i64 2
%33 = load float, float* %32
%34 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 2
%35 = load float, float* %34
%36 = fmul float %35, %3
%37 = call float @llvm.fmuladd.f32(float %33, float %20, float %36)
%38 = getelementptr inbounds float, float* %2, i64 2
store float %37, float* %38
%39 = getelementptr inbounds float, float* %0, i64 3
%40 = load float, float* %39
%41 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 3
%42 = load float, float* %41
%43 = fmul float %42, %3
%44 = call float @llvm.fmuladd.f32(float %40, float %20, float %43)
%45 = getelementptr inbounds float, float* %2, i64 3
store float %44, float* %45
br label %82
46: ; preds = %15
%47 = call i64 @acos(float %16)
%48 = sitofp i64 %47 to float
%49 = fsub float 1.000000e+00, %3
%50 = fmul float %49, %48
%51 = call i64 @sin(float %50)
%52 = sitofp i64 %51 to float
%53 = fmul float %48, %3
%54 = call i64 @sin(float %53)
%55 = sitofp i64 %54 to float
%56 = load float, float* %0
%57 = load float, float* %8
%58 = fmul float %57, %55
%59 = call float @llvm.fmuladd.f32(float %56, float %52, float %58)
store float %59, float* %2
%60 = getelementptr inbounds float, float* %0, i64 1
%61 = load float, float* %60
%62 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 1
%63 = load float, float* %62
%64 = fmul float %63, %55
%65 = call float @llvm.fmuladd.f32(float %61, float %52, float %64)
%66 = getelementptr inbounds float, float* %2, i64 1
store float %65, float* %66
%67 = getelementptr inbounds float, float* %0, i64 2
%68 = load float, float* %67
%69 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 2
%70 = load float, float* %69
%71 = fmul float %70, %55
%72 = call float @llvm.fmuladd.f32(float %68, float %52, float %71)
%73 = getelementptr inbounds float, float* %2, i64 2
store float %72, float* %73
%74 = getelementptr inbounds float, float* %0, i64 3
%75 = load float, float* %74
%76 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 3
%77 = load float, float* %76
%78 = fmul float %77, %55
%79 = call float @llvm.fmuladd.f32(float %75, float %52, float %78)
%80 = getelementptr inbounds float, float* %2, i64 3
store float %79, float* %80
%81 = call i32 @floats_normalize(float* %2, i32 4, float* %2)
br label %82
82: ; preds = %19, %46
ret void
}