DiscretizedCallableFixedRateBond::DiscretizedCallableFixedRateBond(
                                          const CallableBond::arguments& args,
                                          const Date& referenceDate,
                                          const DayCounter& dayCounter)
    : arguments_(args) {

        redemptionTime_ = dayCounter.yearFraction(referenceDate,
                                                  args.redemptionDate);

        couponTimes_.resize(args.couponDates.size());
        for (Size i=0; i<couponTimes_.size(); ++i)
            couponTimes_[i] =
                dayCounter.yearFraction(referenceDate,
                                        args.couponDates[i]);

        callabilityTimes_.resize(args.callabilityDates.size());
        for (Size i=0; i<callabilityTimes_.size(); ++i)
            callabilityTimes_[i] =
                dayCounter.yearFraction(referenceDate,
                                        args.callabilityDates[i]);

        // similar to the tree swaption engine, we collapse similar coupon
        // and exercise dates to avoid mispricing. Delete if unnecessary.

        for (Size i=0; i<callabilityTimes_.size(); i++) {
            Time exerciseTime = callabilityTimes_[i];
            for (Size j=0; j<couponTimes_.size(); j++) {
                if (withinNextWeek(exerciseTime, couponTimes_[j]))
                    couponTimes_[j] = exerciseTime;
            }
        }
    }
DiscretizedSwaption::DiscretizedSwaption(const Swaption::arguments& args,
        const Date& referenceDate,
        const DayCounter& dayCounter)
    : DiscretizedOption(boost::shared_ptr<DiscretizedAsset>(),
                        args.exercise->type(),
                        std::vector<Time>()),
      arguments_(args),exerciseIndex_(new std::vector<std::pair<bool, std::pair<Size, Real> > >) {

    exerciseTimes_.resize(arguments_.exercise->dates().size());
    for (Size i=0; i<exerciseTimes_.size(); ++i)
        exerciseTimes_[i] =
            dayCounter.yearFraction(referenceDate,
                                    arguments_.exercise->date(i));

    // Date adjustments can get time vectors out of synch.
    // Here, we try and collapse similar dates which could cause
    // a mispricing.
    for (Size i=0; i<arguments_.exercise->dates().size(); i++) {
        Date exerciseDate = arguments_.exercise->date(i);
        for (Size j=0; j<arguments_.fixedPayDates.size(); j++) {
            if (withinNextWeek(exerciseDate,
                               arguments_.fixedPayDates[j])
                    // coupons in the future are dealt with below
                    && arguments_.fixedResetDates[j] < referenceDate)
                arguments_.fixedPayDates[j] = exerciseDate;
        }
        for (Size j=0; j<arguments_.fixedResetDates.size(); j++) {
            if (withinPreviousWeek(exerciseDate,
                                   arguments_.fixedResetDates[j]))
                arguments_.fixedResetDates[j] = exerciseDate;
        }
        for (Size j=0; j<arguments_.floatingResetDates.size(); j++) {
            if (withinPreviousWeek(exerciseDate,
                                   arguments_.floatingResetDates[j]))
                arguments_.floatingResetDates[j] = exerciseDate;
        }
    }

    Time lastFixedPayment =
        dayCounter.yearFraction(referenceDate,
                                arguments_.fixedPayDates.back());
    Time lastFloatingPayment =
        dayCounter.yearFraction(referenceDate,
                                arguments_.floatingPayDates.back());
    lastPayment_ = std::max(lastFixedPayment,lastFloatingPayment);

    underlying_ = boost::shared_ptr<DiscretizedAsset>(
                      new DiscretizedSwap(arguments_,
                                          referenceDate,
                                          dayCounter));
    underlyingAsSwap_ = boost::dynamic_pointer_cast<DiscretizedSwap>(underlying_);
    QL_REQUIRE(underlyingAsSwap_ != nullptr, "Underlying must be a DiscreteSwap object.");
}