// File: /workspace/github_cpp_makefile_star2_O3/myudelson[P]hmm-scalable/utils.cpp
// Function: doLog10Scale1DGentle(double*, double*, signed char)
NUMBER doLog10Scale1DGentle(NUMBER *grad, NUMBER *par, NPAR size) {
	NPAR i;
	NUMBER max_10_scale = 0, candidate, min_delta = 1, max_grad = 0, scale;
	for(i=0; i<size; i++) {
		if( fabs(grad[i]) < SAFETY ) // 0 gradient
			continue;
        // scale
        if(max_grad < fabs(grad[i]))
            max_grad = fabs(grad[i]);
		candidate = ceil( log10( fabs(grad[i]) ) );
		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]<0)*(1-par[i]) + (grad[i]>0)*(par[i]) +
        ( (fabs(par[i])< SAFETY) || (fabs(1-par[i])< 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);
    
    scale = (max_grad!=0) ? ( 0.95 * min_delta / max_grad ) / pow(10, max_10_scale) : 1;
    if(scale==std::numeric_limits<double>::infinity() || scale==(-1*std::numeric_limits<double>::infinity()) ) {
        fprintf(stderr,"WARNING! scale is Infinite\n");
    }
    
    NUMBER v;
    if(max_10_scale > 0) {
        for(i=0; i<size; i++) {
            
            v = ( 0.95 * min_delta / max_grad) * grad[i] / pow(10, max_10_scale);
            if(v!=v) {
                fprintf(stderr,"WARNING! NaN to be set!\n");
            }
            
            grad[i] = ( 0.95 * min_delta / max_grad) * grad[i] / pow(10, max_10_scale);
        }
    }
    return scale; //( 0.95 * min_delta / max_grad ) / pow(10, max_10_scale);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x20, %rsp
movl %edx, %ebp
movq %rdi, %rbx
movzbl %bpl, %r15d
testb %bpl, %bpl
jle 0x955b
movq %rsi, %r14
movsd 0x2a4af(%rip), %xmm2    # 0x338f0
xorl %r12d, %r12d
movapd 0x2a4e4(%rip), %xmm3    # 0x33930
movsd 0x2a4a4(%rip), %xmm6    # 0x338f8
xorpd %xmm1, %xmm1
xorpd %xmm4, %xmm4
movsd (%rbx,%r12,8), %xmm0
andpd %xmm3, %xmm0
ucomisd %xmm0, %xmm6
ja 0x953a
movapd %xmm0, %xmm3
maxsd %xmm4, %xmm3
movsd %xmm3, (%rsp)
movsd %xmm2, 0x8(%rsp)
movsd %xmm1, 0x10(%rsp)
callq 0x4110
callq 0x4090
movsd 0x2a45d(%rip), %xmm6    # 0x338f8
maxsd 0x10(%rsp), %xmm0
movsd (%rbx,%r12,8), %xmm1
xorpd %xmm2, %xmm2
cmpltsd %xmm1, %xmm2
movapd %xmm1, %xmm3
cmpltsd 0x2a443(%rip), %xmm3    # 0x33900
movsd 0x2a42b(%rip), %xmm5    # 0x338f0
andpd %xmm5, %xmm3
movsd (%r14,%r12,8), %xmm1
movapd %xmm5, %xmm4
subsd %xmm1, %xmm4
andpd %xmm5, %xmm2
mulsd %xmm1, %xmm2
mulsd %xmm4, %xmm3
addsd %xmm2, %xmm3
movapd 0x2a441(%rip), %xmm2    # 0x33930
andpd %xmm2, %xmm1
andpd %xmm2, %xmm4
cmpltsd %xmm6, %xmm4
andpd %xmm5, %xmm4
cmpltsd %xmm6, %xmm1
movapd %xmm1, %xmm2
andnpd %xmm4, %xmm2
andpd %xmm5, %xmm1
orpd %xmm2, %xmm1
movsd 0x8(%rsp), %xmm2
addsd %xmm3, %xmm1
ucomisd %xmm1, %xmm2
jbe 0x9529
movapd %xmm1, %xmm2
movsd (%rsp), %xmm4
movapd %xmm0, %xmm1
movapd 0x2a3f6(%rip), %xmm3    # 0x33930
incq %r12
cmpq %r12, %r15
jne 0x945c
mulsd 0x2a3ca(%rip), %xmm2    # 0x33918
movsd %xmm2, 0x8(%rsp)
movsd %xmm4, (%rsp)
jmp 0x9576
movsd 0x2a3b5(%rip), %xmm0    # 0x33918
movsd %xmm0, 0x8(%rsp)
xorpd %xmm0, %xmm0
movsd %xmm0, (%rsp)
xorpd %xmm1, %xmm1
movsd 0x2a392(%rip), %xmm0    # 0x33910
movsd %xmm1, 0x10(%rsp)
callq 0x4420
movsd (%rsp), %xmm1
divsd %xmm0, %xmm1
ucomisd 0x2a366(%rip), %xmm1    # 0x33900
movsd 0x8(%rsp), %xmm2
divsd %xmm1, %xmm2
movsd %xmm2, 0x8(%rsp)
jne 0x95ae
jnp 0x95fb
movsd 0x2a35a(%rip), %xmm0    # 0x33910
movsd 0x10(%rsp), %xmm1
callq 0x4420
movsd 0x8(%rsp), %xmm2
movapd %xmm2, %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x18(%rsp)
movq %xmm1, %rax
btrq $0x3f, %rax
movabsq $0x7ff0000000000000, %rcx # imm = 0x7FF0000000000000
cmpq %rcx, %rax
jne 0x9609
callq 0x47cb
movsd 0x8(%rsp), %xmm2
jmp 0x9609
movsd 0x2a2ed(%rip), %xmm0    # 0x338f0
movsd %xmm0, 0x18(%rsp)
testb %bpl, %bpl
setle %al
xorpd %xmm0, %xmm0
movsd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
setbe %cl
orb %al, %cl
jne 0x96ae
xorl %r14d, %r14d
movsd 0x2a2dd(%rip), %xmm0    # 0x33910
movsd (%rbx,%r14,8), %xmm3
mulsd %xmm2, %xmm3
movsd %xmm3, (%rsp)
callq 0x4420
movsd (%rsp), %xmm1
divsd %xmm0, %xmm1
ucomisd %xmm1, %xmm1
jp 0x96a7
movsd (%rbx,%r14,8), %xmm0
mulsd 0x8(%rsp), %xmm0
movsd %xmm0, (%rsp)
movsd 0x2a2a1(%rip), %xmm0    # 0x33910
movsd 0x10(%rsp), %xmm1
callq 0x4420
movsd (%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, (%rbx,%r14,8)
incq %r14
cmpq %r14, %r15
movsd 0x8(%rsp), %xmm2
movsd 0x10(%rsp), %xmm1
movsd 0x2a26d(%rip), %xmm0    # 0x33910
jne 0x9633
jmp 0x96ae
callq 0x47e7
jmp 0x9656
movsd 0x18(%rsp), %xmm0
addq $0x20, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq