// File: tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Isect.cpp
// Function: gaps::R2Intersects(gaps::R2Ray const&, gaps::R2Circle const&, gaps::R2Point*, gaps::R2Vector*, double*)
RNClassID R2Intersects(const R2Ray& ray, const R2Circle& circle, 
    R2Point *hit_point1, R2Vector *hit_normal1, RNScalar *hit_t1)
{
    // Check if circle contains ray start point
    if (R2Contains(circle, ray.Start())) {
	if (hit_point1) *hit_point1 = ray.Start();
	if (hit_normal1) *hit_normal1 = ray.Vector();
	if (hit_t1) *hit_t1 = 0.0;
	return R2_SPAN_CLASS_ID;
    }
    else {
	// Check if ray points towards circle
	R2Vector EO = circle.Center() - ray.Start();
	RNScalar v = EO.Dot(ray.Vector());
	if (RNIsNegativeOrZero(v)) {
	    // Ray points away from circle
	    return RN_NULL_CLASS_ID;
	}
	else {
	    // Compute possible intersection -- Graphics Gems I, p. 388    
	    RNScalar disc = circle.Radius() * circle.Radius() - (EO.Dot(EO) - v*v);
	    if (RNIsNegative(disc)) {
		// No intersection
		return RN_NULL_CLASS_ID;
	    }
	    else {
		// Ray intersects circle (it grazes if disc is zero)
		// Compute first intersection
		if (hit_t1 || hit_point1 || hit_normal1) {
		    RNScalar d = sqrt(disc);
		    RNScalar t = v - d;
		    if (hit_t1) *hit_t1 = t;
		    if (hit_point1) *hit_point1 = ray.Start() + t * ray.Vector();
		    if (hit_normal1) {
			R2Point p, *pp;
			if (hit_point1) pp = hit_point1;
			else { p = ray.Start() + t * ray.Vector(); pp = &p; }
			*hit_normal1 = (*pp - circle.Centroid()) / circle.Radius();
		    }
		}

		// Compute second intersection
		// if (hit_t2 || hit_point2 || hit_normal2) {
		//     t = v + d;
		//     if (hit_point2) *hit_point2 = ray.Start() + t * ray.Vector();
		//     if (hit_t2) *hit_t2 = t;
		// }

		// Return result
		if (RNIsZero(disc)) return R2_POINT_CLASS_ID;
	        else return R2_SPAN_CLASS_ID;
	    }
	}
    }
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x128(%rsp)
movq %rsi, 0x120(%rsp)
movq %rdx, 0x118(%rsp)
movq %rcx, 0x110(%rsp)
movq %r8, 0x108(%rsp)
movq 0x120(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x128(%rsp), %rdi
callq 0xa3560
movq 0x48(%rsp), %rdi
movq %rax, %rsi
callq 0xa2cb0
cmpl $0x0, %eax
je 0xa4b65
cmpq $0x0, 0x118(%rsp)
je 0xa4b13
movq 0x128(%rsp), %rdi
callq 0xa3560
movq %rax, %rsi
movq 0x118(%rsp), %rdi
callq 0xc33e0
cmpq $0x0, 0x110(%rsp)
je 0xa4b3b
movq 0x128(%rsp), %rdi
callq 0xa35c0
movq %rax, %rsi
movq 0x110(%rsp), %rdi
callq 0xc4350
cmpq $0x0, 0x108(%rsp)
je 0xa4b55
movq 0x108(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movl $0x4, 0x134(%rsp)
jmp 0xa4f07
movq 0x120(%rsp), %rdi
callq 0xa3530
movq %rax, 0x40(%rsp)
movq 0x128(%rsp), %rdi
callq 0xa3560
movq 0x40(%rsp), %rsi
movq %rax, %rdx
leaq 0xf8(%rsp), %rdi
callq 0xc3830
movq 0x128(%rsp), %rdi
callq 0xa35c0
movq %rax, %rsi
leaq 0xf8(%rsp), %rdi
callq 0xc3f40
movsd %xmm0, 0xf0(%rsp)
movsd 0xf0(%rsp), %xmm0
leaq 0xd3911(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x382c0
cmpl $0x0, %eax
je 0xa4bed
movl $0x0, 0x134(%rsp)
jmp 0xa4f07
movq 0x120(%rsp), %rdi
callq 0xa36b0
movsd %xmm0, 0x38(%rsp)
movq 0x120(%rsp), %rdi
callq 0xa36b0
movsd %xmm0, 0x30(%rsp)
leaq 0xf8(%rsp), %rsi
movq %rsi, %rdi
callq 0xc3f40
movsd 0x30(%rsp), %xmm2
movaps %xmm0, %xmm3
movsd 0x38(%rsp), %xmm0
movsd 0xf0(%rsp), %xmm1
movsd 0xf0(%rsp), %xmm4
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm4, %xmm1
addsd %xmm3, %xmm1
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xe8(%rsp)
movsd 0xe8(%rsp), %xmm0
leaq 0xd3845(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0xa4cb9
movl $0x0, 0x134(%rsp)
jmp 0xa4f07
cmpq $0x0, 0x108(%rsp)
jne 0xa4cde
cmpq $0x0, 0x118(%rsp)
jne 0xa4cde
cmpq $0x0, 0x110(%rsp)
je 0xa4ed1
movsd 0xe8(%rsp), %xmm0
callq 0xf390
movsd %xmm0, 0xe0(%rsp)
movsd 0xf0(%rsp), %xmm0
subsd 0xe0(%rsp), %xmm0
movsd %xmm0, 0xd8(%rsp)
cmpq $0x0, 0x108(%rsp)
je 0xa4d30
movsd 0xd8(%rsp), %xmm0
movq 0x108(%rsp), %rax
movsd %xmm0, (%rax)
cmpq $0x0, 0x118(%rsp)
je 0xa4dae
movq 0x128(%rsp), %rdi
callq 0xa3560
movq %rax, 0x28(%rsp)
movsd 0xd8(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x128(%rsp), %rdi
callq 0xa35c0
movsd 0x20(%rsp), %xmm0
movq %rax, %rsi
leaq 0xb8(%rsp), %rdi
callq 0xa5c30
movq 0x28(%rsp), %rsi
leaq 0xc8(%rsp), %rdi
leaq 0xb8(%rsp), %rdx
callq 0xc37a0
movq 0x118(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0xc33e0
cmpq $0x0, 0x110(%rsp)
je 0xa4ecf
leaq 0xa8(%rsp), %rdi
callq 0xc3130
cmpq $0x0, 0x118(%rsp)
je 0xa4dea
movq 0x118(%rsp), %rax
movq %rax, 0xa0(%rsp)
jmp 0xa4e6d
movq 0x128(%rsp), %rdi
callq 0xa3560
movq %rax, 0x18(%rsp)
movsd 0xd8(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x128(%rsp), %rdi
callq 0xa35c0
movsd 0x10(%rsp), %xmm0
movq %rax, %rsi
leaq 0x80(%rsp), %rdi
callq 0xa5c30
movq 0x18(%rsp), %rsi
leaq 0x90(%rsp), %rdi
leaq 0x80(%rsp), %rdx
callq 0xc37a0
leaq 0xa8(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0xc33e0
leaq 0xa8(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x120(%rsp), %rsi
movq (%rsi), %rax
leaq 0x50(%rsp), %rdi
callq *0x38(%rax)
movq 0x8(%rsp), %rsi
leaq 0x60(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0xc3830
movq 0x120(%rsp), %rdi
callq 0xa36b0
leaq 0x70(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0xc49d0
movq 0x110(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0xc4350
jmp 0xa4ed1
movsd 0xe8(%rsp), %xmm0
leaq 0xd35ff(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x36b80
cmpl $0x0, %eax
je 0xa4efc
movl $0x1, 0x134(%rsp)
jmp 0xa4f07
movl $0x4, 0x134(%rsp)
movl 0x134(%rsp), %eax
addq $0x138, %rsp            # imm = 0x138
retq
nopw %cs:(%rax,%rax)