class SwaptionCashFixedIborLinearTSRMethod {

  public MultipleCurrencyAmount presentValue(final SwaptionCashFixedIbor swaption, final SABRSwaptionProviderInterface sabrData) {
    ArgumentChecker.notNull(swaption, "Swaption");
    ArgumentChecker.notNull(sabrData, "SABR swaption provider");
    MulticurveProviderInterface multicurves = sabrData.getMulticurveProvider();
    Currency ccy = swaption.getCurrency();
    final AnnuityCouponFixed annuityFixed = swaption.getUnderlyingSwap().getFixedLeg();
    final double nominal = Math.abs(annuityFixed.getNthPayment(0).getNotional());
    final double discountFactorSettle = multicurves.getDiscountFactor(ccy, swaption.getSettlementTime());
    final double annuityPhysical = METHOD_SWAP.presentValueBasisPoint(swaption.getUnderlyingSwap(), multicurves) / nominal;
    final double strike = swaption.getStrike();
    final double forward = swaption.getUnderlyingSwap().accept(PRDC, multicurves);
    // Linear approximation
    final double[] alpha = new double[2];
    for (int loopcpn = 0; loopcpn < annuityFixed.getNumberOfPayments(); loopcpn++) {
      alpha[1] += annuityFixed.getNthPayment(loopcpn).getPaymentYearFraction();
    }
    alpha[1] = 1 / alpha[1];
    alpha[0] = (discountFactorSettle / annuityPhysical - alpha[1]) / forward;

    final LinearTSRIntegrant integrant = new LinearTSRIntegrant(swaption, sabrData.getSABRParameter(), forward, alpha);

    @SuppressWarnings("synthetic-access")
    final double strikePart = integrant.k(strike) * integrant.bs(strike);
    final double absoluteTolerance = 1.0E-2;
    final double relativeTolerance = 1.0E-5;
    final RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(absoluteTolerance, relativeTolerance, _nbIteration);
    double integralPart;
    try {
      if (swaption.isCall()) {
        integralPart = integrator.integrate(integrant, strike, strike + _integrationInterval);
      } else {
        integralPart = integrator.integrate(integrant, 0.0, strike);
      }
    } catch (final Exception e) {
      throw new RuntimeException(e);
    }
    final double pv = nominal * annuityPhysical * (strikePart + integralPart) * (swaption.isLong() ? 1.0 : -1.0);
    return MultipleCurrencyAmount.of(swaption.getCurrency(), pv);
  }

}