// File: /workspace/github_cpp_makefile_star2_O3/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
movq %rdi, %r14
movzbl %dl, %eax
movq %rax, 0x38(%rsp)
movl %ecx, 0x8(%rsp)
movzbl %cl, %eax
movq %rax, 0x40(%rsp)
movl %r8d, 0xc(%rsp)
movzbl %r8b, %r13d
testb %dl, %dl
jle 0x9b44
movq %rsi, %r12
movl %edx, 0x34(%rsp)
movsd 0x29f4e(%rip), %xmm4    # 0x338f0
xorl %ebp, %ebp
movapd 0x29f84(%rip), %xmm2    # 0x33930
movsd 0x29f44(%rip), %xmm6    # 0x338f8
xorpd %xmm0, %xmm0
xorpd %xmm3, %xmm3
cmpb $0x0, 0x8(%rsp)
jle 0x9b22
xorl %ebx, %ebx
movapd %xmm0, %xmm1
movapd %xmm4, %xmm5
movapd %xmm3, %xmm7
cmpb $0x0, 0xc(%rsp)
jle 0x9afc
movq (%r14,%rbp,8), %rax
xorl %r15d, %r15d
movq (%rax,%rbx,8), %rcx
movsd (%rcx,%r15,8), %xmm0
andpd %xmm2, %xmm0
ucomisd %xmm0, %xmm6
jbe 0x9a0c
movapd %xmm7, %xmm3
movapd %xmm5, %xmm4
movapd %xmm1, %xmm0
jmp 0x9ae2
movapd %xmm0, %xmm2
maxsd %xmm1, %xmm2
movsd %xmm2, (%rsp)
movsd %xmm5, 0x10(%rsp)
movsd %xmm7, 0x28(%rsp)
callq 0x4110
callq 0x4090
movsd 0x29ec1(%rip), %xmm6    # 0x338f8
movapd %xmm0, %xmm3
maxsd 0x28(%rsp), %xmm3
movq (%r14,%rbp,8), %rax
movq (%rax,%rbx,8), %rcx
movsd (%rcx,%r15,8), %xmm0
xorpd %xmm1, %xmm1
cmpltsd %xmm0, %xmm1
cmpltsd 0x29e9f(%rip), %xmm0    # 0x33900
movsd 0x29e87(%rip), %xmm5    # 0x338f0
andpd %xmm5, %xmm0
movq (%r12,%rbp,8), %rcx
movq (%rcx,%rbx,8), %rcx
movsd (%rcx,%r15,8), %xmm4
movapd %xmm5, %xmm2
subsd %xmm4, %xmm2
andpd %xmm5, %xmm1
mulsd %xmm4, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movapd 0x29e95(%rip), %xmm1    # 0x33930
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 0x10(%rsp), %xmm2
orpd %xmm1, %xmm4
addsd %xmm0, %xmm4
ucomisd %xmm4, %xmm2
ja 0x9ad5
movapd %xmm2, %xmm4
movapd 0x29e53(%rip), %xmm2    # 0x33930
movsd (%rsp), %xmm0
incq %r15
movapd %xmm0, %xmm1
movapd %xmm4, %xmm5
movapd %xmm3, %xmm7
cmpq %r15, %r13
jne 0x99e7
jmp 0x9b08
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 0x99d5
incq %rbp
cmpq 0x38(%rsp), %rbp
jne 0x99bc
mulsd 0x29de0(%rip), %xmm4    # 0x33918
movapd %xmm4, 0x10(%rsp)
movl 0x34(%rsp), %edx
jmp 0x9b5a
movsd 0x29dcc(%rip), %xmm0    # 0x33918
movapd %xmm0, 0x10(%rsp)
xorpd %xmm3, %xmm3
xorpd %xmm0, %xmm0
movsd %xmm0, (%rsp)
movsd %xmm3, 0x28(%rsp)
testb %dl, %dl
setg %bl
movsd 0x29d9e(%rip), %xmm0    # 0x33910
movapd %xmm3, %xmm1
callq 0x4420
movsd 0x28(%rsp), %xmm1
ucomisd 0x29d77(%rip), %xmm1    # 0x33900
movsd (%rsp), %xmm2
divsd %xmm0, %xmm2
seta %al
testb %bl, %al
movapd %xmm2, %xmm0
je 0x9c2c
movapd 0x10(%rsp), %xmm2
divsd %xmm0, %xmm2
xorl %ebx, %ebx
movapd %xmm2, 0x10(%rsp)
cmpb $0x0, 0x8(%rsp)
jle 0x9c20
xorl %r15d, %r15d
cmpb $0x0, 0xc(%rsp)
jle 0x9c16
movq (%r14,%rbx,8), %rax
movq (%rax,%r15,8), %rax
xorl %r12d, %r12d
movsd (%rax,%r12,8), %xmm0
mulsd %xmm2, %xmm0
movsd %xmm0, (%rsp)
movsd 0x29d2a(%rip), %xmm0    # 0x33910
callq 0x4420
movapd 0x10(%rsp), %xmm2
movsd 0x28(%rsp), %xmm1
movsd (%rsp), %xmm3
divsd %xmm0, %xmm3
movq (%r14,%rbx,8), %rax
movq (%rax,%r15,8), %rax
movsd %xmm3, (%rax,%r12,8)
incq %r12
cmpq %r12, %r13
jne 0x9bcf
incq %r15
cmpq 0x40(%rsp), %r15
jne 0x9bbd
incq %rbx
cmpq 0x38(%rsp), %rbx
jne 0x9bb3
jmp 0x9c3c
movapd 0x10(%rsp), %xmm2
divsd %xmm0, %xmm2
movapd %xmm2, 0x10(%rsp)
movsd 0x29ccc(%rip), %xmm0    # 0x33910
callq 0x4420
movapd 0x10(%rsp), %xmm1
divsd %xmm0, %xmm1
movapd %xmm1, %xmm0
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq