      module face_class 
        use face_abs_class
        implicit none
        private
        public :: face

        ! Type def for the stack data
        type, extends(face_abs) :: face
           private
           integer (kind=8) :: hi,lo
           contains
             private
             procedure         :: face_equal
             procedure         :: face_le
             procedure         :: face_assign
             procedure, public :: face_write
        end type face

        interface face
          module procedure make_face
        end interface face

        contains

        ! overloaded .eq.
        logical function face_equal(a,b)
           implicit none
           class(face), intent(in)     :: a
           class(face_abs), intent(in) :: b

           face_equal = .false.

           select type (b)
            type is (face)         
             if (a%lo.eq.b%lo .and. a%hi.eq.b%hi) 
     &            face_equal=.true.
           end select
        end function face_equal

        ! overloaded .le.
        logical function face_le(a,b)
           implicit none
           class(face), intent(in)     :: a
           class(face_abs), intent(in) :: b

           face_le = .false.

           select type (b)
            type is (face)         
             if ( (a%lo.le.b%lo .and. a%hi.eq.b%hi)
     &        .or. (a%hi.lt.b%hi) ) face_le=.true.
           end select
        end function face_le

        ! overloaded =
        subroutine face_assign(a,b)
            implicit none
            class(face), intent(out)    :: a
            class(face_abs), intent(in) :: b
            select type (b)
              type is (face)
                a%lo = b%lo
                a%hi = b%hi
            end select 
        end subroutine face_assign

        ! output
        subroutine face_write(a)
          implicit none
          class(face), intent(in) :: a
          write(*,*) a%hi,a%lo
        end subroutine face_write
 

        ! Constructor 
        type(face) function make_face(a,b,c,d)
          use mergesort_class
          implicit none
          integer, intent(in)           :: a,b,c
          integer, optional, intent(in) :: d
          integer                       :: m(4)
          integer (kind=8)              :: n(4)

          n(1) = int8(a)
          n(2) = int8(b)
          n(3) = int8(c)

          if (present(d)) then
            n(4) = int8(d)
          else
            n(4)= int8(0)
          end if

          call mergesort(n,4,m)

          call mvbits(n(4),0,32,make_face%lo,0)
          call mvbits(n(3),0,32,make_face%lo,32)
          call mvbits(n(2),0,32,make_face%hi,0)
          call mvbits(n(1),0,32,make_face%hi,32)
        end function make_face

      end module face_class
