Skip to content

Commit 953ab60

Browse files
authored
Merge pull request #91 from cicirello/development
Various code improvements and minor optimizations
2 parents d7d32dd + 20cc206 commit 953ab60

16 files changed

+1109
-320
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,26 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7-
## [Unreleased] - 2021-02-05
7+
## [Unreleased] - 2021-02-13
88

99
### Added
1010

1111
### Changed
12+
* Minor optimizations to ReversalDistance and ReinsertionDistance.
13+
* Refactored the RandomVariates.nextCauchy methods to remove redundancy.
14+
* Refactored org.cicirello.math.rand.BTPE to remove redundancy.
15+
* Refactored various methods of RandomIndexer to remove redundancy.
16+
* Minor optimizations to RandomIndexer.sample methods.
1217

1318
### Deprecated
1419

1520
### Removed
1621

1722
### Fixed
23+
* Fixed large magnitude negative input case in MathFunctions.logGamma.
1824

1925
### CI/CD
26+
* Test cases added to improve test coverage.
2027

2128

2229
## [2.3.0] - 2021-01-30

src/org/cicirello/math/MathFunctions.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019 Vincent A. Cicirello, <https://www.cicirello.org/>.
2+
* Copyright 2019-2021 Vincent A. Cicirello, <https://www.cicirello.org/>.
33
*
44
* This file is part of JavaPermutationTools (https://jpt.cicirello.org/).
55
*
@@ -26,8 +26,7 @@
2626
* MathFunctions is a class of utility methods that implement various mathematical functions.
2727
*
2828
* @author <a href=https://www.cicirello.org/ target=_top>Vincent A. Cicirello</a>, <a href=https://www.cicirello.org/ target=_top>https://www.cicirello.org/</a>
29-
* @version 8.22.2019
30-
* @since 2.0
29+
* @version 2.12.2021
3130
*
3231
*/
3332
public final class MathFunctions {
@@ -75,16 +74,23 @@ public static double logGamma(double n) {
7574
// input parameter is too large to calculate function
7675
return Double.NEGATIVE_INFINITY;
7776
} else if (n < -34.0) {
77+
if (n < -4.5035996273704955e15) {
78+
// inputs lower than this are essentially negative integers
79+
// due to precision of floating-point numbers.
80+
// This is the smallest negative double with an ulp less than 1.
81+
return Double.POSITIVE_INFINITY;
82+
}
7883
n = -n;
79-
double p = ((int)n);
84+
double p = ((long)n);
8085
if (p == n) return Double.POSITIVE_INFINITY;
8186
double z = n - p;
8287
if (z > 0.5) {
8388
p = p + 1.0;
8489
z = p - n;
8590
}
8691
z = n * Math.sin(z * Math.PI);
87-
if (z == 0.0) return Double.POSITIVE_INFINITY;
92+
// This check doesn't seem to be necessary given addition of first check in block.
93+
// if (z == 0.0) return Double.POSITIVE_INFINITY;
8894
// ln(PI)
8995
final double LOG_PI = 1.14472988584940017414;
9096
return LOG_PI - Math.log(z) - logGamma(n);

src/org/cicirello/math/la/JacobiDiagonalization.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018 Vincent A. Cicirello, <https://www.cicirello.org/>.
2+
* Copyright 2018, 2021 Vincent A. Cicirello, <https://www.cicirello.org/>.
33
*
44
* This file is part of JavaPermutationTools (https://jpt.cicirello.org/).
55
*
@@ -26,8 +26,7 @@
2626
* This class uses Jacobi iteration to compute the eigenvalues and eigenvectors of a symmetric matrix, provided as a 2-D Java array.
2727
*
2828
* @author <a href=https://www.cicirello.org/ target=_top>Vincent A. Cicirello</a>, <a href=https://www.cicirello.org/ target=_top>https://www.cicirello.org/</a>
29-
* @version 1.18.7.1
30-
* @since 1.3
29+
* @version 2.15.2021
3130
*/
3231
public class JacobiDiagonalization {
3332

@@ -150,7 +149,7 @@ private boolean oneIteration(double epsilon) {
150149
for (int j = 0; j < N; j++) {
151150
if (i==j) continue;
152151
double absAij = Math.abs(a[i][j]);
153-
if (absAij > 0 && absAij < EPSILON) {
152+
if (absAij > 0 && absAij < epsilon) {
154153
// zero out any small entries
155154
absAij = a[i][j] = 0.0;
156155
}
@@ -175,11 +174,13 @@ private boolean oneIteration(double epsilon) {
175174
}
176175
return true;
177176
}
177+
/* This appears to be an impossibility, so I'm removing it.
178178
// If a_pq is small, simply set entry to 0 and don't rotate.
179179
if (a_pq < epsilon) {
180180
a[p][q] = 0;
181181
return false;
182182
}
183+
*/
183184
// compute some values
184185
double f = -a_pq;
185186
double g = 0.5*(a[p][p]-a[q][q]);

src/org/cicirello/math/la/MatrixOps.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018-2019 Vincent A. Cicirello, <https://www.cicirello.org/>.
2+
* Copyright 2018-2021 Vincent A. Cicirello, <https://www.cicirello.org/>.
33
*
44
* This file is part of JavaPermutationTools (https://jpt.cicirello.org/).
55
*
@@ -27,8 +27,7 @@
2727
* represented as 2-D Java arrays.
2828
*
2929
* @author <a href=https://www.cicirello.org/ target=_top>Vincent A. Cicirello</a>, <a href=https://www.cicirello.org/ target=_top>https://www.cicirello.org/</a>
30-
* @version 1.19.5.16
31-
* @since 1.3
30+
* @version 2.13.2021
3231
*/
3332
public final class MatrixOps {
3433

@@ -38,7 +37,8 @@ private MatrixOps() {}
3837
/**
3938
* Transpose a square matrix inline.
4039
* @param matrix the matrix to transpose, with result replacing contents of matrix.
41-
* @return The matrix is returned for convenience for passing to other methods requiring a matrix as parameter. It is the same
40+
* @return The matrix is returned for convenience for passing to other
41+
* methods requiring a matrix as parameter. It is the same
4242
* object reference that was passed as a parameter.
4343
*/
4444
public static int[][] transposeSquareMatrixInline(int[][] matrix) {
@@ -237,7 +237,7 @@ public static double[][] difference(double[][] A, double[][] B) {
237237
public static int[][] product(int[][] A, int[][] B, int[][] C) {
238238
if (A.length == 0 && B.length > 0 || A.length > 0 && B.length == 0) {
239239
throw new IllegalArgumentException("If either matrix has 0 rows, both must.");
240-
} else if (A.length == 0 && B.length == 0) {
240+
} else if (A.length == 0) {
241241
if (C==null) return new int[0][0];
242242
else if (C.length==0) return C;
243243
else throw new IllegalArgumentException("C's dimensions are inconsistent with A and B.");
@@ -269,7 +269,7 @@ public static int[][] product(int[][] A, int[][] B, int[][] C) {
269269
public static double[][] product(double[][] A, double[][] B, double[][] C) {
270270
if (A.length == 0 && B.length > 0 || A.length > 0 && B.length == 0) {
271271
throw new IllegalArgumentException("If either matrix has 0 rows, both must.");
272-
} else if (A.length == 0 && B.length == 0) {
272+
} else if (A.length == 0) {
273273
if (C==null) return new double[0][0];
274274
else if (C.length==0) return C;
275275
else throw new IllegalArgumentException("C's dimensions are inconsistent with A and B.");

src/org/cicirello/math/rand/BTPE.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019 Vincent A. Cicirello, <https://www.cicirello.org/>.
2+
* Copyright 2019-2021 Vincent A. Cicirello, <https://www.cicirello.org/>.
33
*
44
* This file is part of JavaPermutationTools (https://jpt.cicirello.org/).
55
*
@@ -47,9 +47,7 @@
4747
* one instance of BTPE per thread using ThreadLocal.</p>
4848
*
4949
* @author <a href=https://www.cicirello.org/ target=_top>Vincent A. Cicirello</a>, <a href=https://www.cicirello.org/ target=_top>https://www.cicirello.org/</a>
50-
* @version 9.4.2019
51-
* @since 2.0
52-
*
50+
* @version 2.12.2021
5351
*/
5452
final class BTPE {
5553

@@ -61,14 +59,7 @@ final class BTPE {
6159
* @return A pseudorandom integer from a binomial distribution.
6260
*/
6361
public static int nextBinomial(int n, double p, Random generator) {
64-
BTPE btpe = tl.get();
65-
if (btpe == null) {
66-
btpe = new BTPE(n, p);
67-
tl.set(btpe);
68-
} else if (btpe.n != n || btpe.p != p) {
69-
btpe.init(n, p);
70-
}
71-
return btpe.next(generator);
62+
return threadLocalInstance(n, p).next(generator);
7263
}
7364

7465
/**
@@ -79,20 +70,28 @@ public static int nextBinomial(int n, double p, Random generator) {
7970
* @return A pseudorandom integer from a binomial distribution.
8071
*/
8172
public static int nextBinomial(int n, double p, SplittableRandom generator) {
73+
return threadLocalInstance(n, p).next(generator);
74+
}
75+
76+
// We cache constants until n or p changes. We use ThreadLocal for
77+
// cache so that we are thread safe. Each thread has its own cache.
78+
private static final ThreadLocal<BTPE> tl = new ThreadLocal<BTPE>();
79+
80+
/*
81+
* Private helper to handle getting the thread local instance of BTPE,
82+
* initializing if necessary, and generating if it doesn't already exist.
83+
*/
84+
private static BTPE threadLocalInstance(int n, double p) {
8285
BTPE btpe = tl.get();
8386
if (btpe == null) {
8487
btpe = new BTPE(n, p);
8588
tl.set(btpe);
8689
} else if (btpe.n != n || btpe.p != p) {
8790
btpe.init(n, p);
8891
}
89-
return btpe.next(generator);
92+
return btpe;
9093
}
9194

92-
// We cache constants until n or p changes. We use ThreadLocal for
93-
// cache so that we are thread safe. Each thread has its own cache.
94-
private static final ThreadLocal<BTPE> tl = new ThreadLocal<BTPE>();
95-
9695
// Variables for caching constants that only change when n or p changes.
9796
// Constant cache for BTPE and simple inverse based approach
9897
private int n;

0 commit comments

Comments
 (0)