// File: 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
movq %rsp, %rbp
subq $0x60, %rsp
movb %r8b, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movb %dl, -0x11(%rbp)
movb %cl, -0x12(%rbp)
movb %al, -0x13(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x20(%rbp)
movsd 0x44c9c(%rip), %xmm0    # 0x4fa08
movsd %xmm0, -0x30(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x38(%rbp)
movb $0x0, -0x14(%rbp)
movsbl -0x14(%rbp), %eax
movsbl -0x11(%rbp), %ecx
cmpl %ecx, %eax
jge 0xb044
movb $0x0, -0x15(%rbp)
movsbl -0x15(%rbp), %eax
movsbl -0x12(%rbp), %ecx
cmpl %ecx, %eax
jge 0xb035
movb $0x0, -0x16(%rbp)
movsbl -0x16(%rbp), %eax
movsbl -0x13(%rbp), %ecx
cmpl %ecx, %eax
jge 0xb026
movq -0x8(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movaps 0x44cb4(%rip), %xmm0    # 0x4fa90
pand %xmm0, %xmm1
movsd 0x44c28(%rip), %xmm0    # 0x4fa10
ucomisd %xmm1, %xmm0
jbe 0xadf3
jmp 0xb019
movsd -0x38(%rbp), %xmm1
movq -0x8(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movaps 0x44c71(%rip), %xmm2    # 0x4fa90
pand %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jbe 0xae59
movq -0x8(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movaps 0x44c40(%rip), %xmm1    # 0x4fa90
pand %xmm1, %xmm0
movsd %xmm0, -0x38(%rbp)
movq -0x8(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movaps 0x44c10(%rip), %xmm1    # 0x4fa90
pand %xmm1, %xmm0
callq 0x5140
callq 0x50a0
movsd %xmm0, -0x28(%rbp)
movsd -0x28(%rbp), %xmm0
ucomisd -0x20(%rbp), %xmm0
jbe 0xaea9
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
movq -0x8(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
xorps %xmm0, %xmm0
ucomisd (%rax,%rcx,8), %xmm0
seta %al
andb $0x1, %al
movzbl %al, %eax
cvtsi2sd %eax, %xmm0
movq -0x10(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd 0x44b0d(%rip), %xmm2    # 0x4fa08
subsd (%rax,%rcx,8), %xmm2
movq -0x8(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
xorps %xmm3, %xmm3
ucomisd %xmm3, %xmm1
seta %al
andb $0x1, %al
movzbl %al, %eax
cvtsi2sd %eax, %xmm1
movq -0x10(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x10(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movaps 0x44b09(%rip), %xmm0    # 0x4fa90
pand %xmm0, %xmm1
movb $0x1, %al
movsd 0x44a7b(%rip), %xmm0    # 0x4fa10
ucomisd %xmm1, %xmm0
movb %al, -0x39(%rbp)
ja 0xafe3
movq -0x10(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd 0x44a47(%rip), %xmm1    # 0x4fa08
subsd (%rax,%rcx,8), %xmm1
movaps 0x44ac3(%rip), %xmm0    # 0x4fa90
pand %xmm0, %xmm1
movsd 0x44a37(%rip), %xmm0    # 0x4fa10
ucomisd %xmm1, %xmm0
seta %al
movb %al, -0x39(%rbp)
movsd -0x48(%rbp), %xmm0
movb -0x39(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
cvtsi2sd %eax, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
movsd -0x28(%rbp), %xmm1
movsd -0x30(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0xb017
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
jmp 0xb019
movb -0x16(%rbp), %al
addb $0x1, %al
movb %al, -0x16(%rbp)
jmp 0xada5
jmp 0xb028
movb -0x15(%rbp), %al
addb $0x1, %al
movb %al, -0x15(%rbp)
jmp 0xad91
jmp 0xb037
movb -0x14(%rbp), %al
addb $0x1, %al
movb %al, -0x14(%rbp)
jmp 0xad7d
movsd -0x38(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0xa, %edi
callq 0xc7b0
movaps %xmm0, %xmm1
movsd -0x50(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0x38(%rbp)
movsd -0x20(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xb157
movb $0x0, -0x14(%rbp)
movsbl -0x14(%rbp), %eax
movsbl -0x11(%rbp), %ecx
cmpl %ecx, %eax
jge 0xb155
movb $0x0, -0x15(%rbp)
movsbl -0x15(%rbp), %eax
movsbl -0x12(%rbp), %ecx
cmpl %ecx, %eax
jge 0xb146
movb $0x0, -0x16(%rbp)
movsbl -0x16(%rbp), %eax
movsbl -0x13(%rbp), %ecx
cmpl %ecx, %eax
jge 0xb137
movsd 0x44970(%rip), %xmm0    # 0x4fa30
mulsd -0x30(%rbp), %xmm0
divsd -0x38(%rbp), %xmm0
movq -0x8(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0x58(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0xa, %edi
callq 0xc7b0
movaps %xmm0, %xmm1
movsd -0x58(%rbp), %xmm0
divsd %xmm1, %xmm0
movq -0x8(%rbp), %rax
movsbq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x15(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x16(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movb -0x16(%rbp), %al
addb $0x1, %al
movb %al, -0x16(%rbp)
jmp 0xb0ac
jmp 0xb139
movb -0x15(%rbp), %al
addb $0x1, %al
movb %al, -0x15(%rbp)
jmp 0xb098
jmp 0xb148
movb -0x14(%rbp), %al
addb $0x1, %al
movb %al, -0x14(%rbp)
jmp 0xb084
jmp 0xb157
movsd 0x448d1(%rip), %xmm0    # 0x4fa30
mulsd -0x30(%rbp), %xmm0
divsd -0x38(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0xa, %edi
callq 0xc7b0
movaps %xmm0, %xmm1
movsd -0x60(%rbp), %xmm0
divsd %xmm1, %xmm0
addq $0x60, %rsp
popq %rbp
retq
nop