// File: /workspace/github_cpp_makefile_star2_O1/myudelson[P]hmm-scalable/utils.cpp
// Function: doLog10Scale3DGentle(double***, double***, signed char, signed char, signed char)
NUMBER doLog10Scale3DGentle(NUMBER ***grad, NUMBER ***par, NPAR size1, NPAR size2, NPAR size3) {
    NPAR i,j,k;
    NUMBER max_10_scale = 0, candidate, min_delta = 1, max_grad = 0;
    for(i=0; i<size1; i++)
        for(j=0; j<size2; j++)
            for(k=0; k<size3; k++) {
                if( fabs(grad[i][j][k]) < SAFETY ) // 0 gradient
                    continue;
                // scale
                if(max_grad < fabs(grad[i][j][k]))
                    max_grad = fabs(grad[i][j][k]);
                candidate = ceil( log10( fabs(grad[i][j][k]) ) );
                if(candidate > max_10_scale)
                    max_10_scale = candidate;
                // delta: if grad<0 - distance to 1, if grad>0 - distance to 0
                candidate = (grad[i][j][k]<0)*(1-par[i][j][k]) + (grad[i][j][k]>0)*(par[i][j][k]) +
                ( (fabs(par[i][j][k])< SAFETY) || (fabs(1-par[i][j][k])< SAFETY) ); // these terms are there to avoid already extreme 0, 1 values
                if( candidate < min_delta)
                    min_delta = candidate;
            }
    max_grad = max_grad / pow(10, max_10_scale);
    if(max_10_scale >0 )
        for(i=0; i<size1; i++)
            for(j=0; j<size2; j++)
                for(k=0; k<size3; k++)
                    grad[i][j][k] = ( 0.95 * min_delta / max_grad) * grad[i][j][k] / pow(10, max_10_scale);
    return ( 0.95 * min_delta / max_grad ) / pow(10, max_10_scale);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %edx, %ebx
movq %rdi, %r14
movzbl %bl, %eax
movq %rax, 0x38(%rsp)
movl %ecx, 0x10(%rsp)
movzbl %cl, %eax
movq %rax, 0x40(%rsp)
movl %r8d, 0x14(%rsp)
movzbl %r8b, %r13d
testb %bl, %bl
jle 0x9ad6
movq %rsi, %r12
movl %ebx, 0x34(%rsp)
movsd 0x2afbe(%rip), %xmm4    # 0x348f0
xorl %ebp, %ebp
movapd 0x2aff4(%rip), %xmm2    # 0x34930
movsd 0x2afb4(%rip), %xmm6    # 0x348f8
xorpd %xmm0, %xmm0
xorpd %xmm3, %xmm3
cmpb $0x0, 0x10(%rsp)
jle 0x9ab4
xorl %ebx, %ebx
movapd %xmm0, %xmm1
movapd %xmm4, %xmm5
movapd %xmm3, %xmm7
cmpb $0x0, 0x14(%rsp)
jle 0x9a8e
xorl %r15d, %r15d
movq (%r14,%rbp,8), %rax
movq (%rax,%rbx,8), %rax
movsd (%rax,%r15,8), %xmm0
andpd %xmm2, %xmm0
ucomisd %xmm0, %xmm6
jbe 0x999c
movapd %xmm7, %xmm3
movapd %xmm5, %xmm4
movapd %xmm1, %xmm0
jmp 0x9a74
movapd %xmm0, %xmm2
maxsd %xmm1, %xmm2
movsd %xmm2, 0x8(%rsp)
movsd %xmm5, 0x20(%rsp)
movsd %xmm7, 0x18(%rsp)
callq 0x4110
callq 0x4090
movsd 0x2af30(%rip), %xmm6    # 0x348f8
movapd %xmm0, %xmm3
maxsd 0x18(%rsp), %xmm3
movq (%r14,%rbp,8), %rax
movq (%rax,%rbx,8), %rax
movsd (%rax,%r15,8), %xmm0
xorpd %xmm1, %xmm1
cmpltsd %xmm0, %xmm1
cmpltsd 0x2af0e(%rip), %xmm0    # 0x34900
movsd 0x2aef6(%rip), %xmm5    # 0x348f0
andpd %xmm5, %xmm0
movq (%r12,%rbp,8), %rax
movq (%rax,%rbx,8), %rax
movsd (%rax,%r15,8), %xmm4
movapd %xmm5, %xmm2
subsd %xmm4, %xmm2
andpd %xmm5, %xmm1
mulsd %xmm4, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movapd 0x2af04(%rip), %xmm1    # 0x34930
andpd %xmm1, %xmm4
andpd %xmm1, %xmm2
cmpltsd %xmm6, %xmm2
andpd %xmm5, %xmm2
cmpltsd %xmm6, %xmm4
movapd %xmm4, %xmm1
andnpd %xmm2, %xmm1
andpd %xmm5, %xmm4
movsd 0x20(%rsp), %xmm2
orpd %xmm1, %xmm4
addsd %xmm0, %xmm4
ucomisd %xmm4, %xmm2
ja 0x9a66
movapd %xmm2, %xmm4
movapd 0x2aec2(%rip), %xmm2    # 0x34930
movsd 0x8(%rsp), %xmm0
incq %r15
movapd %xmm0, %xmm1
movapd %xmm4, %xmm5
movapd %xmm3, %xmm7
cmpq %r15, %r13
jne 0x9973
jmp 0x9a9a
movapd %xmm7, %xmm3
movapd %xmm5, %xmm4
movapd %xmm1, %xmm0
incq %rbx
movapd %xmm0, %xmm1
movapd %xmm4, %xmm5
movapd %xmm3, %xmm7
cmpq 0x40(%rsp), %rbx
jne 0x9965
incq %rbp
cmpq 0x38(%rsp), %rbp
jne 0x994c
mulsd 0x2ae4e(%rip), %xmm4    # 0x34918
movapd %xmm4, 0x20(%rsp)
movl 0x34(%rsp), %ebx
jmp 0x9aec
movsd 0x2ae3a(%rip), %xmm0    # 0x34918
movapd %xmm0, 0x20(%rsp)
xorpd %xmm3, %xmm3
xorpd %xmm0, %xmm0
movsd %xmm0, 0x8(%rsp)
movsd %xmm3, 0x18(%rsp)
movsd 0x2ae10(%rip), %xmm0    # 0x34910
movapd %xmm3, %xmm1
callq 0x4420
movsd 0x18(%rsp), %xmm1
movsd 0x8(%rsp), %xmm2
divsd %xmm0, %xmm2
ucomisd 0x2addf(%rip), %xmm1    # 0x34900
setbe %al
movapd 0x20(%rsp), %xmm0
divsd %xmm2, %xmm0
movapd %xmm0, 0x20(%rsp)
testb %bl, %bl
setle %cl
orb %al, %cl
jne 0x9bc2
xorl %ebx, %ebx
cmpb $0x0, 0x10(%rsp)
jle 0x9bb8
xorl %r15d, %r15d
cmpb $0x0, 0x14(%rsp)
movapd 0x20(%rsp), %xmm0
jle 0x9bae
xorl %r12d, %r12d
movq (%r14,%rbx,8), %rax
movq (%rax,%r15,8), %rax
movsd (%rax,%r12,8), %xmm2
mulsd %xmm0, %xmm2
movsd %xmm2, 0x8(%rsp)
movsd 0x2ad93(%rip), %xmm0    # 0x34910
callq 0x4420
movsd 0x18(%rsp), %xmm1
movsd 0x8(%rsp), %xmm2
divsd %xmm0, %xmm2
movapd 0x20(%rsp), %xmm0
movq (%r14,%rbx,8), %rax
movq (%rax,%r15,8), %rax
movsd %xmm2, (%rax,%r12,8)
incq %r12
cmpq %r12, %r13
jne 0x9b5d
incq %r15
cmpq 0x40(%rsp), %r15
jne 0x9b4d
incq %rbx
cmpq 0x38(%rsp), %rbx
jne 0x9b43
movsd 0x2ad46(%rip), %xmm0    # 0x34910
callq 0x4420
movapd 0x20(%rsp), %xmm1
divsd %xmm0, %xmm1
movapd %xmm1, %xmm0
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq