// File: /workspace/github_cpp_makefile_star2_O2/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 %rbx
subq $0xc0, %rsp
movq %rdi, %rbx
movupd 0xe8(%rsp), %xmm8
movapd 0xd0(%rsp), %xmm7
subpd %xmm7, %xmm8
movapd %xmm8, %xmm2
unpckhpd %xmm8, %xmm2            # xmm2 = xmm2[1],xmm8[1]
movsd 0x108(%rsp), %xmm3
movapd %xmm7, %xmm1
unpckhpd %xmm7, %xmm1            # xmm1 = xmm1[1],xmm7[1]
movapd %xmm1, %xmm4
subsd %xmm3, %xmm4
mulsd %xmm2, %xmm4
mulsd %xmm2, %xmm2
movapd %xmm8, %xmm5
mulsd %xmm8, %xmm5
addsd %xmm2, %xmm5
movsd 0xf8(%rsp), %xmm10
movsd 0xe0(%rsp), %xmm9
subsd %xmm9, %xmm10
movapd %xmm10, %xmm12
mulsd %xmm10, %xmm12
addsd %xmm5, %xmm12
movsd 0x100(%rsp), %xmm2
movapd %xmm7, %xmm5
subsd %xmm2, %xmm5
mulsd %xmm8, %xmm5
addsd %xmm4, %xmm5
movsd 0x110(%rsp), %xmm4
movapd %xmm9, %xmm11
subsd %xmm4, %xmm11
mulsd %xmm10, %xmm11
addsd %xmm5, %xmm11
addsd %xmm11, %xmm11
movapd %xmm1, %xmm5
mulsd %xmm3, %xmm1
mulsd %xmm3, %xmm3
movapd %xmm2, %xmm6
mulsd %xmm2, %xmm6
addsd %xmm3, %xmm6
movapd %xmm4, %xmm3
mulsd %xmm4, %xmm3
addsd %xmm6, %xmm3
movapd %xmm7, %xmm6
mulsd %xmm7, %xmm6
addsd %xmm3, %xmm6
mulsd %xmm5, %xmm5
addsd %xmm6, %xmm5
movapd %xmm9, %xmm3
mulsd %xmm9, %xmm3
addsd %xmm5, %xmm3
mulsd %xmm7, %xmm2
addsd %xmm1, %xmm2
mulsd %xmm9, %xmm4
addsd %xmm2, %xmm4
addsd %xmm4, %xmm4
subsd %xmm4, %xmm3
mulsd %xmm0, %xmm0
subsd %xmm0, %xmm3
movsd 0x9f533(%rip), %xmm1    # 0x103ff8
mulsd %xmm12, %xmm1
mulsd %xmm3, %xmm1
movapd %xmm11, %xmm0
mulsd %xmm11, %xmm0
addsd %xmm1, %xmm0
xorpd %xmm1, %xmm1
movapd %xmm1, 0x20(%rsp)
andq $0x0, 0x30(%rsp)
movapd 0x975ac(%rip), %xmm2    # 0xfc0a0
andpd %xmm0, %xmm2
movsd 0x9ba98(%rip), %xmm1    # 0x100598
ucomisd %xmm2, %xmm1
jbe 0x64b55
xorpd 0x9bac1(%rip), %xmm11   # 0x1005d0
addsd %xmm12, %xmm12
divsd %xmm12, %xmm11
mulsd %xmm11, %xmm10
addsd %xmm10, %xmm9
unpcklpd %xmm11, %xmm11          # xmm11 = xmm11[0,0]
mulpd %xmm11, %xmm8
addpd %xmm8, %xmm7
leaq 0x80(%rsp), %rsi
movapd %xmm7, (%rsi)
movsd %xmm9, 0x10(%rsi)
leaq 0x20(%rsp), %rdi
callq 0x2468e
pushq $0x1
jmp 0x64ca6
xorl %eax, %eax
xorpd %xmm1, %xmm1
ucomisd %xmm0, %xmm1
ja 0x64ca7
ucomisd %xmm1, %xmm0
movapd %xmm7, 0x60(%rsp)
movapd %xmm8, 0x50(%rsp)
movsd %xmm9, 0x18(%rsp)
movsd %xmm10, 0x10(%rsp)
movapd %xmm11, 0x40(%rsp)
movapd %xmm0, 0x70(%rsp)
jb 0x64b99
sqrtsd %xmm0, %xmm0
jmp 0x64bce
movsd %xmm12, 0x8(%rsp)
callq 0x4390
movsd 0x8(%rsp), %xmm12
movapd 0x40(%rsp), %xmm11
movsd 0x10(%rsp), %xmm10
movsd 0x18(%rsp), %xmm9
movapd 0x50(%rsp), %xmm8
movapd 0x60(%rsp), %xmm7
addsd %xmm12, %xmm12
subsd %xmm11, %xmm0
movsd %xmm12, 0x8(%rsp)
divsd %xmm12, %xmm0
movapd %xmm10, %xmm1
mulsd %xmm0, %xmm1
addsd %xmm9, %xmm1
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
mulpd %xmm8, %xmm0
addpd %xmm7, %xmm0
leaq 0x80(%rsp), %rsi
movapd %xmm0, (%rsi)
movsd %xmm1, 0x10(%rsi)
leaq 0x20(%rsp), %rdi
callq 0x2468e
movapd 0x40(%rsp), %xmm5
xorpd 0x9b9a8(%rip), %xmm5    # 0x1005d0
xorpd %xmm1, %xmm1
movapd 0x70(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x64c3e
sqrtsd %xmm0, %xmm0
jmp 0x64c4f
movapd %xmm5, 0x40(%rsp)
callq 0x4390
movapd 0x40(%rsp), %xmm5
movapd 0x60(%rsp), %xmm1
movapd 0x50(%rsp), %xmm2
movsd 0x18(%rsp), %xmm3
movsd 0x10(%rsp), %xmm4
movsd 0x8(%rsp), %xmm6
subsd %xmm0, %xmm5
divsd %xmm6, %xmm5
mulsd %xmm5, %xmm4
addsd %xmm4, %xmm3
unpcklpd %xmm5, %xmm5            # xmm5 = xmm5[0,0]
mulpd %xmm5, %xmm2
addpd %xmm2, %xmm1
leaq 0xa0(%rsp), %rsi
movapd %xmm1, (%rsi)
movsd %xmm3, 0x10(%rsi)
leaq 0x20(%rsp), %rdi
callq 0x2468e
pushq $0x2
popq %rax
movl %eax, (%rbx)
leaq 0x8(%rbx), %rdi
leaq 0x20(%rsp), %rsi
callq 0xa66e
leaq 0x20(%rsp), %rdi
callq 0xb83e
movq %rbx, %rax
addq $0xc0, %rsp
popq %rbx
retq
jmp 0x64cd3
jmp 0x64cd3
jmp 0x64cd3
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0xb83e
movq %rbx, %rdi
callq 0x4780