#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 */
double sqrt(double const);
void ecef2ned_matrix(const double ref_ecef[3], double M[3][3]) {
  double hyp_az, hyp_el;
  double sin_el, cos_el, sin_az, cos_az;
  hyp_az = sqrt(ref_ecef[0] * ref_ecef[0] + ref_ecef[1] * ref_ecef[1]);
  hyp_el = sqrt(hyp_az * hyp_az + ref_ecef[2] * ref_ecef[2]);
  sin_el = ref_ecef[2] / hyp_el;
  cos_el = hyp_az / hyp_el;
  sin_az = ref_ecef[1] / hyp_az;
  cos_az = ref_ecef[0] / hyp_az;
  M[0][0] = -sin_el * cos_az;
  M[0][1] = -sin_el * sin_az;
  M[0][2] = cos_el;
  M[1][0] = -sin_az;
  M[1][1] = cos_az;
  M[1][2] = 0.0;
  M[2][0] = -cos_el * cos_az;
  M[2][1] = -cos_el * sin_az;
  M[2][2] = -sin_el;
}


x86 assembly (clang, -O0):
<ecef2ned_matrix>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm1
mov    -0x8(%rbp),%rax
mulsd  0x8(%rax),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
call   1030 <sqrt@plt>
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  -0x18(%rbp),%xmm2
mov    -0x8(%rbp),%rax
movsd  0x10(%rax),%xmm1
mov    -0x8(%rbp),%rax
mulsd  0x10(%rax),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
call   1030 <sqrt@plt>
movsd  %xmm0,-0x20(%rbp)
mov    -0x8(%rbp),%rax
movsd  0x10(%rax),%xmm0
divsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x18(%rbp),%xmm0
divsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm0
divsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm0
divsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x28(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  -0x40(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x28(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  -0x38(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x8(%rax)
movsd  -0x30(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x10(%rax)
movsd  -0x38(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x18(%rax)
movsd  -0x40(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x20(%rax)
mov    -0x10(%rbp),%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x28(%rax)
movsd  -0x30(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  -0x40(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x30(%rax)
movsd  -0x30(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  -0x38(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x38(%rax)
movsd  -0x28(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x40(%rax)
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<ecef2ned_matrix>:
push   %r14
push   %rbx
sub    $0x18,%rsp
mov    %rsi,%r14
mov    %rdi,%rbx
movsd  (%rdi),%xmm0
movsd  0x8(%rdi),%xmm1
mulsd  %xmm1,%xmm1
mulsd  %xmm0,%xmm0
addsd  %xmm1,%xmm0
xorpd  %xmm2,%xmm2
ucomisd %xmm2,%xmm0
jb     1142 <ecef2ned_matrix+0x32>
sqrtsd %xmm0,%xmm3
jmp    114f <ecef2ned_matrix+0x3f>
call   1030 <sqrt@plt>
xorpd  %xmm2,%xmm2
movapd %xmm0,%xmm3
movsd  0x10(%rbx),%xmm1
mulsd  %xmm1,%xmm1
movapd %xmm3,%xmm0
mulsd  %xmm3,%xmm0
addsd  %xmm1,%xmm0
ucomisd %xmm2,%xmm0
jb     1170 <ecef2ned_matrix+0x60>
sqrtsd %xmm0,%xmm0
jmp    117f <ecef2ned_matrix+0x6f>
movapd %xmm3,(%rsp)
call   1030 <sqrt@plt>
movapd (%rsp),%xmm3
movapd %xmm3,%xmm1
divsd  %xmm0,%xmm1
movupd (%rbx),%xmm2
unpcklpd %xmm3,%xmm3
divpd  %xmm3,%xmm2
movsd  0x10(%rbx),%xmm3
movapd 0xe60(%rip),%xmm4
xorpd  %xmm4,%xmm3
divsd  %xmm0,%xmm3
movapd %xmm3,%xmm0
unpcklpd %xmm3,%xmm0
mulpd  %xmm2,%xmm0
movupd %xmm0,(%r14)
movsd  %xmm1,0x10(%r14)
movapd %xmm2,%xmm0
unpckhpd %xmm2,%xmm0
xorpd  %xmm4,%xmm0
unpcklpd %xmm2,%xmm0
movupd %xmm0,0x18(%r14)
movq   $0x0,0x28(%r14)
xorpd  %xmm4,%xmm1
pshufd $0x44,%xmm1,%xmm0
mulpd  %xmm2,%xmm0
movupd %xmm0,0x30(%r14)
movsd  %xmm3,0x40(%r14)
add    $0x18,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
define void @ecef2ned_matrix(double* %0, [3 x double]* %1) {
%3 = alloca double*
%4 = alloca [3 x double]*
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca double
store double* %0, double** %3
store [3 x double]* %1, [3 x double]** %4
%11 = load double*, double** %3
%12 = getelementptr inbounds double, double* %11, i64 0
%13 = load double, double* %12
%14 = load double*, double** %3
%15 = getelementptr inbounds double, double* %14, i64 0
%16 = load double, double* %15
%17 = load double*, double** %3
%18 = getelementptr inbounds double, double* %17, i64 1
%19 = load double, double* %18
%20 = load double*, double** %3
%21 = getelementptr inbounds double, double* %20, i64 1
%22 = load double, double* %21
%23 = fmul double %19, %22
%24 = call double @llvm.fmuladd.f64(double %13, double %16, double %23)
%25 = call double @sqrt(double %24)
store double %25, double* %5
%26 = load double, double* %5
%27 = load double, double* %5
%28 = load double*, double** %3
%29 = getelementptr inbounds double, double* %28, i64 2
%30 = load double, double* %29
%31 = load double*, double** %3
%32 = getelementptr inbounds double, double* %31, i64 2
%33 = load double, double* %32
%34 = fmul double %30, %33
%35 = call double @llvm.fmuladd.f64(double %26, double %27, double %34)
%36 = call double @sqrt(double %35)
store double %36, double* %6
%37 = load double*, double** %3
%38 = getelementptr inbounds double, double* %37, i64 2
%39 = load double, double* %38
%40 = load double, double* %6
%41 = fdiv double %39, %40
store double %41, double* %7
%42 = load double, double* %5
%43 = load double, double* %6
%44 = fdiv double %42, %43
store double %44, double* %8
%45 = load double*, double** %3
%46 = getelementptr inbounds double, double* %45, i64 1
%47 = load double, double* %46
%48 = load double, double* %5
%49 = fdiv double %47, %48
store double %49, double* %9
%50 = load double*, double** %3
%51 = getelementptr inbounds double, double* %50, i64 0
%52 = load double, double* %51
%53 = load double, double* %5
%54 = fdiv double %52, %53
store double %54, double* %10
%55 = load double, double* %7
%56 = fneg double %55
%57 = load double, double* %10
%58 = fmul double %56, %57
%59 = load [3 x double]*, [3 x double]** %4
%60 = getelementptr inbounds [3 x double], [3 x double]* %59, i64 0
%61 = getelementptr inbounds [3 x double], [3 x double]* %60, i64 0, i64 0
store double %58, double* %61
%62 = load double, double* %7
%63 = fneg double %62
%64 = load double, double* %9
%65 = fmul double %63, %64
%66 = load [3 x double]*, [3 x double]** %4
%67 = getelementptr inbounds [3 x double], [3 x double]* %66, i64 0
%68 = getelementptr inbounds [3 x double], [3 x double]* %67, i64 0, i64 1
store double %65, double* %68
%69 = load double, double* %8
%70 = load [3 x double]*, [3 x double]** %4
%71 = getelementptr inbounds [3 x double], [3 x double]* %70, i64 0
%72 = getelementptr inbounds [3 x double], [3 x double]* %71, i64 0, i64 2
store double %69, double* %72
%73 = load double, double* %9
%74 = fneg double %73
%75 = load [3 x double]*, [3 x double]** %4
%76 = getelementptr inbounds [3 x double], [3 x double]* %75, i64 1
%77 = getelementptr inbounds [3 x double], [3 x double]* %76, i64 0, i64 0
store double %74, double* %77
%78 = load double, double* %10
%79 = load [3 x double]*, [3 x double]** %4
%80 = getelementptr inbounds [3 x double], [3 x double]* %79, i64 1
%81 = getelementptr inbounds [3 x double], [3 x double]* %80, i64 0, i64 1
store double %78, double* %81
%82 = load [3 x double]*, [3 x double]** %4
%83 = getelementptr inbounds [3 x double], [3 x double]* %82, i64 1
%84 = getelementptr inbounds [3 x double], [3 x double]* %83, i64 0, i64 2
store double 0.000000e+00, double* %84
%85 = load double, double* %8
%86 = fneg double %85
%87 = load double, double* %10
%88 = fmul double %86, %87
%89 = load [3 x double]*, [3 x double]** %4
%90 = getelementptr inbounds [3 x double], [3 x double]* %89, i64 2
%91 = getelementptr inbounds [3 x double], [3 x double]* %90, i64 0, i64 0
store double %88, double* %91
%92 = load double, double* %8
%93 = fneg double %92
%94 = load double, double* %9
%95 = fmul double %93, %94
%96 = load [3 x double]*, [3 x double]** %4
%97 = getelementptr inbounds [3 x double], [3 x double]* %96, i64 2
%98 = getelementptr inbounds [3 x double], [3 x double]* %97, i64 0, i64 1
store double %95, double* %98
%99 = load double, double* %7
%100 = fneg double %99
%101 = load [3 x double]*, [3 x double]** %4
%102 = getelementptr inbounds [3 x double], [3 x double]* %101, i64 2
%103 = getelementptr inbounds [3 x double], [3 x double]* %102, i64 0, i64 2
store double %100, double* %103
ret void
}

LLVM IR (-O2):
define void @ecef2ned_matrix(double* nocapture %0, [3 x double]* nocapture writeonly %1) {
%3 = load double, double* %0
%4 = getelementptr inbounds double, double* %0, i64 1
%5 = load double, double* %4
%6 = fmul double %5, %5
%7 = tail call double @llvm.fmuladd.f64(double %3, double %3, double %6)
%8 = tail call double @sqrt(double %7)
%9 = getelementptr inbounds double, double* %0, i64 2
%10 = load double, double* %9
%11 = fmul double %10, %10
%12 = tail call double @llvm.fmuladd.f64(double %8, double %8, double %11)
%13 = tail call double @sqrt(double %12)
%14 = load double, double* %9
%15 = fdiv double %8, %13
%16 = bitcast double* %0 to <2 x double>*
%17 = load <2 x double>, <2 x double>* %16
%18 = insertelement <2 x double> poison, double %8, i64 0
%19 = shufflevector <2 x double> %18, <2 x double> poison, <2 x i32> zeroinitializer
%20 = fdiv <2 x double> %17, %19
%21 = fneg double %14
%22 = fdiv double %21, %13
%23 = insertelement <2 x double> poison, double %22, i64 0
%24 = shufflevector <2 x double> %23, <2 x double> poison, <2 x i32> zeroinitializer
%25 = fmul <2 x double> %24, %20
%26 = bitcast [3 x double]* %1 to <2 x double>*
store <2 x double> %25, <2 x double>* %26
%27 = getelementptr inbounds [3 x double], [3 x double]* %1, i64 0, i64 2
store double %15, double* %27
%28 = extractelement <2 x double> %20, i64 1
%29 = fneg double %28
%30 = getelementptr inbounds [3 x double], [3 x double]* %1, i64 1, i64 0
store double %29, double* %30
%31 = getelementptr inbounds [3 x double], [3 x double]* %1, i64 1, i64 1
%32 = extractelement <2 x double> %20, i64 0
store double %32, double* %31
%33 = getelementptr inbounds [3 x double], [3 x double]* %1, i64 1, i64 2
store double 0.000000e+00, double* %33
%34 = fneg double %15
%35 = getelementptr inbounds [3 x double], [3 x double]* %1, i64 2, i64 0
%36 = insertelement <2 x double> poison, double %34, i64 0
%37 = shufflevector <2 x double> %36, <2 x double> poison, <2 x i32> zeroinitializer
%38 = fmul <2 x double> %20, %37
%39 = bitcast double* %35 to <2 x double>*
store <2 x double> %38, <2 x double>* %39
%40 = getelementptr inbounds [3 x double], [3 x double]* %1, i64 2, i64 2
store double %22, double* %40
ret void
}