@Override
 public int hashCode() {
   final int prime = 31;
   int result = 1;
   result = prime * result + _barrier.hashCode();
   long temp;
   temp = Double.doubleToLongBits(_rebate);
   result = prime * result + (int) (temp ^ (temp >>> 32));
   result = prime * result + _underlyingOption.hashCode();
   return result;
 }
  /**
   * Computes the price of a barrier option in the Black world.
   *
   * @param option The underlying European vanilla option.
   * @param barrier The barrier.
   * @param rebate The rebate. This is paid <b>immediately</b> if the knock-out barrier is hit and
   *     at expiry if the knock-in barrier is not hit
   * @param spot The spot price.
   * @param costOfCarry The cost of carry (i.e. the forward = spot*exp(costOfCarry*T) )
   * @param rate The interest rate.
   * @param sigma The Black volatility.
   * @return The price.
   */
  public double getPrice(
      final EuropeanVanillaOption option,
      final Barrier barrier,
      final double rebate,
      final double spot,
      final double costOfCarry,
      final double rate,
      final double sigma) {
    Validate.notNull(option, "option");
    Validate.notNull(barrier, "barrier");
    final boolean isKnockIn = (barrier.getKnockType() == KnockType.IN);
    final boolean isDown = (barrier.getBarrierType() == BarrierType.DOWN);

    // in these pathological cases the barrier is hit immediately so the value is just from the
    // rebate (knock-out) or a European option (knock-in)
    if (isDown && spot <= barrier.getBarrierLevel()
        || !isDown && spot >= barrier.getBarrierLevel()) {
      if (isKnockIn) {
        return blackPrice(
            spot,
            option.getStrike(),
            option.getTimeToExpiry(),
            rate,
            costOfCarry,
            sigma,
            option.isCall());
      } else {
        return rebate;
      }
    } else {
      if (isKnockIn) {
        return inBarrier(
            spot,
            barrier.getBarrierLevel(),
            option.getStrike(),
            option.getTimeToExpiry(),
            rate,
            costOfCarry,
            sigma,
            option.isCall(),
            rebate);
      } else {
        return outBarrier(
            spot,
            barrier.getBarrierLevel(),
            option.getStrike(),
            option.getTimeToExpiry(),
            rate,
            costOfCarry,
            sigma,
            option.isCall(),
            rebate);
      }
    }
  }