// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Isect.cpp
// Function: gaps::R3Intersects(gaps::R3Line const&, gaps::R3Box const&, gaps::R3Point*)
RNClassID R3Intersects(const R3Line& line, const R3Box& box, 
    R3Point *hit_point)
{
    RNClassID id = RN_NULL_CLASS_ID;
    R3Point point1;
    RNScalar tval1;

    // Check if box contains point on line
    if (R3Contains(box, line.Point())) {
	if (hit_point) *hit_point = line.Point();
	return R3_SPAN_CLASS_ID;
    }
    else {
	// Find parametric distance to front plane in each dimension
	for (RNDimension dim = RN_X; dim <= RN_Z; dim++) {
	    if (RNIsPositive(line.Vector()[dim])) {
		RNScalar delta = box.Min()[dim] - line.Point()[dim];
		tval1 = delta / line.Vector()[dim];
	    }
	    else if (RNIsNegative(line.Vector()[dim])) {
		RNScalar delta = box.Max()[dim] - line.Point()[dim];
		tval1 = delta / line.Vector()[dim];
	    }
	    else {
		continue;
	    }
	    
	    // Compute intersection point on plane
	    RNDimension dim1 = (dim + 1) % 3;
	    RNDimension dim2 = (dim + 2) % 3;
	    point1[dim] = (line.Vector()[dim] > 0.0) ? box.Min()[dim] : box.Max()[dim];
	    assert(RNIsEqual(point1[dim], line.Point()[dim] + line.Vector()[dim] * tval1));
	    point1[dim1] = line.Point()[dim1] + line.Vector()[dim1] * tval1;
	    point1[dim2] = line.Point()[dim2] + line.Vector()[dim2] * tval1;
	    
	    // Check if intersection point on plane is inside box
	    if ((RNIsLessOrEqual(point1[dim1], box.Max()[dim1])) &&
		(RNIsGreaterOrEqual(point1[dim1], box.Min()[dim1])) &&
		(RNIsLessOrEqual(point1[dim2], box.Max()[dim2])) &&
		(RNIsGreaterOrEqual(point1[dim2], box.Min()[dim2]))) {
		// Found first intersection point 
		id = R3_SPAN_CLASS_ID;
		break;
	    }
	}

	// Fill in results
	if (id != RN_NULL_CLASS_ID) {
	    if (hit_point) *hit_point = point1;
	}
	
	// Return intersection 
	return id;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rdx, %rbx
movq %rsi, %r15
movq %rdi, %r14
leaq 0x10(%rsp), %r12
movq %r12, %rdi
callq 0x37b4a
movq %r15, %rdi
movq %r14, %rsi
callq 0x419e0
pushq $0x4
popq %rbp
testl %eax, %eax
je 0x3d5b5
testq %rbx, %rbx
je 0x3d700
movq %rbx, %rdi
movq %r14, %rsi
callq 0x37e36
jmp 0x3d700
movq %rbx, 0x8(%rsp)
leaq 0x9d5e7(%rip), %rax     # 0xdaba8
movsd (%rax), %xmm0
movapd 0x55a63(%rip), %xmm1    # 0x93030
xorpd %xmm0, %xmm1
xorl %r8d, %r8d
pushq $0x8
popq %rax
pushq $0x20
popq %rcx
leaq 0x20(%r15), %rdx
leaq 0x8(%r15), %rsi
xorpd %xmm2, %xmm2
pushq $0x2
popq %rdi
cmpq $0x3, %r8
je 0x3d6fe
movsd 0x18(%r14,%r8,8), %xmm4
ucomisd %xmm0, %xmm4
movq %rax, %r9
ja 0x3d611
ucomisd %xmm4, %xmm1
movq %rcx, %r9
ja 0x3d611
incq %r8
jmp 0x3d5e9
addq %r15, %r9
movsd (%r9,%r8,8), %xmm3
subsd (%r14,%r8,8), %xmm3
divsd %xmm4, %xmm3
ucomisd %xmm2, %xmm4
movq %rdx, %r13
cmovaq %rsi, %r13
leaq 0x1(%r8), %r9
leal -0x1(%r8), %r10d
cmpq $0x2, %r8
movq %r12, %rbx
movl %r9d, %r12d
movl $0x0, %r11d
cmovneq %r12, %r11
movq %rbx, %r12
testq %r8, %r8
movslq %r10d, %r10
movsd (%r13,%r8,8), %xmm4
movsd %xmm4, 0x10(%rsp,%r8,8)
movsd 0x18(%r14,%r11,8), %xmm4
mulsd %xmm3, %xmm4
addsd (%r14,%r11,8), %xmm4
movsd %xmm4, 0x10(%rsp,%r11,8)
cmoveq %rdi, %r10
mulsd 0x18(%r14,%r10,8), %xmm3
addsd (%r14,%r10,8), %xmm3
movsd %xmm3, 0x10(%rsp,%r10,8)
movsd 0x10(%rsp,%r11,8), %xmm4
movapd %xmm4, %xmm5
subsd 0x20(%r15,%r11,8), %xmm5
ucomisd %xmm5, %xmm0
movq %r9, %r8
jb 0x3d5e9
subsd 0x8(%r15,%r11,8), %xmm4
ucomisd %xmm1, %xmm4
movq %r9, %r8
jb 0x3d5e9
movapd %xmm3, %xmm4
subsd 0x20(%r15,%r10,8), %xmm4
ucomisd %xmm4, %xmm0
movq %r9, %r8
jb 0x3d5e9
subsd 0x8(%r15,%r10,8), %xmm3
ucomisd %xmm1, %xmm3
movq %r9, %r8
jb 0x3d5e9
movq %r12, %r14
movq 0x8(%rsp), %rbx
jmp 0x3d59c
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq