package water.util;
import static water.util.Utils.*;
import org.junit.Assert;
import org.junit.Test;
import java.util.Random;
import static water.TestUtil.ari;
import static water.TestUtil.arf;
public class UtilsTest {
@Test public void testApproxMathImpl() {
final int loops = 1000000;
final long seed = new Random().nextLong();
final float eps = 1e-20f;
Random rng = new Random(seed);
Log.info("Seed: " + seed);
for (float maxVal : new float[]{1, Float.MAX_VALUE}) {
Log.info("Testing " + loops + " numbers in interval [0, " + maxVal + "].");
// float square
{
float err = 0;
for (int i=0;i<loops;++i) {
final float x = eps + rng.nextFloat() * maxVal;
err = Math.max(Math.abs(err), Math.abs((float)Math.sqrt(x)-approxSqrt(x))/(float)Math.sqrt(x));
}
Log.info("rel. error for approxSqrt(float): " + err);
Assert.assertTrue("rel. error for approxSqrt(float): " + err, Math.abs(err) < 5e-2);
}
// double square
{
double err = 0;
for (int i=0;i<loops;++i) {
final double x = eps + rng.nextFloat() * maxVal;
err = Math.max(Math.abs(err), Math.abs(Math.sqrt(x)-approxSqrt(x))/Math.sqrt(x));
}
Log.info("rel. error for approxSqrt(double): " + err);
Assert.assertTrue("rel. error for approxSqrt(double): " + err, Math.abs(err) < 5e-2);
}
// float inv square
{
float err = 0;
for (int i=0;i<loops;++i) {
final float x = eps + rng.nextFloat() * maxVal;
err = Math.max(Math.abs(err), Math.abs((float)(1./Math.sqrt(x))-approxInvSqrt(x))*(float)Math.sqrt(x));
}
Log.info("rel. error for approxInvSqrt(float): " + err);
Assert.assertTrue("rel. error for approxInvSqrt(float): " + err, Math.abs(err) < 2e-2);
}
// double inv square
{
double err = 0;
for (int i=0;i<loops;++i) {
final double x = eps + rng.nextFloat() * maxVal;
err = Math.max(Math.abs(err), Math.abs((1./Math.sqrt(x))-approxInvSqrt(x))*Math.sqrt(x));
}
Log.info("rel. error for approxInvSqrt(double): " + err);
Assert.assertTrue("rel. error for approxInvSqrt(double): " + err, Math.abs(err) < 2e-2);
}
// double exp
{
double err = 0;
for (int i=0;i<loops;++i) {
final double x = 30 - rng.nextDouble() * 60;
err = Math.max(Math.abs(err), Math.abs(Math.exp(x)-approxExp(x))/Math.exp(x));
}
Log.info("rel. error for approxExp(double): " + err);
Assert.assertTrue("rel. error for approxExp(double): " + err, Math.abs(err) < 5e-2);
}
// double log
{
double err = 0;
for (int i=0;i<loops;++i) {
final double x = eps + rng.nextFloat() * maxVal;
err = Math.abs(Math.log(x)-approxLog(x))/Math.abs(Math.log(x));
if (!Double.isInfinite(err) && !Double.isNaN(err))
err = Math.max(err, Math.abs(Math.log(x)-approxLog(x))/Math.abs(Math.log(x)));
}
Log.info("rel. error for approxLog(double): " + err);
Assert.assertTrue("rel. error for approxLog(double): " + err, Math.abs(err) < 1e-3);
}
}
int[] idx = Utils.seq(0, 13 + new Random().nextInt(10000));
int[] shuffled_idx = new int[idx.length];
Utils.shuffleArray(idx, idx.length, shuffled_idx, new Random().nextLong(), 0);
Utils.shuffleArray(idx, idx.length-13, shuffled_idx, new Random().nextLong(), 13);
}
@Test
public void sumSquareTest() {
float[] a = new float[993];
for (int i=0;i<a.length;++i) a[i] = new Random(0xDECAF).nextFloat();
Assert.assertTrue(Math.abs(sumSquares(a) - sumSquares(a, 0,443) - sumSquares(a, 443,983) - sumSquares(a, 983,993)) < 1e-5);
}
@Test
public void testPartitione() {
Assert.assertArrayEquals( ari(5,5), Utils.partitione(10, arf(0.5f)) );
Assert.assertArrayEquals( ari(5,5,0), Utils.partitione(10, arf(0.5f, 0.5f)) );
Assert.assertArrayEquals( ari(6,7), Utils.partitione(13, arf(0.5f)) );
Assert.assertArrayEquals( ari(6,7,0), Utils.partitione(13, arf(0.5f, 0.5f)) );
// more splits
Assert.assertArrayEquals( ari(3,3,7), Utils.partitione(13, arf(0.25f, 0.25f)) );
Assert.assertArrayEquals( ari(3,3,7,0), Utils.partitione(13, arf(0.25f, 0.25f, 0.5f)) );
}
}