// File: Luthaf[P]zeopp/geometry.cc
// Function: findLineIntersections(Point, Point, Point, double)
pair<int, vector<Point> > findLineIntersections(Point p1, Point p2, Point circCenter, double rad){

  double tolerance = 0.00001; // Tolerance for determining whether two numbers are equal

  double a = (p2[0] - p1[0])*(p2[0] - p1[0]) + (p2[1] - p1[1])*(p2[1] - p1[1]) + (p2[2] - p1[2])*(p2[2] - p1[2]);
  double b = 2.0*((p2[0] - p1[0])*(p1[0] - circCenter[0]) + (p2[1] - p1[1])*(p1[1] - circCenter[1]) + (p2[2] - p1[2])*(p1[2] - circCenter[2]));
  double c = circCenter[0]*circCenter[0] + circCenter[1]*circCenter[1] + circCenter[2]*circCenter[2] 
    + p1[0]*p1[0] + p1[1]*p1[1] + p1[2]*p1[2] 
    - 2.0*(circCenter[0]*p1[0] +circCenter[1]*p1[1] + circCenter[2]*p1[2]) - rad*rad;

  double discriminant = b*b - 4.0*a*c;

  int numResults;
  vector<Point> results;

  if(abs(discriminant) < tolerance){
    // Discriminant is zero. Line is tangent and therefore only has one intersection
    numResults = 1;
    double u = (-b/(2.0*a));
    Point intersection = p1.add((p2.subtract(p1)).scale(u));
    results.push_back(intersection);
  }
  else if (discriminant < 0){
    //Disciminant is negative. No intersection between line and sphere.
    numResults = 0;
  }
  else{
    //Discriminant is positive. Two intersection points exist
    numResults = 2;

    double u1 = ((-b + sqrt(discriminant))/(2.0*a));
    Point intersection1 = p1.add((p2.subtract(p1)).scale(u1));
    results.push_back(intersection1);

    double u2 = ((-b - sqrt(discriminant))/(2.0*a));
    Point intersection2 = p1.add((p2.subtract(p1)).scale(u2));
    results.push_back(intersection2);
  }
  return pair<int, vector<Point> > (numResults, results);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x350, %rsp            # imm = 0x350
movq %rdi, %rax
movq %rax, -0x328(%rbp)
movq %rax, %rdi
movq %rdi, -0x320(%rbp)
leaq 0x40(%rbp), %rcx
movq %rcx, -0x1e8(%rbp)
leaq 0x28(%rbp), %rdi
movq %rdi, -0x288(%rbp)
leaq 0x10(%rbp), %rcx
movq %rcx, -0x1e0(%rbp)
movq %rax, -0x8(%rbp)
movsd %xmm0, -0x10(%rbp)
movabsq $0x3ee4f8b588e368f1, %rax # imm = 0x3EE4F8B588E368F1
movq %rax, -0x18(%rbp)
xorl %esi, %esi
movl %esi, -0x208(%rbp)
callq 0xe9d70
movl -0x208(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x318(%rbp)
callq 0xe9d70
movsd -0x318(%rbp), %xmm0
movq -0x288(%rbp), %rdi
movl -0x208(%rbp), %esi
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x2f0(%rbp)
callq 0xe9d70
movl -0x208(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x310(%rbp)
callq 0xe9d70
movsd -0x310(%rbp), %xmm0
movq -0x288(%rbp), %rdi
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x2e8(%rbp)
movl $0x1, %esi
movl %esi, -0x204(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x308(%rbp)
callq 0xe9d70
movsd -0x308(%rbp), %xmm0
movq -0x288(%rbp), %rdi
movl -0x204(%rbp), %esi
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x2f8(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x300(%rbp)
callq 0xe9d70
movsd -0x300(%rbp), %xmm3
movsd -0x2f8(%rbp), %xmm1
movsd -0x2f0(%rbp), %xmm0
movsd -0x2e8(%rbp), %xmm2
movq -0x288(%rbp), %rdi
movsd (%rax), %xmm4
subsd %xmm4, %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x2c8(%rbp)
movl $0x2, %esi
movl %esi, -0x1d4(%rbp)
callq 0xe9d70
movq -0x1e0(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm0
movsd %xmm0, -0x2e0(%rbp)
callq 0xe9d70
movsd -0x2e0(%rbp), %xmm0
movq -0x288(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x2d0(%rbp)
callq 0xe9d70
movq -0x1e0(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm0
movsd %xmm0, -0x2d8(%rbp)
callq 0xe9d70
movsd -0x2d8(%rbp), %xmm2
movsd -0x2d0(%rbp), %xmm0
movsd -0x2c8(%rbp), %xmm1
movq -0x288(%rbp), %rdi
movl -0x208(%rbp), %esi
movsd (%rax), %xmm3
subsd %xmm3, %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x20(%rbp)
callq 0xe9d70
movl -0x208(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x2c0(%rbp)
callq 0xe9d70
movsd -0x2c0(%rbp), %xmm0
movl -0x208(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x298(%rbp)
callq 0xe9d70
movl -0x208(%rbp), %esi
movq -0x1e8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x2b8(%rbp)
callq 0xe9d70
movsd -0x2b8(%rbp), %xmm0
movq -0x288(%rbp), %rdi
movl -0x204(%rbp), %esi
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x290(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x2b0(%rbp)
callq 0xe9d70
movsd -0x2b0(%rbp), %xmm0
movl -0x204(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x2a0(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x2a8(%rbp)
callq 0xe9d70
movsd -0x2a8(%rbp), %xmm3
movsd -0x2a0(%rbp), %xmm1
movsd -0x298(%rbp), %xmm0
movsd -0x290(%rbp), %xmm2
movq -0x288(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm4
subsd %xmm4, %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x268(%rbp)
callq 0xe9d70
movq -0x1e0(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm0
movsd %xmm0, -0x280(%rbp)
callq 0xe9d70
movsd -0x280(%rbp), %xmm0
movq -0x1e0(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x270(%rbp)
callq 0xe9d70
movq -0x1e8(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm0
movsd %xmm0, -0x278(%rbp)
callq 0xe9d70
movsd -0x278(%rbp), %xmm2
movsd -0x270(%rbp), %xmm0
movsd -0x268(%rbp), %xmm1
movl -0x208(%rbp), %esi
movq -0x1e8(%rbp), %rdi
movsd (%rax), %xmm3
subsd %xmm3, %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
addsd %xmm0, %xmm0
movsd %xmm0, -0x28(%rbp)
callq 0xe9d70
movl -0x208(%rbp), %esi
movq -0x1e8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x258(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x250(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x260(%rbp)
callq 0xe9d70
movsd -0x260(%rbp), %xmm1
movsd -0x258(%rbp), %xmm0
movsd -0x250(%rbp), %xmm2
movq -0x1e8(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x240(%rbp)
callq 0xe9d70
movq -0x1e8(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm0
movsd %xmm0, -0x248(%rbp)
callq 0xe9d70
movsd -0x248(%rbp), %xmm0
movsd -0x240(%rbp), %xmm1
movl -0x208(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x230(%rbp)
callq 0xe9d70
movl -0x208(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x238(%rbp)
callq 0xe9d70
movsd -0x238(%rbp), %xmm0
movsd -0x230(%rbp), %xmm1
movl -0x204(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x220(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x228(%rbp)
callq 0xe9d70
movsd -0x228(%rbp), %xmm0
movsd -0x220(%rbp), %xmm1
movq -0x1e0(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x210(%rbp)
callq 0xe9d70
movq -0x1e0(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm0
movsd %xmm0, -0x218(%rbp)
callq 0xe9d70
movsd -0x218(%rbp), %xmm0
movsd -0x210(%rbp), %xmm1
movl -0x208(%rbp), %esi
movq -0x1e8(%rbp), %rdi
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x1c0(%rbp)
callq 0xe9d70
movl -0x208(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x1f8(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x1f0(%rbp)
callq 0xe9d70
movl -0x204(%rbp), %esi
movq -0x1e0(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x200(%rbp)
callq 0xe9d70
movsd -0x200(%rbp), %xmm1
movsd -0x1f8(%rbp), %xmm0
movsd -0x1f0(%rbp), %xmm2
movq -0x1e8(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x1c8(%rbp)
callq 0xe9d70
movq -0x1e0(%rbp), %rdi
movl -0x1d4(%rbp), %esi
movsd (%rax), %xmm0
movsd %xmm0, -0x1d0(%rbp)
callq 0xe9d70
movsd -0x1d0(%rbp), %xmm1
movsd -0x1c8(%rbp), %xmm2
movsd -0x1c0(%rbp), %xmm0
movsd (%rax), %xmm3
mulsd %xmm3, %xmm1
addsd %xmm2, %xmm1
addsd %xmm1, %xmm1
subsd %xmm1, %xmm0
movsd -0x10(%rbp), %xmm1
mulsd %xmm1, %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x30(%rbp)
movsd -0x28(%rbp), %xmm0
movsd -0x20(%rbp), %xmm1
movsd 0x10f956(%rip), %xmm2   # 0x1fbcd0
mulsd %xmm2, %xmm1
movsd -0x30(%rbp), %xmm2
mulsd %xmm2, %xmm1
mulsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x38(%rbp)
leaq -0x58(%rbp), %rdi
callq 0xed40
movsd -0x38(%rbp), %xmm0
callq 0x162b0
movsd %xmm0, -0x1b8(%rbp)
jmp 0xec3b1
movsd -0x1b8(%rbp), %xmm1
movsd -0x18(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0xec4b2
movq -0x288(%rbp), %rsi
movq -0x1e0(%rbp), %rax
movl $0x1, -0x3c(%rbp)
movaps 0x10f8fc(%rip), %xmm1   # 0x1fbce0
movsd -0x28(%rbp), %xmm0
pxor %xmm1, %xmm0
movsd -0x20(%rbp), %xmm1
addsd %xmm1, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x70(%rbp)
movq 0x10(%rax), %rcx
movq %rcx, -0xc0(%rbp)
movups (%rax), %xmm0
movaps %xmm0, -0xd0(%rbp)
movq -0xc0(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x10(%rax)
movaps -0xd0(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0xb8(%rbp), %rdi
callq 0xe9ef0
jmp 0xec43a
movsd -0x70(%rbp), %xmm0
leaq -0xa0(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0xea000
jmp 0xec454
movq -0x1e0(%rbp), %rsi
movq -0x90(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x10(%rax)
movups -0xa0(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0x88(%rbp), %rdi
callq 0xe9cb0
jmp 0xec481
leaq -0x58(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x59bf0
jmp 0xec493
jmp 0xec69b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x58(%rbp), %rdi
callq 0xefe0
jmp 0xec6ca
xorps %xmm0, %xmm0
ucomisd -0x38(%rbp), %xmm0
jbe 0xec4c8
movl $0x0, -0x3c(%rbp)
jmp 0xec699
movl $0x2, -0x3c(%rbp)
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x330(%rbp)
movsd -0x38(%rbp), %xmm0
callq 0x53f0
movsd -0x330(%rbp), %xmm1
movq -0x1e0(%rbp), %rax
movq -0x288(%rbp), %rsi
subsd %xmm1, %xmm0
movsd -0x20(%rbp), %xmm1
addsd %xmm1, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0xd8(%rbp)
movq 0x10(%rax), %rcx
movq %rcx, -0x130(%rbp)
movups (%rax), %xmm0
movaps %xmm0, -0x140(%rbp)
movq -0x130(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x10(%rax)
movaps -0x140(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0x120(%rbp), %rdi
callq 0xe9ef0
jmp 0xec550
movsd -0xd8(%rbp), %xmm0
leaq -0x108(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0xea000
jmp 0xec56d
movq -0x1e0(%rbp), %rsi
movq -0xf8(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x10(%rax)
movups -0x108(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0xf0(%rbp), %rdi
callq 0xe9cb0
jmp 0xec59a
leaq -0x58(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x59bf0
jmp 0xec5ac
movaps 0x10f72d(%rip), %xmm1   # 0x1fbce0
movsd -0x28(%rbp), %xmm0
pxor %xmm1, %xmm0
movsd %xmm0, -0x338(%rbp)
movsd -0x38(%rbp), %xmm0
callq 0x53f0
movq -0x1e0(%rbp), %rax
movq -0x288(%rbp), %rsi
movaps %xmm0, %xmm1
movsd -0x338(%rbp), %xmm0
subsd %xmm1, %xmm0
movsd -0x20(%rbp), %xmm1
addsd %xmm1, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x148(%rbp)
movq 0x10(%rax), %rcx
movq %rcx, -0x1a0(%rbp)
movups (%rax), %xmm0
movaps %xmm0, -0x1b0(%rbp)
movq -0x1a0(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x10(%rax)
movaps -0x1b0(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0x190(%rbp), %rdi
callq 0xe9ef0
jmp 0xec63b
movsd -0x148(%rbp), %xmm0
leaq -0x178(%rbp), %rdi
leaq -0x190(%rbp), %rsi
callq 0xea000
jmp 0xec658
movq -0x1e0(%rbp), %rsi
movq -0x168(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x10(%rax)
movups -0x178(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0x160(%rbp), %rdi
callq 0xe9cb0
jmp 0xec685
leaq -0x58(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0x59bf0
jmp 0xec697
jmp 0xec699
jmp 0xec69b
movq -0x328(%rbp), %rdi
leaq -0x3c(%rbp), %rsi
leaq -0x58(%rbp), %rdx
callq 0xed270
jmp 0xec6b1
leaq -0x58(%rbp), %rdi
callq 0xefe0
movq -0x320(%rbp), %rax
addq $0x350, %rsp            # imm = 0x350
popq %rbp
retq
movq -0x60(%rbp), %rdi
callq 0x58f0
nopw %cs:(%rax,%rax)