
module testsuite

  use oakleaf

  ! testing suite

  integer, parameter, private :: rp = selected_real_kind(15)

  type :: suite
     integer :: n
     real(rp) :: t,dt,s,sig
   contains
     procedure :: stdstat, stdwstat,robstat,robwstat,qtstat,poistat
  end type suite

contains

  subroutine stdstat(this,x)

    class(suite) :: this
    real(rp), dimension(:), intent(in) :: x

    associate( t => this%t, dt => this%dt, s => this%s, sig => this%sig, &
         n => this%n)

      n = size(x)
      t = sum(x) / n
      s = sqrt(sum( (x-t)**2 / (n-1) ))
      sig = s
      dt = s / sqrt(real(n))
      write(*,*) "Amean:",t,dt,sig,s
    end associate

  end subroutine stdstat


  subroutine stdwstat(this,x,dx)

    real(rp), dimension(:), intent(in) :: x,dx
    class(suite) :: this

    associate( t => this%t, dt => this%dt, s => this%s, sig => this%sig, &
         n => this%n)
      n = size(x)
      t = sum(x/dx**2)/sum(1/dx**2)
      s = sqrt(sum((t-x)**2/dx**2)/(n-1))
      sig = sqrt(sum((t-x)**2)/(n-1))
      dt = sqrt(s**2/sum(1/dx**2))
      write(*,*) "AWmean:",t,dt,sig,s
    end associate

  end subroutine stdwstat

  subroutine robstat(this,x)

    real(rp), dimension(:), intent(in) :: x
    class(suite) :: this

    logical :: reli
    real :: t1,t2

    associate( t => this%t, dt => this%dt, s => this%s, sig => this%sig, &
         n => this%n)
      call cpu_time(t1)
      call rmean(x,t,dt,sig,s,reli,verbose=.true.)
      call cpu_time(t2)

      write(*,*) "Rmean:",t,dt,sig,s,reli,nint(1e3*(t2-t1)),"ms"!,&
      !       abs(t - mean) < dt .and. abs(stdsig - s) < 0.1
    end associate

  end subroutine robstat

  subroutine robwstat(this,x,dx)

    real(rp), dimension(:), intent(in) :: x,dx
    class(suite) :: this

    logical :: reli
    real :: t1,t2

    associate( t => this%t, dt => this%dt, s => this%s, sig => this%sig, &
         n => this%n)
      call cpu_time(t1)
      call rmean(x,dx,t,dt,sig,s,reli,verbose=.true.)
      call cpu_time(t2)

      write(*,*) "RWmean:",t,dt,sig,s,reli,nint(1e3*(t2-t1)),"ms"!,&
      !       abs(t - mean) < dt .and. abs(stdsig - s) < 0.1
    end associate

  end subroutine robwstat

  subroutine qtstat(this,x)

    real(rp), dimension(:), intent(in) :: x
    class(suite) :: this

    associate( t => this%t, dt => this%dt, s => this%s, n => this%n)
      call qmean(x,t,s)
      write(*,*) "Qmean:",t,s
    end associate

  end subroutine qtstat

  subroutine poistat(this,x,dx,y,dy)

    real(rp), dimension(:), intent(in) :: x,dx,y,dy
    class(suite) :: this

    logical :: reli
    real :: t1,t2

    associate( t => this%t, dt => this%dt, s => this%s, n => this%n)
      call cpu_time(t1)
      call fmean(x,dx,y,dy,t,dt,s,reliable=reli,verbose=.true.)
      call cpu_time(t2)

      write(*,*) "fmean:",t,dt,s,reli,nint(1e3*(t2-t1)),"ms"
    end associate

  end subroutine poistat

  subroutine tester(proc)

    interface
       subroutine proc
       end subroutine proc
    end interface

    write(*,*) "Starting .."
    call proc
    write(*,*)
    write(*,*)

  end subroutine tester


end module testsuite
