下面列出了怎么用java.util.function.DoubleUnaryOperator的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Returns an infinite sequential ordered {@code DoubleStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
*
* <p>The first element (position {@code 0}) in the {@code DoubleStream}
* will be the provided {@code seed}. For {@code n > 0}, the element at
* position {@code n}, will be the result of applying the function {@code f}
* to the element at position {@code n - 1}.
*
* @param seed the initial element
* @param f a function to be applied to to the previous element to produce
* a new element
* @return a new sequential {@code DoubleStream}
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
double t = seed;
@Override
public boolean hasNext() {
return true;
}
@Override
public double nextDouble() {
double v = t;
t = f.applyAsDouble(t);
return v;
}
};
return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
iterator,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
}
@Override
public final DoubleStream map(DoubleUnaryOperator mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.applyAsDouble(t));
}
};
}
};
}
@Override
public double getValue(final CharacteristicFunctionModel model) throws CalculationException {
final CharacteristicFunction modelCF = model.apply(getMaturity());
final double lineOfIntegration = 0.5 * getIntegrationDomainImagUpperBound()+getIntegrationDomainImagLowerBound();
final DoubleUnaryOperator integrand = new DoubleUnaryOperator() {
@Override
public double applyAsDouble(final double real) {
final Complex z = new Complex(real,lineOfIntegration);
return modelCF.apply(z.negate()).multiply(AbstractFourierTransformProduct.this.apply(z)).getReal();
}
};
final RealIntegral integrator = new SimpsonRealIntegrator(-100.0, 100.0, 20000, true);
return integrator.integrate(integrand) / 2.0 / Math.PI;
}
@Override
public double integrate(final DoubleUnaryOperator integrand) {
final double lowerBound = getLowerBound();
final double upperBound = getUpperBound();
final double range = upperBound-lowerBound;
final int numberOfDoubleSizeIntervalls = (int) ((numberOfEvaluationPoints-1) / 2.0);
final double doubleIntervall = range / numberOfDoubleSizeIntervalls;
final double singleIntervall = 0.5 * doubleIntervall;
IntStream intervals = IntStream.range(1, numberOfDoubleSizeIntervalls);
if(useParallelEvaluation) {
intervals = intervals.parallel();
}
double sum = intervals.mapToDouble(
i -> integrand.applyAsDouble(lowerBound + i * doubleIntervall) + 2 * integrand.applyAsDouble(lowerBound + i * doubleIntervall + singleIntervall)
).sum();
sum += 2.0 * integrand.applyAsDouble(lowerBound + singleIntervall);
return (integrand.applyAsDouble(lowerBound) + 2.0 * sum + integrand.applyAsDouble(upperBound)) / 3.0 * singleIntervall;
}
@Override
public final DoubleStream map(DoubleUnaryOperator mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.applyAsDouble(t));
}
};
}
};
}
private Optional<DoubleUnaryOperator> operatorAsUnary(DoubleBinaryOperator op) {
String unaryRep;
if (op instanceof ScalarFunctions.Add) unaryRep = "f(a)(a + a)";
else if (op instanceof ScalarFunctions.Multiply) unaryRep = "f(a)(a * a)";
else if (op instanceof ScalarFunctions.Subtract) unaryRep = "f(a)(0)";
else if (op instanceof ScalarFunctions.Divide) unaryRep = "f(a)(1)";
else if (op instanceof ScalarFunctions.Equal) unaryRep = "f(a)(1)";
else if (op instanceof ScalarFunctions.Greater) unaryRep = "f(a)(0)";
else if (op instanceof ScalarFunctions.Less) unaryRep = "f(a)(0)";
else if (op instanceof ScalarFunctions.Max) unaryRep = "f(a)(a)";
else if (op instanceof ScalarFunctions.Min) unaryRep = "f(a)(a)";
else if (op instanceof ScalarFunctions.Mean) unaryRep = "f(a)(a)";
else if (op instanceof ScalarFunctions.Pow) unaryRep = "f(a)(pow(a,a))";
else if (op instanceof ScalarFunctions.SquaredDifference) unaryRep = "f(a)(0)";
else return Optional.empty();
return Optional.of(new DoubleUnaryOperator() {
@Override
public double applyAsDouble(double operand) { return op.applyAsDouble(operand, operand); }
@Override
public String toString() { return unaryRep; }
});
}
protected String getBottomLeftText(Args args) {
boolean useMatrixTransfer = transfer.code() == 18
|| transfer.isDefinedByEOTF();
String name = useMatrixTransfer
? transfer.toString()
: "BT.1886";
DoubleUnaryOperator eotf = useMatrixTransfer
? transfer::toLinear
: TRUE_BLACK_TRANSFER::eotf;
CIExyY xyY = getColor(args, eotf);
return format("EOTF: %s %s", name, formatCIE(xyY));
}
@Override
public double integrate(final DoubleUnaryOperator integrand) {
final double lowerBound = getLowerBound();
final double upperBound = getUpperBound();
final double range = upperBound-lowerBound;
final int numberOfDoubleSizeIntervalls = (int) ((numberOfEvaluationPoints-1) / 2.0);
final double doubleIntervall = range / numberOfDoubleSizeIntervalls;
final double singleIntervall = 0.5 * doubleIntervall;
IntStream intervals = IntStream.range(1, numberOfDoubleSizeIntervalls);
if(useParallelEvaluation) {
intervals = intervals.parallel();
}
double sum = intervals.mapToDouble(
i -> integrand.applyAsDouble(lowerBound + i * doubleIntervall) + 2 * integrand.applyAsDouble(lowerBound + i * doubleIntervall + singleIntervall)
).sum();
sum += 2.0 * integrand.applyAsDouble(lowerBound + singleIntervall);
return (integrand.applyAsDouble(lowerBound) + 2.0 * sum + integrand.applyAsDouble(upperBound)) / 3.0 * singleIntervall;
}
@Override
public final DoubleStream map(DoubleUnaryOperator mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.applyAsDouble(t));
}
};
}
};
}
@Override
public final DoubleStream map(DoubleUnaryOperator mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.applyAsDouble(t));
}
};
}
};
}
/**
* Returns an infinite sequential ordered {@code DoubleStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
*
* <p>The first element (position {@code 0}) in the {@code DoubleStream}
* will be the provided {@code seed}. For {@code n > 0}, the element at
* position {@code n}, will be the result of applying the function {@code f}
* to the element at position {@code n - 1}.
*
* @param seed the initial element
* @param f a function to be applied to to the previous element to produce
* a new element
* @return a new sequential {@code DoubleStream}
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
double t = seed;
@Override
public boolean hasNext() {
return true;
}
@Override
public double nextDouble() {
double v = t;
t = f.applyAsDouble(t);
return v;
}
};
return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
iterator,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
}
/**
* Returns an infinite sequential ordered {@code DoubleStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
*
* <p>The first element (position {@code 0}) in the {@code DoubleStream}
* will be the provided {@code seed}. For {@code n > 0}, the element at
* position {@code n}, will be the result of applying the function {@code f}
* to the element at position {@code n - 1}.
*
* <p>The action of applying {@code f} for one element
* <a href="../concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
* the action of applying {@code f} for subsequent elements. For any given
* element the action may be performed in whatever thread the library
* chooses.
*
* @param seed the initial element
* @param f a function to be applied to the previous element to produce
* a new element
* @return a new sequential {@code DoubleStream}
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
double prev;
boolean started;
@Override
public boolean tryAdvance(DoubleConsumer action) {
Objects.requireNonNull(action);
double t;
if (started)
t = f.applyAsDouble(prev);
else {
t = seed;
started = true;
}
action.accept(prev = t);
return true;
}
};
return StreamSupport.doubleStream(spliterator, false);
}
/**
* Returns an infinite sequential ordered {@code DoubleStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
*
* <p>The first element (position {@code 0}) in the {@code DoubleStream}
* will be the provided {@code seed}. For {@code n > 0}, the element at
* position {@code n}, will be the result of applying the function {@code f}
* to the element at position {@code n - 1}.
*
* <p>The action of applying {@code f} for one element
* <a href="../concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
* the action of applying {@code f} for subsequent elements. For any given
* element the action may be performed in whatever thread the library
* chooses.
*
* @param seed the initial element
* @param f a function to be applied to the previous element to produce
* a new element
* @return a new sequential {@code DoubleStream}
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
double prev;
boolean started;
@Override
public boolean tryAdvance(DoubleConsumer action) {
Objects.requireNonNull(action);
double t;
if (started)
t = f.applyAsDouble(prev);
else {
t = seed;
started = true;
}
action.accept(prev = t);
return true;
}
};
return StreamSupport.doubleStream(spliterator, false);
}
/**
* Returns an infinite sequential ordered {@code DoubleStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
*
* <p>The first element (position {@code 0}) in the {@code DoubleStream}
* will be the provided {@code seed}. For {@code n > 0}, the element at
* position {@code n}, will be the result of applying the function {@code f}
* to the element at position {@code n - 1}.
*
* @param seed the initial element
* @param f a function to be applied to to the previous element to produce
* a new element
* @return a new sequential {@code DoubleStream}
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
double t = seed;
@Override
public boolean hasNext() {
return true;
}
@Override
public double nextDouble() {
double v = t;
t = f.applyAsDouble(t);
return v;
}
};
return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
iterator,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
}
@Override
public final DoubleStream map(DoubleUnaryOperator mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.applyAsDouble(t));
}
};
}
};
}
/**
* Returns an infinite sequential ordered {@code DoubleStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
*
* <p>The first element (position {@code 0}) in the {@code DoubleStream}
* will be the provided {@code seed}. For {@code n > 0}, the element at
* position {@code n}, will be the result of applying the function {@code f}
* to the element at position {@code n - 1}.
*
* @param seed the initial element
* @param f a function to be applied to the previous element to produce
* a new element
* @return a new sequential {@code DoubleStream}
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
double t = seed;
@Override
public boolean hasNext() {
return true;
}
@Override
public double nextDouble() {
double v = t;
t = f.applyAsDouble(t);
return v;
}
};
return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
iterator,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
}
/**
* Returns an infinite sequential ordered {@code DoubleStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
*
* <p>The first element (position {@code 0}) in the {@code DoubleStream}
* will be the provided {@code seed}. For {@code n > 0}, the element at
* position {@code n}, will be the result of applying the function {@code f}
* to the element at position {@code n - 1}.
*
* @param seed the initial element
* @param f a function to be applied to to the previous element to produce
* a new element
* @return a new sequential {@code DoubleStream}
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
double t = seed;
@Override
public boolean hasNext() {
return true;
}
@Override
public double nextDouble() {
double v = t;
t = f.applyAsDouble(t);
return v;
}
};
return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
iterator,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
}
@Test
void testRootEndpoints() {
final DoubleUnaryOperator f = new Sin();
final BrentSolver solver = new BrentSolver(DEFAULT_ABSOLUTE_ACCURACY,
DEFAULT_RELATIVE_ACCURACY,
DEFAULT_FUNCTION_ACCURACY);
// Endpoint is root.
double result = solver.findRoot(f, Math.PI, 4);
Assertions.assertEquals(Math.PI, result, DEFAULT_ABSOLUTE_ACCURACY);
result = solver.findRoot(f, 3, Math.PI);
Assertions.assertEquals(Math.PI, result, DEFAULT_ABSOLUTE_ACCURACY);
result = solver.findRoot(f, Math.PI, 3.5, 4);
Assertions.assertEquals(Math.PI, result, DEFAULT_ABSOLUTE_ACCURACY);
result = solver.findRoot(f, 3, 3.07, Math.PI);
Assertions.assertEquals(Math.PI, result, DEFAULT_ABSOLUTE_ACCURACY);
}
@Override
protected void learnParameters() {
final List<EStep> potentialArtifacts = eSteps.stream()
.filter(eStep -> eStep.getArtifactProbability() > 0.1).collect(Collectors.toList());
final double totalArtifacts = potentialArtifacts.stream().mapToDouble(EStep::getArtifactProbability).sum();
final double totalNonArtifacts = eSteps.stream().mapToDouble(e -> 1 - e.getArtifactProbability()).sum();
strandArtifactPrior = (totalArtifacts + ARTIFACT_PSEUDOCOUNT) / (totalArtifacts + ARTIFACT_PSEUDOCOUNT + totalNonArtifacts + NON_ARTIFACT_PSEUDOCOUNT);
final double artifactAltCount = potentialArtifacts.stream()
.mapToDouble(e -> e.forwardArtifactResponsibility * e.forwardAltCount + e.reverseArtifactResponsibility * e.reverseAltCount)
.sum();
final double artifactDepth = potentialArtifacts.stream()
.mapToDouble(e -> e.forwardArtifactResponsibility * e.forwardCount + e.reverseArtifactResponsibility * e.reverseCount)
.sum();
final double artifactBetaMean = (artifactAltCount + INITIAL_ALPHA_STRAND) / (artifactDepth + INITIAL_ALPHA_STRAND + INITIAL_BETA_STRAND);
// We do the M step for the beta prior on the artifact allele fraction by brute force single-parameter optimization.
// By estimating the mean empirically as above we can fix mean = alpha / (alpha + beta), hence beta = (1/mean - 1) * alpha.
// This lets us do single-parameter optimization on alpha with beta/alpha fixed.
// brute force optimization is fairly cheap because the objective includes only calls that show some evidence of strand bias.
final DoubleUnaryOperator objective = alpha -> {
final double beta = (1 / artifactBetaMean - 1) * alpha;
return potentialArtifacts.stream()
.mapToDouble( e -> e.getForwardArtifactResponsibility() * artifactStrandLogLikelihood(e.forwardCount, e.forwardAltCount, alpha, beta)
+ e.getReverseArtifactResponsibility() * artifactStrandLogLikelihood(e.reverseCount, e.reverseAltCount, alpha, beta))
.sum();
};
alphaStrand = OptimizationUtils.max(objective, 0.01, 100, INITIAL_ALPHA_STRAND, 0.01, 0.01, 100).getPoint();
betaStrand = (1/artifactBetaMean - 1)*alphaStrand;
// free up memory
eSteps.clear();
}
@Override
public RandomVariable div(final double value) {
return apply(new DoubleUnaryOperator() {
@Override
public double applyAsDouble(final double x) {
return x / value;
}
});
}
private double calculateYValue(double x) {
double y = 0.0;
for (DoubleUnaryOperator function : functions) {
y += function.applyAsDouble(x);
}
return y / (double) functions.size();
}
/**
* Create a random variable by applying a function to a given other implementation of <code>RandomVariable</code>.
*
* @param value Object implementing <code>RandomVariable</code>.
* @param function A function mapping double to double.
*/
public RandomVariableFromFloatArray(final RandomVariable value, final DoubleUnaryOperator function) {
super();
time = value.getFiltrationTime();
realizations = value.isDeterministic() ? null : getFloatArray(value.getRealizationsStream().map(function).toArray());
valueIfNonStochastic = value.isDeterministic() ? function.applyAsDouble(value.get(0)) : Double.NaN;
typePriority = typePriorityDefault;
}
@Test
public void test_mutate() {
DoubleUnaryOperator operator = a -> 1 / a;
double[] testArray = ARRAY_1_2.clone();
DoubleArrayMath.mutate(testArray, operator);
assertThat(testArray).contains(1d, 1d / 2d);
}
public static void main(String[] args) {
DoubleUnaryOperator convertCtoF = curriedConverter(9.0/5, 32);
DoubleUnaryOperator convertUSDtoGBP = curriedConverter(0.6, 0);
DoubleUnaryOperator convertKmtoMi = curriedConverter(0.6214, 0);
System.out.println(convertCtoF.applyAsDouble(24));
System.out.println(convertUSDtoGBP.applyAsDouble(100));
System.out.println(convertKmtoMi.applyAsDouble(20));
DoubleUnaryOperator convertFtoC = expandedCurriedConverter(-32, 5.0/9, 0);
System.out.println(convertFtoC.applyAsDouble(98.6));
}
public static void main(String[] args) throws Exception {
double x = -1;
// manual code, super fast
System.out.println(((2.0 + 2.0 * 2.0) * -x) + 5.0 + 1024.0 / (100.0 + 58.0) * 50.0 * 37.0 - 100.0 + 2.0 * Math.pow(x, 2.0) % 3.0);
DoubleUnaryOperator instance = compile("((2 + 2 * 2) * -x) + 5 + 1024 / (100 + 58) * 50 * 37 - 100 + 2 * x ^ 2 % 3").newInstance();
// generated instance evaluation, literally equivalent to manual code (with a method call around it), except it was dynamically generated
System.out.println(instance.applyAsDouble(x));
}
/**
* This test compares the numerical sampled density (from a histogram) of the Brownian motion W(T)
* with the analytic density.
*/
@Test
public void testDensity() {
final int seed = 3141;
final int numberOfFactors = 1;
final int numberOfPaths = 10000000;
final TimeDiscretization timeDiscretization = new TimeDiscretizationFromArray(0, 10, 1.0);
final BrownianMotion brownianMotion = new BrownianMotionFromMersenneRandomNumbers(timeDiscretization, numberOfFactors, numberOfPaths, seed, abstractRandomVariableFactory);
RandomVariable brownianMotionAtTime = brownianMotion.getBrownianIncrement(0, 0);
for(int timeIndex=1; timeIndex<timeDiscretization.getNumberOfTimeSteps(); timeIndex++) {
final double[] intervalPoints = (new TimeDiscretizationFromArray(-2, 101, 4.0/100)).getAsDoubleArray();
final double[] histOfNormalFromBM = brownianMotionAtTime.getHistogram(intervalPoints);
final double time = brownianMotionAtTime.getFiltrationTime();
final DoubleUnaryOperator densityAnalytic = new DoubleUnaryOperator() {
@Override
public double applyAsDouble(final double x) { return Math.exp(-x*x/2.0/time) / Math.sqrt(2 * Math.PI * time); }
};
for(int i=0; i<intervalPoints.length-1; i++) {
final double center = (intervalPoints[i+1]+intervalPoints[i])/2.0;
final double size = intervalPoints[i+1]-intervalPoints[i];
final double density = histOfNormalFromBM[i+1] / size;
final double densityAnalyt = densityAnalytic.applyAsDouble(center);
Assert.assertEquals("Density", densityAnalyt, density, 5E-3);
}
brownianMotionAtTime = brownianMotionAtTime.add(brownianMotion.getBrownianIncrement(timeIndex, 0));
}
}
/**
* Atomically updates the element at index {@code i} with the results
* of applying the given function, returning the previous value. The
* function should be side-effect-free, since it may be re-applied
* when attempted updates fail due to contention among threads.
*
* @param i the index
* @param updateFunction a side-effect-free function
* @return the previous value
*/
public final double getAndUpdate(int i, DoubleUnaryOperator updateFunction)
{
double prev, next;
do
{
prev = get(i);
next = updateFunction.applyAsDouble(prev);
}
while (!compareAndSet(i, prev, next));
return prev;
}
/**
* This test compares the numerical sampled density (from a histogram) of the Brownian motion W(T)
* with the analytic density.
*/
@Test
public void testDensity() {
final int seed = 3141;
final int numberOfFactors = 1;
final int numberOfPaths = 10000000;
final TimeDiscretization timeDiscretization = new TimeDiscretizationFromArray(0, 10, 1.0);
final BrownianMotion brownianMotion = new BrownianMotionFromMersenneRandomNumbers(timeDiscretization, numberOfFactors, numberOfPaths, seed, abstractRandomVariableFactory);
RandomVariable brownianMotionAtTime = brownianMotion.getBrownianIncrement(0, 0);
for(int timeIndex=1; timeIndex<timeDiscretization.getNumberOfTimeSteps(); timeIndex++) {
final double[] intervalPoints = (new TimeDiscretizationFromArray(-2, 101, 4.0/100)).getAsDoubleArray();
final double[] histOfNormalFromBM = brownianMotionAtTime.getHistogram(intervalPoints);
final double time = brownianMotionAtTime.getFiltrationTime();
final DoubleUnaryOperator densityAnalytic = new DoubleUnaryOperator() {
@Override
public double applyAsDouble(final double x) { return Math.exp(-x*x/2.0/time) / Math.sqrt(2 * Math.PI * time); }
};
for(int i=0; i<intervalPoints.length-1; i++) {
final double center = (intervalPoints[i+1]+intervalPoints[i])/2.0;
final double size = intervalPoints[i+1]-intervalPoints[i];
final double density = histOfNormalFromBM[i+1] / size;
final double densityAnalyt = densityAnalytic.applyAsDouble(center);
Assert.assertEquals("Density", densityAnalyt, density, 5E-3);
}
brownianMotionAtTime = brownianMotionAtTime.add(brownianMotion.getBrownianIncrement(timeIndex, 0));
}
}
/**
* Atomically updates the current value with the results of applying the
* given function, returning the updated value. The function should be
* side-effect-free, since it may be re-applied when attempted updates fail
* due to contention among threads.
*
* @param updateFunction a side-effect-free function
* @return the updated value
*/
public final double updateAndGet(DoubleUnaryOperator updateFunction)
{
double prev, next;
do
{
prev = get();
next = updateFunction.applyAsDouble(prev);
}
while (!compareAndSet(prev, next));
return next;
}
/**
* Create a random variable by applying a function to a given other implementation of <code>RandomVariable</code>.
*
* @param value Object implementing <code>RandomVariable</code>.
* @param function A function mapping double to double.
*/
public RandomVariableLazyEvaluation(final RandomVariable value, final DoubleUnaryOperator function) {
super();
time = value.getFiltrationTime();
realizations = value.isDeterministic() ? null : new IntToDoubleFunction() {
@Override
public double applyAsDouble(final int i) {
return function.applyAsDouble(value.get(i));
}
};
size = value.size();
valueIfNonStochastic = value.isDeterministic() ? function.applyAsDouble(value.get(0)) : Double.NaN;
}