private double secondPartialDerivative(FittingFunction f,int i,int j,double[] p,double delt){
  double[] arg=new double[p.length];
  System.arraycopy(p,0,arg,0,p.length);
  double center=f.evaluate(arg);
  arg[i]+=delt;
  arg[j]+=delt;
  double ff1=f.evaluate(arg);
  arg[j]-=2 * delt;
  double ff2=f.evaluate(arg);
  arg[i]-=2 * delt;
  arg[j]+=2 * delt;
  double ff3=f.evaluate(arg);
  arg[j]-=2 * delt;
  double ff4=f.evaluate(arg);
  if (Double.isNaN(ff1)) {
    ff1=center;
  }
  if (Double.isNaN(ff2)) {
    ff2=center;
  }
  if (Double.isNaN(ff3)) {
    ff3=center;
  }
  if (Double.isNaN(ff4)) {
    ff4=center;
  }
  double fsSum=ff1 - ff2 - ff3 + ff4;
  return fsSum / (4.0 * delt * delt);
}

private double secondPartialDerivative ( FittingFunction f , int i , int j , double [ ] p , double delt ) { double [ ] arg = new double [ p . length ] ; System . arraycopy ( p , 0 , arg , 0 , p . length ) ; double center = f . evaluate ( arg ) ; arg [ i ] += delt ; arg [ j ] += delt ; double ff1 = f . evaluate ( arg ) ; arg [ j ] -= 2 * delt ; double ff2 = f . evaluate ( arg ) ; arg [ i ] -= 2 * delt ; arg [ j ] += 2 * delt ; double ff3 = f . evaluate ( arg ) ; arg [ j ] -= 2 * delt ; double ff4 = f . evaluate ( arg ) ; if ( Double . isNaN ( ff1 ) ) { ff1 = center ; } if ( Double . isNaN ( ff2 ) ) { ff2 = center ; } if ( Double . isNaN ( ff3 ) ) { ff3 = center ; } if ( Double . isNaN ( ff4 ) ) { ff4 = center ; } double fsSum = ff1 - ff2 - ff3 + ff4 ; return fsSum / ( 4.0 * delt * delt ) ; }
this method straightforwardly applies the standard definition of the numerical estimates of the second order partial derivatives . see for example section 5 . 7 of numerical recipes in c .
