blob: eeb8c8b3d87239f26ceab9f63d7604cef5b0ffac [file] [log] [blame]
using Lucene.Net.Randomized.Generators;
using NUnit.Framework;
using System;
using Assert = Lucene.Net.TestFramework.Assert;
namespace Lucene.Net.Util
{
/*
* 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.
*/
[TestFixture]
public class TestMathUtil : LuceneTestCase
{
internal static readonly long[] PRIMES = new long[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
internal static long RandomLong()
{
if (Random.NextBoolean())
{
long l = 1;
if (Random.NextBoolean())
{
l *= -1;
}
foreach (long i in PRIMES)
{
int m = Random.Next(3);
for (int j = 0; j < m; ++j)
{
l *= i;
}
}
return l;
}
else if (Random.NextBoolean())
{
return Random.NextInt64();
}
else
{
return RandomPicks.RandomFrom(Random, new long[] { long.MinValue, long.MaxValue, 0L, -1L, 1L });
}
}
// slow version used for testing
private static bool TryGetGcd(long a, long b, out long result)
{
result = 0;
var c = System.Numerics.BigInteger.GreatestCommonDivisor(a, b);
if (c <= long.MaxValue && c >= long.MinValue)
{
result = (long)c;
return true;
}
return false; // would overflow
}
[Test]
public virtual void TestGCD()
{
int iters = AtLeast(100);
for (int i = 0; i < iters; ++i)
{
long l1 = RandomLong();
long l2 = RandomLong();
long gcd = MathUtil.Gcd(l1, l2);
if (TryGetGcd(l1, l2, out long actualGcd))
{
Assert.AreEqual(actualGcd, gcd);
if (gcd != 0)
{
Assert.AreEqual(l1, (l1 / gcd) * gcd);
Assert.AreEqual(l2, (l2 / gcd) * gcd);
}
}
else
{
// GCD cast to long would fail, try again
i--;
}
}
}
// ported test from commons-math
[Test]
public virtual void TestGCD2()
{
long a = 30;
long b = 50;
long c = 77;
Assert.AreEqual(0, MathUtil.Gcd(0, 0));
Assert.AreEqual(b, MathUtil.Gcd(0, b));
Assert.AreEqual(a, MathUtil.Gcd(a, 0));
Assert.AreEqual(b, MathUtil.Gcd(0, -b));
Assert.AreEqual(a, MathUtil.Gcd(-a, 0));
Assert.AreEqual(10, MathUtil.Gcd(a, b));
Assert.AreEqual(10, MathUtil.Gcd(-a, b));
Assert.AreEqual(10, MathUtil.Gcd(a, -b));
Assert.AreEqual(10, MathUtil.Gcd(-a, -b));
Assert.AreEqual(1, MathUtil.Gcd(a, c));
Assert.AreEqual(1, MathUtil.Gcd(-a, c));
Assert.AreEqual(1, MathUtil.Gcd(a, -c));
Assert.AreEqual(1, MathUtil.Gcd(-a, -c));
Assert.AreEqual(3L * (1L << 45), MathUtil.Gcd(3L * (1L << 50), 9L * (1L << 45)));
Assert.AreEqual(1L << 45, MathUtil.Gcd(1L << 45, long.MinValue));
Assert.AreEqual(long.MaxValue, MathUtil.Gcd(long.MaxValue, 0L));
Assert.AreEqual(long.MaxValue, MathUtil.Gcd(-long.MaxValue, 0L));
Assert.AreEqual(1, MathUtil.Gcd(60247241209L, 153092023L));
Assert.AreEqual(long.MinValue, MathUtil.Gcd(long.MinValue, 0));
Assert.AreEqual(long.MinValue, MathUtil.Gcd(0, long.MinValue));
Assert.AreEqual(long.MinValue, MathUtil.Gcd(long.MinValue, long.MinValue));
}
[Test]
public virtual void TestAcoshMethod()
{
// acosh(NaN) == NaN
Assert.IsTrue(double.IsNaN(MathUtil.Acosh(double.NaN)));
// acosh(1) == +0
Assert.AreEqual(0, J2N.BitConversion.DoubleToInt64Bits(MathUtil.Acosh(1D)));
// acosh(POSITIVE_INFINITY) == POSITIVE_INFINITY
Assert.AreEqual(J2N.BitConversion.DoubleToInt64Bits(double.PositiveInfinity), J2N.BitConversion.DoubleToInt64Bits(MathUtil.Acosh(double.PositiveInfinity)));
// acosh(x) : x < 1 == NaN
Assert.IsTrue(double.IsNaN(MathUtil.Acosh(0.9D))); // x < 1
Assert.IsTrue(double.IsNaN(MathUtil.Acosh(0D))); // x == 0
Assert.IsTrue(double.IsNaN(MathUtil.Acosh(-0D))); // x == -0
Assert.IsTrue(double.IsNaN(MathUtil.Acosh(-0.9D))); // x < 0
Assert.IsTrue(double.IsNaN(MathUtil.Acosh(-1D))); // x == -1
Assert.IsTrue(double.IsNaN(MathUtil.Acosh(-10D))); // x < -1
Assert.IsTrue(double.IsNaN(MathUtil.Acosh(double.NegativeInfinity))); // x == -Inf
double epsilon = 0.000001;
Assert.AreEqual(0, MathUtil.Acosh(1), epsilon);
Assert.AreEqual(1.5667992369724109, MathUtil.Acosh(2.5), epsilon);
Assert.AreEqual(14.719378760739708, MathUtil.Acosh(1234567.89), epsilon);
}
[Test]
public virtual void TestAsinhMethod()
{
// asinh(NaN) == NaN
Assert.IsTrue(double.IsNaN(MathUtil.Asinh(double.NaN)));
// asinh(+0) == +0
Assert.AreEqual(0, J2N.BitConversion.DoubleToInt64Bits(MathUtil.Asinh(0D)));
// asinh(-0) == -0
Assert.AreEqual(J2N.BitConversion.DoubleToInt64Bits(-0D), J2N.BitConversion.DoubleToInt64Bits(MathUtil.Asinh(-0D)));
// asinh(POSITIVE_INFINITY) == POSITIVE_INFINITY
Assert.AreEqual(J2N.BitConversion.DoubleToInt64Bits(double.PositiveInfinity), J2N.BitConversion.DoubleToInt64Bits(MathUtil.Asinh(double.PositiveInfinity)));
// asinh(NEGATIVE_INFINITY) == NEGATIVE_INFINITY
Assert.AreEqual(J2N.BitConversion.DoubleToInt64Bits(double.NegativeInfinity), J2N.BitConversion.DoubleToInt64Bits(MathUtil.Asinh(double.NegativeInfinity)));
double epsilon = 0.000001;
Assert.AreEqual(-14.719378760740035, MathUtil.Asinh(-1234567.89), epsilon);
Assert.AreEqual(-1.6472311463710958, MathUtil.Asinh(-2.5), epsilon);
Assert.AreEqual(-0.8813735870195429, MathUtil.Asinh(-1), epsilon);
Assert.AreEqual(0, MathUtil.Asinh(0), 0);
Assert.AreEqual(0.8813735870195429, MathUtil.Asinh(1), epsilon);
Assert.AreEqual(1.6472311463710958, MathUtil.Asinh(2.5), epsilon);
Assert.AreEqual(14.719378760740035, MathUtil.Asinh(1234567.89), epsilon);
}
[Test]
public virtual void TestAtanhMethod()
{
// atanh(NaN) == NaN
Assert.IsTrue(double.IsNaN(MathUtil.Atanh(double.NaN)));
// atanh(+0) == +0
Assert.AreEqual(0, J2N.BitConversion.DoubleToInt64Bits(MathUtil.Atanh(0D)));
// atanh(-0) == -0
Assert.AreEqual(J2N.BitConversion.DoubleToInt64Bits(-0D), J2N.BitConversion.DoubleToInt64Bits(MathUtil.Atanh(-0D)));
// atanh(1) == POSITIVE_INFINITY
Assert.AreEqual(J2N.BitConversion.DoubleToInt64Bits(double.PositiveInfinity), J2N.BitConversion.DoubleToInt64Bits(MathUtil.Atanh(1D)));
// atanh(-1) == NEGATIVE_INFINITY
Assert.AreEqual(J2N.BitConversion.DoubleToInt64Bits(double.NegativeInfinity), J2N.BitConversion.DoubleToInt64Bits(MathUtil.Atanh(-1D)));
// atanh(x) : Math.abs(x) > 1 == NaN
Assert.IsTrue(double.IsNaN(MathUtil.Atanh(1.1D))); // x > 1
Assert.IsTrue(double.IsNaN(MathUtil.Atanh(double.PositiveInfinity))); // x == Inf
Assert.IsTrue(double.IsNaN(MathUtil.Atanh(-1.1D))); // x < -1
Assert.IsTrue(double.IsNaN(MathUtil.Atanh(double.NegativeInfinity))); // x == -Inf
double epsilon = 0.000001;
Assert.AreEqual(double.NegativeInfinity, MathUtil.Atanh(-1), 0);
Assert.AreEqual(-0.5493061443340549, MathUtil.Atanh(-0.5), epsilon);
Assert.AreEqual(0, MathUtil.Atanh(0), 0);
Assert.AreEqual(0.5493061443340549, MathUtil.Atanh(0.5), epsilon);
Assert.AreEqual(double.PositiveInfinity, MathUtil.Atanh(1), 0);
}
}
}