class DiscreteVolatilityFunctionProviderFromVolSurface extends DiscreteVolatilityFunctionProvider {

  @Override
  public DiscreteVolatilityFunction from(final DoublesPair[] expiryStrikePoints) {
    ArgumentChecker.notNull(expiryStrikePoints, "strikeExpiryPoints");
    final int n = expiryStrikePoints.length;

    return new DiscreteVolatilityFunction() {

      @Override
      public DoubleMatrix1D evaluate(final DoubleMatrix1D x) {
        ArgumentChecker.notNull(x, "x");
        //length of x checked by _volatilitySurfacePro
        DoubleMatrix1D res = new DoubleMatrix1D(n);
        double[] data = res.getData();
        final VolatilitySurface vs = _volatilitySurfacePro.getVolSurface(x);
        for (int i = 0; i < n; i++) {
          data[i] = vs.getVolatility(expiryStrikePoints[i]);
        }
        return res;
      }

      @Override
      public DoubleMatrix2D calculateJacobian(final DoubleMatrix1D x) {
        ArgumentChecker.notNull(x, "x");
        //length of x checked by _volatilitySurfacePro
        final Surface<Double, Double, DoubleMatrix1D> volSurfaceAdjoint = _volatilitySurfacePro.getParameterSensitivitySurface(x);
        final DoubleMatrix2D res = new DoubleMatrix2D(n, _volatilitySurfacePro.getNumModelParameters());
        for (int i = 0; i < n; i++) {
          res.getData()[i] = volSurfaceAdjoint.getZValue(expiryStrikePoints[i]).getData();
        }

        return res;
      }

      @Override
      public int getLengthOfDomain() {
        return _volatilitySurfacePro.getNumModelParameters();
      }

      @Override
      public int getLengthOfRange() {
        return n;
      }

    };
  }

  public  DiscreteVolatilityFunctionProviderFromVolSurface(final VolatilitySurfaceProvider volSurfacePro);

}