// File: /workspace/github_cpp_makefile_star2_O3/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 0xd0256(%rip), %xmm1    # 0x1550a8
mulsd %xmm12, %xmm1
mulsd %xmm3, %xmm1
movapd %xmm11, %xmm0
mulsd %xmm11, %xmm0
addsd %xmm1, %xmm0
xorpd %xmm1, %xmm1
movapd %xmm1, 0x10(%rsp)
movq $0x0, 0x20(%rsp)
movapd 0xc821c(%rip), %xmm2    # 0x14d0a0
andpd %xmm0, %xmm2
movsd 0xcc778(%rip), %xmm1    # 0x151608
ucomisd %xmm2, %xmm1
jbe 0x84eea
xorpd 0xcc7a1(%rip), %xmm11   # 0x151640
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 0xa0(%rsp), %rdx
movapd %xmm7, (%rdx)
movsd %xmm9, 0x10(%rdx)
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
callq 0x2fec4
movl $0x1, %eax
jmp 0x85073
xorl %eax, %eax
xorpd %xmm1, %xmm1
ucomisd %xmm0, %xmm1
ja 0x85073
ucomisd %xmm1, %xmm0
movapd %xmm7, 0x60(%rsp)
movapd %xmm8, 0x50(%rsp)
movsd %xmm9, 0x38(%rsp)
movsd %xmm10, 0x30(%rsp)
movapd %xmm11, 0x40(%rsp)
movapd %xmm0, 0x90(%rsp)
jb 0x84f31
sqrtsd %xmm0, %xmm0
jmp 0x84f66
movsd %xmm12, 0x8(%rsp)
callq 0x4350
movsd 0x8(%rsp), %xmm12
movapd 0x40(%rsp), %xmm11
movsd 0x30(%rsp), %xmm10
movsd 0x38(%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 0xa0(%rsp), %rdx
movapd %xmm0, (%rdx)
movsd %xmm1, 0x10(%rdx)
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
callq 0x2fec4
movapd 0x40(%rsp), %xmm5
xorpd 0xcc67e(%rip), %xmm5    # 0x151640
xorpd %xmm1, %xmm1
movapd 0x90(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x84fdb
sqrtsd %xmm0, %xmm0
jmp 0x84fec
movapd %xmm5, 0x40(%rsp)
callq 0x4350
movapd 0x40(%rsp), %xmm5
movapd 0x60(%rsp), %xmm1
movapd 0x50(%rsp), %xmm2
movsd 0x38(%rsp), %xmm3
movsd 0x30(%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
movapd %xmm1, 0x70(%rsp)
movsd %xmm3, 0x80(%rsp)
movq 0x18(%rsp), %rsi
cmpq 0x20(%rsp), %rsi
je 0x8505f
movq 0x80(%rsp), %rax
movq %rax, 0x10(%rsi)
movapd 0x70(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x18, 0x18(%rsp)
jmp 0x8506e
leaq 0x10(%rsp), %rdi
leaq 0x70(%rsp), %rdx
callq 0x2fec4
movl $0x2, %eax
movl %eax, (%rbx)
leaq 0x8(%rbx), %rdi
leaq 0x10(%rsp), %rsi
callq 0xe868
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x8509a
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq %rbx, %rax
addq $0xc0, %rsp
popq %rbx
retq
jmp 0x850ac
jmp 0x850ac
jmp 0x850ac
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x850c6
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x4470
movq %rbx, %rdi
callq 0x4780