docs: @Override
  	public RandomVariable getNumeraire(double time) throws CalculationException {
  		int timeIndex = liborPeriodDiscretizations[0].getTimeIndex(time);
  		TimeDiscretization liborPeriodDiscretization = liborPeriodDiscretizations[0];
  		if(timeIndex < 0) {
  			// Interpolation of Numeraire: log linear interpolation.
  			int upperIndex = -timeIndex-1;
  			int lowerIndex = upperIndex-1;
  			if(lowerIndex < 0) {
  				throw new IllegalArgumentException("Numeraire requested for time " + time + ". Unsupported");
  			}
  
  			double alpha = (time-liborPeriodDiscretization.getTime(lowerIndex)) / (liborPeriodDiscretization.getTime(upperIndex) - liborPeriodDiscretization.getTime(lowerIndex));
  			RandomVariable numeraire = getNumeraire(liborPeriodDiscretization.getTime(upperIndex)).log().mult(alpha).add(getNumeraire(liborPeriodDiscretization.getTime(lowerIndex)).log().mult(1.0-alpha)).exp();
  
  			/*
  			 * Adjust for discounting, i.e. funding or collateralization
  			 */
  			if(discountCurve != null) {
  				// This includes a control for zero bonds
  				double deterministicNumeraireAdjustment = numeraire.invert().getAverage() / discountCurve.getDiscountFactor(curveModel, time);
  				numeraire = numeraire.mult(deterministicNumeraireAdjustment);
  			}
  
  			return numeraire;
  		}
  
  		/*
  		 * Calculate the numeraire, when time is part of liborPeriodDiscretization
  		 */
  
  		/*
  		 * Check if numeraire cache is values (i.e. process did not change)
  		 */
  		if(getProcess() != numerairesProcess) {
  			numeraires.clear();
  			numerairesProcess = getProcess();
  		}
  
  		/*
  		 * Check if numeraire is part of the cache
  		 */
  		RandomVariable numeraire = numeraires.get(timeIndex);
  		if(numeraire == null) {
  			/*
  			 * Calculate the numeraire for timeIndex
  			 */
  			if(timeIndex == 0) {
  				numeraire = getProcess().getStochasticDriver().getRandomVariableForConstant(1.0);
  			}
  			else {
  				// Initialize to previous numeraire
  				numeraire = getNumeraire(liborPeriodDiscretizations[0].getTime(timeIndex-1));
  
  				double periodStart	= liborPeriodDiscretizations[0].getTime(timeIndex-1);
  				double periodEnd	= liborPeriodDiscretizations[0].getTime(timeIndex);
  				RandomVariable libor = getLIBOR(periodStart, periodStart, periodEnd);
  
  				numeraire = numeraire.accrue(libor, periodEnd-periodStart);
  			}
  
  			// Cache the numeraire
  			numeraires.put(timeIndex, numeraire);
  		}
  
  		/*
  		 * Adjust for discounting, i.e. funding or collateralization
  		 */
  		if(discountCurve != null) {
  			// This includes a control for zero bonds
  			double deterministicNumeraireAdjustment = numeraire.invert().getAverage() / discountCurve.getDiscountFactor(curveModel, time);
  			numeraire = numeraire.mult(deterministicNumeraireAdjustment);
  		}
  
  		return numeraire;
  	}