/* * 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.lucene.util; import java.math.BigInteger; import java.util.Arrays; import com.carrotsearch.randomizedtesting.generators.RandomPicks; public class TestMathUtil extends LuceneTestCase { static long[] PRIMES = new long[] {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; static long randomLong() { if (random().nextBoolean()) { long l = 1; if (random().nextBoolean()) { l *= -1; } for (long i : PRIMES) { final int m = random().nextInt(3); for (int j = 0; j < m; ++j) { l *= i; } } return l; } else if (random().nextBoolean()) { return random().nextLong(); } else { return RandomPicks.randomFrom(random(), Arrays.asList(Long.MIN_VALUE, Long.MAX_VALUE, 0L, -1L, 1L)); } } // slow version used for testing static long gcd(long l1, long l2) { final BigInteger gcd = BigInteger.valueOf(l1).gcd(BigInteger.valueOf(l2)); assert gcd.bitCount() <= 64; return gcd.longValue(); } public void testGCD() { final int iters = atLeast(100); for (int i = 0; i < iters; ++i) { final long l1 = randomLong(); final long l2 = randomLong(); final long gcd = MathUtil.gcd(l1, l2); final long actualGcd = gcd(l1, l2); assertEquals(actualGcd, gcd); if (gcd != 0) { assertEquals(l1, (l1 / gcd) * gcd); assertEquals(l2, (l2 / gcd) * gcd); } } } // ported test from commons-math public void testGCD2() { long a = 30; long b = 50; long c = 77; assertEquals(0, MathUtil.gcd(0, 0)); assertEquals(b, MathUtil.gcd(0, b)); assertEquals(a, MathUtil.gcd(a, 0)); assertEquals(b, MathUtil.gcd(0, -b)); assertEquals(a, MathUtil.gcd(-a, 0)); assertEquals(10, MathUtil.gcd(a, b)); assertEquals(10, MathUtil.gcd(-a, b)); assertEquals(10, MathUtil.gcd(a, -b)); assertEquals(10, MathUtil.gcd(-a, -b)); assertEquals(1, MathUtil.gcd(a, c)); assertEquals(1, MathUtil.gcd(-a, c)); assertEquals(1, MathUtil.gcd(a, -c)); assertEquals(1, MathUtil.gcd(-a, -c)); assertEquals(3L * (1L<<45), MathUtil.gcd(3L * (1L<<50), 9L * (1L<<45))); assertEquals(1L<<45, MathUtil.gcd(1L<<45, Long.MIN_VALUE)); assertEquals(Long.MAX_VALUE, MathUtil.gcd(Long.MAX_VALUE, 0L)); assertEquals(Long.MAX_VALUE, MathUtil.gcd(-Long.MAX_VALUE, 0L)); assertEquals(1, MathUtil.gcd(60247241209L, 153092023L)); assertEquals(Long.MIN_VALUE, MathUtil.gcd(Long.MIN_VALUE, 0)); assertEquals(Long.MIN_VALUE, MathUtil.gcd(0, Long.MIN_VALUE)); assertEquals(Long.MIN_VALUE, MathUtil.gcd(Long.MIN_VALUE, Long.MIN_VALUE)); } public void testAcoshMethod() { // acosh(NaN) == NaN assertTrue(Double.isNaN(MathUtil.acosh(Double.NaN))); // acosh(1) == +0 assertEquals(0, Double.doubleToLongBits(MathUtil.acosh(1D))); // acosh(POSITIVE_INFINITY) == POSITIVE_INFINITY assertEquals(Double.doubleToLongBits(Double.POSITIVE_INFINITY), Double.doubleToLongBits(MathUtil.acosh(Double.POSITIVE_INFINITY))); // acosh(x) : x < 1 == NaN assertTrue(Double.isNaN(MathUtil.acosh(0.9D))); // x < 1 assertTrue(Double.isNaN(MathUtil.acosh(0D))); // x == 0 assertTrue(Double.isNaN(MathUtil.acosh(-0D))); // x == -0 assertTrue(Double.isNaN(MathUtil.acosh(-0.9D))); // x < 0 assertTrue(Double.isNaN(MathUtil.acosh(-1D))); // x == -1 assertTrue(Double.isNaN(MathUtil.acosh(-10D))); // x < -1 assertTrue(Double.isNaN(MathUtil.acosh(Double.NEGATIVE_INFINITY))); // x == -Inf double epsilon = 0.000001; assertEquals(0, MathUtil.acosh(1), epsilon); assertEquals(1.5667992369724109, MathUtil.acosh(2.5), epsilon); assertEquals(14.719378760739708, MathUtil.acosh(1234567.89), epsilon); } public void testAsinhMethod() { // asinh(NaN) == NaN assertTrue(Double.isNaN(MathUtil.asinh(Double.NaN))); // asinh(+0) == +0 assertEquals(0, Double.doubleToLongBits(MathUtil.asinh(0D))); // asinh(-0) == -0 assertEquals(Double.doubleToLongBits(-0D), Double.doubleToLongBits(MathUtil.asinh(-0D))); // asinh(POSITIVE_INFINITY) == POSITIVE_INFINITY assertEquals(Double.doubleToLongBits(Double.POSITIVE_INFINITY), Double.doubleToLongBits(MathUtil.asinh(Double.POSITIVE_INFINITY))); // asinh(NEGATIVE_INFINITY) == NEGATIVE_INFINITY assertEquals(Double.doubleToLongBits(Double.NEGATIVE_INFINITY), Double.doubleToLongBits(MathUtil.asinh(Double.NEGATIVE_INFINITY))); double epsilon = 0.000001; assertEquals(-14.719378760740035, MathUtil.asinh(-1234567.89), epsilon); assertEquals(-1.6472311463710958, MathUtil.asinh(-2.5), epsilon); assertEquals(-0.8813735870195429, MathUtil.asinh(-1), epsilon); assertEquals(0, MathUtil.asinh(0), 0); assertEquals(0.8813735870195429, MathUtil.asinh(1), epsilon); assertEquals(1.6472311463710958, MathUtil.asinh(2.5), epsilon); assertEquals(14.719378760740035, MathUtil.asinh(1234567.89), epsilon ); } public void testAtanhMethod() { // atanh(NaN) == NaN assertTrue(Double.isNaN(MathUtil.atanh(Double.NaN))); // atanh(+0) == +0 assertEquals(0, Double.doubleToLongBits(MathUtil.atanh(0D))); // atanh(-0) == -0 assertEquals(Double.doubleToLongBits(-0D), Double.doubleToLongBits(MathUtil.atanh(-0D))); // atanh(1) == POSITIVE_INFINITY assertEquals(Double.doubleToLongBits(Double.POSITIVE_INFINITY), Double.doubleToLongBits(MathUtil.atanh(1D))); // atanh(-1) == NEGATIVE_INFINITY assertEquals(Double.doubleToLongBits(Double.NEGATIVE_INFINITY), Double.doubleToLongBits(MathUtil.atanh(-1D))); // atanh(x) : Math.abs(x) > 1 == NaN assertTrue(Double.isNaN(MathUtil.atanh(1.1D))); // x > 1 assertTrue(Double.isNaN(MathUtil.atanh(Double.POSITIVE_INFINITY))); // x == Inf assertTrue(Double.isNaN(MathUtil.atanh(-1.1D))); // x < -1 assertTrue(Double.isNaN(MathUtil.atanh(Double.NEGATIVE_INFINITY))); // x == -Inf double epsilon = 0.000001; assertEquals(Double.NEGATIVE_INFINITY, MathUtil.atanh(-1), 0); assertEquals(-0.5493061443340549, MathUtil.atanh(-0.5), epsilon); assertEquals(0, MathUtil.atanh(0), 0); assertEquals(0.5493061443340549, MathUtil.atanh(0.5), epsilon); assertEquals(Double.POSITIVE_INFINITY, MathUtil.atanh(1), 0); } }