You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2022/10/19 20:38:36 UTC
[commons-numbers] branch master updated: NUMBERS-70: Initial user guide
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
The following commit(s) were added to refs/heads/master by this push:
new 07443607 NUMBERS-70: Initial user guide
07443607 is described below
commit 07443607d94fa3caf17dba8e9396c3907115c178
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Mon Oct 17 16:00:29 2022 +0100
NUMBERS-70: Initial user guide
Add test classes to verify the user guide examples.
---
.../commons/numbers/angle/UserGuideTest.java | 65 ++
.../commons/numbers/arrays/UserGuideTest.java | 59 ++
.../numbers/combinatorics/UserGuideTest.java | 94 ++
.../commons/numbers/complex/UserGuideTest.java | 59 ++
.../apache/commons/numbers/core/UserGuideTest.java | 132 +++
.../commons/numbers/field/UserGuideTest.java | 34 +
.../fraction/GeneralizedContinuedFractionTest.java | 4 +-
.../commons/numbers/fraction/UserGuideTest.java | 156 ++++
.../commons/numbers/gamma/UserGuideTest.java | 43 +
.../commons/numbers/primes/UserGuideTest.java | 44 +
.../commons/numbers/quaternion/SlerpTest.java | 6 +-
.../commons/numbers/quaternion/UserGuideTest.java | 84 ++
.../commons/numbers/rootfinder/UserGuideTest.java | 45 +
src/site/apt/userguide/index.apt | 991 +++++++++++++++++++++
src/site/site.xml | 29 +-
src/site/xdoc/userguide/core.xml | 38 -
src/site/xdoc/userguide/index.xml | 35 -
src/site/xdoc/userguide/xdoc.xsl | 68 --
18 files changed, 1832 insertions(+), 154 deletions(-)
diff --git a/commons-numbers-angle/src/test/java/org/apache/commons/numbers/angle/UserGuideTest.java b/commons-numbers-angle/src/test/java/org/apache/commons/numbers/angle/UserGuideTest.java
new file mode 100644
index 00000000..5126fc11
--- /dev/null
+++ b/commons-numbers-angle/src/test/java/org/apache/commons/numbers/angle/UserGuideTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.numbers.angle;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testAngle1() {
+ Angle.Deg a = Angle.Turn.of(0.5).toDeg();
+ Angle.Rad b = a.toRad();
+ Angle.Turn c = b.toTurn();
+ Assertions.assertEquals(0.5, c.getAsDouble());
+ }
+
+ @Test
+ void testAngleNormalizer1() {
+ double angle = Angle.Deg.normalizer(-180).applyAsDouble(270);
+ Assertions.assertEquals(-90.0, angle);
+ }
+
+ @Test
+ void testReduce1() {
+ Reduce reduce = new Reduce(0, 24);
+ double hours1 = reduce.applyAsDouble(173.5);
+ double hours2 = reduce.applyAsDouble(23.5);
+ double hours3 = reduce.applyAsDouble(-10);
+ Assertions.assertEquals(5.5, hours1);
+ Assertions.assertEquals(23.5, hours2);
+ Assertions.assertEquals(14.0, hours3);
+ }
+
+ @Test
+ void testCosAngle1() {
+ double[] v1 = {1, 0};
+ double[] v2 = {0, 1};
+ double[] v3 = {7, 7};
+ double cosAngle1 = CosAngle.value(v1, v1);
+ double cosAngle2 = CosAngle.value(v1, v2);
+ double cosAngle3 = CosAngle.value(v1, v3);
+ Assertions.assertEquals(1, cosAngle1);
+ Assertions.assertEquals(0, cosAngle2);
+ Assertions.assertEquals(0.7071067811865476, cosAngle3);
+ Assertions.assertEquals(45.0, Math.toDegrees(Math.acos(cosAngle3)));
+ }
+}
diff --git a/commons-numbers-arrays/src/test/java/org/apache/commons/numbers/arrays/UserGuideTest.java b/commons-numbers-arrays/src/test/java/org/apache/commons/numbers/arrays/UserGuideTest.java
new file mode 100644
index 00000000..64c20f19
--- /dev/null
+++ b/commons-numbers-arrays/src/test/java/org/apache/commons/numbers/arrays/UserGuideTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.numbers.arrays;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testSortInPlace1() {
+ double[] x = {3, 1, 2};
+ double[] y = {1, 2, 3};
+ double[] z = {0, 5, 7};
+ SortInPlace.ASCENDING.apply(x, y, z);
+ Assertions.assertArrayEquals(new double[] {1, 2, 3}, x);
+ Assertions.assertArrayEquals(new double[] {2, 3, 1}, y);
+ Assertions.assertArrayEquals(new double[] {5, 7, 0}, z);
+ }
+
+ @Test
+ void testMultidimensionalCounter1() {
+ MultidimensionalCounter c = MultidimensionalCounter.of(100, 50);
+ int size = c.getSize();
+ Assertions.assertEquals(5000, size);
+
+ int index = 233;
+ int[] indices1 = c.toMulti(index);
+ int[] indices2 = c.toMulti(index + 1);
+ Assertions.assertArrayEquals(new int[] {4, 33}, indices1);
+ Assertions.assertArrayEquals(new int[] {4, 34}, indices2);
+
+ int index1 = c.toUni(4, 33); // varargs
+ int index2 = c.toUni(indices1);
+ Assertions.assertEquals(index, index1);
+ Assertions.assertEquals(index, index2);
+
+ Assertions.assertArrayEquals(new int[] {0, 49}, c.toMulti(49));
+ Assertions.assertArrayEquals(new int[] {1, 0}, c.toMulti(50));
+ Assertions.assertArrayEquals(new int[] {99, 49}, c.toMulti(4999));
+ }
+}
diff --git a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/UserGuideTest.java b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/UserGuideTest.java
new file mode 100644
index 00000000..38ef9c6d
--- /dev/null
+++ b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/UserGuideTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.numbers.combinatorics;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testBinomialCoefficient1() {
+ long bc1 = BinomialCoefficient.value(66, 33);
+ double bc2 = BinomialCoefficientDouble.value(1029, 514);
+ double bc3 = LogBinomialCoefficient.value(152635712, 125636);
+ Assertions.assertEquals(7219428434016265740L, bc1);
+ // Test with relative tolerance.
+ // Expected values taken from the test suite.
+ Assertions.assertEquals(1.429820686498904e308, bc2, bc2 * 1e-15);
+ Assertions.assertEquals(1017897.199659759, bc3, bc3 * 1e-15);
+ }
+
+ @Test
+ void testFactorial1() {
+ long f1 = Factorial.value(15);
+ double f2 = Factorial.doubleValue(170);
+ double f3 = LogFactorial.create().value(Integer.MAX_VALUE);
+ Assertions.assertEquals(1307674368000L, f1);
+ Assertions.assertEquals(7.257415615307999e306, f2);
+ // This value is taken using LogFactorial.
+ // It should be verified independently.
+ // Currently this asserts the value in the user guide is correct.
+ Assertions.assertEquals(4.3996705655378525e10, f3);
+ }
+
+ @Test
+ void testLogFactorial1() {
+ LogFactorial lf = LogFactorial.create().withCache(50);
+ // This is a compilation test. Just verify the object is created.
+ Assertions.assertNotNull(lf);
+ }
+
+ @Test
+ void testCombinations1() {
+ List<String> actual = new ArrayList<>();
+ Combinations.of(4, 2).iterator().forEachRemaining(c -> actual.add(Arrays.toString(c)));
+ Assertions.assertEquals(Arrays.asList(
+ "[0, 1]",
+ "[0, 2]",
+ "[1, 2]",
+ "[0, 3]",
+ "[1, 3]",
+ "[2, 3]"
+ ), actual);
+ }
+
+ @Test
+ void testCombinationsComparator1() {
+ List<int[]> list = Arrays.asList(new int[][] {
+ {3, 4, 5},
+ {3, 1, 5},
+ {3, 2, 5},
+ {4, 2, 4},
+ });
+ list.sort(Combinations.of(6, 3).comparator());
+ List<String> actual = new ArrayList<>();
+ list.forEach(c -> actual.add(Arrays.toString(c)));
+ Assertions.assertEquals(Arrays.asList(
+ "[4, 2, 4]",
+ "[3, 1, 5]",
+ "[3, 2, 5]",
+ "[3, 4, 5]"
+ ), actual);
+ }
+}
diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/UserGuideTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/UserGuideTest.java
new file mode 100644
index 00000000..72e0ab6d
--- /dev/null
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/UserGuideTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.numbers.complex;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testComplex1() {
+ double x = 3;
+ double y = 4;
+ Complex c1 = Complex.ofCartesian(x, y);
+ // c1 == x + iy
+
+ double rho = 1.23;
+ double theta = Math.PI / 2;
+ Complex c2 = Complex.ofPolar(rho, theta);
+
+ // This is a compilation test. Objects must be valid.
+ Assertions.assertNotNull(c1);
+ Assertions.assertNotNull(c2);
+ }
+
+ @Test
+ void testComplex2() {
+ Complex c1 = Complex.ofCartesian(3, 4);
+ Complex c2 = Complex.ofCartesian(5, 6);
+ Complex c3 = c1.multiply(c2).sqrt();
+
+ double magnitude = c3.abs();
+ double argument = c3.arg();
+
+ boolean finite = c3.isFinite();
+
+ // This is a compilation test. Objects must be valid.
+ Assertions.assertTrue(Double.isFinite(magnitude));
+ Assertions.assertTrue(Double.isFinite(argument));
+ Assertions.assertTrue(finite);
+ }
+}
diff --git a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/UserGuideTest.java b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/UserGuideTest.java
new file mode 100644
index 00000000..537c1a92
--- /dev/null
+++ b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/UserGuideTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.numbers.core;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testNorm1() {
+ double x = Norm.EUCLIDEAN.of(3, -4);
+ double y = Norm.MANHATTAN.of(3, -4, 5);
+ double z = Norm.MAXIMUM.of(new double[] {3, -4, 5, -6, -7, -8});
+ Assertions.assertEquals(5, x);
+ Assertions.assertEquals(12, y);
+ Assertions.assertEquals(8, z);
+
+ double big = Double.MAX_VALUE * 0.5;
+ double length = Norm.EUCLIDEAN.of(big, big, big);
+ double expected = Math.sqrt(0.5 * 0.5 * 3) * Double.MAX_VALUE;
+ Assertions.assertEquals(expected, length, Math.ulp(expected));
+ }
+
+ @Test
+ void testSum1() {
+ double sum1 = Sum.create().add(1)
+ .addProduct(3, 4)
+ .getAsDouble();
+ double sum2 = Sum.of(1).addProduct(3, 4)
+ .getAsDouble();
+ double sum3 = Sum.ofProducts(new double[] {3, 4}, new double[] {5, 6})
+ .getAsDouble();
+ Assertions.assertEquals(13, sum1);
+ Assertions.assertEquals(13, sum2);
+ Assertions.assertEquals(3 * 5 + 4 * 6, sum3);
+
+ Assertions.assertEquals(Double.NaN, Sum.of(1, 2, Double.NaN).getAsDouble());
+ Assertions.assertEquals(Double.NEGATIVE_INFINITY, Sum.of(1, 2, Double.NEGATIVE_INFINITY).getAsDouble());
+ }
+
+ @Test
+ void testSum2() {
+ double x1 = 1e100 + 1 - 2 - 1e100;
+ double x2 = Sum.of(1e100, 1, -2, -1e100).getAsDouble();
+ Assertions.assertEquals(0.0, x1);
+ Assertions.assertEquals(-1.0, x2);
+ }
+
+ @Test
+ void testPrecision1() {
+ // Default allows no numbers between
+ Assertions.assertTrue(Precision.equals(1000.0, 1000.0));
+ Assertions.assertTrue(Precision.equals(1000.0, 1000.0 + Math.ulp(1000.0)));
+ Assertions.assertFalse(Precision.equals(1000.0, 1000.0 + 2 * Math.ulp(1000.0)));
+
+ // Absolute - tolerance is floating-point
+ Assertions.assertFalse(Precision.equals(1000.0, 1001.0));
+ Assertions.assertTrue(Precision.equals(1000.0, 1001.0, 1.0));
+ Assertions.assertTrue(Precision.equals(1000.0, 1000.0 + Math.ulp(1000.0), 0.0));
+
+ // ULP - tolerance is integer
+ Assertions.assertFalse(Precision.equals(1000.0, 1001.0));
+ Assertions.assertFalse(Precision.equals(1000.0, 1001.0, 1));
+ Assertions.assertFalse(Precision.equals(1000.0, 1000.0 + 2 * Math.ulp(1000.0), 1));
+ Assertions.assertTrue(Precision.equals(1000.0, 1000.0 + 2 * Math.ulp(1000.0), 2));
+ Assertions.assertFalse(Precision.equals(1000.0, 1000.0 + 3 * Math.ulp(1000.0), 2));
+
+ // Relative
+ Assertions.assertFalse(Precision.equalsWithRelativeTolerance(1000.0, 1001.0, 1e-6));
+ Assertions.assertTrue(Precision.equalsWithRelativeTolerance(1000.0, 1001.0, 1e-3));
+ }
+
+ @Test
+ void testPrecision2() {
+ Assertions.assertFalse(Precision.equals(Double.NaN, 1000.0));
+ Assertions.assertFalse(Precision.equals(Double.NaN, Double.NaN));
+ Assertions.assertTrue(Precision.equalsIncludingNaN(Double.NaN, Double.NaN));
+
+ Assertions.assertTrue(Precision.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
+ Assertions.assertTrue(Precision.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
+ Assertions.assertFalse(Precision.equals(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
+ }
+
+ @Test
+ void testPrecision3() {
+ Assertions.assertEquals(0, Precision.compareTo(100, 100, 0.0));
+ Assertions.assertEquals(0, Precision.compareTo(100, 101, 1.0));
+ Assertions.assertEquals(-1, Precision.compareTo(100, 102, 1.0));
+ Assertions.assertEquals(1, Precision.compareTo(102, 100, 1.0));
+ }
+
+ @Test
+ void testPrecision4() {
+ Precision.DoubleEquivalence eq = Precision.doubleEquivalenceOfEpsilon(1.0);
+ Assertions.assertFalse(eq.lt(100, 100));
+ Assertions.assertTrue(eq.lte(100, 100));
+ Assertions.assertTrue(eq.eq(100, 100));
+ Assertions.assertTrue(eq.gte(100, 100));
+ Assertions.assertFalse(eq.gt(100, 100));
+ }
+
+ @Test
+ void testPrecision5() {
+ Assertions.assertEquals(678.125, Precision.round(678.125, 4));
+ Assertions.assertEquals(678.125, Precision.round(678.125, 3));
+ Assertions.assertEquals(678.13, Precision.round(678.125, 2));
+ Assertions.assertEquals(678.1, Precision.round(678.125, 1));
+ Assertions.assertEquals(678.0, Precision.round(678.125, 0));
+ Assertions.assertEquals(680.0, Precision.round(678.125, -1));
+ Assertions.assertEquals(700.0, Precision.round(678.125, -2));
+
+ Assertions.assertEquals(0.10000000000000009, Precision.representableDelta(1.0, 0.1));
+ }
+}
diff --git a/commons-numbers-field/src/test/java/org/apache/commons/numbers/field/UserGuideTest.java b/commons-numbers-field/src/test/java/org/apache/commons/numbers/field/UserGuideTest.java
new file mode 100644
index 00000000..136c375d
--- /dev/null
+++ b/commons-numbers-field/src/test/java/org/apache/commons/numbers/field/UserGuideTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.numbers.field;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testField1() {
+ Field<FP64> field = FP64Field.get();
+ FP64 result = field.one().multiply(3).divide(field.one().multiply(4));
+ double value = result.doubleValue();
+ Assertions.assertEquals(0.75, value);
+ }
+}
diff --git a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFractionTest.java b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFractionTest.java
index dd5fd5a9..ff22edf7 100644
--- a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFractionTest.java
+++ b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/GeneralizedContinuedFractionTest.java
@@ -525,7 +525,7 @@ class GeneralizedContinuedFractionTest {
* 5 - ...
* </pre>
*/
- private static class Tan implements Supplier<Coefficient> {
+ static class Tan implements Supplier<Coefficient> {
private double a;
private double b = -1;
@@ -567,7 +567,7 @@ class GeneralizedContinuedFractionTest {
* @param coefficients b coefficients
* @return the generator
*/
- private static Supplier<Coefficient> simpleContinuedFraction(double... coefficients) {
+ static Supplier<Coefficient> simpleContinuedFraction(double... coefficients) {
return new Supplier<Coefficient>() {
/* iteration. */
private int n;
diff --git a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/UserGuideTest.java b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/UserGuideTest.java
new file mode 100644
index 00000000..b226f0e6
--- /dev/null
+++ b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/UserGuideTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.numbers.fraction;
+
+import java.util.function.Supplier;
+import org.apache.commons.numbers.fraction.GeneralizedContinuedFraction.Coefficient;
+import org.apache.commons.numbers.fraction.GeneralizedContinuedFractionTest.Tan;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testFraction1() {
+ int maxIterations = 100;
+
+ // tolerance
+ Fraction a = Fraction.from(0.6152, 0.02, maxIterations);
+ Fraction b = Fraction.from(0.6152, 1.0e-7, maxIterations);
+ Assertions.assertEquals(Fraction.of(3, 5), a);
+ Assertions.assertEquals(Fraction.of(769, 1250), b);
+ Assertions.assertEquals(0.6152, b.doubleValue(), "exact");
+
+ // max denominator
+ Fraction c = Fraction.from(0.6152, 9);
+ Fraction d = Fraction.from(0.6152, 9999);
+ Assertions.assertEquals(Fraction.of(3, 5), c);
+ Assertions.assertEquals(Fraction.of(769, 1250), d);
+
+ // largest possible value
+ Fraction e = Fraction.from(Math.pow(2, 31));
+ Assertions.assertEquals(Fraction.of(Integer.MIN_VALUE, -1), e);
+
+ Assertions.assertThrows(ArithmeticException.class, () -> Fraction.from(1e10));
+ }
+
+ @Test
+ void testFraction2() {
+ Fraction f1 = Fraction.of(-240, 256);
+ Fraction f2 = Fraction.of(15, -16);
+
+ Assertions.assertEquals(-1, f1.signum());
+ Assertions.assertTrue(f1.equals(f2));
+ Assertions.assertEquals(0, f1.compareTo(f2));
+ Assertions.assertEquals(-1, f1.compareTo(Fraction.ZERO));
+
+ Assertions.assertEquals(0, Fraction.of(Integer.MIN_VALUE, Integer.MIN_VALUE).compareTo(Fraction.ONE));
+ }
+
+ @Test
+ void testFraction3() {
+ Fraction result = Fraction.of(1, 2).add(Fraction.of(1, 3))
+ .add(Fraction.of(1, 6));
+ Assertions.assertEquals(Fraction.ONE, result);
+ Assertions.assertEquals(1.0, result.doubleValue(), "exact");
+ Assertions.assertEquals(0.9999999999999999, 1.0 / 2 + 1.0 / 3 + 1.0 / 6, "inexact");
+ }
+
+ @Test
+ void testFraction4() {
+ double a = Fraction.of(1, 8).doubleValue();
+ double b = Fraction.of(1, 3).doubleValue();
+ int c = Fraction.of(8, 3).intValue();
+ Assertions.assertEquals(0.125, a, "exact");
+ Assertions.assertEquals(1.0 / 3, b, "inexact");
+ Assertions.assertEquals(2, c, "inexact, whole number part of 2 2/3");
+ }
+
+ @Test
+ void testBigFraction1() {
+ BigFraction a = BigFraction.from(1.0 / 3);
+ Assertions.assertEquals(BigFraction.of(6004799503160661L, 18014398509481984L), a);
+
+ BigFraction b = BigFraction.from(1.0 / 3, 3);
+ Assertions.assertEquals(BigFraction.of(1, 3), b);
+ }
+
+ /**
+ * Test tan(z). See:
+ * https://en.wikipedia.org/wiki/Trigonometric_functions#Continued_fraction_expansion
+ */
+ @Test
+ void testContinuedFraction1() {
+ final double eps = 1e-8;
+ final ContinuedFraction cf = new ContinuedFraction() {
+ @Override
+ public double getA(int n, double x) {
+ return n < 2 ? x : -x * x;
+ }
+
+ @Override
+ public double getB(int n, double x) {
+ return n == 0 ? 0 : 2 * n - 1;
+ }
+ };
+ double z = 0.125;
+ double result = cf.evaluate(z, eps);
+ double expected = Math.tan(z);
+ Assertions.assertEquals(expected, result, expected * eps * 10);
+ }
+
+ @Test
+ void testGeneralizedContinuedFraction1() {
+ double eps = 1e-10;
+ // Golden ratio
+ Supplier<Coefficient> gen = () -> Coefficient.of(1, 1);
+ double gr1 = GeneralizedContinuedFraction.value(gen, eps);
+ double gr2 = GeneralizedContinuedFraction.value(1, gen, eps);
+ final double expected = 1.6180339887498948;
+ Assertions.assertEquals(expected, gr1, expected * eps * 10);
+ Assertions.assertEquals(expected, gr2, expected * eps * 10);
+ }
+
+ @Test
+ void testGeneralizedContinuedFraction2() {
+ double z = 0.125;
+ double tan1 = GeneralizedContinuedFraction.value(0, new Tan(z));
+
+ // Advance 1 term
+ Tan t = new Tan(z);
+ Coefficient c = t.get();
+ double tan2 = c.getA() / GeneralizedContinuedFraction.value(c.getB(), t);
+
+ // Avoid JDK variations in Math.tan(z)
+ // https://keisan.casio.com/calculator
+ double expected = 0.1256551365751309677927;
+ Assertions.assertEquals(expected, tan1, 2 * Math.ulp(expected));
+ Assertions.assertEquals(expected, tan2);
+ }
+
+ @Test
+ void testGeneralizedContinuedFraction3() {
+ double result1 = GeneralizedContinuedFraction.value(GeneralizedContinuedFractionTest.simpleContinuedFraction(4, 2, 6, 7));
+ double result2 = GeneralizedContinuedFraction.value(4, GeneralizedContinuedFractionTest.simpleContinuedFraction(2, 6, 7));
+ double expected = 415.0 / 93.0;
+ Assertions.assertEquals(expected, result1, Math.ulp(expected));
+ Assertions.assertEquals(expected, result2, Math.ulp(expected));
+ }
+}
diff --git a/commons-numbers-gamma/src/test/java/org/apache/commons/numbers/gamma/UserGuideTest.java b/commons-numbers-gamma/src/test/java/org/apache/commons/numbers/gamma/UserGuideTest.java
new file mode 100644
index 00000000..146155a1
--- /dev/null
+++ b/commons-numbers-gamma/src/test/java/org/apache/commons/numbers/gamma/UserGuideTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.numbers.gamma;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testGamma1() {
+ double result = Erfc.value(1.23);
+ Assertions.assertTrue(0 <= result && result <= 2);
+
+ // Default function evaluation
+ double a = 1.23;
+ double x = 4.56;
+ double result1 = IncompleteGamma.Lower.value(a, x);
+
+ // Parameterize function evaluation
+ double epsilon = 1e-10;
+ int maxIterations = 1000;
+ double result2 = IncompleteGamma.Lower.value(a, x, epsilon, maxIterations);
+ Assertions.assertEquals(result1, result2, result1 * 1e-14);
+ }
+}
diff --git a/commons-numbers-primes/src/test/java/org/apache/commons/numbers/primes/UserGuideTest.java b/commons-numbers-primes/src/test/java/org/apache/commons/numbers/primes/UserGuideTest.java
new file mode 100644
index 00000000..43c25420
--- /dev/null
+++ b/commons-numbers-primes/src/test/java/org/apache/commons/numbers/primes/UserGuideTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.numbers.primes;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testPrimes1() {
+ int n = 51237173;
+ boolean prime = Primes.isPrime(n);
+ int m = Primes.nextPrime(n);
+ Assertions.assertFalse(prime);
+ Assertions.assertEquals(51237233, m);
+
+ List<Integer> f1 = Primes.primeFactors(n);
+ List<Integer> f2 = Primes.primeFactors(m);
+ Assertions.assertEquals(Arrays.asList(13, 863, 4567), f1);
+ Assertions.assertEquals(Arrays.asList(m), f2);
+ // n == 13 * 863 * 4567
+ Assertions.assertEquals(n, f1.stream().mapToInt(i -> i).reduce((i, j) -> i * j).getAsInt());
+ }
+}
diff --git a/commons-numbers-quaternion/src/test/java/org/apache/commons/numbers/quaternion/SlerpTest.java b/commons-numbers-quaternion/src/test/java/org/apache/commons/numbers/quaternion/SlerpTest.java
index 37f34c76..56f2fcb4 100644
--- a/commons-numbers-quaternion/src/test/java/org/apache/commons/numbers/quaternion/SlerpTest.java
+++ b/commons-numbers-quaternion/src/test/java/org/apache/commons/numbers/quaternion/SlerpTest.java
@@ -309,10 +309,10 @@ class SlerpTest {
/**
* Create a quaterion representing a rotation around the +z axis.
- * @param theta
- * @return
+ * @param theta Rotation angle
+ * @return the quaternion
*/
- private static Quaternion createZRotation(final double theta) {
+ static Quaternion createZRotation(final double theta) {
double halfAngle = theta * 0.5;
return Quaternion.of(Math.cos(halfAngle), 0, 0, Math.sin(halfAngle));
diff --git a/commons-numbers-quaternion/src/test/java/org/apache/commons/numbers/quaternion/UserGuideTest.java b/commons-numbers-quaternion/src/test/java/org/apache/commons/numbers/quaternion/UserGuideTest.java
new file mode 100644
index 00000000..60757fed
--- /dev/null
+++ b/commons-numbers-quaternion/src/test/java/org/apache/commons/numbers/quaternion/UserGuideTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.numbers.quaternion;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testQuaternion1() {
+ double w = 2;
+ double x = 3;
+ double y = 4;
+ double z = 5;
+ Quaternion h1 = Quaternion.of(w, x, y, z);
+ Quaternion h2 = Quaternion.of(w, new double[] {x, y, z});
+ Assertions.assertEquals(w, h1.getW());
+ Assertions.assertEquals(w, h1.getScalarPart());
+ Assertions.assertArrayEquals(new double[] {x, y, z}, h1.getVectorPart());
+ Assertions.assertEquals(h1, h2);
+ }
+
+ @Test
+ void testQuaternion2() {
+ Quaternion h = Quaternion.of(1, 2, 3, 4);
+ Quaternion h1 = h.add(Quaternion.ONE);
+ Quaternion hi = h.add(Quaternion.I);
+ Quaternion hj = h.add(Quaternion.J);
+ Quaternion hk = h.add(Quaternion.K);
+ Assertions.assertEquals(Quaternion.of(2, 2, 3, 4), h1);
+ Assertions.assertEquals(Quaternion.of(1, 3, 3, 4), hi);
+ Assertions.assertEquals(Quaternion.of(1, 2, 4, 4), hj);
+ Assertions.assertEquals(Quaternion.of(1, 2, 3, 5), hk);
+ }
+
+ @Test
+ void testQuaternion3() {
+ Quaternion h1 = Quaternion.of(1, 2, 3, 4);
+ Quaternion h2 = Quaternion.of(5, 6, 7, 8);
+ Quaternion result1 = h1.multiply(h2);
+ Quaternion result2 = Quaternion.multiply(h1, h2);
+ Assertions.assertEquals(result1, result2);
+ }
+
+ @Test
+ void testQuaternion4() {
+ Quaternion q1 = Quaternion.of(1, 2, 3, 4);
+ Quaternion q2 = Quaternion.of(1, 2, 3, 4 + 1e-10);
+ Assertions.assertFalse(q1.equals(q2));
+ Assertions.assertTrue(q1.equals(q2, 1e-9));
+ }
+
+ @Test
+ void testSlerp1() {
+ Quaternion q1 = SlerpTest.createZRotation(0.75 * Math.PI);
+ Quaternion q2 = SlerpTest.createZRotation(0.76 * Math.PI);
+
+ Slerp slerp = new Slerp(q1, q2);
+
+ Assertions.assertTrue(slerp.apply(0.0).equals(q1, 1e-7));
+ Assertions.assertTrue(slerp.apply(0.25).equals(SlerpTest.createZRotation(0.7525 * Math.PI), 1e-7));
+ Assertions.assertTrue(slerp.apply(0.5).equals(SlerpTest.createZRotation(0.755 * Math.PI), 1e-7));
+ Assertions.assertTrue(slerp.apply(0.75).equals(SlerpTest.createZRotation(0.7575 * Math.PI), 1e-7));
+ Assertions.assertTrue(slerp.apply(0.0).equals(q1, 1e-7));
+ }
+}
diff --git a/commons-numbers-rootfinder/src/test/java/org/apache/commons/numbers/rootfinder/UserGuideTest.java b/commons-numbers-rootfinder/src/test/java/org/apache/commons/numbers/rootfinder/UserGuideTest.java
new file mode 100644
index 00000000..8ae98b99
--- /dev/null
+++ b/commons-numbers-rootfinder/src/test/java/org/apache/commons/numbers/rootfinder/UserGuideTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.numbers.rootfinder;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for examples contained in the user guide.
+ */
+class UserGuideTest {
+
+ @Test
+ void testBrentSolver1() {
+ double relAccuracy = 1e-6;
+ double absAccuracy = 1e-14;
+ double functionAccuracy = 1e-15;
+ BrentSolver solver = new BrentSolver(relAccuracy,
+ absAccuracy,
+ functionAccuracy);
+ double result1 = solver.findRoot(Math::sin, 3, 4);
+ double result2 = solver.findRoot(Math::sin, 3, 3.14, 4); // With initial guess
+ // result1 ~ result2 ~ Math.PI
+ Assertions.assertEquals(Math.PI, result1, Math.PI * relAccuracy);
+ Assertions.assertEquals(Math.PI, result2, Math.PI * relAccuracy);
+
+ // *** Throws an IllegalArgumentException ***
+ Assertions.assertThrows(IllegalArgumentException.class,
+ () -> solver.findRoot(Math::sin, 2, 3));
+ }
+}
diff --git a/src/site/apt/userguide/index.apt b/src/site/apt/userguide/index.apt
new file mode 100644
index 00000000..ac76376e
--- /dev/null
+++ b/src/site/apt/userguide/index.apt
@@ -0,0 +1,991 @@
+~~
+~~ 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.
+~~
+
+The Apache Commons Numbers User Guide
+
+* Table of contents
+
+ * {{{Overview}Overview}}
+
+ * {{{Examples_Modules}Examples Modules}}
+
+ * {{{Angle}Angle}}
+
+ * {{{Arrays}Arrays}}
+
+ * {{{Combinatorics}Combinatorics}}
+
+ * {{{Complex}Complex}}
+
+ * {{{Core}Core}}
+
+ * {{{Precision}Precision}}
+
+ * {{{Field}Field}}
+
+ * {{{Fraction}Fraction}}
+
+ * {{{Rational_Numbers}Rational Numbers}}
+
+ * {{{Continued_Fractions}Continued Fractions}}
+
+ * {{{Gamma}Gamma}}
+
+ * {{{Primes}Primes}}
+
+ * {{{Quaternion}Quaternion}}
+
+ * {{{Root_Finder}Root Finder}}
+
+ * {{{Dependencies}Dependencies}}
+
+Overview
+
+ <<<Apache Commons Numbers>>> provides number types and utilities.
+
+ The code originated in the {{{https://commons.apache.org/proper/commons-math/}commons-math}}
+ project but was pulled out into a separate project for better
+ maintainability and has since undergone numerous improvements.
+
+ The library is divided into modules:
+
+ * {{{../commons-numbers-angle/index.html}commons-numbers-angle}} - Utilities related to the concept of angle.
+
+ * {{{../commons-numbers-arrays/index.html}commons-numbers-arrays}} - Array utilities.
+
+ * {{{../commons-numbers-combinatorics/index.html}commons-numbers-combinatorics}} - Combinatorics utilities such as factorial and binomial coefficients.
+
+ * {{{../commons-numbers-complex/index.html}commons-numbers-complex}} - Utilities for working with complex numbers.
+
+ * {{{../commons-numbers-core/index.html}commons-numbers-core}} - Basic utilities.
+
+ * {{{../commons-numbers-field/index.html}commons-numbers-field}} - Utilities related to the concept of field.
+
+ * {{{../commons-numbers-fraction/index.html}commons-numbers-fraction}} - Utilities related to fractions such as rational numbers and continued fractions.
+
+ * {{{../commons-numbers-gamma/index.html}commons-numbers-gamma}} - Utilities related to the "Gamma" function.
+
+ * {{{../commons-numbers-primes/index.html}commons-numbers-primes}} - Utilities related to prime numbers.
+
+ * {{{../commons-numbers-quaternion/index.html}commons-numbers-quaternion}} - Utilities for working with quarternion numbers.
+
+ * {{{../commons-numbers-rootfinder/index.html}commons-numbers-rootfinder}} - Utilities for finding the zero of a function.
+
+ []
+
+ The {{{../commons-numbers-bom/index.html}commons-numbers-bom}} artifact provides a
+ Bill of Materials (BOM) to aid in dependency management of the modules.
+
+* Examples Modules
+
+ In addition to the modules above, the Commons Numbers
+ {{{https://commons.apache.org/numbers/download_numbers.cgi}source distribution}}
+ contains example code demonstrating library functionality and/or providing useful
+ development utilities. These modules are not part of the public API of the library and no
+ guarantees are made concerning backwards compatibility. The
+ {{{../commons-numbers-examples/modules.html}example module parent page}}
+ contains a listing of available modules.
+
+Angle
+
+ The {{{../commons-numbers-angle/index.html}commons-numbers-angle}} module
+ provides utilities related to the concept of angle
+ ({{{../commons-numbers-angle/apidocs/org/apache/commons/numbers/angle/package-summary.html}angle API}}).
+
+ The <<<Angle>>> class can be used to convert angles between common units. Sub-classes are used
+ to represent the angle units of degrees, radians and turn.
+
++------------------------------------------+
+Angle.Deg a = Angle.Turn.of(0.5).toDeg();
+Angle.Rad b = a.toRad();
+Angle.Turn c = b.toTurn();
+// c.getAsDouble() == 0.5
++------------------------------------------+
+
+ A normalizer can be used to map any value to the natural interval of the angle unit around a
+ provided lower bound, for example <<<[lo, lo + 360)>>> for degrees:
+
++------------------------------------------+
+// Range: [-180, 180)
+double angle = Angle.Deg.normalizer(-180).applyAsDouble(270);
+// angle == -90.0
++------------------------------------------+
+
+ The normalizer makes use of the <<<Reduce>>> class which can be applied to any interval:
+
++------------------------------------------+
+Reduce reduce = new Reduce(0, 24);
+double hours1 = reduce.applyAsDouble(173.5);
+double hours2 = reduce.applyAsDouble(23.5);
+double hours3 = reduce.applyAsDouble(-10);
+// hours1 == 5.5
+// hours2 == 23.5
+// hours3 == 14.0
++------------------------------------------+
+
+ The <<<Angle>>> class is used extensively in the
+ {{{https://commons.apache.org/proper/commons-geometry/}commons-geometry}} project.
+
+ The <<<CosAngle>>> class computes the cosine of the angle between two vectors using the
+ dot product of two vectors and their magnitudes:
+
+ \( \cos\theta = \frac\{\mathbf\{a\}\cdot\mathbf\{b\}\}\{ \|\mathbf\{a\}\|\ \|\mathbf\{b\}\| \} \)
+
+ The computation uses extended precision methods to increase the overall accuracy of the result
+ at the cost of a moderate increase in the number of computations.
+
++------------------------------------------+
+double[] v1 = {1, 0};
+double[] v2 = {0, 1};
+double[] v3 = {7, 7};
+double cosAngle1 = CosAngle.value(v1, v1);
+double cosAngle2 = CosAngle.value(v1, v2);
+double cosAngle3 = CosAngle.value(v1, v3);
+// cosAngle1 == 1
+// cosAngle2 == 0
+// cosAngle3 == 0.7071067811865476 (sqrt(2) / 2)
+// Math.toDegrees(Math.acos(cosAngle3)) == 45
++------------------------------------------+
+
+Arrays
+
+ The {{{../commons-numbers-arrays/index.html}commons-numbers-arrays}} module
+ provides array utilities
+ ({{{../commons-numbers-arrays/apidocs/org/apache/commons/numbers/arrays/package-summary.html}arrays API}}).
+
+ The <<<SortInPlace>>> class can sort a number of arrays using the order imposed by a specified
+ array:
+
++------------------------------------------+
+double[] x = {3, 1, 2};
+double[] y = {1, 2, 3};
+double[] z = {0, 5, 7};
+SortInPlace.ASCENDING.apply(x, y, z);
+// x == [1, 2, 3]
+// y == [2, 3, 1]
+// z == [5, 7, 0]
++------------------------------------------+
+
+ The <<<MultidimensionalCounter>>> provides a mapping between a unidimensional storage and a
+ multidimensional conceptual structure. Note that successive values for the unidimensional
+ index are used for successive values of the <last> index in the indices of the multidimensional
+ structure. When the dimension size is reached the values roll-over to the next dimension.
+ The class ensures a 1-to-1 mapping from any index within the size to a multidimensional position.
+
++------------------------------------------+
+MultidimensionalCounter c = MultidimensionalCounter.of(100, 50);
+int size = c.getSize();
+// size == 5000
+
+int index = 233;
+int[] indices1 = c.toMulti(index);
+int[] indices2 = c.toMulti(index + 1);
+// indices1 = [4, 33] : 4 * 50 + 33 == 233
+// indices2 = [4, 34] : 4 * 50 + 34 == 234
+
+int index1 = c.toUni(4, 33); // varargs
+int index2 = c.toUni(indices1);
+// index == index1 == index2
+
+c.toMulti(49) // [ 0, 49]
+c.toMulti(50) // [ 1, 0]
+c.toMulti(4999) // [99, 49]
++------------------------------------------+
+
+Combinatorics
+
+ The {{{../commons-numbers-combinatorics/index.html}commons-numbers-combinatorics}} module
+ provides combinatorics utilities such as factorial and binomial coefficients
+ ({{{../commons-numbers-combinatorics/apidocs/org/apache/commons/numbers/combinatorics/package-summary.html}combinatorics API}}).
+
+ The binomial coefficient \( \binom\{n\}\{k\} \) can be evaluated as a <<<long>>>, <<<double>>>
+ or using the natural logarithm.
+
++------------------------------------------+
+long bc1 = BinomialCoefficient.value(63, 33);
+double bc2 = BinomialCoefficientDouble.value(1029, 514);
+double bc3 = LogBinomialCoefficient.value(152635712, 125636);
+// bc1 == 7219428434016265740
+// bc2 ~ 1.429820686498904e308
+// bc3 ~ 1017897.199659759
++------------------------------------------+
+
+ The factorial \( n! \) can be evaluated as a <<<long>>>, <<<double>>> or using the natural
+ logarithm.
+
++------------------------------------------+
+long f1 = Factorial.value(15);
+double f2 = Factorial.doubleValue(170);
+double f3 = LogFactorial.create().value(Integer.MAX_VALUE);
+// f1 == 1307674368000
+// f2 == 7.257415615307999e306
+// f3 == 4.3996705655378525e10
++------------------------------------------+
+
+ Note that if the binomial coefficient or factorial cannot be represented the methods will
+ throw an <<<ArithmeticException>>> in-place of a <<<long>>> value or return infinity
+ in-place of a <<<double>>> value. The logarithm methods will always compute a valid result
+ given the bounds imposed by the <<<int>>> arguments.
+
+ The <<<LogFactorial>>> class can be created with a cache size. All values up to this size
+ are computed upon creation. This functionality can be used when a range of values may be
+ repeatedly required.
+
++------------------------------------------+
+LogFactorial lf = LogFactorial.create().withCache(50);
++------------------------------------------+
+
+ Values outside the cache are computed using <<<LogGamma.value(n + 1.0)>>> from the
+ {{{Gamma}Gamma}} module; this can be used to avoid the object creation of a single-use
+ instance of LogFactorial.
+
+ The combinations defined by the binomial coefficient \( \binom\{n\}\{k\} \) can be
+ iterated using the <<<Combinations>>> class:
+
++------------------------------------------+
+Combinations.of(4, 2).iterator().forEachRemaining(c -> System.out.println(Arrays.toString(c)));
++------------------------------------------+
+
+ Outputs:
+
++------------------------------------------+
+[0, 1]
+[0, 2]
+[1, 2]
+[0, 3]
+[1, 3]
+[2, 3]
++------------------------------------------+
+
+ The lexigraphical order is based on the values in the input array in reverse order. This ordering
+ can be imposed on arbitrary sets using the <<<Comparator\<int[]\>>>> provided by an appropriate
+ <<<Combination>>>:
+
++------------------------------------------+
+List<int[]> list = Arrays.asList(new int[][] {
+ {3, 4, 5},
+ {3, 1, 5},
+ {3, 2, 5},
+ {4, 2, 4},
+});
+list.sort(Combinations.of(6, 3).comparator());
+list.forEach(c -> System.out.println(Arrays.toString(c)));
++------------------------------------------+
+
+ Outputs:
+
++------------------------------------------+
+[4, 2, 4]
+[3, 1, 5]
+[3, 2, 5]
+[3, 4, 5]
++------------------------------------------+
+
+Complex
+
+ The {{{../commons-numbers-complex/index.html}commons-numbers-complex}} module
+ provides utilities for working with complex numbers
+ ({{{../commons-numbers-complex/apidocs/org/apache/commons/numbers/complex/package-summary.html}complex API}}).
+
+ The <<<Complex>>> class is a Cartesian representation of a complex number. The complex number is
+ expressed in the form \( a + ib \) where \( a \) and \( b \) are real numbers and \( i \)
+ is the imaginary unit which satisfies the equation \( i^2 = -1 \). For the
+ complex number \( a + ib \), \( a \) is called the <real part> and
+ \( b \) is called the <imaginary part>. Arithmetic in this class conforms to the C99
+ standard for complex numbers defined in
+ {{{https://www.open-std.org/JTC1/SC22/WG14/www/standards}ISO/IEC 9899}}, Annex G.
+
+ The <<<Complex>>> class is immutable. Instances are constructed with factory methods:
+
++------------------------------------------+
+double x = 3;
+double y = 4;
+Complex c1 = Complex.ofCartesian(x, y);
+// c1 == x + iy
+
+// Convert from polar coordinates
+double rho = 1.23;
+double theta = Math.PI / 2;
+Complex c2 = Complex.ofPolar(rho, theta);
++------------------------------------------+
+
+ Arithmetic operations, elementary functions and trigonometric functions are provided that return
+ new instances of <<<Complex>>> or primitive data types:
+
++------------------------------------------+
+Complex c1 = Complex.ofCartesian(3, 4);
+Complex c2 = Complex.ofCartesian(5, 6);
+Complex c3 = c1.multiply(c2).sqrt();
+
+double magnitude = c3.abs();
+double argument = c3.arg();
+
+boolean finite = c3.isFinite();
++------------------------------------------+
+
+Core
+
+ The {{{../commons-numbers-core/index.html}commons-numbers-core}} module
+ provides basic utilities
+ ({{{../commons-numbers-core/apidocs/org/apache/commons/numbers/core/package-summary.html}core API}}).
+ The classes within this module provide core functionality
+ reused within <<<Apache Commons Numbers>>> and also other projects such as
+ {{{https://commons.apache.org/proper/commons-geometry/}commons-geometry}} and
+ {{{https://commons.apache.org/proper/commons-math/}commons-math}}.
+
+ The interfaces <<<Addition>>> and <<<Multiplication>>> provide generic typed definitions of
+ the arithmetic <add> and <multiply> operations. These are extended by <<<NativeOperators>>>
+ that adds operators that can be implemented in a more performant way. These interfaces are used
+ by the {{{Field}Field}} module.
+
+ The <<<ArithmeticUtils>>> class provides arithmetic utilities such as integer power, unsigned
+ divide and remainder functions; greatest common divisor; and least common multiple. These
+ functions are used by the {{{Fraction}Fraction}} module.
+
+ The <<<Norm>>> class provides implementations of
+ {{{https://en.wikipedia.org/wiki/Norm_(mathematics)}norm}} functions. The implementations
+ may use extended precision methods to increase the overall accuracy of the result
+ at the cost of a moderate increase in the number of computations. The Euclidean implementation
+ handles possible under and overflow of intermediates using scaling.
+
++------------------------------------------+
+double x = Norm.EUCLIDEAN.of(3, -4); // 5
+double y = Norm.MANHATTAN.of(3, -4, 5); // 12
+double z = Norm.MAXIMUM.of(new double[]{3, -4, 5, -6, -7, -8}); // 8
+
+double big = Double.MAX_VALUE * 0.5;
+double length = Norm.EUCLIDEAN.of(big, big, big);
+// length == Math.sqrt(0.5 * 0.5 * 3) * Double.MAX_VALUE
++------------------------------------------+
+
+ The <<<Sum>>> class provides accurate floating-point sums and linear combinations.
+ The class uses techniques to mitigate round off errors resulting from
+ standard floating-point operations, increasing the overall accuracy of
+ results at the cost of a moderate increase in the number of computations.
+ The <<<Sum>>> can add numbers and products of numbers.
+ The result is returned as the high-precision value if it is finite, or the standard IEEE754
+ result otherwise.
+
++------------------------------------------+
+double sum1 = Sum.create().add(1)
+ .addProduct(3, 4)
+ .getAsDouble();
+double sum2 = Sum.of(1).addProduct(3, 4)
+ .getAsDouble();
+double sum3 = Sum.ofProducts(new double[] {3, 4}, new double[] {5, 6})
+ .getAsDouble();
+// sum1 == sum2 == 13.0
+// sum3 == 3 * 5 + 4 * 6
+
+Sum.of(1, 2, Double.NaN).getAsDouble() // NaN
+Sum.of(1, 2, Double.NEGATIVE_INFINITY).getAsDouble() // -inf
++------------------------------------------+
+
+ The implementation provides an effective 106 bit floating point significand. However the
+ significand is split into two <<<double>>> values which may be separated by more than <<<2^53>>>
+ by using the exponent of the second <<<double>>>.
+ This provides protection against cancellation in situations that would not be handled by an
+ IEEE754 binary 128 format with a 113 bit significand:
+
++------------------------------------------+
+double x1 = 1e100 + 1 - 2 - 1e100;
+double x2 = Sum.of(1e100, 1, -2, -1e100).getAsDouble();
+// x1 == 0.0
+// x2 == -1.0
++------------------------------------------+
+
+ The class can be used to:
+
+ * Reduce cancellation effects that occur when large magnitude numbers
+ with opposite signs are summed together with relatively small values;
+
+ * Provide accurate summation of numbers with the same sign irrespective of input order.
+
+ []
+
+* Precision
+
+ The <<<Precision>>> class provides comparison of floating-point numbers using relative, absolute
+ and unit of least precision ({{{https://en.wikipedia.org/wiki/Unit_in_the_last_place}ULP}})
+ tolerances. Comparison using the relative tolerance \( \epsilon \) is symmetric as the relative
+ delta is computed using the largest magnitude of the input pair of numbers:
+
+ \( \frac\{|a - b|\}\{\operatorname\{max\}(|a|, |b|)\} \le \epsilon \)
+
+ Comparisons using the ULP argument specifies the allowed distance <between> two numbers.
+ Numbers are equal if they have <<<(ulp - 1)>>> representable numbers or fewer <between> <<<a>>>
+ and <<<b>>>. Use <<<ulp = 0>>> for binary equality.
+
+ Note: The default implementation for equality allows no numbers <between> <<<a>>> and <<<b>>>.
+ It is equivalent to <<<Precision.equals(a, b, 1)>>>. Thus using a floating-point delta of
+ <<<0.0>>> may indicate numbers are equal when they are not <binary> equal (see example below).
+
++------------------------------------------+
+// Default allows no numbers between
+Precision.equals(1000.0, 1000.0) // true
+Precision.equals(1000.0, 1000.0 + Math.ulp(1000.0)) // true
+Precision.equals(1000.0, 1000.0 + 2 * Math.ulp(1000.0)) // false
+
+// Absolute - tolerance is floating-point
+Precision.equals(1000.0, 1001.0) // false
+Precision.equals(1000.0, 1001.0, 1.0) // true
+Precision.equals(1000.0, 1000.0 + Math.ulp(1000.0), 0.0) // true (but not binary equal)
+
+// ULP - tolerance is integer
+Precision.equals(1000.0, 1001.0) // false
+Precision.equals(1000.0, 1001.0, 1) // false
+Precision.equals(1000.0, 1000.0 + 2 * Math.ulp(1000.0), 1) // false
+Precision.equals(1000.0, 1000.0 + 2 * Math.ulp(1000.0), 2) // true (n - 1) numbers between
+Precision.equals(1000.0, 1000.0 + 3 * Math.ulp(1000.0), 2) // false
+
+// Relative
+Precision.equalsWithRelativeTolerance(1000.0, 1001.0, 1e-6) // false
+Precision.equalsWithRelativeTolerance(1000.0, 1001.0, 1e-3) // true
++------------------------------------------+
+
+ Equality using <<<NaN>>> values will be <<<false>>>. To allow two <<<NaN>>> values to be
+ equal requires the use of the method <<<equalsIncludingNaN>>>. Special handling of <<<NaN>>>
+ values allows the default implementation to be optimized for the typical use case comparing
+ finite numbers. Note that infinity values are equal.
+
++------------------------------------------+
+Precision.equals(Double.NaN, 1000.0) // false
+Precision.equals(Double.NaN, Double.NaN) // false
+Precision.equalsIncludingNaN(Double.NaN, Double.NaN) // true
+
+Precision.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY) // true
+Precision.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY) // true
+Precision.equals(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY) // false
++------------------------------------------+
+
+ <<<Precision>>> provides a <<<compareTo>>> method to provide ordering of numbers that are
+ not considered equal using the tolerance:
+
++------------------------------------------+
+Precision.compareTo(100, 100, 0.0) // 0
+Precision.compareTo(100, 101, 1.0) // 0
+Precision.compareTo(100, 102, 1.0) // -1
+Precision.compareTo(102, 100, 1.0) // 1
++------------------------------------------+
+
+ The comparison uses the natural ordering and is symmetric with regard to <<<NaN>>> values.
+ The comparison using <<<\<, ==, \>>>> is extended in the <<<DoubleEquivalence>>> interface
+ that supports <<<\<=, \>=>>> and signum.
+
++------------------------------------------+
+Precision.DoubleEquivalence eq = Precision.doubleEquivalenceOfEpsilon(1.0);
+eq.lt(100, 100) // false
+eq.lte(100, 100) // true
+eq.eq(100, 100) // true
+eq.gte(100, 100) // true
+eq.gt(100, 100) // false
++------------------------------------------+
+
+ <<<Precision>>> also provides methods for other floating-point operations such as rounding and
+ computing a representable delta from a number and an ideal delta.
+
++------------------------------------------+
+// Round to a number of digits to the right of the decimal point
+Precision.round(678.125, 4) // 678.125
+Precision.round(678.125, 3) // 678.125
+Precision.round(678.125, 2) // 678.13
+Precision.round(678.125, 1) // 678.1
+Precision.round(678.125, 0) // 678.0
+Precision.round(678.125, -1) // 680.0
+Precision.round(678.125, -2) // 700.0
+
+Precision.representableDelta(1.0, 0.1) // 0.10000000000000009
++------------------------------------------+
+
+Field
+
+ The {{{../commons-numbers-field/index.html}commons-numbers-field}} module
+ provides utilities related to the concept of field
+ ({{{../commons-numbers-field/apidocs/org/apache/commons/numbers/field/package-summary.html}field API}}).
+
+ A field is any set of elements that satisfies the field axioms for both addition and
+ multiplication and is a commutative division algebra. The <<<Field>>> interface
+ defines the operations of a field. Implementations are provided for rational numbers
+ as <<<FractionField>>> and <<<BigFractionField>>>; and real numbers as <<<FP64Field>>>.
+
++------------------------------------------+
+Field<FP64> field = FP64Field.get();
+FP64 result = field.one().multiply(3).divide(field.one().multiply(4));
+double value = result.doubleValue();
+// value = 0.75
++------------------------------------------+
+
+ The field abstraction can be used to program computations independently of the underlying
+ representation as any <<<Field\<T\>>>> can be manipulated using the arithmetic operations of
+ add, subtract, multiply and divide.
+
+Fraction
+
+ The {{{../commons-numbers-fraction/index.html}commons-numbers-fraction}} module
+ provides fraction utilities
+ ({{{../commons-numbers-fraction/apidocs/org/apache/commons/numbers/fraction/package-summary.html}fraction API}}).
+ Classes are provided to represent rational numbers and to evaluate continued fractions.
+
+* Rational Numbers
+
+ The <<<Fraction>>> class is a representation of a rational number <<<p / q>>> using
+ <<<int>>> values for the numerator <<<p>>> and denominator <<<q>>>.
+
+ Instances are constructed with factory methods:
+
++------------------------------------------+
+int p = 3;
+int q = 4;
+Fraction f = Fraction.of(p, q);
+// f == 3 / 4
++------------------------------------------+
+
+ <<<Fraction>>> can be created using a <<<double>>>. The floating-point number may not be exactly
+ representable; a continued fraction is used to converge on a rational representation within a
+ specified absolute tolerance, or a maximum denominator. An <<<ArithmeticException>>> is thrown
+ if the algorithm fails to converge or the number is not representable.
+
++------------------------------------------+
+int maxIterations = 100;
+// tolerance
+Fraction a = Fraction.from(0.6152, 0.02, maxIterations);
+Fraction b = Fraction.from(0.6152, 1.0e-7, maxIterations);
+// a = 3 / 5 == 0.6
+// b = 769 / 1250 == 0.6152 (exact)
+
+// max denominator
+Fraction c = Fraction.from(0.6152, 9);
+Fraction d = Fraction.from(0.6152, 9999);
+// c = 3 / 5 == 0.6
+// d = 769 / 1250 == 0.6152 (exact)
+
+Fraction e = Fraction.from(Math.pow(2, 31));
+// e = Integer.MIN_VALUE / -1
+
+// *** Throws an ArithmeticException ***
+Fraction.from(Math.pow(2, 32));
++------------------------------------------+
+
+ The fraction is represented in reduced form using the greatest common divisor. For example
+ <<<240 / 256>>> is reduced to <<<15 / 16>>>. The sign can be either in the numerator or
+ the denominator; the sign of the fraction is accessed using the <<<signum()>>> method.
+ Fraction equality can be evaluated using <<<equals()>>>. The class implements <<<Comparable\<Fraction\>>>>
+ to allow sorting using the natural order imposed by the fraction's sign and magnitude.
+
++------------------------------------------+
+Fraction f1 = Fraction.of(-240, 256);
+Fraction f2 = Fraction.of(15, -16);
+
+f1.signum() == -1
+f1.equals(f2) == true
+f1.compareTo(f2) == 0
+f1.compareTo(Fraction.ZERO) == -1
+
+Fraction.of(Integer.MIN_VALUE, Integer.MIN_VALUE).compareTo(Fraction.ONE) == 0
++------------------------------------------+
+
+ Arithmetic operations are provided that return new instances of <<<Fraction>>>. Note that
+ fraction operations are <exact>.
+
++------------------------------------------+
+Fraction result = Fraction.of(1, 2).add(Fraction.of(1, 3))
+ .add(Fraction.of(1, 6));
+// result == 1 / 1
+// Note: 1.0 / 2 + 1.0 / 3 + 1.0 / 6 == 0.9999999999999999 (inexact)
++------------------------------------------+
+
+ <<<Fraction>>> extends <<<java.lang.Number>>> and can be converted to other primitive numbers
+ with possible loss of precision:
+
++------------------------------------------+
+double a = Fraction.of(1, 8).doubleValue();
+double b = Fraction.of(1, 3).doubleValue();
+int c = Fraction.of(8, 3).intValue();
+// a == 0.125 (exact)
+// b == 1.0 / 3 (inexact)
+// c == 2 (inexact, whole number part of 2 2/3)
++------------------------------------------+
+
+ <<<Fraction>>> is limited to rational numbers representable using <<<int>>> values. Operations
+ that cannot be represented will raise an <<<ArithmeticException>>>. Intermediate
+ computations may use the <<<long>>> datatype and arithmetic is relatively fast.
+
+ The <<<BigFraction>>> class uses <<<BigInteger>>> for the numerator and denominator and can
+ provide exact arithmetic up to the limitations of <<<BigInteger>>>. This is documented as
+ at least <<<+/- 2^Integer.MAX_VALUE>>> (exclusive) and may support values outside of that range.
+
+ The <<<BigFraction>>> class provides all the arithmetic operations of <<<Fraction>>> and
+ can be used when <<<Fraction>>> cannot represent the rational numbers; there will be a performance
+ cost to using <<<BigFraction>>> due to the switch from primitive values to <<<BigInteger>>> for
+ computations.
+
+ <<<BigFraction>>> can be constructed from <<<int>>>, <<<long>>> or <<<BigInteger>>> numerator
+ and denominators.
+
++------------------------------------------+
+BigFraction a = BigFraction.of(1, 3);
+// a == 1 / 3
++------------------------------------------+
+
+ The <<<BigFraction>>> conversion of <<<double>>> values can be exact, or adjusted to be
+ within a provided tolerance. Note that exact conversion may create an unexpected rational
+ number as it is limited by the precision of the input <<<double>>> value which may be inexact:
+
++------------------------------------------+
+BigFraction a = BigFraction.from(1.0 / 3);
+// a == 6004799503160661 / 18014398509481984
+
+// max denominator
+BigFraction b = BigFraction.from(1.0 / 3, 3);
+// b == 1 / 3
++------------------------------------------+
+
+* Continued Fractions
+
+ A generalized continued fraction is an expression of the form:
+
+ \( x = b_0 + \cfrac\{a_1\}\{b_1 + \cfrac\{a_2\}\{b_2 + \cfrac\{a_3\}\{b_3 + \cfrac\{a_4\}\{b_4 + \ddots\,\}\}\}\} \)
+
+ Classes are provided to evaluate the expression through iteration to a provided error tolerance.
+ The user must supply the coefficients \( a \) and \( b \).
+
+ The <<<ContinuedFraction>>> class requires a function to supply the <n>th coefficients; the
+ API allows the fraction function to be evaluated for different arguments. This is useful when
+ the coefficients can be computed using a formula based on the index and the argument.
+ The class is abstract and must be extended to provide the coefficients \( a \) and \( b \).
+ For example the following fraction:
+
+ \( \tan(z) = \cfrac\{z\}\{1 - \cfrac\{z^2\}\{3 - \cfrac\{z^2\}\{5 - \ddots\,\}\}\} \)
+
+ Can be computed using:
+
++------------------------------------------+
+ContinuedFraction cf = new ContinuedFraction() {
+ @Override
+ public double getA(int n, double x) {
+ return n < 2 ? x : -x * x;
+ }
+
+ @Override
+ public double getB(int n, double x) {
+ return n == 0 ? 0 : 2 * n - 1;
+ }
+};
+
+double eps = 1e-8;
+double z = 0.125;
+double result = cf.evaluate(z, eps);
+// result ~ Math.tan(z)
++------------------------------------------+
+
+ The <<<GeneralizedContinuedFraction>>> class requires a generator for the next pair of
+ coefficients. This is useful when the coefficients can be computed using the previous values.
+ The class evaluates the fraction using static methods and a supplied generator of coefficients.
+ This can be done with the generator supplying the initial term \( b_0 \) where \( a_0 \) is
+ ignored, or with the generator starting at \( (a_1, b_1) \) and the term \( b_0 \) provided
+ separately.
+
+ For example the golden ratio:
+
+ \( x = 1 + \cfrac\{1\}\{1 + \cfrac\{1\}\{1 + \cfrac\{1\}\{1 + \ddots\,\}\}\} \)
+
+ Can be computed as:
+
++------------------------------------------+
+double eps = 1e-10;
+double gr1 = GeneralizedContinuedFraction.value(() -> Coefficient.of(1, 1), eps);
+double gr2 = GeneralizedContinuedFraction.value(1, () -> Coefficient.of(1, 1), eps);
+// gr1 ~ gr2 ~ 1.6180339887498948...
++------------------------------------------+
+
+ Whether to separate the term \( b_0 \) depends on the fraction and the algorithm convergence.
+ See the
+ {{{../commons-numbers-fraction/apidocs/org/apache/commons/numbers/fraction/GeneralizedContinuedFraction.html}GeneralizedContinuedFraction}}
+ documentation for details. Note that it is also possible to evaluate part of the fraction using
+ only later terms and then computing the final result by including the early terms.
+
+ An example using a recursive generator for the evaluation of \( \tan(z) \) is computed using:
+
++------------------------------------------+
+static class Tan implements Supplier<Coefficient> {
+ private double a;
+ private double b = -1;
+
+ /**
+ * @param z Argument z
+ */
+ Tan(double z) {
+ a = z;
+ }
+
+ @Override
+ public Coefficient get() {
+ b += 2;
+ // Special first case
+ if (b == 1) {
+ double z = a;
+ // Update the term for the rest of the fraction.
+ // The continuant is subtracted from the b terms, thus all the
+ // remaining a terms are negative.
+ a *= -z;
+ return Coefficient.of(z, b);
+ }
+ return Coefficient.of(a, b);
+ }
+}
+
+double z = 0.125;
+double tan1 = GeneralizedContinuedFraction.value(0, new Tan(z));
+
+// Advance 1 term
+Tan t = new Tan(z);
+Coefficient c = t.get();
+double tan2 = c.getA() / GeneralizedContinuedFraction.value(c.getB(), t);
+
+// tan1 ~ Math.tan(z)
+// tan2 == Math.tan(z) (more accurate)
++------------------------------------------+
+
+ A simple continued fraction will have an \( a \) coefficient of 1. For example the following
+ fraction:
+
+ \( \frac\{415\}\{93\} = 4 + \cfrac\{1\}\{2 + \cfrac\{1\}\{6 + \cfrac\{1\}\{7\}\}\} \)
+
+ can be evaluated as a simple continued fraction using:
+
++------------------------------------------+
+private static Supplier<Coefficient> simpleContinuedFraction(double... coefficients) {
+ return new Supplier<Coefficient>() {
+ /* iteration. */
+ private int n;
+ /* denominator terms. */
+ private double[] b = coefficients.clone();
+
+ @Override
+ public Coefficient get() {
+ if (n != b.length) {
+ // Return the next term
+ return Coefficient.of(1, b[n++]);
+ }
+ return Coefficient.of(0, 1);
+ }
+ };
+}
+
+double result1 = GeneralizedContinuedFraction.value(simpleContinuedFraction(4, 2, 6, 7));
+double result2 = GeneralizedContinuedFraction.value(4, simpleContinuedFraction(2, 6, 7));
+// result1 ~ result2 ~ 415.0 / 93.0
++------------------------------------------+
+
+Gamma
+
+ The {{{../commons-numbers-gamma/index.html}commons-numbers-gamma}} module
+ provides utilities related to the "Gamma" function
+ ({{{../commons-numbers-gamma/apidocs/org/apache/commons/numbers/gamma/package-summary.html}gamma API}}).
+
+*---+---+
+Gamma function | \\( \\Gamma(a) \\)
+*---+---+
+Incomplete gamma functions (lower and upper) | \\( \\Gamma(a) = \\gamma(a, x) + \\Gamma(a, x) \\)
+*---+---+
+Regularized gamma functions (lower and upper) | \\( 1 = P(a, x) + Q(a, x) \\)
+*---+---+
+Ratio of gamma functions | \\( \\frac\\{\\Gamma(a)\\}\\{\\Gamma(b)\\} \\)
+*---+---+
+Digamma function | \\( \\frac\\{d\\}\\{dx\\}(\\ln \\Gamma(x)) \\)
+*---+---+
+Trigamma function | \\( \\psi_1(x) = \\frac\\{d^2\\}\\{dx^2\\} (\\ln \\Gamma(x)) \\)
+*---+---+
+Logarithm of the absolute value of the gamma function | \\( \\ln\\, \\lvert \\Gamma(x) \\rvert \\)
+*---+---+
+Beta function | \\( B(a, b) = \\frac\\{\\Gamma(a)\\ \\Gamma(b)\\}\\{\\Gamma(a+b)\\} \\)
+*---+---+
+Incomplete beta function (and the complement) | \\( B_x(a, b) = \\int_0^x t^\\{a-1\\}\\,(1-t)^\\{b-1\\}\\,dt \\)
+*---+---+
+Logarithm of the beta function | \\( \\ln B(a, b) \\)
+*---+---+
+Error function | \\( \\operatorname\\{erf\\}(z) \\)
+*---+---+
+Complementary error function | \\( \\operatorname\\{erfc\\}(z) \\)
+*---+---+
+Scaled complementary error function | \\( \\operatorname\\{erfcx\\}(z) \\)
+*---+---+
+Difference between error function values | \\( \\operatorname\\{erf\\}(a) - \\operatorname\\{erf\\}(b) \\)
+*---+---+
+Inverse error functions |
+*---+---+
+
+ Functions are provided using static class methods. These may be optionally parameterized
+ if the method uses an iterative computation to control the function evaluation. For example:
+
++------------------------------------------+
+double result = Erfc.value(1.23);
+
+// Default function evaluation
+double a = 1.23;
+double x = 4.56;
+double result1 = IncompleteGamma.Lower.value(a, x);
+
+// Parameterize function evaluation
+double epsilon = 1e-10;
+int maxIterations = 1000;
+double result2 = IncompleteGamma.Lower.value(a, x, epsilon, maxIterations);
+// result1 ~ result2
++------------------------------------------+
+
+ The gamma functions are used to evaluate many of the probability distributions provided in the
+ {{{https://commons.apache.org/proper/commons-statistics/}commons-statistics}} project.
+
+Primes
+
+ The {{{../commons-numbers-primes/index.html}commons-numbers-primes}} module
+ provides utilities related to prime numbers
+ ({{{../commons-numbers-primes/apidocs/org/apache/commons/numbers/primes/package-summary.html}primes API}}).
+
+ The <<<Primes>>> class provides static methods for working with prime numbers in the range of
+ an <<<int>>>. Methods are provided to determine if a value is prime, compute the next prime
+ after a value and the prime factors of a number.
+
++------------------------------------------+
+int n = 51237173;
+boolean prime = Primes.isPrime(n);
+int m = Primes.nextPrime(n);
+// prime == false
+// m == 51237233
+
+List<Integer> f1 = Primes.primeFactors(n);
+List<Integer> f2 = Primes.primeFactors(m);
+// f1 == [13, 863, 4567]
+// f2 == [51237233]
+// n == 13 * 863 * 4567
++------------------------------------------+
+
+Quaternion
+
+ The {{{../commons-numbers-quaternion/index.html}commons-numbers-quaternion}} module
+ provides utilities for working with quarternion numbers
+ ({{{../commons-numbers-quaternion/apidocs/org/apache/commons/numbers/quaternion/package-summary.html}quaternion API}}).
+
+ The <<<Quaternion>>> class represents Hamilton's hypecomplex number in the form
+ \( H = w + x\,i + y\,j + z\,k \), where \( w \) is the scalar component and \( [x, y, z] \) is
+ the vector component.
+
+ The class is immutable and instances are constructed with factory methods. Getters are provided
+ for access to the components:
+
++------------------------------------------+
+double w = 2;
+double x = 3;
+double y = 4;
+double z = 5;
+Quaternion h1 = Quaternion.of(w, x, y, z);
+Quaternion h2 = Quaternion.of(w, new double[]{x, y, z});
+h1.getW(); // w
+h1.getScalarPart(); // w
+h1.getVectorPart(); // [x, y, z]
+// h1 == h2
++------------------------------------------+
+
+ Methods are provided for arithmetic (add, subtract, multiply) and other quaternion operations
+ such as scaling, dot product, negation, conjugation and normalization.
+
++------------------------------------------+
+Quaternion h = Quaternion.of(1, 2, 3, 4);
+Quaternion h1 = h.add(Quaternion.ONE); // [2, 2, 3, 4]
+Quaternion hi = h.add(Quaternion.I); // [1, 3, 3, 4]
+Quaternion hj = h.add(Quaternion.J); // [1, 2, 4, 4]
+Quaternion hk = h.add(Quaternion.K); // [1, 2, 3, 5]
++------------------------------------------+
+
+ The binary operations acting on two <<<Quaternion>>> instances are provided as instance
+ methods and static methods for convenience when using method references as lambda functions:
+
++------------------------------------------+
+Quaternion h1 = Quaternion.of(1, 2, 3, 4);
+Quaternion h2 = Quaternion.of(5, 6, 7, 8);
+Quaternion result1 = h1.multiply(h2);
+Quaternion result2 = Quaternion.multiply(h1, h2);
+// result1 == result2
++------------------------------------------+
+
+ The class evaluates binary equality using <<<equals(Object)>>> and provides a helper method
+ to evaluate equality within an absolute tolerance:
+
++------------------------------------------+
+Quaternion q1 = Quaternion.of(1, 2, 3, 4);
+Quaternion q2 = Quaternion.of(1, 2, 3, 4 + 1e-10);
+q1.equals(q2); // false
+q1.equals(q2, 1e-9); // true
++------------------------------------------+
+
+ Quaternions are used to apply rotations in 3-dimensional Euclidean space in the
+ {{{https://commons.apache.org/proper/commons-geometry/}commons-geometry}} project.
+
+ The <<<Slerp>>> class performs spherical linear interpolation
+ ({{{https://en.wikipedia.org/wiki/Slerp}Slerp}}). The algorithm is designed to interpolate
+ smoothly between two rotations/orientations, producing a constant-speed motion along an arc.
+
++------------------------------------------+
+static Quaternion createZRotation(final double theta) {
+ double halfAngle = theta * 0.5;
+ return Quaternion.of(Math.cos(halfAngle), 0, 0, Math.sin(halfAngle));
+}
+
+Quaternion q1 = createZRotation(0.75 * Math.PI);
+Quaternion q2 = createZRotation(0.76 * Math.PI);
+
+Slerp slerp = new Slerp(q1, q2);
+
+slerp.apply(0.0) // ~ q1
+slerp.apply(0.25) // ~ createZRotation(0.7525 * Math.PI)
+slerp.apply(0.5) // ~ createZRotation(0.755 * Math.PI)
+slerp.apply(0.75) // ~ createZRotation(0.7575 * Math.PI)
+slerp.apply(1.0) // ~ q2
++------------------------------------------+
+
+Root Finder
+
+ The {{{../commons-numbers-rootfinder/index.html}commons-numbers-rootfinder}} module
+ provides utilities for finding the zero of a function
+ ({{{../commons-numbers-rootfinder/apidocs/org/apache/commons/numbers/rootfinder/package-summary.html}rootfinder API}}).
+
+ The <<<BrentSolver>>> class implements the Brent algorithm for finding the zeros of real
+ univariate functions. The solver requires an interval that brackets a root and will raise an
+ exception if there is no sign change between the bounds \( [a, b] \). The relative \( \epsilon \)
+ and absolute \( \delta \) accuracy specify the convergence tolerance for the function value
+ \( x \) to zero as: \( 2\,\epsilon\,|x| + \delta \).
+ The function accuracy is used to return the initial bracket bounds, or initial guess,
+ if the function value is within the specified accuracy of zero.
+
++------------------------------------------+
+double relAccuracy = 1e-6;
+double absAccuracy = 1e-14;
+double functionAccuracy = 1e-15;
+BrentSolver solver = new BrentSolver(relAccuracy,
+ absAccuracy,
+ functionAccuracy);
+double result1 = solver.findRoot(Math::sin, 3, 4);
+double result2 = solver.findRoot(Math::sin, 3, 3.14, 4); // With initial guess
+// result1 ~ result2 ~ Math.PI
+
+// *** Throws an IllegalArgumentException ***
+solver.findRoot(Math::sin, 2, 3);
++------------------------------------------+
+
+Dependencies
+
+ Apache Commons Numbers requires JDK 1.8+ and has no runtime dependencies.
diff --git a/src/site/site.xml b/src/site/site.xml
index dcdf3d08..02e20845 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -23,6 +23,12 @@
</bannerRight>
<body>
+ <head>
+ <![CDATA[<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
+ </script>
+ <link rel="stylesheet" href="$relativePath/style/module.css" type="text/css" />]]>
+ </head>
+
<menu name="Numbers">
<item name="Overview" href="/index.html"/>
<item name="Downloads" href="http://commons.apache.org/numbers/download_numbers.cgi"/>
@@ -34,15 +40,22 @@
<item name="Developers Guide" href="/developers.html"/>
</menu>
- <!-- <menu name="User Guide">
+ <menu name="User Guide">
<item name="Contents" href="/userguide/index.html"/>
- </menu> -->
+ </menu>
+ </body>
- <head>
- <![CDATA[<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
- </script>
- <link rel="stylesheet" href="$relativePath/style/module.css" type="text/css" />]]>
- </head>
+ <custom>
+ <!-- Custom properties controlling the commons-skin template. -->
+ <commonsSkin>
+ <!--
+ Convert preformatted source section tags to prettyprint:
+ <div class="source"><pre> to <div class="source"><pre class="prettyprint">
+ -->
+ <prettyPrintSourcePreTags>true</prettyPrintSourcePreTags>
- </body>
+ <!-- Add the "linenums" class to the prettyprint enabled source tags -->
+ <prettyPrintLineNumbersEnabled>false</prettyPrintLineNumbersEnabled>
+ </commonsSkin>
+ </custom>
</project>
diff --git a/src/site/xdoc/userguide/core.xml b/src/site/xdoc/userguide/core.xml
deleted file mode 100644
index e9dcee83..00000000
--- a/src/site/xdoc/userguide/core.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
- 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.
- -->
-
-<document>
- <properties>
- <title>User Guide - Module "core"</title>
- </properties>
-
-<body>
-
-<section name="Core">
-
-<subsection name="1.1 Section" href="section">
- <p>
- Contribution welcome...
- </p>
-</subsection>
-
-</section>
-
-</body>
-</document>
diff --git a/src/site/xdoc/userguide/index.xml b/src/site/xdoc/userguide/index.xml
deleted file mode 100644
index 726df01d..00000000
--- a/src/site/xdoc/userguide/index.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
- 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.
- -->
-
-<document url="index.html">
- <properties>
- <title>The Commons Numbers User Guide - Table of Contents</title>
- </properties>
-
- <body>
- <section name="Table of Contents" href="toc">
- <ul>
- <li>
- <a href="core.html">1. Core</a>
- </li>
- </ul>
- </section>
- </body>
-
-</document>
diff --git a/src/site/xdoc/userguide/xdoc.xsl b/src/site/xdoc/userguide/xdoc.xsl
deleted file mode 100644
index cfbd5f52..00000000
--- a/src/site/xdoc/userguide/xdoc.xsl
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- 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.
- -->
-
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:template match="/">
- <html xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <head>
- <xsl:apply-templates select="/document/properties/title"/>
- <xsl:apply-templates select="/document/meta"/>
- <style type="text/css">
- @import url("../style/tigris.css");
- @import url("../style/maven.css");
- @import url("../style/project.css");
- </style>
- <link rel="stylesheet" href="../style/print.css" type="text/css" media="print"></link>
- </head>
- <xsl:apply-templates select="/document/body"/>
- </html>
- </xsl:template>
- <xsl:template match="body">
- <body>
- <div class="app">
- <xsl:apply-templates/>
- </div>
- </body>
- </xsl:template>
- <xsl:template match="section">
- <div>
- <h3><xsl:value-of select="@name"/></h3>
- <xsl:apply-templates/>
- </div>
- </xsl:template>
- <xsl:template match="subsection">
- <div>
- <h4><xsl:value-of select="@name"/></h4>
- <xsl:apply-templates/>
- </div>
- </xsl:template>
- <xsl:template match="source">
- <div id="source">
- <pre>
- <xsl:apply-templates/>
- </pre>
- </div>
- </xsl:template>
- <xsl:template match="node()|@*">
- <xsl:copy>
- <xsl:apply-templates select="@*"/>
- <xsl:apply-templates/>
- </xsl:copy>
- </xsl:template>
-</xsl:stylesheet>