// File: philipperemy[P]digital-setting-circles/Calc.cpp
// Function: Calc::optimizeZ3()
bool Calc::optimizeZ3()
{

  double maxGuess;
  double upperGuess, lowerGuess;
  double upperError, lowerError;

  // Our residual error threshold
  const double maxErr = 0.01*radPerDeg;

  int ntries;

  // Calculate the true angular separation of the two stars,
  // based on their RA/Dec.  This need be calculated only once.
  const double trueSep = calcSeparation(alignRA[1], alignDec[1], alignRA[2], alignDec[2]);

  if (!MathLib::finite(trueSep)) {
    printDebugMsg("Can't calculate star separation!");
    return false;
  }

  if (trueSep < 5.0*radPerDeg) {
    printDebugMsg("Stars too close together!");
    return false;
  }

  maxGuess = 10.0*radPerDeg;
  if (maxGuess > trueSep/2)
    maxGuess = trueSep/2;


  Z3 = upperGuess = maxGuess;
  upperError = calcApparentSeparation() - trueSep;
  if (MathLib::fabs(upperError) <= maxErr) {
    printDebugMsg("Lucky pos. first guess");
    return true;  // Lucky guess!
  }

  Z3 = lowerGuess = -maxGuess;
  lowerError = calcApparentSeparation() - trueSep;
  if (MathLib::fabs(lowerError) <= maxErr) {
    printDebugMsg("Lucky neg. first guess");
    return true;  // Lucky guess!
  }

  // For the interpolation to succeed, the upper and
  // lower errors must be of opposite sign.
  if (upperError * lowerError > 0.0) {
    printDebugMsg("Correct Z3 out of range");
    return false;
  }

  ntries = 0;
  for (;;) {
    double newGuess, newError;
    ntries++;

    // Interpolate between the upper and lower guesses to
    // get a new guess.

    Z3 = newGuess = lowerGuess +
	((lowerError/(lowerError-upperError))*(upperGuess-lowerGuess));

    newError = calcApparentSeparation() - trueSep;

    if (MathLib::fabs(newError) <= maxErr) {
        std::cout << "Converged after " << ntries << " tries: Z3= " << Z3*degPerRad << std::endl;
      return true;  // We have converged!  Z3 is set.
    }

    if (ntries > 25) {
      printDebugMsg("No convergence after 25 tries");
      return false;  // Failure to converge
    }

    // NewGuess replaces either lowerGuess or upperGuess, depending
    // on the sign of the newError.

    if (lowerError * newError > 0) {
      // newError has the same sign as lowerError
      lowerGuess = newGuess;
      lowerError = newError;
    } else {
      upperGuess = newGuess;
      upperError = newError;
    }
  }

  // We should never get here!
  printDebugMsg("Broke out of loop!?!");

  return false;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1a0, %rsp            # imm = 0x1A0
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x168(%rbp)
movsd 0x33c4e(%rip), %xmm0    # 0x38030
movsd %xmm0, -0x40(%rbp)
movsd 0x2d0(%rdi), %xmm0
movsd 0x2e8(%rdi), %xmm1
movsd 0x2d8(%rdi), %xmm2
movsd 0x2f0(%rdi), %xmm3
callq 0x42d0
movsd %xmm0, -0x50(%rbp)
movsd -0x50(%rbp), %xmm0
callq 0x79e0
cmpl $0x0, %eax
jne 0x44b1
leaq -0x71(%rbp), %rdi
movq %rdi, -0x170(%rbp)
callq 0x3550
movq -0x170(%rbp), %rdx
leaq 0x33c36(%rip), %rsi     # 0x38078
leaq -0x70(%rbp), %rdi
callq 0x5b40
jmp 0x444d
movq -0x168(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x3a30
jmp 0x445f
leaq -0x70(%rbp), %rdi
callq 0x31c0
leaq -0x71(%rbp), %rdi
callq 0x3370
movb $0x0, -0x1(%rbp)
jmp 0x4a26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x44a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x31c0
leaq -0x71(%rbp), %rdi
callq 0x3370
jmp 0x4a34
movsd 0x33b7f(%rip), %xmm0    # 0x38038
ucomisd -0x50(%rbp), %xmm0
jbe 0x4566
leaq -0xa9(%rbp), %rdi
movq %rdi, -0x178(%rbp)
callq 0x3550
movq -0x178(%rbp), %rdx
leaq 0x33bb4(%rip), %rsi     # 0x38099
leaq -0xa8(%rbp), %rdi
callq 0x5b40
jmp 0x44f3
movq -0x168(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x3a30
jmp 0x4508
leaq -0xa8(%rbp), %rdi
callq 0x31c0
leaq -0xa9(%rbp), %rdi
callq 0x3370
movb $0x0, -0x1(%rbp)
jmp 0x4a26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x4555
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x31c0
leaq -0xa9(%rbp), %rdi
callq 0x3370
jmp 0x4a34
movsd 0x33ada(%rip), %xmm0    # 0x38048
movsd %xmm0, -0x18(%rbp)
movsd -0x18(%rbp), %xmm0
movsd -0x50(%rbp), %xmm1
movsd 0x33abb(%rip), %xmm2    # 0x38040
divsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x45a5
movsd -0x50(%rbp), %xmm0
movsd 0x33aa4(%rip), %xmm1    # 0x38040
divsd %xmm1, %xmm0
movsd %xmm0, -0x18(%rbp)
movq -0x168(%rbp), %rdi
movsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
movsd %xmm0, 0x308(%rdi)
callq 0x4210
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
movsd -0x30(%rbp), %xmm0
callq 0x7940
movaps %xmm0, %xmm1
movsd 0x33a4e(%rip), %xmm0    # 0x38030
ucomisd %xmm1, %xmm0
jb 0x468e
leaq -0xd1(%rbp), %rdi
movq %rdi, -0x180(%rbp)
callq 0x3550
movq -0x180(%rbp), %rdx
leaq 0x33aa6(%rip), %rsi     # 0x380b3
leaq -0xd0(%rbp), %rdi
callq 0x5b40
jmp 0x461b
movq -0x168(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x3a30
jmp 0x4630
leaq -0xd0(%rbp), %rdi
callq 0x31c0
leaq -0xd1(%rbp), %rdi
callq 0x3370
movb $0x1, -0x1(%rbp)
jmp 0x4a26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x467d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0x31c0
leaq -0xd1(%rbp), %rdi
callq 0x3370
jmp 0x4a34
movq -0x168(%rbp), %rdi
movsd -0x18(%rbp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movsd %xmm0, -0x28(%rbp)
movsd %xmm0, 0x308(%rdi)
callq 0x4210
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
movsd -0x38(%rbp), %xmm0
callq 0x7940
movaps %xmm0, %xmm1
movsd 0x3394e(%rip), %xmm0    # 0x38030
ucomisd %xmm1, %xmm0
jb 0x478e
leaq -0xf9(%rbp), %rdi
movq %rdi, -0x188(%rbp)
callq 0x3550
movq -0x188(%rbp), %rdx
leaq 0x339bd(%rip), %rsi     # 0x380ca
leaq -0xf8(%rbp), %rdi
callq 0x5b40
jmp 0x471b
movq -0x168(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x3a30
jmp 0x4730
leaq -0xf8(%rbp), %rdi
callq 0x31c0
leaq -0xf9(%rbp), %rdi
callq 0x3370
movb $0x1, -0x1(%rbp)
jmp 0x4a26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x477d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x31c0
leaq -0xf9(%rbp), %rdi
callq 0x3370
jmp 0x4a34
movsd -0x30(%rbp), %xmm0
mulsd -0x38(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x4847
leaq -0x121(%rbp), %rdi
movq %rdi, -0x190(%rbp)
callq 0x3550
movq -0x190(%rbp), %rdx
leaq 0x3391b(%rip), %rsi     # 0x380e1
leaq -0x120(%rbp), %rdi
callq 0x5b40
jmp 0x47d4
movq -0x168(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x3a30
jmp 0x47e9
leaq -0x120(%rbp), %rdi
callq 0x31c0
leaq -0x121(%rbp), %rdi
callq 0x3370
movb $0x0, -0x1(%rbp)
jmp 0x4a26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x4836
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x31c0
leaq -0x121(%rbp), %rdi
callq 0x3370
jmp 0x4a34
movl $0x0, -0x44(%rbp)
movq -0x168(%rbp), %rdi
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
movsd -0x28(%rbp), %xmm1
movsd -0x38(%rbp), %xmm0
movsd -0x38(%rbp), %xmm2
subsd -0x30(%rbp), %xmm2
divsd %xmm2, %xmm0
movsd -0x20(%rbp), %xmm2
subsd -0x28(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x130(%rbp)
movsd %xmm0, 0x308(%rdi)
callq 0x4210
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x138(%rbp)
movsd -0x138(%rbp), %xmm0
callq 0x7940
movaps %xmm0, %xmm1
movsd 0x3376e(%rip), %xmm0    # 0x38030
ucomisd %xmm1, %xmm0
jb 0x492c
movq 0x436f9(%rip), %rdi     # 0x47fc8
leaq 0x33823(%rip), %rsi     # 0x380f9
callq 0x3320
movq %rax, %rdi
movl -0x44(%rbp), %esi
callq 0x3500
movq %rax, %rdi
leaq 0x3381a(%rip), %rsi     # 0x3810a
callq 0x3320
movq %rax, %rdi
movq -0x168(%rbp), %rax
movsd 0x33749(%rip), %xmm0    # 0x38050
mulsd 0x308(%rax), %xmm0
callq 0x35f0
movq %rax, %rdi
movq 0x4368a(%rip), %rsi     # 0x47fa8
callq 0x3350
movb $0x1, -0x1(%rbp)
jmp 0x4a26
cmpl $0x19, -0x44(%rbp)
jle 0x49d5
leaq -0x159(%rbp), %rdi
movq %rdi, -0x198(%rbp)
callq 0x3550
movq -0x198(%rbp), %rdx
leaq 0x337c0(%rip), %rsi     # 0x38117
leaq -0x158(%rbp), %rdi
callq 0x5b40
jmp 0x4965
movq -0x168(%rbp), %rdi
leaq -0x158(%rbp), %rsi
callq 0x3a30
jmp 0x497a
leaq -0x158(%rbp), %rdi
callq 0x31c0
leaq -0x159(%rbp), %rdi
callq 0x3370
movb $0x0, -0x1(%rbp)
jmp 0x4a26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x49c7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x31c0
leaq -0x159(%rbp), %rdi
callq 0x3370
jmp 0x4a34
movsd -0x38(%rbp), %xmm0
mulsd -0x138(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x4a07
movsd -0x130(%rbp), %xmm0
movsd %xmm0, -0x28(%rbp)
movsd -0x138(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
jmp 0x4a21
movsd -0x130(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
movsd -0x138(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
jmp 0x484e
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
movq -0x80(%rbp), %rdi
callq 0x3540
nopl (%rax)