#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 acosf(float);
int /*<<< orphan*/ quat(float *, float, float, float, float);
float quat_dot(float *, float *);
int /*<<< orphan*/ quat_negative(float *, float *);
float sinf(float);
float *quat_slerp(float *result, float *a, float *b, float p) {
  float tmp_a[4];
  float tmp_b[4];
  float cos_theta = quat_dot(a, b);
  float p0;
  float p1;
  quat(tmp_a, a[0], a[1], a[2], a[3]);
  quat(tmp_b, b[0], b[1], b[2], b[3]);
  if (cos_theta < 0.0f) {
    quat_negative(tmp_b, tmp_b);
    cos_theta = -cos_theta;
  }
  if (cos_theta > 0.95f) {
    p0 = 1.0f - p;
    p1 = p;
  } else {
    float theta = acosf(cos_theta);
    float sin_theta = sinf(theta);
    p0 = sinf((1.0f - p) * theta) / sin_theta;
    p1 = sinf(p * theta) / sin_theta;
  }
  result[0] = tmp_a[0] * p0 + tmp_b[0] * p1;
  result[1] = tmp_a[1] * p0 + tmp_b[1] * p1;
  result[2] = tmp_a[2] * p0 + tmp_b[2] * p1;
  result[3] = tmp_a[3] * p0 + tmp_b[3] * p1;
  return result;
}


x86 assembly (clang, -O0):
<quat_slerp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movss  %xmm0,-0x1c(%rbp)
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%rsi
call   1070 <quat_dot@plt>
movss  %xmm0,-0x44(%rbp)
lea    -0x30(%rbp),%rdi
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm2
mov    -0x10(%rbp),%rax
movss  0xc(%rax),%xmm3
call   1060 <quat@plt>
lea    -0x40(%rbp),%rdi
mov    -0x18(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x18(%rbp),%rax
movss  0x8(%rax),%xmm2
mov    -0x18(%rbp),%rax
movss  0xc(%rax),%xmm3
call   1060 <quat@plt>
xorps  %xmm0,%xmm0
ucomiss -0x44(%rbp),%xmm0
jbe    1204 <quat_slerp+0xb4>
lea    -0x40(%rbp),%rdi
lea    -0x40(%rbp),%rsi
call   1050 <quat_negative@plt>
movss  -0x44(%rbp),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
movss  %xmm0,-0x44(%rbp)
movss  -0x44(%rbp),%xmm0
movss  0xdef(%rip),%xmm1
ucomiss %xmm1,%xmm0
jbe    123b <quat_slerp+0xeb>
movss  0xde2(%rip),%xmm0
subss  -0x1c(%rbp),%xmm0
movss  %xmm0,-0x48(%rbp)
movss  -0x1c(%rbp),%xmm0
movss  %xmm0,-0x4c(%rbp)
jmp    1293 <quat_slerp+0x143>
movss  -0x44(%rbp),%xmm0
call   1040 <acosf@plt>
movss  %xmm0,-0x50(%rbp)
movss  -0x50(%rbp),%xmm0
call   1030 <sinf@plt>
movss  %xmm0,-0x54(%rbp)
movss  0xda3(%rip),%xmm0
subss  -0x1c(%rbp),%xmm0
mulss  -0x50(%rbp),%xmm0
call   1030 <sinf@plt>
divss  -0x54(%rbp),%xmm0
movss  %xmm0,-0x48(%rbp)
movss  -0x1c(%rbp),%xmm0
mulss  -0x50(%rbp),%xmm0
call   1030 <sinf@plt>
divss  -0x54(%rbp),%xmm0
movss  %xmm0,-0x4c(%rbp)
movss  -0x30(%rbp),%xmm0
movss  -0x48(%rbp),%xmm2
movss  -0x40(%rbp),%xmm1
mulss  -0x4c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,(%rax)
movss  -0x2c(%rbp),%xmm0
movss  -0x48(%rbp),%xmm2
movss  -0x3c(%rbp),%xmm1
mulss  -0x4c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,0x4(%rax)
movss  -0x28(%rbp),%xmm0
movss  -0x48(%rbp),%xmm2
movss  -0x38(%rbp),%xmm1
mulss  -0x4c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,0x8(%rax)
movss  -0x24(%rbp),%xmm0
movss  -0x48(%rbp),%xmm2
movss  -0x34(%rbp),%xmm1
mulss  -0x4c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,0xc(%rax)
mov    -0x8(%rbp),%rax
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<quat_slerp>:
push   %r15
push   %r14
push   %rbx
sub    $0x60,%rsp
movaps %xmm0,0x10(%rsp)
mov    %rdx,%r15
mov    %rsi,%rbx
mov    %rdi,%r14
mov    %rsi,%rdi
mov    %rdx,%rsi
call   1070 <quat_dot@plt>
movaps %xmm0,(%rsp)
movss  (%rbx),%xmm0
movss  0x4(%rbx),%xmm1
movss  0x8(%rbx),%xmm2
movss  0xc(%rbx),%xmm3
lea    0x50(%rsp),%rdi
call   1060 <quat@plt>
movss  (%r15),%xmm0
movss  0x4(%r15),%xmm1
movss  0x8(%r15),%xmm2
movss  0xc(%r15),%xmm3
lea    0x20(%rsp),%rdi
call   1060 <quat@plt>
xorps  %xmm0,%xmm0
movaps (%rsp),%xmm1
ucomiss %xmm1,%xmm0
jbe    1244 <quat_slerp+0xf4>
lea    0x20(%rsp),%rdi
mov    %rdi,%rsi
call   1050 <quat_negative@plt>
movaps 0xe28(%rip),%xmm0
movaps (%rsp),%xmm1
xorps  %xmm0,%xmm1
movaps %xmm1,(%rsp)
movaps (%rsp),%xmm0
ucomiss 0xe22(%rip),%xmm0
ja     1250 <quat_slerp+0x100>
call   1040 <acosf@plt>
movss  %xmm0,(%rsp)
call   1030 <sinf@plt>
movaps %xmm0,0x40(%rsp)
movss  0xe08(%rip),%xmm0
subss  0x10(%rsp),%xmm0
mulss  (%rsp),%xmm0
call   1030 <sinf@plt>
movaps %xmm0,0x30(%rsp)
movss  (%rsp),%xmm0
mulss  0x10(%rsp),%xmm0
call   1030 <sinf@plt>
unpcklps 0x30(%rsp),%xmm0
movaps 0x40(%rsp),%xmm1
shufps $0x0,%xmm1,%xmm1
divps  %xmm1,%xmm0
jmp    1264 <quat_slerp+0x114>
movaps %xmm1,%xmm0
ucomiss 0xdc2(%rip),%xmm0
jbe    11f0 <quat_slerp+0xa0>
movss  0xdbc(%rip),%xmm1
movaps 0x10(%rsp),%xmm0
subss  %xmm0,%xmm1
unpcklps %xmm1,%xmm0
movaps %xmm0,%xmm1
shufps $0x0,%xmm0,%xmm1
mulps  0x20(%rsp),%xmm1
shufps $0x55,%xmm0,%xmm0
mulps  0x50(%rsp),%xmm0
addps  %xmm1,%xmm0
movups %xmm0,(%r14)
mov    %r14,%rax
add    $0x60,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

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

LLVM IR (-O2):
define float* @quat_slerp(float* returned writeonly %0, float* %1, float* %2, float %3) {
%5 = alloca <4 x float>
%6 = alloca <4 x float>
%7 = bitcast <4 x float>* %5 to i8*
%8 = bitcast <4 x float>* %6 to i8*
%9 = tail call float @quat_dot(float* %1, float* %2)
%10 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 0
%11 = load float, float* %1
%12 = getelementptr inbounds float, float* %1, i64 1
%13 = load float, float* %12
%14 = getelementptr inbounds float, float* %1, i64 2
%15 = load float, float* %14
%16 = getelementptr inbounds float, float* %1, i64 3
%17 = load float, float* %16
%18 = call i32 @quat(float* %10, float %11, float %13, float %15, float %17)
%19 = getelementptr inbounds <4 x float>, <4 x float>* %6, i64 0, i64 0
%20 = load float, float* %2
%21 = getelementptr inbounds float, float* %2, i64 1
%22 = load float, float* %21
%23 = getelementptr inbounds float, float* %2, i64 2
%24 = load float, float* %23
%25 = getelementptr inbounds float, float* %2, i64 3
%26 = load float, float* %25
%27 = call i32 @quat(float* %19, float %20, float %22, float %24, float %26)
%28 = fcmp olt float %9, 0.000000e+00
br i1 %28, label %29, label %32
29: ; preds = %4
%30 = call i32 @quat_negative(float* %19, float* %19)
%31 = fneg float %9
br label %32
32: ; preds = %29, %4
%33 = phi float [ %31, %29 ], [ %9, %4 ]
%34 = fcmp ogt float %33, 0x3FEE666660000000
br i1 %34, label %35, label %39
35: ; preds = %32
%36 = fsub float 1.000000e+00, %3
%37 = insertelement <2 x float> poison, float %3, i64 0
%38 = insertelement <2 x float> %37, float %36, i64 1
br label %52
39: ; preds = %32
%40 = call float @acosf(float %33)
%41 = call float @sinf(float %40)
%42 = fsub float 1.000000e+00, %3
%43 = fmul float %42, %40
%44 = call float @sinf(float %43)
%45 = fmul float %40, %3
%46 = call float @sinf(float %45)
%47 = insertelement <2 x float> poison, float %46, i64 0
%48 = insertelement <2 x float> %47, float %44, i64 1
%49 = insertelement <2 x float> poison, float %41, i64 0
%50 = shufflevector <2 x float> %49, <2 x float> poison, <2 x i32> zeroinitializer
%51 = fdiv <2 x float> %48, %50
br label %52
52: ; preds = %39, %35
%53 = phi <2 x float> [ %38, %35 ], [ %51, %39 ]
%54 = load <4 x float>, <4 x float>* %5
%55 = load <4 x float>, <4 x float>* %6
%56 = shufflevector <2 x float> %53, <2 x float> undef, <4 x i32> zeroinitializer
%57 = fmul <4 x float> %56, %55
%58 = shufflevector <2 x float> %53, <2 x float> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
%59 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %54, <4 x float> %58, <4 x float> %57)
%60 = bitcast float* %0 to <4 x float>*
store <4 x float> %59, <4 x float>* %60
ret float* %0
}