public override void calculate()
        {
            Utils.QL_REQUIRE(process_.x0() > 0.0, () => "negative or null underlying given");

            StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff;

            Utils.QL_REQUIRE(payoff != null, () => "non-striked payoff given");

            Exercise exercise = arguments_.exercise;

            double t = process_.riskFreeRate().link.dayCounter().yearFraction(process_.riskFreeRate().link.referenceDate(),
                                                                              exercise.lastDate());

            double a     = model_.link.parameters()[0];
            double sigma = model_.link.parameters()[1];
            double eta   = process_.blackVolatility().link.blackVol(exercise.lastDate(), payoff.strike());

            double varianceOffset;

            if (a * t > Math.Pow(Const.QL_EPSILON, 0.25))
            {
                double v  = sigma * sigma / (a * a) * (t + 2 / a * Math.Exp(-a * t) - 1 / (2 * a) * Math.Exp(-2 * a * t) - 3 / (2 * a));
                double mu = 2 * rho_ * sigma * eta / a * (t - 1 / a * (1 - Math.Exp(-a * t)));

                varianceOffset = v + mu;
            }
            else
            {
                // low-a algebraic limit
                double v  = sigma * sigma * t * t * t * (1 / 3.0 - 0.25 * a * t + 7 / 60.0 * a * a * t * t);
                double mu = rho_ * sigma * eta * t * t * (1 - a * t / 3.0 + a * a * t * t / 12.0);

                varianceOffset = v + mu;
            }

            Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(
                new ShiftedBlackVolTermStructure(varianceOffset, process_.blackVolatility()));

            GeneralizedBlackScholesProcess adjProcess =
                new GeneralizedBlackScholesProcess(process_.stateVariable(),
                                                   process_.dividendYield(),
                                                   process_.riskFreeRate(),
                                                   volTS);

            AnalyticEuropeanEngine bsmEngine = new AnalyticEuropeanEngine(adjProcess);

            VanillaOption option = new VanillaOption(payoff, exercise);

            option.setupArguments(bsmEngine.getArguments());

            bsmEngine.calculate();

            results_ = bsmEngine.getResults() as OneAssetOption.Results;
        }