module normbin2_mod


  use chain_mod
  use bin2
  use adj_mod

  implicit none

  integer,              private, save          :: n1, n2, nd
  real,                 private, save          :: xmin1, xmin2, d1, d2
  real, dimension(:,:), private, save, pointer :: xy
  real, dimension(:),   private, save, pointer :: fold, tmp

contains

  ! --------------------------------------------------------------------------------	
  subroutine normbin2_init( n10, n20, nd0, xmin10, xmin20, d10, d20, xy0 )
    integer                        :: n10, n20, nd0, stat
    real                           :: xmin10, xmin20, d10, d20
    real, dimension(:,:)           :: xy0
    real, dimension(:), pointer    :: ones

    allocate( tmp(n1*n2) )
    allocate( xy(nd0,2) );  xy = xy0
    n1=n10;  n2=n20;  d1=d10;  d2=d20
    xmin1=xmin10;  xmin2=xmin20
    nd = nd0

    allocate( tmp(n1*n2) )

    call bin2_init( n1, n2, xmin1, d1, xmin2, d2, xy )

    allocate( fold(n1*n2), ones(nd) )
    ones = 1.0; fold = 0.0
    stat = bin2_lop( .true., .false., fold, ones )
    deallocate( ones)

  end subroutine normbin2_init
  ! --------------------------------------------------------------------------------	

  ! --------------------------------------------------------------------------------	
  integer function normbin2_lop( adj, add, gridded, data )
    integer                        :: stat
    logical                        :: adj, add
    real, dimension(:)             :: data, gridded

    call chain( bin2_lop, foldnorm_lop, adj, add, gridded, data, tmp )

    normbin2_lop = 0
  end function normbin2_lop
  ! --------------------------------------------------------------------------------	

  ! --------------------------------------------------------------------------------	
  integer function foldnorm_lop( adj, add, model, data )
    integer                        :: stat
    logical                        :: adj, add
    real, dimension(:)             :: data, model

    call adjnull( adj, add, model, data)

    if( adj) then
       where(fold > 0) model = model + data/fold
    else
       where(fold > 0) data = data + model/fold
    end if

    foldnorm_lop = 0

  end function foldnorm_lop

  ! --------------------------------------------------------------------------------	
  subroutine normbin2_close()
    call bin2_close()
    deallocate( xy, fold)
    deallocate( tmp )
  end subroutine normbin2_close
  ! --------------------------------------------------------------------------------	

  ! --------------------------------------------------------------------------------	
  subroutine get_fold( fold_out )
    real, dimension(:), intent(OUT) :: fold_out
    fold_out = fold	
  end subroutine get_fold
  ! --------------------------------------------------------------------------------	

end module normbin2_mod
