// File: /workspace/github_cpp_makefile_star2_O3/sus304[P]ForRocket/src/environment/satmo1976.cpp
// Function: standardatmosphere1976::LowerAtmosphere(double)
std::vector<double> standardatmosphere1976::LowerAtmosphere(double geometric_altitude) {
    using Layer = std::array<double, 8>;
    Layer height_array = {0.0, 11.0, 20.0, 32.0, 47.0, 51.0, 71.0, 84.852};  // [km] geopotential height
    Layer temperature_gradient_array = {-6.5, 0.0, 1.0, 2.8, 0.0, -2.8, -2.0, 0.0};  // [K/km] Temperature gradient
    Layer temperature_array = {288.15, 216.65, 216.65, 228.65, 270.65, 270.65, 214.65, 186.946};  // [K]
    // Layer pressure_array = {101325.0, 22632.0, 5474.9, 868.02, 110.91, 66.939, 3.9564, 0.3734};  // [Pa]
    Layer pressure_gradient_array = {1.0, 2.233611e-1, 5.403295e-2, 8.5666784e-3, 1.0945601e-3, 6.6063531e-4, 3.9046834e-5, 3.68501e-6};

    double geopotential_height = geometric_altitude * earth_radius / (geometric_altitude + earth_radius);  // geopotential altitude

    int j = 7;  // Layer number
    int i = 0;
    for (; i < 7;) {
        int k = (i + j) / 2;
        if (geopotential_height < height_array[k]) {
            j = k;
        } else {
            i = k;
        }
        if (j <= i + 1) {
            break;
        }
    }

    double temp_gradient = temperature_gradient_array[i];
    double temp_base = temperature_array[i];
    double delta_height = geopotential_height - height_array[i];
    double temp_local = temp_base + temp_gradient * delta_height;
    double theta = temp_local / temperature_array[0];

    double delta; 
    if (temp_gradient == 0.0) {
        delta = pressure_gradient_array[i] * std::exp(-gmr * delta_height / temp_base);
    } else {
        delta = pressure_gradient_array[i] * std::pow(temp_base / temp_local, gmr / temp_gradient);
    }
    double sigma = delta / theta;

    std::vector<double> res = {sigma * density_sealevel, delta * pressure_sealevel, theta * temp_sealevel};
    return res;
}

// Assembly:
pushq %rbx
subq $0x80, %rsp
movapd %xmm0, %xmm1
movq %rdi, %rbx
xorpd %xmm0, %xmm0
movupd %xmm0, 0x38(%rsp)
movupd %xmm0, 0x28(%rsp)
movq $0x0, 0x58(%rsp)
movabsq $-0x3fe6000000000000, %rax # imm = 0xC01A000000000000
movq %rax, 0x20(%rsp)
movaps 0x22f74(%rip), %xmm0    # 0x3ac60
movups %xmm0, 0x30(%rsp)
movaps 0x22f78(%rip), %xmm0    # 0x3ac70
movups %xmm0, 0x48(%rsp)
movsd 0x3166b(%rip), %xmm2    # 0x49370
movapd %xmm2, %xmm0
mulsd %xmm1, %xmm0
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
movl $0x7, %edx
xorl %ecx, %ecx
leaq 0x22f5d(%rip), %rax     # 0x3ac80
cmpl $0x6, %ecx
jg 0x17d4f
leal (%rdx,%rcx), %edi
movl %edi, %esi
shrl $0x1f, %esi
addl %edi, %esi
sarl %esi
movslq %esi, %rdi
movsd (%rax,%rdi,8), %xmm1
ucomisd %xmm0, %xmm1
ja 0x17d46
movl %esi, %ecx
jmp 0x17d48
movl %esi, %edx
leal 0x1(%rcx), %esi
cmpl %esi, %edx
jg 0x17d23
movslq %ecx, %rcx
movsd 0x20(%rsp,%rcx,8), %xmm3
leaq 0x22f61(%rip), %rdx     # 0x3acc0
movsd (%rdx,%rcx,8), %xmm2
subsd (%rax,%rcx,8), %xmm0
movapd %xmm3, %xmm4
mulsd %xmm0, %xmm4
addsd %xmm2, %xmm4
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm3
leaq 0x22f7c(%rip), %rax     # 0x3ad00
movsd (%rax,%rcx,8), %xmm1
movaps %xmm1, 0x10(%rsp)
movsd %xmm4, 0x8(%rsp)
jne 0x17db7
jp 0x17db7
movsd 0x315f0(%rip), %xmm1    # 0x49390
xorpd 0x22968(%rip), %xmm1    # 0x3a710
mulsd %xmm1, %xmm0
divsd %xmm2, %xmm0
callq 0x55f0
jmp 0x17dd0
divsd %xmm4, %xmm2
movsd 0x315cd(%rip), %xmm1    # 0x49390
divsd %xmm3, %xmm1
movapd %xmm2, %xmm0
callq 0x55d0
movapd 0x10(%rsp), %xmm1
mulsd %xmm0, %xmm1
movsd 0x8(%rsp), %xmm2
divsd 0x22de8(%rip), %xmm2    # 0x3abd0
movapd %xmm1, %xmm0
divsd %xmm2, %xmm0
unpcklpd %xmm1, %xmm0            # xmm0 = xmm0[0],xmm1[0]
movsd 0x315ac(%rip), %xmm1    # 0x493a8
movhpd 0x3159c(%rip), %xmm1    # xmm1 = xmm1[0],mem[0]
mulpd %xmm0, %xmm1
leaq 0x60(%rsp), %rsi
movapd %xmm1, (%rsi)
mulsd 0x3157f(%rip), %xmm2    # 0x49398
movsd %xmm2, 0x10(%rsi)
leaq 0x7(%rsp), %rcx
movl $0x3, %edx
movq %rbx, %rdi
callq 0x17f80
movq %rbx, %rax
addq $0x80, %rsp
popq %rbx
retq