/* (non-Javadoc)
@see net.finmath.stochastic.RandomVariable#getStandardDeviation(net.finmath.stochastic.RandomVariable)
432385
@Override
	public double getStandardDeviation(RandomVariable probabilities) {
		if(isDeterministic()) {
			return 0.0;
		}
		if(size() == 0) {
			return Double.NaN;
		}

		return Math.sqrt(getVariance(probabilities));
	}
147395
@Override
	public RandomVariable add(RandomVariable randomVariable) {
		if(randomVariable.getTypePriority() > this.getTypePriority()) {
			// Check type priority
			return randomVariable.add(this);
		}

		return new RandomVariableDifferentiableAD(
				getValues().add(randomVariable.getValues()),
				Arrays.asList(this, randomVariable),
				OperatorType.ADD);
	}
76466
public static double standardDeviation(double[] x, double mean) {
        if (x.length == 0) {
            return Double.NaN;
        }
        if (x.length == 1) {
            return 0.0;
        }
        return Math.sqrt(variance(x, mean));
    }
607042
@Override
	public RandomVariableInterface getVolatility(int timeIndex, int component) {
		synchronized (volatility) {
			if(volatility[timeIndex][component] == null) {
				volatility[timeIndex][component] = randomVariableFactory.createRandomVariable(getTimeDiscretization().getTime(timeIndex), volatilityMatrix[timeIndex][component]);
			}
		}

		return volatility[timeIndex][component];
	}
401963
public RandomVariable[]	getParameter() {
		double[] parameterAsDouble = this.getParameterAsDouble();
		RandomVariable[] parameter = new RandomVariable[parameterAsDouble.length];
		for(int i=0; i<parameter.length; i++) {
			parameter[i] = new Scalar(parameterAsDouble[i]);
		}
		return parameter;
	}
726065
@Override
	public RandomVariable squared() {
		return apply(new DoubleUnaryOperator() {
			@Override
			public double applyAsDouble(double x) {
				return x * x;
			}
		});
	}
193278
@Override
	public double getQuantileExpectation(double quantileStart, double quantileEnd) {
		return ((RandomVariableDifferentiableAADStochasticNonOptimized) getValues()).getValues().getQuantileExpectation(quantileStart, quantileEnd);
	}
480265
@Override
    public StandardJavaFileManager getStandardFileManager(
            DiagnosticListener<? super JavaFileObject> diagnosticListener,
            Locale locale,
            Charset charset) {
        Context context = new Context();
        context.put(Locale.class, locale);
        if (diagnosticListener != null)
            context.put(DiagnosticListener.class, diagnosticListener);
        PrintWriter pw = (charset == null)
                ? new PrintWriter(System.err, true)
                : new PrintWriter(new OutputStreamWriter(System.err, charset), true);
        context.put(Log.outKey, pw);
        return new JavacFileManager(context, true, charset);
    }
848946
public RandomVariableInterface addProduct(RandomVariableInterface factor1, RandomVariableInterface factor2) {
		// Set time of this random variable to maximum of time with respect to which measurability is known.
		double newTime = Math.max(Math.max(time, factor1.getFiltrationTime()), factor2.getFiltrationTime());

		if(isDeterministic() && factor1.isDeterministic() && factor2.isDeterministic()) {
			double newValueIfNonStochastic = valueIfNonStochastic + (factor1.get(0) * factor2.get(0));
			return new RandomVariableLowMemory(newTime, newValueIfNonStochastic);
		}
		else if(isDeterministic() && !factor1.isDeterministic() && !factor2.isDeterministic()) {
			double[] factor1Realizations = factor1.getRealizations();
			double[] factor2Realizations = factor2.getRealizations();
			double[] newRealizations = new double[Math.max(size(), factor1.size())];
			for(int i=0; i<newRealizations.length; i++) {
				newRealizations[i]		 = valueIfNonStochastic + factor1Realizations[i] * factor2Realizations[i];
			}
			return new RandomVariableLowMemory(newTime, newRealizations);
		}
		else if(!isDeterministic() && !factor1.isDeterministic() && !factor2.isDeterministic()) {
			double[] factor1Realizations = factor1.getRealizations();
			double[] factor2Realizations = factor2.getRealizations();
			double[] newRealizations = new double[Math.max(size(), factor1.size())];
			for(int i=0; i<newRealizations.length; i++) {
				newRealizations[i]		 = realizations[i] + factor1Realizations[i] * factor2Realizations[i];
			}
			return new RandomVariableLowMemory(newTime, newRealizations);
		}
		else {
			double[] newRealizations = new double[Math.max(Math.max(size(), factor1.size()), factor2.size())];
			for(int i=0; i<newRealizations.length; i++) {
				newRealizations[i]		 = get(i) + factor1.get(i) * factor2.get(i);
			}
			return new RandomVariableLowMemory(newTime, newRealizations);
		}
	}
538753
public double getAndAdd(int i, double delta)
    {
        while(true)
        {
            double orig = get(i);
            double newVal = orig + delta;
            if(compareAndSet(i, orig, newVal))
                return orig;
        }
    }
1343334
private RandomVariableInterface[] getBasisFunctions(RandomVariableInterface underlying) {
		double min = underlying.getMin();
		double max = underlying.getMax();

		ArrayList<RandomVariableInterface> basisFunctionList = new ArrayList<RandomVariableInterface>();
		double[] discretization = (new TimeDiscretization(min, numberOfBins, (max-min)/numberOfBins)).getAsDoubleArray();
		for(double discretizationStep : discretization) {
			RandomVariableInterface indicator = underlying.barrier(underlying.sub(discretizationStep), new RandomVariable(1.0), 0.0);
			basisFunctionList.add(indicator);
		}

		return basisFunctionList.toArray(new RandomVariableInterface[0]);
	}
416500
public static IntDoubleVector getRandomBernoulliDirection(int p) {
        IntDoubleVector e = new IntDoubleDenseVector(p);
        for (int i=0; i<p; i++) {
            // Bernoulli distribution chooses either positive or negative 1.
            e.set(i, (Prng.nextBoolean()) ? 1 : -1);
        }
        return e;
    }
925254
@Override
	public RandomVariableInterface getVolatility(int timeIndex, int liborIndex) {
		// Create a very simple volatility model here
		double time             = getTimeDiscretization().getTime(timeIndex);
		double maturity         = getLiborPeriodDiscretization().getTime(liborIndex);
		double timeToMaturity   = maturity-time;

		double volatilityInstanteaneous;
		if(timeToMaturity <= 0)
		{
			volatilityInstanteaneous = 0.0;   // This forward rate is already fixed, no volatility
		}
		else
		{
			volatilityInstanteaneous = (a[liborIndex] + b[liborIndex] * timeToMaturity) * Math.exp(-c[liborIndex] * timeToMaturity) + d[liborIndex];
		}
		if(volatilityInstanteaneous < 0.0) {
			volatilityInstanteaneous = Math.max(volatilityInstanteaneous,0.0);
		}

		return new RandomVariable(getTimeDiscretization().getTime(timeIndex),volatilityInstanteaneous);
	}
966273
public double[] getStandardComponents(double[] x){
		if(x.length != originalN){
			throw new IllegalArgumentException("wrong array dimension: " + x.length);
		}
		double[] ret = new double[standardN];
		for(int i=0; i<x.length; i++){
			if (splittedVariablesList.contains(i)) {
				// this variable was splitted: x = xPlus-xMinus
				if(x[i] >= 0){
					//value for xPlus
					ret[standardS + i] = x[i];
				}else{
					int pos = -1;
					for(int k=0; k<splittedVariablesList.size(); k++){
						if(splittedVariablesList.get(k)==i){
							pos = k;
							break;
						}
					}
					//value for xMinus
					ret[standardS + x.length + pos] = -x[i];
				}
			}else{
				ret[standardS + i] = x[i];
			}
		}
		if(standardS>0){
			DoubleMatrix1D residuals = ColtUtils.zMult(standardA, F1.make(ret), standardB, -1);
			for(int i=0; i<standardS; i++){
				ret[i] = -residuals.get(i) + ret[i];
			}
		}
		return ret;
	}
532554
@Override
	public RandomVariable div(double value) {
		return apply(new DoubleUnaryOperator() {
			@Override
			public double applyAsDouble(double x) {
				return x / value;
			}
		});
	}
162519
@Override
	public RandomVariable mult(double value) {
		return apply(new DoubleUnaryOperator() {
			@Override
			public double applyAsDouble(double x) {
				return x * value;
			}
		});
	}
751971
@Override
    public double getStdDev() {
        // two-pass algorithm for variance, avoids numeric overflow

        if (values.length <= 1) {
            return 0;
        }

        final double mean = getMean();
        double variance = 0;

        for (int i = 0; i < values.length; i++) {
            final double diff = values[i] - mean;
            variance += normWeights[i] * diff*diff;
        }

        return Math.sqrt(variance);
    }