// File: /workspace/github_cpp_makefile_star2_O2/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 %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rsi, %r14
movq %rdi, %rbx
xorl %r15d, %r15d
testb %dl, %dl
cmovlel %r15d, %edx
movslq %edx, %r13
movsd 0x25b55(%rip), %xmm1    # 0x2c8f0
movapd 0x25b8d(%rip), %xmm3    # 0x2c930
movsd 0x25b4d(%rip), %xmm6    # 0x2c8f8
xorpd %xmm4, %xmm4
xorpd %xmm2, %xmm2
cmpq %r15, %r13
je 0x6ea9
movsd (%rbx,%r15,8), %xmm0
andpd %xmm3, %xmm0
ucomisd %xmm0, %xmm6
jbe 0x6dd5
movapd %xmm2, %xmm0
jmp 0x6e9d
movapd %xmm0, %xmm3
maxsd %xmm4, %xmm3
movsd %xmm3, 0x8(%rsp)
movsd %xmm1, 0x10(%rsp)
movsd %xmm2, 0x18(%rsp)
callq 0x4100
callq 0x4090
movsd 0x25af7(%rip), %xmm6    # 0x2c8f8
maxsd 0x18(%rsp), %xmm0
movsd (%rbx,%r15,8), %xmm1
xorpd %xmm2, %xmm2
cmpltsd %xmm1, %xmm2
movapd %xmm1, %xmm3
cmpltsd 0x25add(%rip), %xmm3    # 0x2c900
movsd 0x25ac5(%rip), %xmm5    # 0x2c8f0
andpd %xmm5, %xmm3
movsd (%r14,%r15,8), %xmm1
movapd %xmm5, %xmm4
subsd %xmm1, %xmm4
andpd %xmm5, %xmm2
mulsd %xmm1, %xmm2
mulsd %xmm4, %xmm3
addsd %xmm2, %xmm3
movapd 0x25adb(%rip), %xmm2    # 0x2c930
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 0x10(%rsp), %xmm2
addsd %xmm3, %xmm1
ucomisd %xmm1, %xmm2
ja 0x6e8f
movapd %xmm2, %xmm1
movapd 0x25a99(%rip), %xmm3    # 0x2c930
movsd 0x8(%rsp), %xmm4
incq %r15
movapd %xmm0, %xmm2
jmp 0x6db3
movsd %xmm1, 0x10(%rsp)
movsd 0x25a59(%rip), %xmm0    # 0x2c910
movapd %xmm2, %xmm1
movsd %xmm2, 0x18(%rsp)
movsd %xmm4, 0x8(%rsp)
callq 0x4440
movsd 0x8(%rsp), %xmm3
divsd %xmm0, %xmm3
xorpd %xmm4, %xmm4
ucomisd %xmm4, %xmm3
jne 0x6ee2
jnp 0x6f52
movsd 0x25a2e(%rip), %xmm0    # 0x2c918
mulsd 0x10(%rsp), %xmm0
movsd %xmm3, 0x8(%rsp)
divsd %xmm3, %xmm0
movsd %xmm0, 0x20(%rsp)
movsd 0x25a08(%rip), %xmm0    # 0x2c910
movsd 0x18(%rsp), %xmm1
callq 0x4440
movsd 0x20(%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x20(%rsp)
movq %xmm1, %rax
btrq $0x3f, %rax
movabsq $0x7ff0000000000000, %rcx # imm = 0x7FF0000000000000
cmpq %rcx, %rax
je 0x7041
movsd 0x10(%rsp), %xmm2
movsd 0x8(%rsp), %xmm3
xorpd %xmm4, %xmm4
jmp 0x6f66
movsd 0x25996(%rip), %xmm0    # 0x2c8f0
movsd %xmm0, 0x20(%rsp)
movsd 0x10(%rsp), %xmm2
movsd 0x18(%rsp), %xmm1
ucomisd %xmm4, %xmm1
jbe 0x702c
mulsd 0x2599a(%rip), %xmm2    # 0x2c918
divsd %xmm3, %xmm2
xorl %ebp, %ebp
leaq 0x25af8(%rip), %r14     # 0x2ca83
pushq $0x18
popq %r15
pushq $0x1
popq %r12
movsd %xmm2, 0x10(%rsp)
cmpq %rbp, %r13
je 0x702c
movsd (%rbx,%rbp,8), %xmm0
mulsd %xmm2, %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x25957(%rip), %xmm0    # 0x2c910
callq 0x4440
movsd 0x8(%rsp), %xmm1
divsd %xmm0, %xmm1
ucomisd %xmm1, %xmm1
jp 0x7012
movsd (%rbx,%rbp,8), %xmm0
mulsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x25929(%rip), %xmm0    # 0x2c910
movsd 0x18(%rsp), %xmm1
callq 0x4440
movsd 0x8(%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, (%rbx,%rbp,8)
incq %rbp
movsd 0x10(%rsp), %xmm2
movsd 0x18(%rsp), %xmm1
jmp 0x6f99
movq 0x31fbf(%rip), %rax     # 0x38fd8
movq (%rax), %rcx
movq %r14, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x44b0
jmp 0x6fce
movsd 0x20(%rsp), %xmm0
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x31f90(%rip), %rax     # 0x38fd8
movq (%rax), %rcx
leaq 0x25a8f(%rip), %rdi     # 0x2cae1
pushq $0x1b
popq %rsi
pushq $0x1
popq %rdx
callq 0x44b0
jmp 0x6f40