* @return The present value.
*/
public MultipleCurrencyAmount presentValue(final SwaptionBermudaFixedIbor swaption, final HullWhiteOneFactorProviderInterface hullWhite) {
ArgumentChecker.notNull(swaption, "Swaption");
ArgumentChecker.notNull(hullWhite, "Hull-White provider");
MulticurveProviderInterface multicurves = hullWhite.getMulticurveProvider();
HullWhiteOneFactorPiecewiseConstantParameters parameters = hullWhite.getHullWhiteParameters();
Currency ccy = swaption.getCurrency();
final int nbExpiry = swaption.getExpiryTime().length;
Validate.isTrue(nbExpiry > 1, "At least two expiry dates required for this method");
double tmpdb;
final double[] theta = new double[nbExpiry + 1]; // Extended expiry time (with 0).
theta[0] = 0.0;
System.arraycopy(swaption.getExpiryTime(), 0, theta, 1, nbExpiry);
final AnnuityPaymentFixed[] cashflow = new AnnuityPaymentFixed[nbExpiry];
for (int loopexp = 0; loopexp < nbExpiry; loopexp++) {
cashflow[loopexp] = swaption.getUnderlyingSwap()[loopexp].accept(CFEC, multicurves);
}
final int[] n = new int[nbExpiry];
final double[][][] alpha = new double[nbExpiry][][];
final double[][][] alpha2 = new double[nbExpiry][][]; // alpha^2
for (int loopexp = 0; loopexp < nbExpiry; loopexp++) {
n[loopexp] = cashflow[loopexp].getNumberOfPayments();
alpha[loopexp] = new double[loopexp + 1][];
alpha2[loopexp] = new double[loopexp + 1][];
for (int k = 0; k <= loopexp; k++) {
alpha[loopexp][k] = new double[n[loopexp]];
alpha2[loopexp][k] = new double[n[loopexp]];
for (int l = 0; l < alpha[loopexp][k].length; l++) {
alpha[loopexp][k][l] = MODEL.alpha(parameters, theta[k], theta[k + 1], theta[k + 1], cashflow[loopexp].getNthPayment(l).getPaymentTime());
alpha2[loopexp][k][l] = alpha[loopexp][k][l] * alpha[loopexp][k][l];
}
}
}
final int nbPoint2 = 2 * NB_POINT + 1;
final int[] startInt = new int[nbExpiry - 1];
final int[] endInt = new int[nbExpiry - 1];
for (int i = 1; i < nbExpiry - 1; i++) {
startInt[i] = 0;
endInt[i] = nbPoint2 - 1;
}
startInt[0] = NB_POINT;
endInt[0] = NB_POINT;
final double[][] t = new double[nbExpiry][]; // payment time
final double[][] dfS = new double[nbExpiry][]; // discount factor
final double[] beta = new double[nbExpiry];
final double[][] h = new double[nbExpiry][];
final double[][] sa2 = new double[nbExpiry][];
for (int loopexp = 0; loopexp < nbExpiry; loopexp++) {
beta[loopexp] = MODEL.beta(parameters, theta[loopexp], theta[loopexp + 1]);
t[loopexp] = new double[n[loopexp]];
dfS[loopexp] = new double[n[loopexp]];
h[loopexp] = new double[n[loopexp]];
sa2[loopexp] = new double[n[loopexp]];
for (int loopcf = 0; loopcf < n[loopexp]; loopcf++) {
t[loopexp][loopcf] = cashflow[loopexp].getNthPayment(loopcf).getPaymentTime();
dfS[loopexp][loopcf] = multicurves.getDiscountFactor(ccy, t[loopexp][loopcf]);
h[loopexp][loopcf] = (1 - Math.exp(-parameters.getMeanReversion() * t[loopexp][loopcf])) / parameters.getMeanReversion();
tmpdb = 0.0;
for (int k = 0; k <= loopexp; k++) {
tmpdb += alpha2[loopexp][k][loopcf];
}