class CapFloorIborHullWhiteMethod {

  public double[] presentValueHullWhiteSensitivity(final CapFloorIbor cap, final HullWhiteOneFactorProviderInterface hullWhite) {
    ArgumentChecker.notNull(cap, "The cap/floor shoud not be null");
    ArgumentChecker.notNull(hullWhite, "The Hull-White data shoud not be null");
    final Currency ccy = cap.getCurrency();
    final HullWhiteOneFactorPiecewiseConstantParameters parameters = hullWhite.getHullWhiteParameters();
    final MulticurveProviderInterface multicurves = hullWhite.getMulticurveProvider();
    final double tp = cap.getPaymentTime();
    final double[] t = new double[2];
    t[0] = cap.getFixingPeriodStartTime();
    t[1] = cap.getFixingPeriodEndTime();
    final double deltaF = cap.getFixingAccrualFactor();
    final double deltaP = cap.getPaymentYearFraction();
    final double k = cap.getStrike();
    final double omega = (cap.isCap() ? 1.0 : -1.0);
    // Forward sweep
    final double dfPay = multicurves.getDiscountFactor(ccy, tp);
    final double forward = multicurves.getSimplyCompoundForwardRate(cap.getIndex(), t[0], t[1], deltaF);
    final int nbSigma = parameters.getVolatility().length;
    final double[] alpha = new double[2];
    final double[][] alphaDerivatives = new double[2][nbSigma];
    for (int loopcf = 0; loopcf < 2; loopcf++) {
      alpha[loopcf] = _model.alpha(parameters, 0.0, cap.getFixingTime(), tp, t[loopcf], alphaDerivatives[loopcf]);
    }
    final double kappa = (Math.log((1 + deltaF * k) / (1.0 + deltaF * forward)) - (alpha[1] * alpha[1] - alpha[0] * alpha[0]) / 2.0) / (alpha[1] - alpha[0]);
    final double[] n = new double[2];
    for (int loopcf = 0; loopcf < 2; loopcf++) {
      n[loopcf] = NORMAL.getCDF(omega * (-kappa - alpha[loopcf]));
    }
    // Backward sweep
    final double pvBar = 1.0;
    final double[] nBar = new double[2];
    nBar[1] = deltaP / deltaF * dfPay * omega * (1.0 + deltaF * k) * cap.getNotional() * pvBar;
    nBar[0] = deltaP / deltaF * dfPay * omega * (1.0 + deltaF * forward) * cap.getNotional();
    final double[] alphaBar = new double[2];
    for (int loopcf = 0; loopcf < 2; loopcf++) {
      alphaBar[loopcf] = NORMAL.getPDF(omega * (-kappa - alpha[loopcf])) * -omega * nBar[loopcf];
    }
    final double[] sigmaBar = new double[nbSigma];
    for (int loopcf = 0; loopcf < 2; loopcf++) {
      for (int loopsigma = 0; loopsigma < nbSigma; loopsigma++) {
        sigmaBar[loopsigma] += alphaDerivatives[loopcf][loopsigma] * alphaBar[loopcf];
      }
    }
    return sigmaBar;
  }

  private  CapFloorIborHullWhiteMethod();

}