// File: alan0201tw[P]RayTracer/src/util.cpp
// Function: perlin_interpolate(vec3 (*) [2][2], float, float, float)
float perlin_interpolate(vec3 _data[2][2][2], float _u, float _v, float _w)
{
    // Reference :
    // https://github.com/RayTracing/TheNextWeek/issues/6
    //
    // in the original implementation in the book, the dot product
    // will return negative results, causing the produced image haing
    // several dark bands. 
    // Accoring to the github issue, this can be resolved by rescaling
    // the interpolation result from [-1, 1] to [0, 1].

    float uu = _u * _u * (3 - 2 * _u);
    float vv = _v * _v * (3 - 2 * _v);
    float ww = _w * _w * (3 - 2 * _w);

    float accum = 0.0f;
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            for(int k = 0; k < 2; k++)
            {
                vec3 weight(_u - i, _v - j, _w - k);
                accum += (i * uu + (1 - i) * (1 - uu)) *
                         (j * vv + (1 - j) * (1 - vv)) *
                         (k * ww + (1 - k) * (1 - ww)) * dot(_data[i][j][k], weight);
            }
        }
    }
    return 0.5f * (accum + 1.0f);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movss %xmm0, -0xc(%rbp)
movss %xmm1, -0x10(%rbp)
movss %xmm2, -0x14(%rbp)
movss -0xc(%rbp), %xmm0
mulss -0xc(%rbp), %xmm0
movss -0xc(%rbp), %xmm2
addss %xmm2, %xmm2
movss 0x59812(%rip), %xmm1    # 0x7e4c8
subss %xmm2, %xmm1
mulss %xmm1, %xmm0
movss %xmm0, -0x18(%rbp)
movss -0x10(%rbp), %xmm0
mulss -0x10(%rbp), %xmm0
movss -0x10(%rbp), %xmm2
addss %xmm2, %xmm2
movss 0x597ea(%rip), %xmm1    # 0x7e4c8
subss %xmm2, %xmm1
mulss %xmm1, %xmm0
movss %xmm0, -0x1c(%rbp)
movss -0x14(%rbp), %xmm0
mulss -0x14(%rbp), %xmm0
movss -0x14(%rbp), %xmm2
addss %xmm2, %xmm2
movss 0x597c2(%rip), %xmm1    # 0x7e4c8
subss %xmm2, %xmm1
mulss %xmm1, %xmm0
movss %xmm0, -0x20(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
cmpl $0x2, -0x28(%rbp)
jge 0x24e91
movl $0x0, -0x2c(%rbp)
cmpl $0x2, -0x2c(%rbp)
jge 0x24e81
movl $0x0, -0x30(%rbp)
cmpl $0x2, -0x30(%rbp)
jge 0x24e71
movss -0xc(%rbp), %xmm0
cvtsi2ssl -0x28(%rbp), %xmm1
subss %xmm1, %xmm0
movss -0x10(%rbp), %xmm1
cvtsi2ssl -0x2c(%rbp), %xmm2
subss %xmm2, %xmm1
movss -0x14(%rbp), %xmm2
cvtsi2ssl -0x30(%rbp), %xmm3
subss %xmm3, %xmm2
leaq -0x3c(%rbp), %rdi
callq 0xf9b0
cvtsi2ssl -0x28(%rbp), %xmm0
movss -0x18(%rbp), %xmm2
movl $0x1, %eax
subl -0x28(%rbp), %eax
cvtsi2ss %eax, %xmm1
movss 0x5945d(%rip), %xmm3    # 0x7e1fc
subss -0x18(%rbp), %xmm3
mulss %xmm3, %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
cvtsi2ssl -0x2c(%rbp), %xmm1
movss -0x1c(%rbp), %xmm3
movl $0x1, %eax
subl -0x2c(%rbp), %eax
cvtsi2ss %eax, %xmm2
movss 0x5942e(%rip), %xmm4    # 0x7e1fc
subss -0x1c(%rbp), %xmm4
mulss %xmm4, %xmm2
mulss %xmm3, %xmm1
addss %xmm2, %xmm1
mulss %xmm1, %xmm0
cvtsi2ssl -0x30(%rbp), %xmm1
movss -0x20(%rbp), %xmm3
movl $0x1, %eax
subl -0x30(%rbp), %eax
cvtsi2ss %eax, %xmm2
movss 0x593fb(%rip), %xmm4    # 0x7e1fc
subss -0x20(%rbp), %xmm4
mulss %xmm4, %xmm2
mulss %xmm3, %xmm1
addss %xmm2, %xmm1
mulss %xmm1, %xmm0
movss %xmm0, -0x40(%rbp)
movq -0x8(%rbp), %rdi
movslq -0x28(%rbp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movslq -0x2c(%rbp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
movslq -0x30(%rbp), %rax
imulq $0xc, %rax, %rax
addq %rax, %rdi
leaq -0x3c(%rbp), %rsi
callq 0x11900
movaps %xmm0, %xmm2
movss -0x40(%rbp), %xmm0
movss -0x24(%rbp), %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, -0x24(%rbp)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x24d44
jmp 0x24e73
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x24d33
jmp 0x24e83
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x24d22
movss 0x59363(%rip), %xmm1    # 0x7e1fc
addss -0x24(%rbp), %xmm1
movss 0x5937e(%rip), %xmm0    # 0x7e224
mulss %xmm1, %xmm0
addq $0x40, %rsp
popq %rbp
retq