#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 M_PI;
float asin(float);
float atan2(float, float);
void Quaternion_ToEuler(float *q, float *rpy) {
  float R[3][3];
  R[0][0] = 2.0f * (q[0] * q[0] + q[1] * q[1]) - 1.0f;
  R[0][1] = 2.0f * (q[1] * q[2] + q[0] * q[3]);
  R[0][2] = 2.0f * (q[1] * q[3] - q[0] * q[2]);
  R[1][2] = 2.0f * (q[2] * q[3] + q[0] * q[1]);
  R[2][2] = 2.0f * (q[0] * q[0] + q[3] * q[3]) - 1.0f;
  rpy[0] = atan2(R[1][2], R[2][2]);
  if (rpy[0] == M_PI)
    rpy[0] = -M_PI / 2;
  if (R[0][2] >= 1.0f)
    rpy[1] = -M_PI / 2;
  else if (R[0][2] <= -1.0f)
    rpy[1] = M_PI / 2;
  else
    rpy[1] = asin(-R[0][2]);
  rpy[2] = atan2(R[0][1], R[0][0]);
  if (rpy[2] < 0.0f) {
    rpy[2] += 2 * M_PI;
  }
  if (rpy[2] > 2 * M_PI) {
    rpy[2] = 0.0f;
  }
}


x86 assembly (clang, -O0):
<Quaternion_ToEuler>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm2
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x8(%rbp),%rax
mulss  0x4(%rax),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
addss  %xmm0,%xmm0
movss  0xe9a(%rip),%xmm1
addss  %xmm1,%xmm0
movss  %xmm0,-0x40(%rbp)
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm2
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x8(%rbp),%rax
mulss  0xc(%rax),%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
movss  0xe62(%rip),%xmm0
mulss  %xmm1,%xmm0
movss  %xmm0,-0x3c(%rbp)
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm2
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x8(%rbp),%rax
mulss  0x8(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
movss  0xe19(%rip),%xmm0
mulss  %xmm1,%xmm0
movss  %xmm0,-0x38(%rbp)
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm1
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm2
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x8(%rbp),%rax
mulss  0x4(%rax),%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
movss  0xddd(%rip),%xmm0
mulss  %xmm1,%xmm0
movss  %xmm0,-0x2c(%rbp)
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm2
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm1
mov    -0x8(%rbp),%rax
mulss  0xc(%rax),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
addss  %xmm0,%xmm0
movss  0xd9a(%rip),%xmm1
addss  %xmm1,%xmm0
movss  %xmm0,-0x20(%rbp)
movss  -0x2c(%rbp),%xmm0
movss  -0x20(%rbp),%xmm1
call   1030 <atan2@plt>
mov    -0x10(%rbp),%rax
movss  %xmm0,(%rax)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
mov    0x2d53(%rip),%rax
ucomiss (%rax),%xmm0
jne    12d0 <Quaternion_ToEuler+0x1b0>
jp     12d0 <Quaternion_ToEuler+0x1b0>
mov    0x2d3d(%rip),%rax
movss  (%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
movss  0xd40(%rip),%xmm1
divss  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movss  %xmm0,(%rax)
movss  -0x38(%rbp),%xmm0
movss  0xd2b(%rip),%xmm1
ucomiss %xmm1,%xmm0
jb     1318 <Quaternion_ToEuler+0x1f8>
mov    0x2cfb(%rip),%rax
movss  (%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
movss  0xcfe(%rip),%xmm1
divss  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movss  %xmm0,0x4(%rax)
jmp    1374 <Quaternion_ToEuler+0x254>
movss  0xce0(%rip),%xmm0
ucomiss -0x38(%rbp),%xmm0
jb     134f <Quaternion_ToEuler+0x22f>
mov    0x2cb7(%rip),%rax
movss  (%rax),%xmm0
movss  0xcc7(%rip),%xmm1
divss  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movss  %xmm0,0x4(%rax)
jmp    136f <Quaternion_ToEuler+0x24f>
movss  -0x38(%rbp),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
call   1040 <asin@plt>
mov    -0x10(%rbp),%rax
movss  %xmm0,0x4(%rax)
jmp    1374 <Quaternion_ToEuler+0x254>
movss  -0x3c(%rbp),%xmm0
movss  -0x40(%rbp),%xmm1
call   1030 <atan2@plt>
mov    -0x10(%rbp),%rax
movss  %xmm0,0x8(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
ucomiss 0x8(%rax),%xmm0
jbe    13be <Quaternion_ToEuler+0x29e>
mov    0x2c44(%rip),%rax
movss  (%rax),%xmm0
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm1
addss  %xmm0,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,0x8(%rax)
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
movss  0xc35(%rip),%xmm1
mov    0x2c12(%rip),%rax
mulss  (%rax),%xmm1
ucomiss %xmm1,%xmm0
jbe    13ef <Quaternion_ToEuler+0x2cf>
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movss  %xmm0,0x8(%rax)
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<Quaternion_ToEuler>:
push   %r14
push   %rbx
sub    $0x28,%rsp
mov    %rsi,%rbx
movss  (%rdi),%xmm3
movss  0x4(%rdi),%xmm6
movaps %xmm6,%xmm0
mulss  %xmm6,%xmm0
movaps %xmm3,%xmm2
mulss  %xmm3,%xmm2
addss  %xmm2,%xmm0
addss  %xmm0,%xmm0
movss  %xmm0,0xc(%rsp)
movss  0x8(%rdi),%xmm0
movss  0xc(%rdi),%xmm1
movaps %xmm3,%xmm4
mulss  %xmm1,%xmm4
movaps %xmm6,%xmm5
mulss  %xmm0,%xmm5
addss  %xmm4,%xmm5
movss  %xmm5,0x8(%rsp)
movaps %xmm0,%xmm4
mulss  %xmm3,%xmm4
mulss  %xmm6,%xmm3
mulss  %xmm1,%xmm6
subss  %xmm4,%xmm6
addss  %xmm6,%xmm6
movaps %xmm6,0x10(%rsp)
mulss  %xmm1,%xmm0
addss  %xmm3,%xmm0
addss  %xmm0,%xmm0
mulss  %xmm1,%xmm1
addss  %xmm2,%xmm1
addss  %xmm1,%xmm1
addss  0xe53(%rip),%xmm1
call   1030 <atan2@plt>
movss  %xmm0,(%rbx)
mov    0x2e2b(%rip),%r14
movss  (%r14),%xmm1
ucomiss %xmm1,%xmm0
jne    11d5 <Quaternion_ToEuler+0xb5>
jp     11d5 <Quaternion_ToEuler+0xb5>
mulss  0xe33(%rip),%xmm1
movss  %xmm1,(%rbx)
movss  0xc(%rsp),%xmm1
movss  0xe1d(%rip),%xmm3
addss  %xmm3,%xmm1
movss  0x8(%rsp),%xmm2
addss  %xmm2,%xmm2
movaps 0x10(%rsp),%xmm0
ucomiss 0xe0b(%rip),%xmm0
jae    122a <Quaternion_ToEuler+0x10a>
ucomiss %xmm0,%xmm3
jae    1239 <Quaternion_ToEuler+0x119>
xorps  0xe05(%rip),%xmm0
movss  %xmm1,0xc(%rsp)
movss  %xmm2,0x8(%rsp)
call   1040 <asin@plt>
movss  0x8(%rsp),%xmm2
movss  0xc(%rsp),%xmm1
jmp    1246 <Quaternion_ToEuler+0x126>
movss  (%r14),%xmm0
mulss  0xdcd(%rip),%xmm0
jmp    1246 <Quaternion_ToEuler+0x126>
movss  (%r14),%xmm0
mulss  0xdc6(%rip),%xmm0
movss  %xmm0,0x4(%rbx)
movaps %xmm2,%xmm0
call   1030 <atan2@plt>
movss  %xmm0,0x8(%rbx)
xorps  %xmm1,%xmm1
ucomiss %xmm0,%xmm1
movss  (%r14),%xmm1
jbe    1275 <Quaternion_ToEuler+0x155>
movaps %xmm1,%xmm2
addss  %xmm1,%xmm2
addss  %xmm2,%xmm0
movss  %xmm0,0x8(%rbx)
addss  %xmm1,%xmm1
ucomiss %xmm1,%xmm0
jbe    1285 <Quaternion_ToEuler+0x165>
movl   $0x0,0x8(%rbx)
add    $0x28,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
@M_PI = global float 0.000000e+00
define void @Quaternion_ToEuler(float* %0, float* %1) {
%3 = alloca float*
%4 = alloca float*
%5 = alloca [3 x [3 x float]]
store float* %0, float** %3
store float* %1, float** %4
%6 = load float*, float** %3
%7 = getelementptr inbounds float, float* %6, i64 0
%8 = load float, float* %7
%9 = load float*, float** %3
%10 = getelementptr inbounds float, float* %9, i64 0
%11 = load float, float* %10
%12 = load float*, float** %3
%13 = getelementptr inbounds float, float* %12, i64 1
%14 = load float, float* %13
%15 = load float*, float** %3
%16 = getelementptr inbounds float, float* %15, i64 1
%17 = load float, float* %16
%18 = fmul float %14, %17
%19 = call float @llvm.fmuladd.f32(float %8, float %11, float %18)
%20 = call float @llvm.fmuladd.f32(float 2.000000e+00, float %19, float -1.000000e+00)
%21 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 0
%22 = getelementptr inbounds [3 x float], [3 x float]* %21, i64 0, i64 0
store float %20, float* %22
%23 = load float*, float** %3
%24 = getelementptr inbounds float, float* %23, i64 1
%25 = load float, float* %24
%26 = load float*, float** %3
%27 = getelementptr inbounds float, float* %26, i64 2
%28 = load float, float* %27
%29 = load float*, float** %3
%30 = getelementptr inbounds float, float* %29, i64 0
%31 = load float, float* %30
%32 = load float*, float** %3
%33 = getelementptr inbounds float, float* %32, i64 3
%34 = load float, float* %33
%35 = fmul float %31, %34
%36 = call float @llvm.fmuladd.f32(float %25, float %28, float %35)
%37 = fmul float 2.000000e+00, %36
%38 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 0
%39 = getelementptr inbounds [3 x float], [3 x float]* %38, i64 0, i64 1
store float %37, float* %39
%40 = load float*, float** %3
%41 = getelementptr inbounds float, float* %40, i64 1
%42 = load float, float* %41
%43 = load float*, float** %3
%44 = getelementptr inbounds float, float* %43, i64 3
%45 = load float, float* %44
%46 = load float*, float** %3
%47 = getelementptr inbounds float, float* %46, i64 0
%48 = load float, float* %47
%49 = load float*, float** %3
%50 = getelementptr inbounds float, float* %49, i64 2
%51 = load float, float* %50
%52 = fmul float %48, %51
%53 = fneg float %52
%54 = call float @llvm.fmuladd.f32(float %42, float %45, float %53)
%55 = fmul float 2.000000e+00, %54
%56 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 0
%57 = getelementptr inbounds [3 x float], [3 x float]* %56, i64 0, i64 2
store float %55, float* %57
%58 = load float*, float** %3
%59 = getelementptr inbounds float, float* %58, i64 2
%60 = load float, float* %59
%61 = load float*, float** %3
%62 = getelementptr inbounds float, float* %61, i64 3
%63 = load float, float* %62
%64 = load float*, float** %3
%65 = getelementptr inbounds float, float* %64, i64 0
%66 = load float, float* %65
%67 = load float*, float** %3
%68 = getelementptr inbounds float, float* %67, i64 1
%69 = load float, float* %68
%70 = fmul float %66, %69
%71 = call float @llvm.fmuladd.f32(float %60, float %63, float %70)
%72 = fmul float 2.000000e+00, %71
%73 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 1
%74 = getelementptr inbounds [3 x float], [3 x float]* %73, i64 0, i64 2
store float %72, float* %74
%75 = load float*, float** %3
%76 = getelementptr inbounds float, float* %75, i64 0
%77 = load float, float* %76
%78 = load float*, float** %3
%79 = getelementptr inbounds float, float* %78, i64 0
%80 = load float, float* %79
%81 = load float*, float** %3
%82 = getelementptr inbounds float, float* %81, i64 3
%83 = load float, float* %82
%84 = load float*, float** %3
%85 = getelementptr inbounds float, float* %84, i64 3
%86 = load float, float* %85
%87 = fmul float %83, %86
%88 = call float @llvm.fmuladd.f32(float %77, float %80, float %87)
%89 = call float @llvm.fmuladd.f32(float 2.000000e+00, float %88, float -1.000000e+00)
%90 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 2
%91 = getelementptr inbounds [3 x float], [3 x float]* %90, i64 0, i64 2
store float %89, float* %91
%92 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 1
%93 = getelementptr inbounds [3 x float], [3 x float]* %92, i64 0, i64 2
%94 = load float, float* %93
%95 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 2
%96 = getelementptr inbounds [3 x float], [3 x float]* %95, i64 0, i64 2
%97 = load float, float* %96
%98 = call float @atan2(float %94, float %97)
%99 = load float*, float** %4
%100 = getelementptr inbounds float, float* %99, i64 0
store float %98, float* %100
%101 = load float*, float** %4
%102 = getelementptr inbounds float, float* %101, i64 0
%103 = load float, float* %102
%104 = load float, float* @M_PI
%105 = fcmp oeq float %103, %104
br i1 %105, label %106, label %112
106: ; preds = %2
%107 = load float, float* @M_PI
%108 = fneg float %107
%109 = fdiv float %108, 2.000000e+00
%110 = load float*, float** %4
%111 = getelementptr inbounds float, float* %110, i64 0
store float %109, float* %111
br label %112
112: ; preds = %106, %2
%113 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 0
%114 = getelementptr inbounds [3 x float], [3 x float]* %113, i64 0, i64 2
%115 = load float, float* %114
%116 = fcmp oge float %115, 1.000000e+00
br i1 %116, label %117, label %123
117: ; preds = %112
%118 = load float, float* @M_PI
%119 = fneg float %118
%120 = fdiv float %119, 2.000000e+00
%121 = load float*, float** %4
%122 = getelementptr inbounds float, float* %121, i64 1
store float %120, float* %122
br label %142
123: ; preds = %112
%124 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 0
%125 = getelementptr inbounds [3 x float], [3 x float]* %124, i64 0, i64 2
%126 = load float, float* %125
%127 = fcmp ole float %126, -1.000000e+00
br i1 %127, label %128, label %133
128: ; preds = %123
%129 = load float, float* @M_PI
%130 = fdiv float %129, 2.000000e+00
%131 = load float*, float** %4
%132 = getelementptr inbounds float, float* %131, i64 1
store float %130, float* %132
br label %141
133: ; preds = %123
%134 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 0
%135 = getelementptr inbounds [3 x float], [3 x float]* %134, i64 0, i64 2
%136 = load float, float* %135
%137 = fneg float %136
%138 = call float @asin(float %137)
%139 = load float*, float** %4
%140 = getelementptr inbounds float, float* %139, i64 1
store float %138, float* %140
br label %141
141: ; preds = %133, %128
br label %142
142: ; preds = %141, %117
%143 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 0
%144 = getelementptr inbounds [3 x float], [3 x float]* %143, i64 0, i64 1
%145 = load float, float* %144
%146 = getelementptr inbounds [3 x [3 x float]], [3 x [3 x float]]* %5, i64 0, i64 0
%147 = getelementptr inbounds [3 x float], [3 x float]* %146, i64 0, i64 0
%148 = load float, float* %147
%149 = call float @atan2(float %145, float %148)
%150 = load float*, float** %4
%151 = getelementptr inbounds float, float* %150, i64 2
store float %149, float* %151
%152 = load float*, float** %4
%153 = getelementptr inbounds float, float* %152, i64 2
%154 = load float, float* %153
%155 = fcmp olt float %154, 0.000000e+00
br i1 %155, label %156, label %162
156: ; preds = %142
%157 = load float, float* @M_PI
%158 = load float*, float** %4
%159 = getelementptr inbounds float, float* %158, i64 2
%160 = load float, float* %159
%161 = call float @llvm.fmuladd.f32(float 2.000000e+00, float %157, float %160)
store float %161, float* %159
br label %162
162: ; preds = %156, %142
%163 = load float*, float** %4
%164 = getelementptr inbounds float, float* %163, i64 2
%165 = load float, float* %164
%166 = load float, float* @M_PI
%167 = fmul float 2.000000e+00, %166
%168 = fcmp ogt float %165, %167
br i1 %168, label %169, label %172
169: ; preds = %162
%170 = load float*, float** %4
%171 = getelementptr inbounds float, float* %170, i64 2
store float 0.000000e+00, float* %171
br label %172
172: ; preds = %169, %162
ret void
}

LLVM IR (-O2):
@M_PI = global float 0.000000e+00
define void @Quaternion_ToEuler(float* nocapture %0, float* nocapture %1) {
%3 = load float, float* %0
%4 = getelementptr inbounds float, float* %0, i64 1
%5 = load float, float* %4
%6 = fmul float %5, %5
%7 = tail call float @llvm.fmuladd.f32(float %3, float %3, float %6)
%8 = tail call float @llvm.fmuladd.f32(float %7, float 2.000000e+00, float -1.000000e+00)
%9 = getelementptr inbounds float, float* %0, i64 2
%10 = load float, float* %9
%11 = getelementptr inbounds float, float* %0, i64 3
%12 = load float, float* %11
%13 = fmul float %3, %12
%14 = tail call float @llvm.fmuladd.f32(float %5, float %10, float %13)
%15 = fmul float %14, 2.000000e+00
%16 = fneg float %3
%17 = fmul float %10, %16
%18 = tail call float @llvm.fmuladd.f32(float %5, float %12, float %17)
%19 = fmul float %18, 2.000000e+00
%20 = fmul float %3, %5
%21 = tail call float @llvm.fmuladd.f32(float %10, float %12, float %20)
%22 = fmul float %21, 2.000000e+00
%23 = fmul float %12, %12
%24 = tail call float @llvm.fmuladd.f32(float %3, float %3, float %23)
%25 = tail call float @llvm.fmuladd.f32(float %24, float 2.000000e+00, float -1.000000e+00)
%26 = tail call float @atan2(float %22, float %25)
store float %26, float* %1
%27 = load float, float* @M_PI
%28 = fcmp oeq float %26, %27
br i1 %28, label %29, label %31
29: ; preds = %2
%30 = fmul float %27, -5.000000e-01
store float %30, float* %1
br label %31
31: ; preds = %29, %2
%32 = fcmp ult float %19, 1.000000e+00
br i1 %32, label %36, label %33
33: ; preds = %31
%34 = load float, float* @M_PI
%35 = fmul float %34, -5.000000e-01
br label %44
36: ; preds = %31
%37 = fcmp ugt float %19, -1.000000e+00
br i1 %37, label %41, label %38
38: ; preds = %36
%39 = load float, float* @M_PI
%40 = fmul float %39, 5.000000e-01
br label %44
41: ; preds = %36
%42 = fneg float %19
%43 = tail call float @asin(float %42)
br label %44
44: ; preds = %38, %41, %33
%45 = phi float [ %40, %38 ], [ %43, %41 ], [ %35, %33 ]
%46 = getelementptr inbounds float, float* %1, i64 1
store float %45, float* %46
%47 = tail call float @atan2(float %15, float %8)
%48 = getelementptr inbounds float, float* %1, i64 2
store float %47, float* %48
%49 = fcmp olt float %47, 0.000000e+00
%50 = load float, float* @M_PI
br i1 %49, label %51, label %53
51: ; preds = %44
%52 = tail call float @llvm.fmuladd.f32(float %50, float 2.000000e+00, float %47)
store float %52, float* %48
br label %53
53: ; preds = %44, %51
%54 = phi float [ %52, %51 ], [ %47, %44 ]
%55 = fmul float %50, 2.000000e+00
%56 = fcmp ogt float %54, %55
br i1 %56, label %57, label %58
57: ; preds = %53
store float 0.000000e+00, float* %48
br label %58
58: ; preds = %57, %53
ret void
}