// File: redpony[P]libpopt/optimize_test.cc
// Function: TestPersistentOptimizer(Optimizer*)
double TestPersistentOptimizer(Optimizer* opt) {
  cerr << "\nTESTING PERSISTENT OPTIMIZER\n";
  // f(x,y) = 4x1^2 + x1*x2 + x2^2 + x3^2 + 6x3 + 5
  // df/dx1 = 8*x1 + x2
  // df/dx2 = 2*x2 + x1
  // df/dx3 = 2*x3 + 6
  vector<double> x(3);
  vector<double> g(3);
  x[0] = 8;
  x[1] = 8;
  x[2] = 8;
  double obj = 0;
  string state;
  bool converged = false;
  while (!converged) {
    g[0] = 8 * x[0] + x[1];
    g[1] = 2 * x[1] + x[0];
    g[2] = 2 * x[2] + 6;
    obj = 4 * x[0]*x[0] + x[0] * x[1] + x[1]*x[1] + x[2]*x[2] + 6 * x[2] + 5;

    {
      if (state.size() > 0) {
        istringstream is(state, ios::binary);
        opt->Load(&is);
      }
      opt->Optimize(obj, g, &x);
      ostringstream os(ios::binary); opt->Save(&os); state = os.str();

    }

    cerr << x[0] << " " << x[1] << " " << x[2] << endl;
    cerr << "   obj=" << obj << "\td/dx1=" << g[0] << " d/dx2=" << g[1] << " d/dx3=" << g[2] << endl;
    converged = opt->HasConverged();
    if (!converged) {
      // now screw up the state (should be undone by Load)
      obj += 2.0;
      g[1] = -g[2];
      vector<double> x2 = x;
      try {
        opt->Optimize(obj, g, &x2);
      } catch (...) { }
    }
  }
  return obj;
}

// Assembly:
subq $0x4c8, %rsp            # imm = 0x4C8
movq %rdi, 0x4c0(%rsp)
movq 0xe31a(%rip), %rdi      # 0x11ff0
leaq 0xa3e5(%rip), %rsi      # 0xe0c2
callq 0x3210
leaq 0x4a7(%rsp), %rdi
movq %rdi, 0x108(%rsp)
callq 0x4610
movq 0x108(%rsp), %rdx
leaq 0x4a8(%rsp), %rdi
movl $0x3, %esi
callq 0x4620
jmp 0x3d13
leaq 0x4a7(%rsp), %rdi
callq 0x46a0
leaq 0x477(%rsp), %rdi
movq %rdi, 0x100(%rsp)
callq 0x4610
movq 0x100(%rsp), %rdx
leaq 0x478(%rsp), %rdi
movl $0x3, %esi
callq 0x4620
jmp 0x3d51
leaq 0x477(%rsp), %rdi
callq 0x46a0
leaq 0x4a8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x46b0
movsd 0xa291(%rip), %xmm0     # 0xe008
movsd %xmm0, (%rax)
leaq 0x4a8(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movsd 0xa273(%rip), %xmm0     # 0xe008
movsd %xmm0, (%rax)
leaq 0x4a8(%rsp), %rdi
movl $0x2, %esi
callq 0x46b0
movsd 0xa255(%rip), %xmm0     # 0xe008
movsd %xmm0, (%rax)
xorps %xmm0, %xmm0
movsd %xmm0, 0x468(%rsp)
leaq 0x448(%rsp), %rdi
callq 0x3300
movb $0x0, 0x447(%rsp)
movb 0x447(%rsp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x3dea
jmp 0x4556
leaq 0x4a8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x46b0
movsd (%rax), %xmm0
movsd %xmm0, 0x98(%rsp)
leaq 0x4a8(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movsd 0x98(%rsp), %xmm0
movsd (%rax), %xmm1
movsd 0xa1d9(%rip), %xmm2     # 0xe008
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xa0(%rsp)
leaq 0x478(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x46b0
movsd 0xa0(%rsp), %xmm0
movsd %xmm0, (%rax)
leaq 0x4a8(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movsd (%rax), %xmm0
movsd %xmm0, 0xa8(%rsp)
leaq 0x4a8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x46b0
movsd 0xa8(%rsp), %xmm0
movsd (%rax), %xmm1
addsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xb0(%rsp)
leaq 0x478(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movsd 0xb0(%rsp), %xmm0
movsd %xmm0, (%rax)
leaq 0x4a8(%rsp), %rdi
movl $0x2, %esi
callq 0x46b0
movsd (%rax), %xmm0
addsd %xmm0, %xmm0
movsd 0xa123(%rip), %xmm1     # 0xe010
addsd %xmm1, %xmm0
movsd %xmm0, 0xb8(%rsp)
leaq 0x478(%rsp), %rdi
movl $0x2, %esi
callq 0x46b0
movsd 0xb8(%rsp), %xmm0
movsd %xmm0, (%rax)
leaq 0x4a8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x46b0
movsd 0xa0e6(%rip), %xmm0     # 0xe018
mulsd (%rax), %xmm0
movsd %xmm0, 0xc8(%rsp)
leaq 0x4a8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x46b0
movsd (%rax), %xmm0
movsd %xmm0, 0xd0(%rsp)
leaq 0x4a8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x46b0
movsd (%rax), %xmm0
movsd %xmm0, 0xc0(%rsp)
leaq 0x4a8(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movsd 0xc0(%rsp), %xmm1
movsd 0xc8(%rsp), %xmm0
movsd 0xd0(%rsp), %xmm2
mulsd (%rax), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xe0(%rsp)
leaq 0x4a8(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movsd (%rax), %xmm0
movsd %xmm0, 0xd8(%rsp)
leaq 0x4a8(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movsd 0xd8(%rsp), %xmm0
movsd 0xe0(%rsp), %xmm1
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xf0(%rsp)
leaq 0x4a8(%rsp), %rdi
movl $0x2, %esi
callq 0x46b0
movsd (%rax), %xmm0
movsd %xmm0, 0xe8(%rsp)
leaq 0x4a8(%rsp), %rdi
movl $0x2, %esi
callq 0x46b0
movsd 0xe8(%rsp), %xmm0
movsd 0xf0(%rsp), %xmm1
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xf8(%rsp)
leaq 0x4a8(%rsp), %rdi
movl $0x2, %esi
callq 0x46b0
movsd 0xf8(%rsp), %xmm1
movsd (%rax), %xmm0
movsd 0x9f7c(%rip), %xmm2     # 0xe010
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd 0x9f7c(%rip), %xmm1     # 0xe020
addsd %xmm1, %xmm0
movsd %xmm0, 0x468(%rsp)
leaq 0x448(%rsp), %rdi
callq 0x3170
cmpq $0x0, %rax
jbe 0x4198
leaq 0x2c0(%rsp), %rdi
leaq 0x448(%rsp), %rsi
movl $0x4, %edx
callq 0x3370
jmp 0x40e4
movq 0x4c0(%rsp), %rdi
leaq 0x2c0(%rsp), %rsi
callq 0x71b0
jmp 0x40fb
leaq 0x2c0(%rsp), %rdi
callq 0x30f0
jmp 0x4198
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x498(%rsp)
movl %eax, 0x494(%rsp)
leaq 0x4a7(%rsp), %rdi
callq 0x46a0
jmp 0x45bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x498(%rsp)
movl %eax, 0x494(%rsp)
leaq 0x477(%rsp), %rdi
callq 0x46a0
jmp 0x45b2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x498(%rsp)
movl %eax, 0x494(%rsp)
jmp 0x4598
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x498(%rsp)
movl %eax, 0x494(%rsp)
leaq 0x2c0(%rsp), %rdi
callq 0x30f0
jmp 0x4598
movq 0x4c0(%rsp), %rdi
leaq 0x468(%rsp), %rsi
leaq 0x478(%rsp), %rdx
leaq 0x4a8(%rsp), %rcx
callq 0x46d0
jmp 0x41bf
leaq 0x148(%rsp), %rdi
movl $0x4, %esi
callq 0x31e0
jmp 0x41d3
movq 0x4c0(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0x7130
jmp 0x41ea
leaq 0x128(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0x3240
jmp 0x4201
leaq 0x448(%rsp), %rdi
leaq 0x128(%rsp), %rsi
movq %rsi, 0x88(%rsp)
callq 0x32b0
movq 0x88(%rsp), %rdi
callq 0x3140
leaq 0x148(%rsp), %rdi
callq 0x3070
xorl %eax, %eax
movl %eax, %esi
leaq 0x4a8(%rsp), %rdi
callq 0x46b0
movsd (%rax), %xmm0
movq 0xdd9c(%rip), %rdi      # 0x11ff0
callq 0x3400
movq %rax, 0x90(%rsp)
jmp 0x4263
movq 0x90(%rsp), %rdi
leaq 0xa030(%rip), %rsi      # 0xe2a2
callq 0x3210
movq %rax, 0x80(%rsp)
jmp 0x4281
leaq 0x4a8(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movq 0x80(%rsp), %rdi
movsd (%rax), %xmm0
callq 0x3400
movq %rax, 0x78(%rsp)
jmp 0x42ab
movq 0x78(%rsp), %rdi
leaq 0x9feb(%rip), %rsi      # 0xe2a2
callq 0x3210
movq %rax, 0x70(%rsp)
jmp 0x42c3
leaq 0x4a8(%rsp), %rdi
movl $0x2, %esi
callq 0x46b0
movq 0x70(%rsp), %rdi
movsd (%rax), %xmm0
callq 0x3400
movq %rax, 0x68(%rsp)
jmp 0x42ea
movq 0x68(%rsp), %rdi
movq 0xdcca(%rip), %rsi      # 0x11fc0
callq 0x3250
jmp 0x42fd
movq 0xdcec(%rip), %rdi      # 0x11ff0
leaq 0x9d97(%rip), %rsi      # 0xe0a2
callq 0x3210
movq %rax, 0x60(%rsp)
jmp 0x4317
movq 0x60(%rsp), %rdi
movsd 0x468(%rsp), %xmm0
callq 0x3400
movq %rax, 0x58(%rsp)
jmp 0x4331
movq 0x58(%rsp), %rdi
leaq 0x9d6d(%rip), %rsi      # 0xe0aa
callq 0x3210
movq %rax, 0x50(%rsp)
jmp 0x4349
xorl %eax, %eax
movl %eax, %esi
leaq 0x478(%rsp), %rdi
callq 0x46b0
movq 0x50(%rsp), %rdi
movsd (%rax), %xmm0
callq 0x3400
movq %rax, 0x48(%rsp)
jmp 0x436f
movq 0x48(%rsp), %rdi
leaq 0x9d37(%rip), %rsi      # 0xe0b2
callq 0x3210
movq %rax, 0x40(%rsp)
jmp 0x4387
leaq 0x478(%rsp), %rdi
movl $0x1, %esi
callq 0x46b0
movq 0x40(%rsp), %rdi
movsd (%rax), %xmm0
callq 0x3400
movq %rax, 0x38(%rsp)
jmp 0x43ae
movq 0x38(%rsp), %rdi
leaq 0x9d00(%rip), %rsi      # 0xe0ba
callq 0x3210
movq %rax, 0x30(%rsp)
jmp 0x43c6
leaq 0x478(%rsp), %rdi
movl $0x2, %esi
callq 0x46b0
movq 0x30(%rsp), %rdi
movsd (%rax), %xmm0
callq 0x3400
movq %rax, 0x28(%rsp)
jmp 0x43ed
movq 0x28(%rsp), %rdi
movq 0xdbc7(%rip), %rsi      # 0x11fc0
callq 0x3250
jmp 0x4400
movq 0x4c0(%rsp), %rdi
callq 0x47c0
movb %al, 0x27(%rsp)
jmp 0x4413
movb 0x27(%rsp), %al
andb $0x1, %al
movb %al, 0x447(%rsp)
testb $0x1, 0x447(%rsp)
jne 0x4551
movsd 0x468(%rsp), %xmm0
movsd 0x9bf1(%rip), %xmm1     # 0xe030
addsd %xmm1, %xmm0
movsd %xmm0, 0x468(%rsp)
leaq 0x478(%rsp), %rdi
movq %rdi, 0x8(%rsp)
movl $0x2, %esi
callq 0x46b0
movq 0x8(%rsp), %rdi
movsd (%rax), %xmm0
movaps 0x9bfd(%rip), %xmm1     # 0xe070
pxor %xmm1, %xmm0
movaps %xmm0, 0x10(%rsp)
movl $0x1, %esi
callq 0x46b0
movaps 0x10(%rsp), %xmm0
movlpd %xmm0, (%rax)
leaq 0x110(%rsp), %rdi
leaq 0x4a8(%rsp), %rsi
callq 0x4830
jmp 0x44a6
movq 0x4c0(%rsp), %rdi
leaq 0x468(%rsp), %rsi
leaq 0x478(%rsp), %rdx
leaq 0x110(%rsp), %rcx
callq 0x46d0
jmp 0x44cd
jmp 0x451f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x498(%rsp)
movl %eax, 0x494(%rsp)
leaq 0x148(%rsp), %rdi
callq 0x3070
jmp 0x4598
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x498(%rsp)
movl %eax, 0x494(%rsp)
movq 0x498(%rsp), %rdi
callq 0x30c0
callq 0x3360
jmp 0x451d
jmp 0x451f
leaq 0x110(%rsp), %rdi
callq 0x47d0
jmp 0x4551
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x498(%rsp)
movl %eax, 0x494(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x47d0
jmp 0x4598
jmp 0x3dd8
movsd 0x468(%rsp), %xmm0
movsd %xmm0, (%rsp)
leaq 0x448(%rsp), %rdi
callq 0x3140
leaq 0x478(%rsp), %rdi
callq 0x47d0
leaq 0x4a8(%rsp), %rdi
callq 0x47d0
movsd (%rsp), %xmm0
addq $0x4c8, %rsp            # imm = 0x4C8
retq
leaq 0x448(%rsp), %rdi
callq 0x3140
leaq 0x478(%rsp), %rdi
callq 0x47d0
leaq 0x4a8(%rsp), %rdi
callq 0x47d0
movq 0x498(%rsp), %rdi
callq 0x33b0
nopl (%rax)