[an error occurred while processing this directive]
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//
//  Project:   Talina Gaming System (TgS) (∂)
//  File:      TgS Collision - Box-Linear.cpp
//  Author:    Andrew Aye (EMail: andrew.aye@gmail.com, Web: http://www.andrewaye.com) 
//  Version:   3.11
//
// ------------------------------------------------------------------------------------------------------------------------------ //
//
//  Copyright: © 2002-2008, Andrew Aye.  All Rights Reserved.
//
//  This software is free for non-commercial use. Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met: 
//    Redistributions of source code must retain this copyright notice, this list of conditions and the following disclaimers. 
//    Redistributions in binary form must reproduce this copyright notice, this list of conditions and the following
//      disclaimers in the documentation and other materials provided with the distribution. 
//
//  Neither the names of the copyright owner nor the names of its contributors may be used to endorse or promote products derived
//  from this software without specific prior written permission. 
//
//  The intellectual property rights of the algorithms used reside with Andrew Aye.  You may not use this software, in whole or
//  in part, in support of any commercial product without the express written consent of the author.
//
//  There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //




// ============================================================================================================================== //

namespace TGS { // START TGS ///////////////////////////////////////////////////////////////////////////////////////////////////////
namespace COL { // START COL ///////////////////////////////////////////////////////////////////////////////////////////////////////

// ============================================================================================================================== //

// ---- Box_DoF3 ------------------------------------------------------------------------------------------------------- //
//  -- Internal Function -- (Helper to create contact points the box and linear - three degrees of freedom)
// Input:  tvDS: The difference vector between the origin of the two primitives (absolute value)
// Input:  tvD0: Direction of the Linear
// Input:  tgBX0: Box primitive
// Output: tyLN0: Parametric parameter to generate the point of proximity on the linear
// Output: tvDS: The difference vector between the two points of closest proximity
// Return: Result Code
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TYPE Box_DoF3( TYPE *ptyLN0, PC_(VECTOR,DIM) ptvDS, M_(VECTOR,DIM) tvD0, CR_(BOX,DIM) tgBX0 )
{
    T_(VECTOR,DIM)                      tvD1_D1, tvD1_MN, tvD1_MX, tvMN_MN, tvMX_MX;

    C_(VECTOR,DIM)                      tvMN = MATH::F_SUB( *ptvDS, tgBX0.Query_ExtentList() );
    C_(VECTOR,DIM)                      tvMX = MATH::F_ADD( *ptvDS, tgBX0.Query_ExtentList() );
    C_(VECTOR,DIM)                      tvD1xMN = MATH::F_CX( tvD0, tvMN );

    tvD1_D1 = MATH::F_MUL( tvD0, tvD0 );
    tvD1_MN = MATH::F_MUL( tvD0, tvMN );
    tvD1_MX = MATH::F_MUL( tvD0, tvMX );
    tvMN_MN = MATH::F_MUL( tvMN, tvMN );
    tvMX_MX = MATH::F_MUL( tvMX, tvMX );

    const TYPE                          tyD1_D1 = MATH::F_LSQ( tvD0 );

    TgUINT                              i0, i1, i2;

    if (tvD1xMN.Z() >= TYPE(0.0))
    {
        i0 = tvD1xMN.X() >= TYPE(0.0) ? 2 : 1;
        i1 = tvD1xMN.X() >= TYPE(0.0) ? 0 : 2;
        i2 = tvD1xMN.X() >= TYPE(0.0) ? 1 : 0;
    }
    else
    {
        i0 = tvD1xMN.Y() >= TYPE(0.0) ? 0 : 2;
        i1 = tvD1xMN.Y() >= TYPE(0.0) ? 1 : 0;
        i2 = tvD1xMN.Y() >= TYPE(0.0) ? 2 : 1;
    }

    (*ptvDS)(i0) = tgBX0.Query_Extent(i0);

    if (tvD0(i0)*tvMX(i2) >= tvD0(i2)*tvMN(i0) && tvD0(i0)*tvMX(i1) >= tvD0(i1)*tvMN(i0))
    {
        const TYPE                          tyINV = TYPE(1.0) / tvD0(i0);

        (*ptvDS)(i1) -= tvD0(i1)*tvMN(i0)*tyINV;
        (*ptvDS)(i2) -= tvD0(i2)*tvMN(i0)*tyINV;

        *ptyLN0 = -tvMN(i0)*tyINV;

        return (TYPE(0.0));
    };

    const TYPE                          tyTMP = tvMX(i1) - tvD0(i1)*(tvD1_MN(i0) + tvD1_MX(i2)) / (tvD1_D1(i0) + tvD1_D1(i2));

    if (tvD0(i0)*tvMX(i1) >= tvD0(i1)*tvMN(i0) || (tyTMP >= TYPE(0.0) && tvD0(i0)*tvMX(i2) < tvD0(i2)*tvMN(i0)))
    {
        const TYPE                          tyLength = TYPE(2.0)*tgBX0.Query_Extent(i1);
        const TYPE                          tyT = P::FSEL(tyLength - tyTMP, P::FSEL( tyTMP, tyTMP, TYPE(0.0) ), tyLength );
        const TYPE                          tyTB = tvMX(i1) - tyT;
        const TYPE                          tyDT = tvD1_MN(i0) + tvD1_MX(i2) + tvD0(i1)*tyTB;
        const TYPE                          tyPM = -tyDT / tyD1_D1;

        (*ptvDS)(i1) = -tgBX0.Query_Extent(i1) + tyT;
        (*ptvDS)(i2) = -tgBX0.Query_Extent(i2);
        *ptyLN0 = tyPM;

        return (tvMN_MN(i0) + tvMX_MX(i2) + tyDT*tyPM + tyTB*tyTB);
    }
    else
    {
        const TYPE                          tyTMP = tvMX(i2) - tvD0(i2)*(tvD1_MN(i0) + tvD1_MX(i1)) / (tvD1_D1(i0) + tvD1_D1(i1));

        const TYPE                          tyLength = TYPE(2.0)*tgBX0.Query_Extent(i2);
        const TYPE                          tyT = P::FSEL(tyLength - tyTMP, P::FSEL( tyTMP, tyTMP, TYPE(0.0) ), tyLength );
        const TYPE                          tyTB = tvMX(i2) - tyT;
        const TYPE                          tyDT = tvD1_MN(i0) + tvD1_MX(i1) + tvD0(i2)*tyTB;
        const TYPE                          tyPM = -tyDT / tyD1_D1;

        (*ptvDS)(i1) = -tgBX0.Query_Extent(i1);
        (*ptvDS)(i2) = -tgBX0.Query_Extent(i2) + tyT;
        *ptyLN0 = tyPM;

        return (tvMN_MN(i0) + tvMX_MX(i1) + tyDT*tyPM + tyTB*tyTB);
    };
};

template TgFLOAT32 Box_DoF3( P_TgFLOAT32, PC_TgF4VECTOR, M_TgF4VECTOR, CR_TgF4BOX );


// ============================================================================================================================== //

// ---- Box_DoF2 ------------------------------------------------------------------------------------------------------- //
//  -- Internal Function -- (Helper to create contact points the box and linear - two degrees of freedom)
// Input:  tvDS: The difference vector between the origin of the two primitives
// Input:  tvD0: Direction of the Linear
// Input:  i0,i1,i2: Used to give the face order for the test
// Input:  tgBX0: Box primitive
// Output: tyLN0: Parametric parameter to generate the point of proximity on the linear
// Output: tvDS: The difference vector between the two points of closest proximity
// Return: Result Code
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TYPE Box_DoF2( TYPE *ptyLN0, PC_(VECTOR,DIM) ptvDS, M_(VECTOR,DIM) tvD0, C_TgINT i0, C_TgINT i1, C_TgINT i2, CR_(BOX,DIM) tgBX0 )
{
    // Construct the direction vector from the box corner at the positive extents to the line origin.

    const TYPE                          tyMinDT0 = (*ptvDS)(i0) - tgBX0.Query_Extent(i0);
    const TYPE                          tyMinDT1 = (*ptvDS)(i1) - tgBX0.Query_Extent(i1);

    const TYPE                          tyMinDT1_DN0 = tvD0(i0)*tyMinDT1;
    const TYPE                          tyMinDT0_DN1 = tvD0(i1)*tyMinDT0;

    T_(VECTOR,DIM)                      tvD1_D1;

    tvD1_D1 = MATH::F_MUL( tvD0, tvD0 );

    //const TYPE                          tyD1_D1 = MATH::F_LSQ( tvD0 );

    if (tyMinDT0_DN1 >= tyMinDT1_DN0)
    {
        (*ptvDS)(i0) = tgBX0.Query_Extent(i0);

        const TYPE                          tyMaxDT1 = (*ptvDS)(i1) + tgBX0.Query_Extent(i1);
        const TYPE                          tyDT = tyMinDT0_DN1 - tvD0(i0)*tyMaxDT1;

        if (tyDT >= TYPE(0.0)) //« Line is outside of the box.
        {
            const TYPE                          tyTMP0 = TYPE(1.0) / (tvD1_D1(i0) + tvD1_D1(i1));

            (*ptvDS)(i1) = -tgBX0.Query_Extent(i1);
            *ptyLN0 = -(tvD0(i0)*tyMinDT0 + tvD0(i1)*tyMaxDT1)*tyTMP0;

            return (tyDT*tyDT*tyTMP0);
        }
        else //« Line intersects the box.
        {
            const TYPE                          tyTMP0 = TYPE(1.0) / tvD0(i0);

            (*ptvDS)(i1) -= tyMinDT0_DN1*tyTMP0;
            *ptyLN0 = -tyMinDT0*tyTMP0;

            return (TYPE(0.0));
        }
    }
    else
    {
        (*ptvDS)(i1) = tgBX0.Query_Extent(i1);

        const TYPE                          tyMaxDT0 = (*ptvDS)(i0) + tgBX0.Query_Extent(i0);
        const TYPE                          tyDT = tyMinDT1_DN0 - tvD0(i1)*tyMaxDT0;

        if (tyDT >= TYPE(0.0)) //« Line is outside of the box.
        {
            const TYPE                          tyTMP0 = TYPE(1.0) / (tvD1_D1(i0) + tvD1_D1(i1));

            (*ptvDS)(i0) = -tgBX0.Query_Extent(i0);
            *ptyLN0 = -(tvD0(i0)*tyMaxDT0 + tvD0(i1)*tyMinDT1)*tyTMP0;

            return (tyDT*tyDT*tyTMP0);
        }
        else //« Line intersects the box.
        {
            const TYPE                          tyTMP0 = TYPE(1.0) / tvD0(i1);

            (*ptvDS)(i0) -= tyMinDT1_DN0*tyTMP0;
            *ptyLN0 = -tyMinDT1*tyTMP0;

            return (TYPE(0.0));
        }
    }
}

template TgFLOAT32 Box_DoF2( P_TgFLOAT32, PC_TgF4VECTOR, M_TgF4VECTOR, C_TgINT, C_TgINT, C_TgINT, CR_TgF4BOX );


// ============================================================================================================================== //

// ---- TTgCSQ_BXLN ------------------------------------------------------------------------------------------------------------- //
//  -- Internal Function -- 
// Input:  tgBX0: Box primitive
// Input:  tvS0,tvD0: Origin and Direction for Linear
// Output: tyB0,tyB1,tyB2: Parametric parameters to generate the point of closest proximity on the box (one for each axis)
// Output: tyLN0: Parametric parameter to generate the point of proximity on the linear
// Return: Minimal distance between the two primitives or negative type max if they intersect or are invalid.
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM, bool bC0, bool bC1>
TYPE TTgCSQ_BXLN<TYPE,DIM,bC0,bC1>::DO(
    TYPE *ptyB0, TYPE *ptyB1, TYPE *ptyB2, TYPE *ptyLN0, CR_(BOX,DIM) tgBX0, M_(VECTOR,DIM) tvS0, M_(VECTOR,DIM) tvD0
) {
    // Compute coordinates of line in box coordinate system

    T_(VECTOR,DIM)                      tvDS = MATH::F_SUB( tvS0, tgBX0.Query_Origin() );

    const TYPE                          tyD1_X0 = MATH::F_DOT( tvD0, tgBX0.Query_AxisUnit0() );
    const TYPE                          tyD1_X1 = MATH::F_DOT( tvD0, tgBX0.Query_AxisUnit1() );
    const TYPE                          tyD1_X2 = MATH::F_DOT( tvD0, tgBX0.Query_AxisUnit2() );

    const TYPE                          tyDS_X0 = MATH::F_DOT( tvDS, tgBX0.Query_AxisUnit0() );
    const TYPE                          tyDS_X1 = MATH::F_DOT( tvDS, tgBX0.Query_AxisUnit1() );
    const TYPE                          tyDS_X2 = MATH::F_DOT( tvDS, tgBX0.Query_AxisUnit2() );

    T_(VECTOR,DIM)                      tvDN;

    tvDS = MATH::F_SETV<TYPE,DIM>(
        P::FSEL(tyD1_X0, tyDS_X0,-tyDS_X0),
        P::FSEL(tyD1_X1, tyDS_X1,-tyDS_X1),
        P::FSEL(tyD1_X2, tyDS_X2,-tyDS_X2)
    );

    tvDN = MATH::F_SETV<TYPE,DIM>( P::ABS(tyD1_X0), P::ABS(tyD1_X1), P::ABS(tyD1_X2) );

    // Calculate the distance and place of closest contact.

    TYPE                                   tyDistSq = TYPE(0.0);

    switch ((Near_Zero( tvD0.X() ) ? 0 : 1) + (Near_Zero( tvD0.Y() ) ? 0 : 2) + (Near_Zero( tvD0.Z() ) ? 0 : 4)) {
    case 7: { // (+,+,+)

        tyDistSq += Box_DoF3( ptyLN0, &tvDS, tvDN, tgBX0 ); 

        *ptyB0 = P::FSEL( tyD1_X0, tvDS.X(), -tvDS.X() );
        *ptyB1 = P::FSEL( tyD1_X1, tvDS.Y(), -tvDS.Y() );
        *ptyB2 = P::FSEL( tyD1_X2, tvDS.Z(), -tvDS.Z() );

        break;
    }
        
    case 6: { // (+,+,0)

        tyDistSq += Box_DoF2( ptyLN0, &tvDS, tvDN, 0,1,2, tgBX0 );

        const TYPE                          tyT2 = P::ABS( tvDS.Z() ) - tgBX0.Query_Extent2();
        const TYPE                          tyZ = P::FSEL( tyT2, P::Copy_Sign( tgBX0.Query_Extent2(), tvDS.Z() ), tvDS.Z() );

        tyDistSq += P::FSEL( tyT2, tyT2*tyT2, TYPE(0.0) );

        *ptyB0 = P::FSEL( tyD1_X0, tvDS.X(), -tvDS.X() );
        *ptyB1 = P::FSEL( tyD1_X1, tvDS.Y(), -tvDS.Y() );
        *ptyB2 = P::FSEL( tyD1_X2, tyZ, -tyZ );

        break;
    }

    case 5: { // (+,0,+)

        tyDistSq += Box_DoF2( ptyLN0, &tvDS, tvDN, 0,2,1, tgBX0 );

        const TYPE                          tyT1 = P::ABS( tvDS.Y() ) - tgBX0.Query_Extent1();
        const TYPE                          tyY = P::FSEL( tyT1, P::Copy_Sign( tgBX0.Query_Extent1(), tvDS.Y() ), tvDS.Y() );

        tyDistSq += P::FSEL( tyT1, tyT1*tyT1, TYPE(0.0) );

        *ptyB0 = P::FSEL( tyD1_X0, tvDS.X(), -tvDS.X() );
        *ptyB1 = P::FSEL( tyD1_X1, tyY, -tyY );
        *ptyB2 = P::FSEL( tyD1_X2, tvDS.Z(), -tvDS.Z() );

        break;
    }

    case 3: { // (0,+,+)

        tyDistSq += Box_DoF2( ptyLN0, &tvDS, tvDN, 1,2,0, tgBX0 );

        const TYPE                          tyT0 = P::ABS( tvDS.X() ) - tgBX0.Query_Extent0();
        const TYPE                          tyX = P::FSEL( tyT0, P::Copy_Sign( tgBX0.Query_Extent0(), tvDS.X() ), tvDS.X() );

        tyDistSq += P::FSEL( tyT0, tyT0*tyT0,TYPE(0.0) );

        *ptyB0 = P::FSEL( tyD1_X0, tyX, -tyX );
        *ptyB1 = P::FSEL( tyD1_X1, tvDS.Y(), -tvDS.Y() );
        *ptyB2 = P::FSEL( tyD1_X2, tvDS.Z(), -tvDS.Z() );

        break;
    }

    case 4: { // (+,0,0)

        const TYPE                          tyT1 = P::ABS( tvDS.Y() ) - tgBX0.Query_Extent1();
        const TYPE                          tyT2 = P::ABS( tvDS.Z() ) - tgBX0.Query_Extent2();
        const TYPE                          tyY = P::FSEL( tyT1, P::Copy_Sign( tgBX0.Query_Extent1(), tvDS.Y() ), tvDS.Y() );
        const TYPE                          tyZ = P::FSEL( tyT2, P::Copy_Sign( tgBX0.Query_Extent2(), tvDS.Z() ), tvDS.Z() );

        tyDistSq += P::FSEL( tyT1, tyT1*tyT1,TYPE(0.0) ) + P::FSEL( tyT2, tyT2*tyT2,TYPE(0.0) );

        *ptyB0 = TYPE(0.0);
        *ptyB1 = P::FSEL( tyD1_X1, tyY, -tyY );
        *ptyB2 = P::FSEL( tyD1_X2, tyZ, -tyZ );
        *ptyLN0 = -(tvDS.X() / tvDN.X());

        break;
    }

    case 2: { // (0,+,0)

        const TYPE                          tyT0 = P::ABS( tvDS.X() ) - tgBX0.Query_Extent0();
        const TYPE                          tyT2 = P::ABS( tvDS.Z() ) - tgBX0.Query_Extent2();
        const TYPE                          tyX = P::FSEL( tyT0, P::Copy_Sign( tgBX0.Query_Extent0(), tvDS.X() ), tvDS.X() );
        const TYPE                          tyZ = P::FSEL( tyT2, P::Copy_Sign( tgBX0.Query_Extent2(), tvDS.Z() ), tvDS.Z() );

        tyDistSq += P::FSEL( tyT0, tyT0*tyT0,TYPE(0.0) ) + P::FSEL( tyT2, tyT2*tyT2,TYPE(0.0) );

        *ptyB0 = P::FSEL( tyD1_X0, tyX, -tyX );
        *ptyB1 = TYPE(0.0);
        *ptyB2 = P::FSEL( tyD1_X2, tyZ, -tyZ );
        *ptyLN0 = -(tvDS.Y() / tvDN.Y());

        break;
    }

    case 1: { // (0,0,+)

        const TYPE                          tyT0 = P::ABS( tvDS.X() ) - tgBX0.Query_Extent0();
        const TYPE                          tyT1 = P::ABS( tvDS.Y() ) - tgBX0.Query_Extent1();
        const TYPE                          tyX = P::FSEL( tyT0, P::Copy_Sign( tgBX0.Query_Extent0(), tvDS.X() ), tvDS.X() );
        const TYPE                          tyY = P::FSEL( tyT1, P::Copy_Sign( tgBX0.Query_Extent1(), tvDS.Y() ), tvDS.Y() );

        tyDistSq += P::FSEL( tyT0, tyT0*tyT0,TYPE(0.0) ) + P::FSEL( tyT1, tyT1*tyT1,TYPE(0.0) );

        *ptyB0 = P::FSEL( tyD1_X0, tyX, -tyX );
        *ptyB1 = P::FSEL( tyD1_X1, tyY, -tyY );
        *ptyB2 = TYPE(0.0);
        *ptyLN0 = -(tvDS.Z() / tvDN.Z());

        break;
    }

    case 0: { // (0,0,0)
        const TYPE                          tyT0 = P::ABS( tvDS.X() ) - tgBX0.Query_Extent0();
        const TYPE                          tyT1 = P::ABS( tvDS.Y() ) - tgBX0.Query_Extent1();
        const TYPE                          tyT2 = P::ABS( tvDS.Z() ) - tgBX0.Query_Extent2();

        const TYPE                          tyX = P::FSEL( tyT0, P::Copy_Sign( tgBX0.Query_Extent0(), tvDS.X() ), tvDS.X() );
        const TYPE                          tyY = P::FSEL( tyT1, P::Copy_Sign( tgBX0.Query_Extent1(), tvDS.Y() ), tvDS.Y() );
        const TYPE                          tyZ = P::FSEL( tyT2, P::Copy_Sign( tgBX0.Query_Extent2(), tvDS.Z() ), tvDS.Z() );

        tyDistSq += P::FSEL( tyT0, tyT0*tyT0,TYPE(0.0) ) + P::FSEL( tyT1, tyT1*tyT1,TYPE(0.0) ) + P::FSEL( tyT2, tyT2*tyT2,TYPE(0.0) );

        *ptyB0 = P::FSEL( tyD1_X0, tyX, -tyX );
        *ptyB1 = P::FSEL( tyD1_X1, tyY, -tyY );
        *ptyB2 = P::FSEL( tyD1_X2, tyZ, -tyZ );
        *ptyLN0 = TYPE(0.0);

        break;
    }
    };

    if (bC0 && *ptyLN0 < TYPE(0.0))
    {
        *ptyLN0 = TYPE(0.0);
        return (F_ClosestSq( ptyB0,ptyB1,ptyB2, tgBX0, tvS0 ));
    };

    if (bC1 && *ptyLN0 > TYPE(1.0))
    {
        *ptyLN0 = TYPE(1.0);
        return (F_ClosestSq( ptyB0,ptyB1,ptyB2, tgBX0, MATH::F_ADD( tvS0, tvD0 ) ));
    };

    return (tyDistSq);
};


// ============================================================================================================================== //

// ---- F_Clip ------------------------------------------------------------------------------------------------------------------ //
//  -- Internal Function -- bC0, bC1 : Indicate the termination condition of the linear {bc0,bC1}
//
// Input:  tgBX0: Box primitive
// Input:  tvS0,tvD0: Origin and Direction for the Linear
// Output: tyLN0,tyLN1: Parametric parameter to generate the two points of the linear contained inside the clip space.
// Return: Result Code.
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM, bool bC0, bool bC1>
TgRESULT TTgCLP_BXLN<TYPE,DIM,bC0,bC1>::DO( TYPE *ptyLN0, TYPE *ptyLN1, CR_(BOX,DIM) tgBX0, M_(VECTOR,DIM) tvS0, M_(VECTOR,DIM) tvD0 )
{
    TgASSERT( tgBX0.Is_Valid() );

    T_(VECTOR,DIM)                      tvDS = MATH::F_SUB( tvS0, tgBX0.Query_Origin() );
    TYPE                                tyDS_N,tyD1_N;

    TYPE                                tyMin = -LIMITS<TYPE>::MAX;
    TYPE                                tyMax =  LIMITS<TYPE>::MAX;

    // Quick out - Does the linear exist outside of the clip region.

    tyDS_N = MATH::F_DOT(tgBX0.Query_AxisUnit0(),tvDS);
    tyD1_N = MATH::F_DOT(tgBX0.Query_AxisUnit0(),tvD0);

    if (bC0 && tyDS_N < -tgBX0.Query_Extent0())
    {
        if (tyD1_N < TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N < -tgBX0.Query_Extent0())))
        {
            return (TgE_NOINTERSECT);
        };
    }
    else if (bC0 && tyDS_N > tgBX0.Query_Extent0())
    {
        if (tyD1_N > TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N > tgBX0.Query_Extent0())))
        {
            return (TgE_NOINTERSECT);
        };
    };

    // Find the non-capped intersections of this linear with the two enclosing planes.

    if (tyD1_N < -LIMITS<TYPE>::EPSILON)
    {
        tyMin = P::FSEL( tyDS_N + tyD1_N*tyMin - tgBX0.Query_Extent0(), (tgBX0.Query_Extent0() - tyDS_N) / tyD1_N, tyMin );
        tyMax = P::FSEL( tyDS_N + tyD1_N*tyMax + tgBX0.Query_Extent0(), tyMax, -(tgBX0.Query_Extent0() + tyDS_N) / tyD1_N );
    }
    else if (tyD1_N > LIMITS<TYPE>::EPSILON)
    {
        tyMin = P::FSEL( tyDS_N + tyD1_N*tyMin + tgBX0.Query_Extent0(), tyMin, -(tgBX0.Query_Extent0() + tyDS_N) / tyD1_N );
        tyMax = P::FSEL( tyDS_N + tyD1_N*tyMax - tgBX0.Query_Extent0(), (tgBX0.Query_Extent0() - tyDS_N) / tyD1_N, tyMax );
    };

    // Quick out - Does the linear exist outside of the clip region.

    tyDS_N = MATH::F_DOT(tgBX0.Query_AxisUnit1(),tvDS);
    tyD1_N = MATH::F_DOT(tgBX0.Query_AxisUnit1(),tvD0);

    if (bC0 && tyDS_N < -tgBX0.Query_Extent1())
    {
        if (tyD1_N < TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N < -tgBX0.Query_Extent1())))
        {
            return (TgE_NOINTERSECT);
        };
    }
    else if (bC0 && tyDS_N > tgBX0.Query_Extent1())
    {
        if (tyD1_N > TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N > tgBX0.Query_Extent1())))
        {
            return (TgE_NOINTERSECT);
        };
    };

    // Find the non-capped intersections of this linear with the two enclosing planes.

    if (tyD1_N < -LIMITS<TYPE>::EPSILON)
    {
        tyMin = P::FSEL( tyDS_N + tyD1_N*tyMin - tgBX0.Query_Extent1(), (tgBX0.Query_Extent1() - tyDS_N) / tyD1_N, tyMin );
        tyMax = P::FSEL( tyDS_N + tyD1_N*tyMax + tgBX0.Query_Extent1(), tyMax, -(tgBX0.Query_Extent1() + tyDS_N) / tyD1_N );
    }
    else if (tyD1_N > LIMITS<TYPE>::EPSILON)
    {
        tyMin = P::FSEL( tyDS_N + tyD1_N*tyMin + tgBX0.Query_Extent1(), tyMin, -(tgBX0.Query_Extent1() + tyDS_N) / tyD1_N );
        tyMax = P::FSEL( tyDS_N + tyD1_N*tyMax - tgBX0.Query_Extent1(), (tgBX0.Query_Extent1() - tyDS_N) / tyD1_N, tyMax );
    };

    // Quick out - Does the linear exist outside of the clip region.

    tyDS_N = MATH::F_DOT(tgBX0.Query_AxisUnit2(),tvDS);
    tyD1_N = MATH::F_DOT(tgBX0.Query_AxisUnit2(),tvD0);

    if (bC0 && tyDS_N < -tgBX0.Query_Extent2())
    {
        if (tyD1_N < TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N < -tgBX0.Query_Extent2())))
        {
            return (TgE_NOINTERSECT);
        };
    }
    else if (bC0 && tyDS_N > tgBX0.Query_Extent2())
    {
        if (tyD1_N > TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N > tgBX0.Query_Extent2())))
        {
            return (TgE_NOINTERSECT);
        };
    };

    // Find the non-capped intersections of this linear with the two enclosing planes.

    if (tyD1_N < -LIMITS<TYPE>::EPSILON)
    {
        tyMin = P::FSEL( tyDS_N + tyMin*tyD1_N - tgBX0.Query_Extent2(), (tgBX0.Query_Extent2() - tyDS_N) / tyD1_N, tyMin );
        tyMax = P::FSEL( tyDS_N + tyMax*tyD1_N + tgBX0.Query_Extent2(), tyMax, -(tgBX0.Query_Extent2() + tyDS_N) / tyD1_N );
    }
    else if (tyD1_N > LIMITS<TYPE>::EPSILON)
    {
        tyMin = P::FSEL( tyDS_N + tyMin*tyD1_N + tgBX0.Query_Extent2(), tyMin, -(tgBX0.Query_Extent2() + tyDS_N) / tyD1_N );
        tyMax = P::FSEL( tyDS_N + tyMax*tyD1_N - tgBX0.Query_Extent2(), (tgBX0.Query_Extent2() - tyDS_N) / tyD1_N, tyMax );
    };

    // Return the results - capped to the linear legal region.

    if (tyMin > tyMax || tyMin <= -LIMITS<TYPE>::MAX || tyMax >= LIMITS<TYPE>::MAX)
    {
        return (TgE_FAIL);
    };

    if (bC0)
    {
        *ptyLN0 = P::FSEL( *ptyLN0, *ptyLN0, TYPE(0.0) );
        *ptyLN1 = P::FSEL( *ptyLN1, *ptyLN1, TYPE(0.0) );
    };

    if (bC1)
    {
        *ptyLN0 = P::FSEL( *ptyLN0 - TYPE(1.0), *ptyLN0, TYPE(1.0) );
        *ptyLN1 = P::FSEL( *ptyLN1 - TYPE(1.0), *ptyLN1, TYPE(1.0) );
    };

    return (TgS_OK);
};


// ============================================================================================================================== //

    template struct TTgCSQ_BXLN<TgFLOAT32,4,0,0>;
    template struct TTgCSQ_BXLN<TgFLOAT32,4,1,0>;
    template struct TTgCSQ_BXLN<TgFLOAT32,4,1,1>;

    template struct TTgCLP_BXLN<TgFLOAT32,4,0,0>;
    template struct TTgCLP_BXLN<TgFLOAT32,4,1,0>;
    template struct TTgCLP_BXLN<TgFLOAT32,4,1,1>;

// ============================================================================================================================== //

}; // END COL //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}; // END TGS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[an error occurred while processing this directive]