// File: jamesgrimmett[P]orbital_determination/ex10-1_linear_least_squares.cc
// Function: main
int main() {

  int i;

  // The state vector (alpha and beta)
  std::vector<double> state;
  // The inverse of the information matrix (A^T * A)^-1
  std::vector<std::vector<double> > inv;

  // The observed values of x and y
  std::vector<double> x_obs = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
  std::vector<double> y_obs = {1.0, 1.0, 2.0, 3.0, 3.0, 4.0, 4.0, 6.0};

  // The two components of the general solution (A^T * A, and A^T * B)
  std::vector<std::vector<double> > ata = {{0.0, 0.0},{0.0, 0.0}};
  std::vector<double> atb = {0.0, 0.0};

  // fill ata and atb
  for ( i = 0; i < 8; i++ ) {
    ata[0][0] += 1.0;
    ata[0][1] += x_obs[i];
    ata[1][0] += x_obs[i];
    ata[1][1] += pow(x_obs[i], 2);

    atb[0] += y_obs[i];
    atb[1] += x_obs[i] * y_obs[i];
  }

  inv = inverse(ata);
  state = dot_product(inv, atb);

  std::cout << "ATA matrix  " << ata[0][0] << "  " << ata[0][1] << std::endl;
  std::cout << "            " << ata[1][0] << "  " << ata[1][1] << std::endl;
  std::cout << "ATb matrix  " << atb[0] << "  " << atb[1] << std::endl; 
  
  std::cout << "\nState:" << std::endl;
  std::cout << "alpha " << state[0] << std::endl;
  std::cout << "beta  " << state[1] << std::endl;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3f0, %rsp            # imm = 0x3F0
movl $0x0, -0x4(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x2540
leaq -0x38(%rbp), %rdi
callq 0x2560
movups 0x3d9d(%rip), %xmm0     # 0x5048
movaps %xmm0, -0x70(%rbp)
movups 0x3d82(%rip), %xmm0     # 0x5038
movaps %xmm0, -0x80(%rbp)
movups 0x3d67(%rip), %xmm0     # 0x5028
movaps %xmm0, -0x90(%rbp)
movups 0x3d49(%rip), %xmm0     # 0x5018
movaps %xmm0, -0xa0(%rbp)
leaq -0xa0(%rbp), %rax
movq %rax, -0x60(%rbp)
movq $0x8, -0x58(%rbp)
leaq -0xa1(%rbp), %rdi
movq %rdi, -0x298(%rbp)
callq 0x2580
movq -0x298(%rbp), %rcx
movq -0x60(%rbp), %rsi
movq -0x58(%rbp), %rdx
leaq -0x50(%rbp), %rdi
callq 0x25a0
jmp 0x1316
leaq -0xa1(%rbp), %rdi
callq 0x2620
movups 0x3d5f(%rip), %xmm0     # 0x5088
movaps %xmm0, -0xf0(%rbp)
movups 0x3d41(%rip), %xmm0     # 0x5078
movaps %xmm0, -0x100(%rbp)
movups 0x3d23(%rip), %xmm0     # 0x5068
movaps %xmm0, -0x110(%rbp)
movups 0x3d05(%rip), %xmm0     # 0x5058
movaps %xmm0, -0x120(%rbp)
leaq -0x120(%rbp), %rax
movq %rax, -0xe0(%rbp)
movq $0x8, -0xd8(%rbp)
leaq -0x121(%rbp), %rdi
movq %rdi, -0x2a0(%rbp)
callq 0x2580
movq -0x2a0(%rbp), %rcx
movq -0xe0(%rbp), %rsi
movq -0xd8(%rbp), %rdx
leaq -0xd0(%rbp), %rdi
callq 0x25a0
jmp 0x13a9
leaq -0x121(%rbp), %rdi
callq 0x2620
movb $0x1, -0x1d2(%rbp)
leaq -0x180(%rbp), %rax
movq %rax, -0x2b0(%rbp)
movq %rax, -0x188(%rbp)
movq $0x0, -0x1a8(%rbp)
movq $0x0, -0x1a0(%rbp)
leaq -0x1a8(%rbp), %rax
movq %rax, -0x198(%rbp)
movq $0x2, -0x190(%rbp)
leaq -0x1a9(%rbp), %rdi
movq %rdi, -0x2a8(%rbp)
callq 0x2580
movq -0x2b0(%rbp), %rdi
movq -0x2a8(%rbp), %rcx
movq -0x198(%rbp), %rsi
movq -0x190(%rbp), %rdx
callq 0x25a0
jmp 0x1436
leaq -0x168(%rbp), %rax
movq %rax, -0x2c0(%rbp)
movq %rax, -0x188(%rbp)
movq $0x0, -0x1d0(%rbp)
movq $0x0, -0x1c8(%rbp)
leaq -0x1d0(%rbp), %rax
movq %rax, -0x1c0(%rbp)
movq $0x2, -0x1b8(%rbp)
leaq -0x1d1(%rbp), %rdi
movq %rdi, -0x2b8(%rbp)
callq 0x2580
movq -0x2c0(%rbp), %rdi
movq -0x2b8(%rbp), %rcx
movq -0x1c0(%rbp), %rsi
movq -0x1b8(%rbp), %rdx
callq 0x25a0
jmp 0x14b0
movb $0x0, -0x1d2(%rbp)
leaq -0x180(%rbp), %rax
movq %rax, -0x150(%rbp)
movq $0x2, -0x148(%rbp)
leaq -0x1d3(%rbp), %rdi
movq %rdi, -0x2c8(%rbp)
callq 0x2640
movq -0x2c8(%rbp), %rcx
movq -0x150(%rbp), %rsi
movq -0x148(%rbp), %rdx
leaq -0x140(%rbp), %rdi
callq 0x2660
jmp 0x1506
leaq -0x1d3(%rbp), %rdi
callq 0x26e0
leaq -0x180(%rbp), %rax
movq %rax, -0x2d8(%rbp)
addq $0x30, %rax
movq %rax, -0x2d0(%rbp)
movq -0x2d0(%rbp), %rdi
addq $-0x18, %rdi
movq %rdi, -0x2e0(%rbp)
callq 0x2700
movq -0x2d8(%rbp), %rcx
movq -0x2e0(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x2d0(%rbp)
jne 0x152b
leaq -0x1d1(%rbp), %rdi
callq 0x2620
leaq -0x1a9(%rbp), %rdi
callq 0x2620
movq $0x0, -0x210(%rbp)
movq $0x0, -0x208(%rbp)
leaq -0x210(%rbp), %rax
movq %rax, -0x200(%rbp)
movq $0x2, -0x1f8(%rbp)
leaq -0x211(%rbp), %rdi
movq %rdi, -0x2e8(%rbp)
callq 0x2580
movq -0x2e8(%rbp), %rcx
movq -0x200(%rbp), %rsi
movq -0x1f8(%rbp), %rdx
leaq -0x1f0(%rbp), %rdi
callq 0x25a0
jmp 0x15d9
leaq -0x211(%rbp), %rdi
callq 0x2620
movl $0x0, -0x8(%rbp)
cmpl $0x8, -0x8(%rbp)
jge 0x1925
leaq -0x140(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2760
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2780
movsd 0x39f6(%rip), %xmm0     # 0x5010
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movslq -0x8(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2780
movsd (%rax), %xmm0
movsd %xmm0, -0x318(%rbp)
leaq -0x140(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2760
movq %rax, %rdi
movl $0x1, %esi
callq 0x2780
movsd -0x318(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movslq -0x8(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2780
movsd (%rax), %xmm0
movsd %xmm0, -0x310(%rbp)
leaq -0x140(%rbp), %rdi
movl $0x1, %esi
callq 0x2760
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2780
movsd -0x310(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movslq -0x8(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2780
movsd (%rax), %xmm0
movsd 0x3941(%rip), %xmm1     # 0x5008
callq 0x1110
movsd %xmm0, -0x308(%rbp)
leaq -0x140(%rbp), %rdi
movl $0x1, %esi
callq 0x2760
movq %rax, %rdi
movl $0x1, %esi
callq 0x2780
movsd -0x308(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movslq -0x8(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
callq 0x2780
movsd (%rax), %xmm0
movsd %xmm0, -0x300(%rbp)
leaq -0x1f0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2780
movsd -0x300(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movslq -0x8(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2780
movsd (%rax), %xmm0
movsd %xmm0, -0x2f8(%rbp)
movslq -0x8(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
callq 0x2780
movsd (%rax), %xmm0
movsd %xmm0, -0x2f0(%rbp)
leaq -0x1f0(%rbp), %rdi
movl $0x1, %esi
callq 0x2780
movsd -0x2f8(%rbp), %xmm0
movsd -0x2f0(%rbp), %xmm2
movsd (%rax), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax)
movl -0x8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8(%rbp)
jmp 0x15ec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0xa1(%rbp), %rdi
callq 0x2620
jmp 0x1df5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0x121(%rbp), %rdi
callq 0x2620
jmp 0x1dec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
jmp 0x1899
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
jmp 0x188d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0x1d3(%rbp), %rdi
callq 0x26e0
leaq -0x180(%rbp), %rax
movq %rax, -0x328(%rbp)
addq $0x30, %rax
movq %rax, -0x320(%rbp)
movq -0x320(%rbp), %rdi
addq $-0x18, %rdi
movq %rdi, -0x330(%rbp)
callq 0x2700
movq -0x328(%rbp), %rcx
movq -0x330(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x320(%rbp)
jne 0x185a
jmp 0x188d
leaq -0x1d1(%rbp), %rdi
callq 0x2620
leaq -0x1a9(%rbp), %rdi
callq 0x2620
testb $0x1, -0x1d2(%rbp)
jne 0x18b0
jmp 0x18fd
movq -0x188(%rbp), %rax
leaq -0x180(%rbp), %rcx
cmpq %rax, %rcx
movq %rax, -0x338(%rbp)
je 0x18fb
movq -0x338(%rbp), %rdi
addq $-0x18, %rdi
movq %rdi, -0x340(%rbp)
callq 0x2700
movq -0x340(%rbp), %rax
leaq -0x180(%rbp), %rcx
cmpq %rcx, %rax
movq %rax, -0x338(%rbp)
jne 0x18ca
jmp 0x18fd
jmp 0x1de0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0x211(%rbp), %rdi
callq 0x2620
jmp 0x1dd4
leaq -0x248(%rbp), %rdi
leaq -0x140(%rbp), %rsi
callq 0x27a0
jmp 0x193a
leaq -0x230(%rbp), %rdi
leaq -0x248(%rbp), %rsi
callq 0x1e20
jmp 0x194f
leaq -0x38(%rbp), %rdi
movq %rdi, -0x348(%rbp)
leaq -0x230(%rbp), %rsi
movq %rsi, -0x350(%rbp)
callq 0x2890
movq -0x350(%rbp), %rdi
callq 0x28c0
leaq -0x248(%rbp), %rdi
callq 0x28c0
movq -0x348(%rbp), %rsi
leaq -0x278(%rbp), %rdi
callq 0x27a0
jmp 0x199a
leaq -0x290(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
callq 0x2920
jmp 0x19af
leaq -0x260(%rbp), %rdi
leaq -0x278(%rbp), %rsi
leaq -0x290(%rbp), %rdx
callq 0x20a0
jmp 0x19cb
leaq -0x20(%rbp), %rdi
leaq -0x260(%rbp), %rsi
movq %rsi, -0x360(%rbp)
callq 0x2a10
movq -0x360(%rbp), %rdi
callq 0x2700
leaq -0x290(%rbp), %rdi
callq 0x2700
leaq -0x278(%rbp), %rdi
callq 0x28c0
movq 0x65cb(%rip), %rdi      # 0x7fd8
leaq 0x3684(%rip), %rsi      # 0x5098
callq 0x1090
movq %rax, -0x358(%rbp)
jmp 0x1a22
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x370(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x2760
movq -0x370(%rbp), %rsi
movq %rax, %rdi
callq 0x2780
movq -0x358(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x1130
movq %rax, -0x368(%rbp)
jmp 0x1a61
movq -0x368(%rbp), %rdi
leaq 0x3640(%rip), %rsi      # 0x50af
callq 0x1090
movq %rax, -0x378(%rbp)
jmp 0x1a7d
xorl %eax, %eax
movl %eax, %esi
leaq -0x140(%rbp), %rdi
callq 0x2760
movq %rax, %rdi
movl $0x1, %esi
callq 0x2780
movq -0x378(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x1130
movq %rax, -0x380(%rbp)
jmp 0x1ab3
movq -0x380(%rbp), %rdi
movq 0x6507(%rip), %rsi      # 0x7fc8
callq 0x10c0
jmp 0x1ac8
movq 0x6509(%rip), %rdi      # 0x7fd8
leaq 0x35cf(%rip), %rsi      # 0x50a5
callq 0x1090
movq %rax, -0x388(%rbp)
jmp 0x1ae4
leaq -0x140(%rbp), %rdi
movl $0x1, %esi
callq 0x2760
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2780
movq -0x388(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x1130
movq %rax, -0x390(%rbp)
jmp 0x1b1a
movq -0x390(%rbp), %rdi
leaq 0x3587(%rip), %rsi      # 0x50af
callq 0x1090
movq %rax, -0x398(%rbp)
jmp 0x1b36
leaq -0x140(%rbp), %rdi
movl $0x1, %esi
movq %rsi, -0x3a8(%rbp)
callq 0x2760
movq -0x3a8(%rbp), %rsi
movq %rax, %rdi
callq 0x2780
movq -0x398(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x1130
movq %rax, -0x3a0(%rbp)
jmp 0x1b76
movq -0x3a0(%rbp), %rdi
movq 0x6444(%rip), %rsi      # 0x7fc8
callq 0x10c0
jmp 0x1b8b
movq 0x6446(%rip), %rdi      # 0x7fd8
leaq 0x3519(%rip), %rsi      # 0x50b2
callq 0x1090
movq %rax, -0x3b0(%rbp)
jmp 0x1ba7
xorl %eax, %eax
movl %eax, %esi
leaq -0x1f0(%rbp), %rdi
callq 0x2780
movq -0x3b0(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x1130
movq %rax, -0x3b8(%rbp)
jmp 0x1bd0
movq -0x3b8(%rbp), %rdi
leaq 0x34d1(%rip), %rsi      # 0x50af
callq 0x1090
movq %rax, -0x3c0(%rbp)
jmp 0x1bec
leaq -0x1f0(%rbp), %rdi
movl $0x1, %esi
callq 0x2780
movq -0x3c0(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x1130
movq %rax, -0x3c8(%rbp)
jmp 0x1c16
movq -0x3c8(%rbp), %rdi
movq 0x63a4(%rip), %rsi      # 0x7fc8
callq 0x10c0
jmp 0x1c2b
movq 0x63a6(%rip), %rdi      # 0x7fd8
leaq 0x3486(%rip), %rsi      # 0x50bf
callq 0x1090
movq %rax, -0x3d0(%rbp)
jmp 0x1c47
movq -0x3d0(%rbp), %rdi
movq 0x6373(%rip), %rsi      # 0x7fc8
callq 0x10c0
jmp 0x1c5c
movq 0x6375(%rip), %rdi      # 0x7fd8
leaq 0x345d(%rip), %rsi      # 0x50c7
callq 0x1090
movq %rax, -0x3d8(%rbp)
jmp 0x1c78
xorl %eax, %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x2780
movq -0x3d8(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x1130
movq %rax, -0x3e0(%rbp)
jmp 0x1c9e
movq -0x3e0(%rbp), %rdi
movq 0x631c(%rip), %rsi      # 0x7fc8
callq 0x10c0
jmp 0x1cb3
movq 0x631e(%rip), %rdi      # 0x7fd8
leaq 0x340d(%rip), %rsi      # 0x50ce
callq 0x1090
movq %rax, -0x3e8(%rbp)
jmp 0x1ccf
leaq -0x20(%rbp), %rdi
movl $0x1, %esi
callq 0x2780
movq -0x3e8(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x1130
movq %rax, -0x3f0(%rbp)
jmp 0x1cf6
movq -0x3f0(%rbp), %rdi
movq 0x62c4(%rip), %rsi      # 0x7fc8
callq 0x10c0
jmp 0x1d0b
leaq -0x1f0(%rbp), %rdi
callq 0x2700
leaq -0x140(%rbp), %rdi
callq 0x28c0
leaq -0xd0(%rbp), %rdi
callq 0x2700
leaq -0x50(%rbp), %rdi
callq 0x2700
leaq -0x38(%rbp), %rdi
callq 0x28c0
leaq -0x20(%rbp), %rdi
callq 0x2700
movl -0x4(%rbp), %eax
addq $0x3f0, %rsp            # imm = 0x3F0
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
jmp 0x1dc8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0x248(%rbp), %rdi
callq 0x28c0
jmp 0x1dc8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
jmp 0x1dbc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0x290(%rbp), %rdi
callq 0x2700
leaq -0x278(%rbp), %rdi
callq 0x28c0
leaq -0x1f0(%rbp), %rdi
callq 0x2700
leaq -0x140(%rbp), %rdi
callq 0x28c0
leaq -0xd0(%rbp), %rdi
callq 0x2700
leaq -0x50(%rbp), %rdi
callq 0x2700
leaq -0x38(%rbp), %rdi
callq 0x28c0
leaq -0x20(%rbp), %rdi
callq 0x2700
movq -0xb0(%rbp), %rdi
callq 0x1120
nopw %cs:(%rax,%rax)