/** * Computes the area under this sine function and above y=0 in the range * [0,period). Where period is defined as <code>1/frequency</code>. * @return The computed area. */ public double area() { // in this computation the phase shift is ignored as it doesn't have any // effect for one period. final double a = getAmplitude(); final double b = getHeight(); final double c = getFrequency(); final double[] roots = roots(); final double d = roots[0]; final double e = roots[1]; return a * Math.sin(Math.PI * c * (d - e)) * Math.sin(HALF_PI - Math.PI * c * (d + e)) / (Math.PI * c) + b * (e - d); }
@Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof IntensityFunctions.SineIntensity) { IntensityFunctions.SineIntensity that = (IntensityFunctions.SineIntensity) o; return (Double.doubleToLongBits(this.amplitude) == Double.doubleToLongBits(that.getAmplitude())) && (Double.doubleToLongBits(this.frequency) == Double.doubleToLongBits(that.getFrequency())) && (Double.doubleToLongBits(this.height) == Double.doubleToLongBits(that.getHeight())) && (Double.doubleToLongBits(this.phaseShift) == Double.doubleToLongBits(that.getPhaseShift())); } return false; }
.height(.1) .build(); assertEquals(.369903, sine.area(), 0.000001); assertEquals( .369903, IntensityFunctions.areaByIntegration(sine, 0, 1d / sine.getFrequency()), 0.000001); assertEquals(.31831, sine.area(), 0.00001); assertEquals( .31831, IntensityFunctions.areaByIntegration(sine, 0, 1d / sine.getFrequency()), 0.00001); assertEquals(.269903, sine.area(), 0.000001); assertEquals( .269903, IntensityFunctions.areaByIntegration(sine, 0, 1d / sine.getFrequency()), 0.000001); .height(10) .build(); assertEquals(36000, sine.area(), 0.00001); assertEquals( 36000, IntensityFunctions.areaByIntegration(sine, 0, 1d / sine.getFrequency()), 0.00001); .height(2)
final SineIntensity si = (SineIntensity) ((NonHomogenous) poisson).lambd; final double period = 1d / si.getFrequency(); final double periods = length / period; final double totalEvents = si.area() * periods; averageIntensity = totalEvents / length; } else {
.area(20) .build(); assertEquals(si20.area(), 20d, 0.000000001); .area(200) .build(); assertEquals(si200.area(), 200d, 0.000000001); .area(2000) .build(); assertEquals(si2000.area(), 2000d, 0.000000001); assertEquals(si20.apply(d) * 10d, si200.apply(d), 0.00001); assertEquals(si20.apply(d) * 100d, si2000.apply(d), 0.00001);
IntensityFunction build(long seed) { if (area.isPresent()) { final SineIntensity ins = SineIntensity.create(this, seed); // first compute current area final double a = ins.area(); // compute factor to adapt amplitude and height final double factor = area.get() / a; // store values final StochasticSupplier<Double> ampl = amplitudeSup; final StochasticSupplier<Double> hei = heightSup; // temporarily overwrite values amplitudeSup = constant(ins.getAmplitude() * factor); heightSup = constant(ins.getHeight() * factor); final SineIntensity si = SineIntensity.create(this, seed); // restore values amplitudeSup = ampl; heightSup = hei; return si; } return SineIntensity.create(this, seed); }
double[] roots() { final double a = getAmplitude(); // we need to cap height since if it is higher there are no roots final double b = Math.min(getHeight(), a); final double c = getFrequency(); final double n1 = -1; final double n2 = 0; final double common = Math.asin(b / a) / (TWO_PI * c); final double rootA = -ONE_FOURTH / c + common - n1 / c; final double rootB = ONE_FOURTH / c - common - n2 / c; if (rootA > rootB) { return new double[] {rootB, rootA}; } return new double[] {rootA, rootB}; }
@Override public double getMax() { return getAmplitude() + getHeight(); }
@Override public Double apply(@Nullable Double x) { if (x == null) { throw new IllegalArgumentException(); } return Math.max(0d, getAmplitude() * Math.sin(x * getFrequency() * TWO_PI - Math.PI * getPhaseShift()) + getHeight()); }
@Override public String toString() { return new StringBuilder().append("{f(x) = ") .append(getAmplitude()).append(" * ") .append("sin(x * ").append(getFrequency()) .append(" * 2pi - pi * ").append(getPhaseShift()) .append(") + ").append(getHeight()).append("}") .toString(); }