// File: spatialfruitsalad[P]volume2position/./bilateral.hpp
// Function: void bilateralFilter::Process<unsigned short>(tomogram3d<unsigned short>&, tomogram3d<unsigned short>&)
void Process(tomogram3d<VALUE>& matrix_in, tomogram3d<VALUE>& matrix_out)
    {
        std::cout << "applying bilateral filter" << std::endl;

        int sx = matrix_in.get_sx();
        int sy = matrix_in.get_sy();
        int sz = matrix_in.get_sz();

        matrix_out.clear();
        matrix_out.initialise (sx, sy, sz, 0);

        // outer loop over the whole image
        for (int k = 0; k != sz; ++k)
        {
            std::cout << k  << " " << std::flush;
            for (int j = 0; j != sy; ++j)
            {
                for (int i = 0; i != sx; ++i)
                {
                    // original value from the old image
                    VALUE orig = matrix_in.get(i,j,k);

                    // calculate boundaries so I don't read from otside the image
                    int imin = std::max (i-tol, 0);
                    int imax = std::min (i+tol, int (sx-1));
                    int jmin = std::max (j-tol, 0);
                    int jmax = std::min (j+tol, int (sy-1));
                    int kmin = std::max (k-tol, 0);
                    int kmax = std::min (k+tol, int (sz-1));

                    double new_val = 0;
                    double sum = 0;
                    // inner loop over the filter kernel
                    for (int ii = imin; ii <= imax; ++ii)
                    {
                        for (int jj = jmin; jj <= jmax; ++jj)
                        {
                            for (int kk = kmin; kk <= kmax; ++kk)
                            {
                                VALUE other = matrix_in.get(ii,jj,kk);  
                                double similarityFactor = getGauss( other - orig);
                                double closenessFactor = mask.get(ii-i+tol, jj-j+tol, kk-k+tol);
                                double currentWeight = closenessFactor * similarityFactor;
                                sum += currentWeight;
                                new_val += other * currentWeight;
                            }
                        }
                    }
                    matrix_out.set(i,j,k,new_val/sum);
                }
            }
        }
        std::cout << "\ndone" << std::endl;
    }

// Assembly:
subq $0xc8, %rsp
movq %rdi, 0xc0(%rsp)
movq %rsi, 0xb8(%rsp)
movq %rdx, 0xb0(%rsp)
movq 0xc0(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x2c76d(%rip), %rdi     # 0x33fc0
leaq 0x2124b(%rip), %rsi     # 0x28aa5
callq 0x3290
movq %rax, %rdi
movq 0x2c737(%rip), %rsi     # 0x33fa0
callq 0x32c0
movq 0xb8(%rsp), %rdi
callq 0x208b0
movl %eax, 0xac(%rsp)
movq 0xb8(%rsp), %rdi
callq 0x208c0
movl %eax, 0xa8(%rsp)
movq 0xb8(%rsp), %rdi
callq 0x208d0
movl %eax, 0xa4(%rsp)
movq 0xb0(%rsp), %rdi
callq 0x7d50
movq 0xb0(%rsp), %rdi
movslq 0xac(%rsp), %rsi
movslq 0xa8(%rsp), %rdx
movslq 0xa4(%rsp), %rcx
xorl %r8d, %r8d
callq 0xee70
movl $0x0, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
cmpl 0xa4(%rsp), %eax
je 0x7cca
movl 0xa0(%rsp), %esi
movq 0x2c6b4(%rip), %rdi     # 0x33fc0
callq 0x3470
movq %rax, %rdi
leaq 0x2132d(%rip), %rsi     # 0x28c48
callq 0x3290
movq %rax, %rdi
movq 0x2c69e(%rip), %rsi     # 0x33fc8
callq 0x32c0
movl $0x0, 0x9c(%rsp)
movl 0x9c(%rsp), %eax
cmpl 0xa8(%rsp), %eax
je 0x7cb2
movl $0x0, 0x98(%rsp)
movl 0x98(%rsp), %eax
cmpl 0xac(%rsp), %eax
je 0x7c9a
movq 0xb8(%rsp), %rdi
movslq 0x98(%rsp), %rsi
movslq 0x9c(%rsp), %rdx
movslq 0xa0(%rsp), %rcx
callq 0xa350
movq 0x8(%rsp), %rcx
movw %ax, 0x96(%rsp)
movl 0x98(%rsp), %eax
subl 0x18(%rcx), %eax
movl %eax, 0x8c(%rsp)
movl $0x0, 0x88(%rsp)
leaq 0x8c(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0x127b0
movq 0x8(%rsp), %rcx
movl (%rax), %eax
movl %eax, 0x90(%rsp)
movl 0x98(%rsp), %eax
addl 0x18(%rcx), %eax
movl %eax, 0x80(%rsp)
movl 0xac(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x7c(%rsp)
leaq 0x80(%rsp), %rdi
leaq 0x7c(%rsp), %rsi
callq 0x127f0
movq 0x8(%rsp), %rcx
movl (%rax), %eax
movl %eax, 0x84(%rsp)
movl 0x9c(%rsp), %eax
subl 0x18(%rcx), %eax
movl %eax, 0x74(%rsp)
movl $0x0, 0x70(%rsp)
leaq 0x74(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x127b0
movq 0x8(%rsp), %rcx
movl (%rax), %eax
movl %eax, 0x78(%rsp)
movl 0x9c(%rsp), %eax
addl 0x18(%rcx), %eax
movl %eax, 0x68(%rsp)
movl 0xa8(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x64(%rsp)
leaq 0x68(%rsp), %rdi
leaq 0x64(%rsp), %rsi
callq 0x127f0
movq 0x8(%rsp), %rcx
movl (%rax), %eax
movl %eax, 0x6c(%rsp)
movl 0xa0(%rsp), %eax
subl 0x18(%rcx), %eax
movl %eax, 0x5c(%rsp)
movl $0x0, 0x58(%rsp)
leaq 0x5c(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x127b0
movq 0x8(%rsp), %rcx
movl (%rax), %eax
movl %eax, 0x60(%rsp)
movl 0xa0(%rsp), %eax
addl 0x18(%rcx), %eax
movl %eax, 0x50(%rsp)
movl 0xa4(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x4c(%rsp)
leaq 0x50(%rsp), %rdi
leaq 0x4c(%rsp), %rsi
callq 0x127f0
movl (%rax), %eax
movl %eax, 0x54(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x40(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x38(%rsp)
movl 0x90(%rsp), %eax
movl %eax, 0x34(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x84(%rsp), %eax
jg 0x7c47
movl 0x78(%rsp), %eax
movl %eax, 0x30(%rsp)
movl 0x30(%rsp), %eax
cmpl 0x6c(%rsp), %eax
jg 0x7c35
movl 0x60(%rsp), %eax
movl %eax, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
cmpl 0x54(%rsp), %eax
jg 0x7c23
movq 0xb8(%rsp), %rdi
movslq 0x34(%rsp), %rsi
movslq 0x30(%rsp), %rdx
movslq 0x2c(%rsp), %rcx
callq 0xa350
movq 0x8(%rsp), %rdi
movw %ax, 0x2a(%rsp)
movzwl 0x2a(%rsp), %eax
movzwl 0x96(%rsp), %ecx
subl %ecx, %eax
cvtsi2sd %eax, %xmm0
callq 0x208e0
movq 0x8(%rsp), %rcx
movsd %xmm0, 0x20(%rsp)
movq %rcx, %rdi
addq $0x20, %rdi
movl 0x34(%rsp), %eax
subl 0x98(%rsp), %eax
addl 0x18(%rcx), %eax
movslq %eax, %rsi
movl 0x30(%rsp), %eax
subl 0x9c(%rsp), %eax
addl 0x18(%rcx), %eax
movslq %eax, %rdx
movl 0x2c(%rsp), %eax
subl 0xa0(%rsp), %eax
addl 0x18(%rcx), %eax
movslq %eax, %rcx
callq 0x209b0
movsd %xmm0, 0x18(%rsp)
movsd 0x18(%rsp), %xmm0
mulsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x10(%rsp), %xmm0
addsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movzwl 0x2a(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd 0x10(%rsp), %xmm2
movsd 0x40(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x40(%rsp)
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x7b30
jmp 0x7c25
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x7b1a
jmp 0x7c37
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0x7b01
movq 0xb0(%rsp), %rdi
movslq 0x98(%rsp), %rsi
movslq 0x9c(%rsp), %rdx
movslq 0xa0(%rsp), %rcx
movsd 0x40(%rsp), %xmm0
movsd 0x38(%rsp), %xmm1
divsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movzwl %ax, %r8d
callq 0xf360
movl 0x98(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x98(%rsp)
jmp 0x7959
jmp 0x7c9c
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x793a
jmp 0x7cb4
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x78ea
movq 0x2c2ef(%rip), %rdi     # 0x33fc0
leaq 0x20de7(%rip), %rsi     # 0x28abf
callq 0x3290
movq %rax, %rdi
movq 0x2c2b9(%rip), %rsi     # 0x33fa0
callq 0x32c0
addq $0xc8, %rsp
retq
nopw %cs:(%rax,%rax)
nop