#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 */
float acos(float);
float floats_dot(float const *, float const *, int);
int /*<<< orphan*/ floats_normalize(float *, int, float *);
int /*<<< orphan*/ memcpy(float *, float const *, int);
float 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 = acos(dot);
    float w0 = sin(angle * (1 - w)), w1 = 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    1319 <floats_quat_slerp+0x1c9>
movss  -0x20(%rbp),%xmm0
call   1030 <acos@plt>
movss  %xmm0,-0x3c(%rbp)
movss  -0x3c(%rbp),%xmm0
movss  0xd7d(%rip),%xmm1
subss  -0x1c(%rbp),%xmm1
mulss  %xmm1,%xmm0
call   1040 <sin@plt>
movss  %xmm0,-0x40(%rbp)
movss  -0x3c(%rbp),%xmm0
mulss  -0x1c(%rbp),%xmm0
call   1040 <sin@plt>
movss  %xmm0,-0x44(%rbp)
movl   $0x0,-0x48(%rbp)
cmpl   $0x4,-0x48(%rbp)
jge    1307 <floats_quat_slerp+0x1b7>
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    12b9 <floats_quat_slerp+0x169>
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    130a <floats_quat_slerp+0x1ba>
call   1030 <acos@plt>
movaps %xmm0,%xmm1
movss  %xmm0,0x2c(%rsp)
movss  0xdbb(%rip),%xmm0
subss  0xc(%rsp),%xmm0
mulss  %xmm1,%xmm0
call   1040 <sin@plt>
movss  %xmm0,0x30(%rsp)
movss  0x2c(%rsp),%xmm0
mulss  0xc(%rsp),%xmm0
call   1040 <sin@plt>
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 %112
72: ; preds = %41
%73 = load float, float* %9
%74 = call float @acos(float %73)
store float %74, float* %13
%75 = load float, float* %13
%76 = load float, float* %8
%77 = fsub float 1.000000e+00, %76
%78 = fmul float %75, %77
%79 = call float @sin(float %78)
store float %79, float* %14
%80 = load float, float* %13
%81 = load float, float* %8
%82 = fmul float %80, %81
%83 = call float @sin(float %82)
store float %83, float* %15
store i32 0, i32* %16
br label %84
84: ; preds = %105, %72
%85 = load i32, i32* %16
%86 = icmp slt i32 %85, 4
br i1 %86, label %87, label %108
87: ; preds = %84
%88 = load float*, float** %5
%89 = load i32, i32* %16
%90 = sext i32 %89 to i64
%91 = getelementptr inbounds float, float* %88, i64 %90
%92 = load float, float* %91
%93 = load float, float* %14
%94 = load i32, i32* %16
%95 = sext i32 %94 to i64
%96 = getelementptr inbounds [4 x float], [4 x float]* %10, i64 0, i64 %95
%97 = load float, float* %96
%98 = load float, float* %15
%99 = fmul float %97, %98
%100 = call float @llvm.fmuladd.f32(float %92, float %93, float %99)
%101 = load float*, float** %7
%102 = load i32, i32* %16
%103 = sext i32 %102 to i64
%104 = getelementptr inbounds float, float* %101, i64 %103
store float %100, float* %104
br label %105
105: ; preds = %87
%106 = load i32, i32* %16
%107 = add nsw i32 %106, 1
store i32 %107, i32* %16
br label %84
108: ; preds = %84
%109 = load float*, float** %7
%110 = load float*, float** %7
%111 = call i32 @floats_normalize(float* %109, i32 4, float* %110)
br label %112
112: ; preds = %108, %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 %79
46: ; preds = %15
%47 = call float @acos(float %16)
%48 = fsub float 1.000000e+00, %3
%49 = fmul float %48, %47
%50 = call float @sin(float %49)
%51 = fmul float %47, %3
%52 = call float @sin(float %51)
%53 = load float, float* %0
%54 = load float, float* %8
%55 = fmul float %52, %54
%56 = call float @llvm.fmuladd.f32(float %53, float %50, float %55)
store float %56, float* %2
%57 = getelementptr inbounds float, float* %0, i64 1
%58 = load float, float* %57
%59 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 1
%60 = load float, float* %59
%61 = fmul float %52, %60
%62 = call float @llvm.fmuladd.f32(float %58, float %50, float %61)
%63 = getelementptr inbounds float, float* %2, i64 1
store float %62, float* %63
%64 = getelementptr inbounds float, float* %0, i64 2
%65 = load float, float* %64
%66 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 2
%67 = load float, float* %66
%68 = fmul float %52, %67
%69 = call float @llvm.fmuladd.f32(float %65, float %50, float %68)
%70 = getelementptr inbounds float, float* %2, i64 2
store float %69, float* %70
%71 = getelementptr inbounds float, float* %0, i64 3
%72 = load float, float* %71
%73 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 3
%74 = load float, float* %73
%75 = fmul float %52, %74
%76 = call float @llvm.fmuladd.f32(float %72, float %50, float %75)
%77 = getelementptr inbounds float, float* %2, i64 3
store float %76, float* %77
%78 = call i32 @floats_normalize(float* %2, i32 4, float* %2)
br label %79
79: ; preds = %19, %46
ret void
}