docs: @Override
  	public RandomVariableInterface[] getDrift(int timeIndex, RandomVariableInterface[] realizationAtTimeIndex, RandomVariableInterface[] realizationPredictor) {
  		double	time				= getTime(timeIndex);
  		int		firstLiborIndex		= this.getLiborPeriodIndex(time)+1;
  		if(firstLiborIndex<0) {
  			firstLiborIndex = -firstLiborIndex-1 + 1;
  		}
  
  		RandomVariableInterface		zero	= getRandomVariableForConstant(0.0);
  
  		// Allocate drift vector and initialize to zero (will be used to sum up drift components)
  		RandomVariableInterface[]	drift = new RandomVariableInterface[getNumberOfComponents()];
  		for(int componentIndex=firstLiborIndex; componentIndex<getNumberOfComponents(); componentIndex++) {
  			drift[componentIndex] = zero;
  		}
  
  		RandomVariableInterface[]	covarianceFactorSums	= new RandomVariableInterface[getNumberOfFactors()];
  		for(int factorIndex=0; factorIndex<getNumberOfFactors(); factorIndex++) {
  			covarianceFactorSums[factorIndex] = zero;
  		}
  
  		if(measure == Measure.SPOT) {
  			// Calculate drift for the component componentIndex (starting at firstLiborIndex, others are zero)
  			for(int componentIndex=firstLiborIndex; componentIndex<getNumberOfComponents(); componentIndex++) {
  				double						periodLength	= liborPeriodDiscretization.getTimeStep(componentIndex);
  				RandomVariableInterface		libor			= realizationAtTimeIndex[componentIndex];
  				RandomVariableInterface		oneStepMeasureTransform = getRandomVariableForConstant(periodLength).discount(libor, periodLength);
  
  				if(stateSpace == StateSpace.LOGNORMAL) {
  					oneStepMeasureTransform = oneStepMeasureTransform.mult(libor);
  				}
  
  				RandomVariableInterface[]	factorLoading   	= getFactorLoading(timeIndex, componentIndex, realizationAtTimeIndex);
  				for(int factorIndex=0; factorIndex<getNumberOfFactors(); factorIndex++) {
  					covarianceFactorSums[factorIndex] = covarianceFactorSums[factorIndex].add(oneStepMeasureTransform.mult(factorLoading[factorIndex]));
  					drift[componentIndex] = drift[componentIndex].addProduct(covarianceFactorSums[factorIndex], factorLoading[factorIndex]);
  				}
  			}
  		}
  		else if(measure == Measure.TERMINAL) {
  			// Calculate drift for the component componentIndex (starting at firstLiborIndex, others are zero)
  			for(int componentIndex=getNumberOfComponents()-1; componentIndex>=firstLiborIndex; componentIndex--) {
  				double					periodLength	= liborPeriodDiscretization.getTimeStep(componentIndex);
  				RandomVariableInterface libor			= realizationAtTimeIndex[componentIndex];
  				RandomVariableInterface oneStepMeasureTransform = getRandomVariableForConstant(periodLength).discount(libor, periodLength);
  
  				if(stateSpace == StateSpace.LOGNORMAL) {
  					oneStepMeasureTransform = oneStepMeasureTransform.mult(libor);
  				}
  
  				RandomVariableInterface[]	factorLoading   	= getFactorLoading(timeIndex, componentIndex, realizationAtTimeIndex);
  				for(int factorIndex=0; factorIndex<getNumberOfFactors(); factorIndex++) {
  					drift[componentIndex] = drift[componentIndex].addProduct(covarianceFactorSums[factorIndex], factorLoading[factorIndex]);
  					covarianceFactorSums[factorIndex] = covarianceFactorSums[factorIndex].sub(oneStepMeasureTransform.mult(factorLoading[factorIndex]));
  				}
  			}
  		}
  
  		if(stateSpace == StateSpace.LOGNORMAL) {
  			// Drift adjustment for log-coordinate in each component
  			for(int componentIndex=firstLiborIndex; componentIndex<getNumberOfComponents(); componentIndex++) {
  				RandomVariableInterface		variance		= covarianceModel.getCovariance(getTime(timeIndex), componentIndex, componentIndex, realizationAtTimeIndex);
  				drift[componentIndex] = drift[componentIndex].addProduct(variance, -0.5);
  			}
  		}
  
  		return drift;
  	}