blob: 2089bf5ce7fa557f05cf1ff09d581a07c5b241c2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
* or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.apache.commons.math3.util;
import org.apache.commons.math3.distribution.RealDistribution;
import org.apache.commons.math3.distribution.UniformRealDistribution;
import org.apache.commons.math3.exception.MathArithmeticException;
import org.apache.commons.math3.exception.NotFiniteNumberException;
import org.apache.commons.math3.exception.NullArgumentException;
import org.apache.commons.math3.exception.util.LocalizedFormats;
import org.apache.commons.math3.random.RandomDataGenerator;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for the MathUtils class.
*
*/
public final class MathUtilsTest {
@Test
public void testEqualsDouble() {
final double x = 1234.5678;
Assert.assertTrue(MathUtils.equals(x, x));
Assert.assertFalse(MathUtils.equals(x, -x));
// Special cases (cf. semantics of JDK's "Double").
// 1. NaN
Assert.assertTrue(MathUtils.equals(Double.NaN, Double.NaN));
// 2. Negative zero
final double mZero = -0d;
final double zero = 0d;
Assert.assertTrue(MathUtils.equals(zero, zero));
Assert.assertTrue(MathUtils.equals(mZero, mZero));
Assert.assertFalse(MathUtils.equals(mZero, zero));
}
@Test
public void testHash() {
double[] testArray = {
Double.NaN,
Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY,
1d,
0d,
1E-14,
(1 + 1E-14),
Double.MIN_VALUE,
Double.MAX_VALUE };
for (int i = 0; i < testArray.length; i++) {
for (int j = 0; j < testArray.length; j++) {
if (i == j) {
Assert.assertEquals(MathUtils.hash(testArray[i]), MathUtils.hash(testArray[j]));
Assert.assertEquals(MathUtils.hash(testArray[j]), MathUtils.hash(testArray[i]));
} else {
Assert.assertTrue(MathUtils.hash(testArray[i]) != MathUtils.hash(testArray[j]));
Assert.assertTrue(MathUtils.hash(testArray[j]) != MathUtils.hash(testArray[i]));
}
}
}
}
@Test
public void testArrayHash() {
Assert.assertEquals(0, MathUtils.hash((double[]) null));
Assert.assertEquals(MathUtils.hash(new double[] {
Double.NaN, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY, 1d, 0d
}),
MathUtils.hash(new double[] {
Double.NaN, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY, 1d, 0d
}));
Assert.assertFalse(MathUtils.hash(new double[] { 1d }) ==
MathUtils.hash(new double[] { FastMath.nextAfter(1d, 2d) }));
Assert.assertFalse(MathUtils.hash(new double[] { 1d }) ==
MathUtils.hash(new double[] { 1d, 1d }));
}
/**
* Make sure that permuted arrays do not hash to the same value.
*/
@Test
public void testPermutedArrayHash() {
double[] original = new double[10];
double[] permuted = new double[10];
RandomDataGenerator random = new RandomDataGenerator();
// Generate 10 distinct random values
for (int i = 0; i < 10; i++) {
final RealDistribution u = new UniformRealDistribution(i + 0.5, i + 0.75);
original[i] = u.sample();
}
// Generate a random permutation, making sure it is not the identity
boolean isIdentity = true;
do {
int[] permutation = random.nextPermutation(10, 10);
for (int i = 0; i < 10; i++) {
if (i != permutation[i]) {
isIdentity = false;
}
permuted[i] = original[permutation[i]];
}
} while (isIdentity);
// Verify that permuted array has different hash
Assert.assertFalse(MathUtils.hash(original) == MathUtils.hash(permuted));
}
@Test
public void testIndicatorByte() {
Assert.assertEquals((byte)1, MathUtils.copySign((byte)1, (byte)2));
Assert.assertEquals((byte)1, MathUtils.copySign((byte)1, (byte)0));
Assert.assertEquals((byte)(-1), MathUtils.copySign((byte)1, (byte)(-2)));
}
@Test
public void testIndicatorInt() {
Assert.assertEquals(1, MathUtils.copySign(1, 2));
Assert.assertEquals(1, MathUtils.copySign(1, 0));
Assert.assertEquals((-1), MathUtils.copySign(1, -2));
}
@Test
public void testIndicatorLong() {
Assert.assertEquals(1L, MathUtils.copySign(1L, 2L));
Assert.assertEquals(1L, MathUtils.copySign(1L, 0L));
Assert.assertEquals(-1L, MathUtils.copySign(1L, -2L));
}
@Test
public void testIndicatorShort() {
Assert.assertEquals((short)1, MathUtils.copySign((short)1, (short)2));
Assert.assertEquals((short)1, MathUtils.copySign((short)1, (short)0));
Assert.assertEquals((short)(-1), MathUtils.copySign((short)1, (short)(-2)));
}
@Test
public void testNormalizeAngle() {
for (double a = -15.0; a <= 15.0; a += 0.1) {
for (double b = -15.0; b <= 15.0; b += 0.2) {
double c = MathUtils.normalizeAngle(a, b);
Assert.assertTrue((b - FastMath.PI) <= c);
Assert.assertTrue(c <= (b + FastMath.PI));
double twoK = FastMath.rint((a - c) / FastMath.PI);
Assert.assertEquals(c, a - twoK * FastMath.PI, 1.0e-14);
}
}
}
@Test
public void testReduce() {
final double period = -12.222;
final double offset = 13;
final double delta = 1.5;
double orig = offset + 122456789 * period + delta;
double expected = delta;
Assert.assertEquals(expected,
MathUtils.reduce(orig, period, offset),
1e-7);
Assert.assertEquals(expected,
MathUtils.reduce(orig, -period, offset),
1e-7);
orig = offset - 123356789 * period - delta;
expected = FastMath.abs(period) - delta;
Assert.assertEquals(expected,
MathUtils.reduce(orig, period, offset),
1e-6);
Assert.assertEquals(expected,
MathUtils.reduce(orig, -period, offset),
1e-6);
orig = offset - 123446789 * period + delta;
expected = delta;
Assert.assertEquals(expected,
MathUtils.reduce(orig, period, offset),
1e-6);
Assert.assertEquals(expected,
MathUtils.reduce(orig, -period, offset),
1e-6);
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, Double.NaN, offset)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.NaN, period, offset)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, period, Double.NaN)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, period,
Double.POSITIVE_INFINITY)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
period, offset)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
Double.POSITIVE_INFINITY, offset)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
period, Double.POSITIVE_INFINITY)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
Double.POSITIVE_INFINITY, offset)));
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
}
@Test
public void testReduceComparedWithNormalizeAngle() {
final double tol = Math.ulp(1d);
final double period = 2 * Math.PI;
for (double a = -15; a <= 15; a += 0.5) {
for (double center = -15; center <= 15; center += 1) {
final double nA = MathUtils.normalizeAngle(a, center);
final double offset = center - Math.PI;
final double r = MathUtils.reduce(a, period, offset);
Assert.assertEquals(nA, r + offset, tol);
}
}
}
@Test
public void testSignByte() {
final byte one = (byte) 1;
Assert.assertEquals((byte) 1, MathUtils.copySign(one, (byte) 2));
Assert.assertEquals((byte) (-1), MathUtils.copySign(one, (byte) (-2)));
}
@Test
public void testSignInt() {
final int one = 1;
Assert.assertEquals(1, MathUtils.copySign(one, 2));
Assert.assertEquals((-1), MathUtils.copySign(one, -2));
}
@Test
public void testSignLong() {
final long one = 1L;
Assert.assertEquals(1L, MathUtils.copySign(one, 2L));
Assert.assertEquals(-1L, MathUtils.copySign(one, -2L));
}
@Test
public void testSignShort() {
final short one = (short) 1;
Assert.assertEquals((short) 1, MathUtils.copySign(one, (short) 2));
Assert.assertEquals((short) (-1), MathUtils.copySign(one, (short) (-2)));
}
@Test
public void testCheckFinite() {
try {
MathUtils.checkFinite(Double.POSITIVE_INFINITY);
Assert.fail("an exception should have been thrown");
} catch (NotFiniteNumberException e) {
// Expected
}
try {
MathUtils.checkFinite(Double.NEGATIVE_INFINITY);
Assert.fail("an exception should have been thrown");
} catch (NotFiniteNumberException e) {
// Expected
}
try {
MathUtils.checkFinite(Double.NaN);
Assert.fail("an exception should have been thrown");
} catch (NotFiniteNumberException e) {
// Expected
}
try {
MathUtils.checkFinite(new double[] {0, -1, Double.POSITIVE_INFINITY, -2, 3});
Assert.fail("an exception should have been thrown");
} catch (NotFiniteNumberException e) {
// Expected
}
try {
MathUtils.checkFinite(new double[] {1, Double.NEGATIVE_INFINITY, -2, 3});
Assert.fail("an exception should have been thrown");
} catch (NotFiniteNumberException e) {
// Expected
}
try {
MathUtils.checkFinite(new double[] {4, 3, -1, Double.NaN, -2, 1});
Assert.fail("an exception should have been thrown");
} catch (NotFiniteNumberException e) {
// Expected
}
}
@Test
public void testCheckNotNull1() {
try {
Object obj = null;
MathUtils.checkNotNull(obj);
} catch (NullArgumentException e) {
// Expected.
}
}
@Test
public void testCheckNotNull2() {
try {
double[] array = null;
MathUtils.checkNotNull(array, LocalizedFormats.INPUT_ARRAY);
} catch (NullArgumentException e) {
// Expected.
}
}
@Test
public void testCopySignByte() {
byte a = MathUtils.copySign(Byte.MIN_VALUE, (byte) -1);
Assert.assertEquals(Byte.MIN_VALUE, a);
final byte minValuePlusOne = Byte.MIN_VALUE + (byte) 1;
a = MathUtils.copySign(minValuePlusOne, (byte) 1);
Assert.assertEquals(Byte.MAX_VALUE, a);
a = MathUtils.copySign(Byte.MAX_VALUE, (byte) -1);
Assert.assertEquals(minValuePlusOne, a);
final byte one = 1;
byte val = -2;
a = MathUtils.copySign(val, one);
Assert.assertEquals(-val, a);
final byte minusOne = -one;
val = 2;
a = MathUtils.copySign(val, minusOne);
Assert.assertEquals(-val, a);
val = 0;
a = MathUtils.copySign(val, minusOne);
Assert.assertEquals(val, a);
val = 0;
a = MathUtils.copySign(val, one);
Assert.assertEquals(val, a);
}
@Test(expected=MathArithmeticException.class)
public void testCopySignByte2() {
MathUtils.copySign(Byte.MIN_VALUE, (byte) 1);
}
}