*> \brief \b ZLAQGE scales a general rectangular matrix, using row and column scaling factors computed by sgeequ.
*
*  =========== DOCUMENTATION ===========
*
* Online html documentation available at
*            http://www.netlib.org/lapack/explore-html/
*
*> \htmlonly
*> Download ZLAQGE + dependencies
*>
*> [TGZ]
*>
*> [ZIP]
*>
*> [TXT]
*> \endhtmlonly
*
*  Definition:
*  ===========
*
*       SUBROUTINE ZLAQGE( M, N, A, LDA, R, C, ROWCND, COLCND, AMAX,
*                          EQUED )
*
*       .. Scalar Arguments ..
*       CHARACTER          EQUED
*       INTEGER            LDA, M, N
*       DOUBLE PRECISION   AMAX, COLCND, ROWCND
*       ..
*       .. Array Arguments ..
*       DOUBLE PRECISION   C( * ), R( * )
*       COMPLEX*16         A( LDA, * )
*       ..
*
*
*> \par Purpose:
*  =============
*>
*> \verbatim
*>
*> ZLAQGE equilibrates a general M by N matrix A using the row and
*> column scaling factors in the vectors R and C.
*> \endverbatim
*
*  Arguments:
*  ==========
*
*> \param[in] M
*> \verbatim
*>          M is INTEGER
*>          The number of rows of the matrix A.  M >= 0.
*> \endverbatim
*>
*> \param[in] N
*> \verbatim
*>          N is INTEGER
*>          The number of columns of the matrix A.  N >= 0.
*> \endverbatim
*>
*> \param[in,out] A
*> \verbatim
*>          A is COMPLEX*16 array, dimension (LDA,N)
*>          On entry, the M by N matrix A.
*>          On exit, the equilibrated matrix.  See EQUED for the form of
*>          the equilibrated matrix.
*> \endverbatim
*>
*> \param[in] LDA
*> \verbatim
*>          LDA is INTEGER
*>          The leading dimension of the array A.  LDA >= max(M,1).
*> \endverbatim
*>
*> \param[in] R
*> \verbatim
*>          R is DOUBLE PRECISION array, dimension (M)
*>          The row scale factors for A.
*> \endverbatim
*>
*> \param[in] C
*> \verbatim
*>          C is DOUBLE PRECISION array, dimension (N)
*>          The column scale factors for A.
*> \endverbatim
*>
*> \param[in] ROWCND
*> \verbatim
*>          ROWCND is DOUBLE PRECISION
*>          Ratio of the smallest R(i) to the largest R(i).
*> \endverbatim
*>
*> \param[in] COLCND
*> \verbatim
*>          COLCND is DOUBLE PRECISION
*>          Ratio of the smallest C(i) to the largest C(i).
*> \endverbatim
*>
*> \param[in] AMAX
*> \verbatim
*>          AMAX is DOUBLE PRECISION
*>          Absolute value of largest matrix entry.
*> \endverbatim
*>
*> \param[out] EQUED
*> \verbatim
*>          EQUED is CHARACTER*1
*>          Specifies the form of equilibration that was done.
*>          = 'N':  No equilibration
*>          = 'R':  Row equilibration, i.e., A has been premultiplied by
*>                  diag(R).
*>          = 'C':  Column equilibration, i.e., A has been postmultiplied
*>                  by diag(C).
*>          = 'B':  Both row and column equilibration, i.e., A has been
*>                  replaced by diag(R) * A * diag(C).
*> \endverbatim
*
*> \par Internal Parameters:
*  =========================
*>
*> \verbatim
*>  THRESH is a threshold value used to decide if row or column scaling
*>  should be done based on the ratio of the row or column scaling
*>  factors.  If ROWCND < THRESH, row scaling is done, and if
*>  COLCND < THRESH, column scaling is done.
*>
*>  LARGE and SMALL are threshold values used to decide if row scaling
*>  should be done based on the absolute size of the largest matrix
*>  element.  If AMAX > LARGE or AMAX  \endverbatim
*
*  Authors:
*  ========
*
*> \author Univ. of Tennessee
*> \author Univ. of California Berkeley
*> \author Univ. of Colorado Denver
*> \author NAG Ltd.
*
*> \date September 2012
*
*> \ingroup complex16GEauxiliary
*
*  =====================================================================
      SUBROUTINE ZLAQGE( M, N, A, LDA, R, C, ROWCND, COLCND, AMAX,
     $                   EQUED )
*
*  -- LAPACK auxiliary routine (version 3.4.2) --
*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
*     September 2012
*
*     .. Scalar Arguments ..
      CHARACTER          EQUED
      INTEGER            LDA, M, N
      DOUBLE PRECISION   AMAX, COLCND, ROWCND
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION   C( * ), R( * )
      COMPLEX*16         A( LDA, * )
*     ..
*
*  =====================================================================
*
*     .. Parameters ..
      DOUBLE PRECISION   ONE, THRESH
      PARAMETER          ( ONE = 1.0D+0, THRESH = 0.1D+0 )
*     ..
*     .. Local Scalars ..
      INTEGER            I, J
      DOUBLE PRECISION   CJ, LARGE, SMALL
*     ..
*     .. External Functions ..
      DOUBLE PRECISION   DLAMCH
      EXTERNAL           DLAMCH
*     ..
*     .. Executable Statements ..
*
*     Quick return if possible
*
      IF( M.LE.0 .OR. N.LE.0 ) THEN
         EQUED = 'N'
         RETURN
      END IF
*
*     Initialize LARGE and SMALL.
*
      SMALL = DLAMCH( 'Safe minimum' ) / DLAMCH( 'Precision' )
      LARGE = ONE / SMALL
*
      IF( ROWCND.GE.THRESH .AND. AMAX.GE.SMALL .AND. AMAX.LE.LARGE )
     $     THEN
*
*        No row scaling
*
         IF( COLCND.GE.THRESH ) THEN
*
*           No column scaling
*
            EQUED = 'N'
         ELSE
*
*           Column scaling
*
            DO 20 J = 1, N
               CJ = C( J )
               DO 10 I = 1, M
                  A( I, J ) = CJ*A( I, J )
   10          CONTINUE
   20       CONTINUE
            EQUED = 'C'
         END IF
      ELSE IF( COLCND.GE.THRESH ) THEN
*
*        Row scaling, no column scaling
*
         DO 40 J = 1, N
            DO 30 I = 1, M
               A( I, J ) = R( I )*A( I, J )
   30       CONTINUE
   40    CONTINUE
         EQUED = 'R'
      ELSE
*
*        Row and column scaling
*
         DO 60 J = 1, N
            CJ = C( J )
            DO 50 I = 1, M
               A( I, J ) = CJ*R( I )*A( I, J )
   50       CONTINUE
   60    CONTINUE
         EQUED = 'B'
      END IF
*
      RETURN
*
*     End of ZLAQGE
*
      END


!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++!
!                          Futility Development Group                          !
!                             All rights reserved.                             !
!                                                                              !
! Futility is a jointly-maintained, open-source project between the University !
! of Michigan and Oak Ridge National Laboratory.  The copyright and license    !
! can be found in LICENSE.txt in the head directory of this repository.        !
!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++!
PROGRAM testGeom_Box
#include "UnitTest.h"
USE ISO_FORTRAN_ENV
USE UnitTest
USE IntrType
USE Constants_Conversion
USE ParameterLists
USE Geom

IMPLICIT NONE

TYPE(PointType) :: point
TYPE(PointType) :: points(2),points2(2),points3(2)
TYPE(LineType) :: line1,lines(2)
TYPE(OBBoxType) :: box,box2,boxs(2)
REAL(SRK) :: e_2d(2),e_3d(3),u1_2d(2),u2_2d(2),u3_2d(2)
REAL(SRK) :: u1_3d(3),u2_3d(3),u3_3d(3)
LOGICAL(SBK) :: bool

CREATE_TEST('Test Geom')
CALL eParams%setQuietMode(.TRUE.)
CALL eParams%setStopOnError(.FALSE.)

REGISTER_SUBTEST('Test OB Box',TestOBBox)
REGISTER_SUBTEST('Test AB Box',testABBox)

FINALIZE_TEST()
!
!===============================================================================
CONTAINS
!
!-------------------------------------------------------------------------------
SUBROUTINE TestOBBox
!Test for clear
  COMPONENT_TEST('%clear()')
  CALL point%init(DIM=3,X=0.1_SRK,Y=0.2_SRK,Z=0.3_SRK)
  box%p0=point
!      ALLOCATE(box%u(3,3),box%e(3))
  box%u(1,:)=(/0.5_SRK,0.5_SRK,0._SRK/)
  box%u(2,:)=(/-0.5_SRK,0.5_SRK,0._SRK/)
  box%u(3,:)=(/0._SRK,0._SRK,1._SRK/)
  box%e=1._SRK
  CALL box%clear()

  bool = .NOT.(ANY(box%u /= 0.0_SRK) .OR. ANY(box%e /= 0.0_SRK) &
      .OR. box%p0%dim /= 0 .OR. ALLOCATED(box%p0%coord))
  ASSERT(bool,'box%clear()')

!Test for set
  COMPONENT_TEST('%set()')
  !input check
  CALL box%clear()
  CALL point%clear()
  CALL point%init(DIM=3,X=0.1_SRK,Y=0.2_SRK,Z=0.3_SRK)
  CALL box%set(point,(/1._SRK,1._SRK,1._SRK/),(/1._SRK,0._SRK,0._SRK/), &
      (/0._SRK,1._SRK,1._SRK/),(/0._SRK,0._SRK,0._SRK/))
  CALL box%set(point,(/1._SRK,1._SRK/),(/1._SRK,0._SRK/), &
      (/0._SRK,1._SRK/),(/0._SRK,1._SRK/))
  CALL box%set(point,(/1._SRK,1._SRK,1._SRK/),(/1._SRK,0._SRK,1._SRK/), &
      (/0._SRK,1._SRK,1._SRK/))
  CALL box%set(point,(/1._SRK,1._SRK/),(/1._SRK,0._SRK/),(/1._SRK,1._SRK/))
  CALL box%set(point,(/1._SRK,2._SRK/),(/0._SRK,0._SRK/),(/1._SRK,0._SRK/))
  CALL point%clear()
  CALL point%init(DIM=2,X=1._SRK,Y=1._SRK)
  CALL box%set(point,(/-1._SRK,2._SRK/),(/0._SRK,0._SRK/),(/1._SRK,0._SRK/))
  CALL box%set(point,(/1._SRK,-2._SRK/),(/0._SRK,0._SRK/),(/1._SRK,0._SRK/))
  !Test for set 2D
  CALL point%clear()
  CALL box%clear()
  CALL point%init(DIM=2,X=1._SRK,Y=1._SRK)
  e_2d=(/SQRT(2._SRK),2*SQRT(2._SRK)/)
  u1_2d=(/1._SRK,1._SRK/)
  u2_2d=(/-1._SRK,1._SRK/)
  u3_2d=(/-1._SRK,1._SRK/)
  CALL box%set(point,e_2d,u1_2d,u2_2d,u3_2d)
  bool = .NOT.(box%p0 /= point .OR. ANY(box%e(1:2) /= e_2d) &
      .OR. .NOT.(ALL(box%u(1:2,1) .APPROXEQ. u1_2d/SQRT(2._SRK))) &
      .OR. .NOT.(ALL(box%u(1:2,2) .APPROXEQ. u2_2d/SQRT(2._SRK))))
  ASSERT(bool, 'box%set(...)')
  !Test for set 3D
  CALL point%clear()
  CALL box%clear()
  CALL point%init(DIM=3,X=1._SRK,Y=1._SRK,Z=1._SRK)
  e_3d=(/SQRT(2._SRK),2*SQRT(2._SRK),1._SRK/)
  u1_3d=(/1._SRK,1._SRK,0._SRK/)
  u2_3d=(/-1._SRK,1._SRK,0._SRK/)
  u3_3d=(/0._SRK,0._SRK,2._SRK/)
  CALL box%set(point,e_3d,u1_3d,u2_3d,u3_3d)
  bool = .NOT.(box%p0 /= point .OR. ANY(box%e /= e_3d) &
      .OR. ANY(.NOT.(box%u(:,1) .APPROXEQ. u1_3d/SQRT(2._SRK))) &
      .OR. ANY(.NOT.(box%u(:,2) .APPROXEQ. u2_3d/SQRT(2._SRK))) &
      .OR. ANY(.NOT.(box%u(:,3) .APPROXEQ. u3_3d*0.5_SRK)) )
  ASSERT(bool, 'box%set(...)')
  CALL box%clear()

!Test for intersection
  COMPONENT_TEST('%intersectLine()')
  !Bad input
  CALL box%clear()
  CALL line1%clear()
  CALL point%clear()
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL point%init(DIM=2,X=1._SRK,Y=1._SRK)
  u1_2d=(/1._SRK,1._SRK/)
  u2_2d=(/-1._SRK,1._SRK/)
  CALL box%set(point,(/1._SRK,1._SRK/),u1_2d,u2_2d)

  CALL points(1)%init(COORD=(/0._SRK,0._SRK,0._SRK/))
  CALL points(2)%init(COORD=(/0._SRK,8._SRK,0._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  !Test for intersection 2D
  CALL box%clear()
  CALL point%clear()
  CALL point%init(DIM=2,X=1._SRK,Y=1._SRK)
  u1_2d=(/1._SRK,1._SRK/)
  u2_2d=(/-1._SRK,1._SRK/)
  CALL box%set(point,(/SQRT(2._SRK),8._SRK/),u1_2d,u2_2d)

  !Normal
  CALL line1%clear()
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/0._SRK,0._SRK/))
  CALL points(2)%init(COORD=(/0._SRK,8._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(ANY(points2(1)%coord /= (/0._SRK,2._SRK/)) &
      .OR. ANY(points2(2)%coord /= (/0._SRK,4._SRK/)))
  ASSERT(bool, 'box%intersectLine(...)')
  !Parallel
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/1._SRK,1._SRK/))
  CALL points(2)%init(COORD=(/2._SRK,2._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(ANY(points2(1)%coord /= (/1._SRK,1._SRK/)) &
      .OR. ANY(points2(2)%coord /= (/2._SRK,2._SRK/)))
  ASSERT(bool, 'box%intersectLine(...)')

  !one point: overlap
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/2._SRK,0._SRK/))
  CALL points(2)%init(COORD=(/2._SRK,2._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(.NOT.(ANY(points2(1)%coord .APPROXEQ. (/2._SRK,2._SRK/))) &
      .OR. .NOT.(ANY(points2(2)%coord .APPROXEQ. (/2._SRK,2._SRK/))))
  ASSERT(bool, 'box%intersectLine(...)')
  !one point

  !Now the intersection method of the line and box object takes the line as
  !an infinit line instead of a segment because of the requirement in modular
  !rays type. Maybe an option could be set to specify whether the line is
  !infinit or finit. So the test is left here to be used then.

  !CALL line1%clear()
  !CALL points(1)%clear()
  !CALL points(2)%clear()
  !CALL points(1)%init(COORD=(/0._SRK,0._SRK/))
  !CALL points(2)%init(COORD=(/0._SRK,3._SRK/))
  !CALL line1%set(points(1),points(2))
  !
  !CALL points2(1)%clear()
  !CALL points2(2)%clear()
  !CALL box%intersectLine(line1,points2(1),points2(2))
  !IF(ANY(points2(1)%coord /= (/0._SRK,2._SRK/)) &
  !  .OR. points2(2)%dim /= -3) THEN
  !  WRITE(*,*) 'CALL box%intersectLine(...) FAILED! 2D'
  !  STOP 666
  !ENDIF

  !No point
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/3._SRK,0._SRK/))
  CALL points(2)%init(COORD=(/3._SRK,2._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(points2(1)%dim /= -3 .OR. points2(2)%dim /= -3)
  ASSERT(bool, 'box%intersectLine(...)')

  !Test for intersection (3D normal box)
  CALL box%clear()
  CALL point%clear()
  CALL point%init(DIM=3,X=1._SRK,Y=1._SRK,Z=0._SRK)
  u1_3d=(/1._SRK,1._SRK,0._SRK/)
  u2_3d=(/-1._SRK,1._SRK,0._SRK/)
  u3_3d=(/0._SRK,0._SRK,1._SRK/)
  CALL box%set(point,(/SQRT(2._SRK),8._SRK,2._SRK/),u1_3d,u2_3d,u3_3d)

  !Normal
  CALL line1%clear()
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/0._SRK,0._SRK,1._SRK/))
  CALL points(2)%init(COORD=(/0._SRK,8._SRK,1._SRK/))
  CALL line1%set(points(2),points(1))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(ANY(.NOT.(points2(2)%coord .APPROXEQ. (/0._SRK,2._SRK,1._SRK/))) &
      .OR. ANY(.NOT.(points2(1)%coord .APPROXEQ. (/0._SRK,4._SRK,1._SRK/))))
  ASSERT(bool, 'box%intersectLine(...)')

  !Parallel
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/1._SRK,1._SRK,1._SRK/))
  CALL points(2)%init(COORD=(/2._SRK,2._SRK,1._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(ANY(points2(1)%coord /= (/1._SRK,1._SRK,1._SRK/)) &
      .OR. ANY(points2(2)%coord /= (/2._SRK,2._SRK,1._SRK/)))
  ASSERT(bool, 'box%intersectLine(...)')

  !one point: overlap
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/2._SRK,0._SRK,1._SRK/))
  CALL points(2)%init(COORD=(/2._SRK,2._SRK,1._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(.NOT.(ANY(points2(1)%coord .APPROXEQ. (/2._SRK,2._SRK,1._SRK/))) &
      .OR. .NOT.(ANY(points2(2)%coord .APPROXEQ. (/2._SRK,2._SRK,1._SRK/))))
  ASSERT(bool, 'box%intersectLine(...)')

  !one point
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/0._SRK,0._SRK,1._SRK/))
  CALL points(2)%init(COORD=(/0._SRK,3._SRK,1._SRK/))
  CALL line1%set(points(1),points(2))

  !CALL points2(1)%clear()
  !CALL points2(2)%clear()
  !CALL box%intersectLine(line1,points2(1),points2(2))
  !IF(.NOT.(ANY(points2(1)%coord .APPROXEQ. (/0._SRK,2._SRK,1._SRK/))) &
  !  .OR. points2(2)%dim /= -3) THEN
  !  WRITE(*,*) 'CALL box%intersectLine(...) FAILED! 3D'
  !  STOP 666
  !ENDIF

  !Test for intersection (3D box: one extention is zero)
  CALL box%clear()
  CALL point%clear()
  CALL point%init(DIM=3,X=1._SRK,Y=1._SRK,Z=0._SRK)
  u1_3d=(/1._SRK,1._SRK,0._SRK/)
  u2_3d=(/-1._SRK,1._SRK,0._SRK/)
  u3_3d=(/0._SRK,0._SRK,1._SRK/)
  CALL box%set(point,(/SQRT(2._SRK),8._SRK,0._SRK/),u1_3d,u2_3d,u3_3d)

  !one point
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/0._SRK,3._SRK,0._SRK/))
  CALL points(2)%init(COORD=(/0._SRK,3._SRK,1._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(.NOT.(ANY(points2(1)%coord .APPROXEQ. (/0._SRK,3._SRK,0._SRK/))) &
      .OR. .NOT.(ANY(points2(2)%coord .APPROXEQ. (/0._SRK,3._SRK,0._SRK/))))
  ASSERT(bool, 'box%intersectLine(...)')

  !No point
  CALL points(1)%clear()
  CALL points(2)%clear()
  CALL points(1)%init(COORD=(/0._SRK,1._SRK,0._SRK/))
  CALL points(2)%init(COORD=(/0._SRK,1._SRK,1._SRK/))
  CALL line1%set(points(1),points(2))

  CALL points2(1)%clear()
  CALL points2(2)%clear()
  CALL box%intersectLine(line1,points2(1),points2(2))
  bool = .NOT.(points2(1)%dim /= -3 .AND. points2(2)%dim /= -3)
  ASSERT(bool, 'box%intersectLine(...)')

!
!Test hasPoint
  COMPONENT_TEST('%inside()')
  CALL box%clear()
  CALL point%clear()
  CALL point%init(DIM=2,X=0.0_SRK,Y=0.0_SRK)
  u1_2d=(/1.0_SRK,0.0_SRK/)
  u2_2d=(/0.0_SRK,1.0_SRK/)
  CALL box%set(point,(/4.0_SRK,4.0_SRK/),u1_2d,u2_2d)
  CALL point%clear()
  CALL point%init(DIM=2,X=2.5_SRK,Y=1.6_SRK)
  ASSERT(box%inside(point),'%hasPoint')
  CALL point%clear()
  CALL point%init(DIM=2,X=-10.0_SRK,Y=-0.5_SRK)
  ASSERT(.NOT.box%inside(point),'%hasPoint')

  CALL box%clear()
  CALL point%clear()
  CALL point%init(DIM=2,X=0.5_SRK,Y=0.5_SRK)
  u1_2d=(/1.0_SRK,1.0_SRK/)
  u2_2d=(/-1.0_SRK,1.0_SRK/)
  CALL box%set(point,(/4.0_SRK,4.0_SRK/),u1_2d,u2_2d)
  CALL point%clear()
  CALL point%init(DIM=2,X=0.5_SRK,Y=1.6_SRK)
  ASSERT(box%inside(point),'%hasPoint')
  CALL point%clear()
  CALL point%init(DIM=2,X=0.0_SRK,Y=-0.5_SRK)
  ASSERT(.NOT.box%inside(point),'%hasPoint')

  !Test for assignment operation
  COMPONENT_TEST('ASSIGNMENT(=)')
  box2=box
  ASSERT(ALL(box%u == box2%u),'box%u assignment equivalence')
  ASSERT(ALL(box%e == box2%e),'box%e assignment equivalence')
  ASSERT(box%p0 == box2%p0,'box%p0 assignment equivalence')

  !Test for equivalence operation (implicitly tests assignment operation)
  COMPONENT_TEST('OPERATOR(==)')
  box2=box
  ASSERT(box == box2,'box equivalence')
  box2%u(:,1)=(/0.0_SRK,1.0_SRK,0.0_SRK/)
  ASSERT(.NOT.(box == box2),'box non-equivalence')
!
!Test for clear
  COMPONENT_TEST('Elemental %clear()')
  CALL boxs(1)%clear()
  CALL boxs(2)%clear()
  CALL point%clear()
  CALL point%init(DIM=2,X=1._SRK,Y=1._SRK)
  u1_2d=(/1._SRK,1._SRK/)
  u2_2d=(/-1._SRK,1._SRK/)
  CALL boxs(1)%set(point,(/SQRT(2._SRK),8._SRK/),u1_2d,u2_2d)
  boxs(2)=boxs(1)
  CALL boxs%clear()

  bool = .NOT.(ANY(boxs(1)%u /= 0.0_SRK).OR. ANY(boxs(1)%e /= 0.0_SRK) &
      .OR. boxs(1)%p0%dim /= 0 .OR. ALLOCATED(boxs(1)%p0%coord) &
      .OR. ANY(boxs(2)%u /= 0.0_SRK).OR. ANY(boxs(2)%e /= 0.0_SRK) &
      .OR. boxs(2)%p0%dim /= 0 .OR. ALLOCATED(boxs(2)%p0%coord))
  ASSERT(bool, 'box%clear()')

!Test for intersection
  COMPONENT_TEST('Elemental %intersectLine()')
  CALL boxs(1)%set(point,(/SQRT(2._SRK),8._SRK/),u1_2d,u2_2d)
  boxs(2)=boxs(1)

  CALL lines%clear()
  CALL points%clear()
  CALL points(1)%init(COORD=(/0._SRK,0._SRK/))
  CALL points(2)%init(COORD=(/0._SRK,8._SRK/))
  CALL lines(1)%set(points(1),points(2))
  lines(2)=lines(1)

  CALL points2%clear()
  CALL points3%clear()
  CALL boxs%intersectLine(lines,points2,points3)
  bool = .NOT.(.NOT.(ANY(points2(1)%coord .APPROXEQ. (/0._SRK,2._SRK/))) &
      .OR. .NOT.(ANY(points3(1)%coord .APPROXEQ. (/0._SRK,4._SRK/))) &
      .OR. .NOT.(ANY(points2(2)%coord .APPROXEQ. (/0._SRK,2._SRK/))) &
      .OR. .NOT.(ANY(points3(2)%coord .APPROXEQ. (/0._SRK,4._SRK/))))
  ASSERT(bool, 'box%intersectLine(...)')
ENDSUBROUTINE
!
!-------------------------------------------------------------------------------
SUBROUTINE testABBox()
  TYPE(PointType) :: point
  TYPE(ABBoxType) :: box

  ALLOCATE(point%coord(3))

  COMPONENT_TEST('Init')
  CALL box%set(0.0_SRK,1.0_SRK,0.0_SRK,3.0_SRK)
  ASSERT_APPROXEQ(box%xMin,0.0_SRK,'%xMin')
  ASSERT_APPROXEQ(box%xMax,1.0_SRK,'%xMax')
  ASSERT_APPROXEQ(box%yMin,0.0_SRK,'%yMin')
  ASSERT_APPROXEQ(box%yMax,3.0_SRK,'%yMax')
  ASSERT_APPROXEQ(box%zMin,0.0_SRK,'%zMin')
  ASSERT_APPROXEQ(box%zMax,0.0_SRK,'%zMax')
  ASSERT(box%isSet,'%isSet')
  ASSERT(box%isOrigin,'%isOrigin')
  ASSERT(.NOT.box%is3D,'%is3D')

  CALL box%clear()
  CALL box%set(1.0_SRK,2.0_SRK,3.0_SRK,4.0_SRK,5.0_SRK,6.0_SRK)
  ASSERT_APPROXEQ(box%xMin,1.0_SRK,'%xMin')
  ASSERT_APPROXEQ(box%xMax,2.0_SRK,'%xMax')
  ASSERT_APPROXEQ(box%yMin,3.0_SRK,'%yMin')
  ASSERT_APPROXEQ(box%yMax,4.0_SRK,'%yMax')
  ASSERT_APPROXEQ(box%zMin,5.0_SRK,'%zMin')
  ASSERT_APPROXEQ(box%zMax,6.0_SRK,'%zMax')
  ASSERT(box%isSet,'%isSet')
  ASSERT(.NOT.box%isOrigin,'%isOrigin')
  ASSERT(box%is3D,'%is3D')
  CALL box%clear()

  COMPONENT_TEST('Clear')
  box%xMin=1.0_SRK
  box%xMax=1.0_SRK
  box%yMin=1.0_SRK
  box%yMax=1.0_SRK
  box%zMin=1.0_SRK
  box%zMax=1.0_SRK
  box%isSet=.TRUE.
  box%isOrigin=.TRUE.
  box%is3D=.TRUE.
  CALL box%clear()
  ASSERT_APPROXEQ(box%xMin,0.0_SRK,'%xMin')
  ASSERT_APPROXEQ(box%xMax,0.0_SRK,'%xMax')
  ASSERT_APPROXEQ(box%yMin,0.0_SRK,'%yMin')
  ASSERT_APPROXEQ(box%yMax,0.0_SRK,'%yMax')
  ASSERT_APPROXEQ(box%zMin,0.0_SRK,'%zMin')
  ASSERT_APPROXEQ(box%zMax,0.0_SRK,'%zMax')
  ASSERT(.NOT.box%isSet,'%isSet')
  ASSERT(.NOT.box%isOrigin,'%isOrigin')
  ASSERT(.NOT.box%is3D,'%is3D')

  COMPONENT_TEST('Inside 2D/2D')
  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=2
  point%coord(1:2)=(/1.5_SRK,1.5_SRK/)
  ASSERT(box%inside(point),'%inside(...)')
  CALL box%clear()

  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=2
  point%coord(1:2)=(/2.5_SRK,1.5_SRK/)
  ASSERT(.NOT.box%inside(point),'%inside(...)')
  CALL box%clear()

  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=2
  point%coord(1:2)=(/0.5_SRK,1.5_SRK/)
  ASSERT(.NOT.box%inside(point),'%inside(...)')
  CALL box%clear()

  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=2
  point%coord(1:2)=(/1.5_SRK,2.5_SRK/)
  ASSERT(.NOT.box%inside(point),'%inside(...)')
  CALL box%clear()

  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=2
  point%coord(1:2)=(/1.5_SRK,0.5_SRK/)
  ASSERT(.NOT.box%inside(point),'%inside(...)')
  CALL box%clear()

  COMPONENT_TEST('Inside 3D/2D')
  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=3
  point%coord(:)=(/1.5_SRK,1.5_SRK,10.0_SRK/)
  ASSERT(box%inside(point),'%inside(...)')
  CALL box%clear()

  COMPONENT_TEST('Inside 3D/3D')
  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=3
  point%coord(:)=(/1.5_SRK,1.5_SRK,1.5_SRK/)
  ASSERT(box%inside(point),'%inside(...)')
  CALL box%clear()

  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=3
  point%coord(:)=(/1.5_SRK,1.5_SRK,2.5_SRK/)
  ASSERT(.NOT.box%inside(point),'%inside(...)')
  CALL box%clear()

  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=3
  point%coord(:)=(/1.5_SRK,1.5_SRK,0.5_SRK/)
  ASSERT(.NOT.box%inside(point),'%inside(...)')
  CALL box%clear()

  COMPONENT_TEST('Inside 2D/3D')
  CALL box%set(1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK,1.0_SRK,2.0_SRK)
  point%dim=2
  point%coord(:)=(/1.5_SRK,1.5_SRK,0.0_SRK/)
  ASSERT(box%inside(point),'%inside(...)')
  FINFO() 'point:',point%dim,point%coord
  FINFO() 'box:',box%xMin,box%xMax,box%yMin,box%yMax
  CALL box%clear()

  CALL point%clear()

ENDSUBROUTINE testABBox

ENDPROGRAM testGeom_Box