##-------------------------------------------------------------------------
## 
## gfimath.pm -- 
## 
## Author          : Pierre Jaccard
## Created On      : 1999/08/03 17:02:52
## Last Modified By: Pierre Jaccard
## Last Modified On: 1999/08/10 18:47:36
## Update Count    : 68
## Directory       : /home/pego/pcd1/codas3c/gfi/lib/perl/
## Version         : 0.0
## Status          : Unknown
## --------------------------------------------------------------------- ++
## DESCRIPTION: 
## 
##    See separate doc.
## 
## --------------------------------------------------------------------- ++
## REVISIONS: 
## --------------------------------------------------------------------- ++
## CHANGES: 
##-------------------------------------------------------------------------

package gfimath;

#------------------------------------------------------------------
# Modules:
#------------------------------------------------------------------

use strict;
use Carp;

#------------------------------------------------------------------
# Declaration:
#------------------------------------------------------------------

BEGIN {
  
  use Exporter ();
  use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);  
  $VERSION = 1.0;
  @ISA = qw(Exporter);

  #--- Exported stuff:
  @EXPORT = qw(&gfimath_interpolate);

  %EXPORT_TAGS = ();

  #--- Exported on demand:
  @EXPORT_OK = ();

}

use vars @EXPORT_OK;

#------------------------------------------------------------------
# Global variables:
#------------------------------------------------------------------

#------------------------------------------------------------------
# File private variables:
#------------------------------------------------------------------

my($BAD, $ADJ);

#------------------------------------------------------------------
# gfimath_interpolate - Linera interpolation
#
# %data = gfimath_interpolate(\@X, \@x, \@data);
#
# Interpolate data from array data given at points at x to new grid values
# given in X. Returns a hash with keys X pointing to an array of
# interpolated values.
#
# Data is an array of references to arrays with data for the given grid. 
#
# Carries out a linear interpolation.
#------------------------------------------------------------------

sub gfimath_interpolate {

  my($N, $n, $i, $j, $j0, $j1, @d, $f);
  my(%data);

  my($X, $x, $data) = @_ ;

  #--- Set bad variables:

  $BAD = $main::BAD || 
    confess("\nVariable BAD not declared in MAIN\n")
      if(!$BAD);
  $ADJ = $main::ADJ_BAD || 
    confess("\nVariable ADJ_BAD not declared in MAIN\n")
      if(!$ADJ);
  
  $N = @{$x};
  $n = @{$data->[0]};

  #--- Loop through new grid points:
  for($i=0; $i<(@{$X}); $i++){

    $j0 = $j1 = -1;

    #--- Get nearest high old grid point:
    $j = 0;
    while(($j < $N) && ($x->[$j] < $X->[$i])){ $j++; }
    $j1 = $j if($j < $N);

    #--- Get nearest low grid point:
    while(($j >= 0) && ($x->[$j] > $X->[$i])){ $j--; }
    $j0 = $j if($j >= 0);
    
    #--- Interpolate data:
    if(($j0 < 0) || ($j1 < 0)){
      
      #--- No interpolation: only bad data
      @d = ();
      for($j=0; $j<$n; $j++){ $d[$j] = $BAD; }
      
    }
    else{
      
      @d  = ();
      
      #--- Calculate interpolation factor:
      if($x->[$j0] < $x->[$j1]){
        $f = ($X->[$i] - $x->[$j0])/($x->[$j1] - $x->[$j0]);
      }else{
        $f = 0.0;
      }

      for($j=0; $j<$n; $j++){
        if(($data->[$j0]->[$j] < $ADJ) && ($data->[$j1]->[$j] < $ADJ)){
          $d[$j] = $data->[$j0]->[$j] + 
            $f * ($data->[$j1]->[$j] - $data->[$j0]->[$j]);
        }else{
          $d[$j] = $BAD;
        }
        #print "$X->[$i] $x->[$j0] $x->[$j1] $f " .
        #  "$data->[$j0]->[$j] $data->[$j1]->[$j] $d[$j]\n";
      }
      
    }
    
    #--- Save data in hash:
    $data{$X->[$i]} = [ @d ];
    
  }
  
  return(%data);
};

1;

  
