package org.yajul.util;
import junit.framework.TestCase;
import org.junit.Test;
import java.util.Random;
import static org.junit.Assert.*;
/**
* Tests for MathUtil.
* <br>
* User: josh
* Date: Jun 3, 2010
* Time: 1:53:21 PM
*/
public class MathUtilTest {
private static final double EPSILON = 1e-9;
@Test
public void testRounding() {
assertEquals("rint 1.235", 1.24, MathUtil.rint(1.235, 2), EPSILON);
assertEquals("rint 1.2349", 1.23, MathUtil.rint(1.2349, 2), EPSILON);
assertEquals("rint -1.235", -1.24, MathUtil.rint(-1.235, 2), EPSILON);
assertEquals("rint -1.2349", -1.23, MathUtil.rint(-1.2349, 2), EPSILON);
assertEquals("rint -1.5", -2, MathUtil.rint(-1.5, 0), EPSILON);
assertEquals("rint -1.4", -1, MathUtil.rint(-1.4, 0), EPSILON);
assertEquals("rint -1.576", -1.58, MathUtil.rint(-1.576, 2), EPSILON);
assertEquals("rint 1.576", 1.58, MathUtil.rint(1.576, 2), EPSILON);
}
@Test
public void testHashCode() {
int h1 = MathUtil.doubleHashCode(3.14159);
int h2 = MathUtil.doubleHashCode(3.142);
assert h1 != h2;
}
@Test
public void testExponentialMovingAverage() {
ExponentialMovingAverage a = new ExponentialMovingAverage(1.0, 0, 0);
ExponentialMovingAverage b = new ExponentialMovingAverage(5.0, 0, 0);
ExponentialMovingAverage c = new ExponentialMovingAverage(15.0, 0, 0);
Random r = new Random(31);
for (int i = 0; i < 1000; i++) {
//long t = r.nextInt(1000);
//double v = r.nextGaussian();
long t = i * 5000;
double v = (i < 100 ? 10.0 : 0.0);
final double alpha = a.alpha(t);
double va = a.next(t, v);
double vb = b.next(t, v);
double vc = c.next(t, v);
//System.out.println("[" + i + "] t=" + t + " v=" + v + " alpha=" + alpha + " : " + va + ", " + vb + ", " + vc);
}
}
public static class ExponentialMovingAverage {
private double w; // Averaging period (seconds)
private double prev; // The previous value.
private long prevTime; // The previous timestamp.
private boolean first = true; // True if this is the first.
public ExponentialMovingAverage(double w, double prev, long prevTime) {
this.w = w;
this.prev = prev;
this.prevTime = prevTime;
}
public double seconds(long time) {
return (double)time / 1000.0;
}
public double diff(long time) {
return seconds(time) - seconds(prevTime);
}
public double alpha(long time) {
return 1.0 - Math.exp(-(diff(time) / (w * 60.0)));
}
public double next(long time, double value) {
if (first) {
first = false;
prevTime = time - 1;
}
double a = alpha(time);
double sn = a * value + (1.0 - a) * prev;
prev = sn;
prevTime = time;
return sn;
}
}
}