to version 3.5.11

This commit is contained in:
wyq 2023-04-16 09:36:10 +08:00
parent 1013d3cbc2
commit ef5cae235b
20 changed files with 1636 additions and 138 deletions

18
.idea/encodings.xml generated
View File

@ -3,8 +3,18 @@
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
<file url="file://$PROJECT_DIR$/meteoinfo-chart/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-chart/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-console/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-console/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-data/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-data/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-dataframe/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-dataframe/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-geo/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-geo/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-geometry/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-geometry/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-image/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-image/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-lab/src/main/java" charset="UTF-8" />
@ -13,6 +23,14 @@
<file url="file://$PROJECT_DIR$/meteoinfo-map/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-math/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-math/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-ndarray/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-ndarray/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-projection/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-projection/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-table/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-table/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-ui/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/meteoinfo-ui/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>

View File

@ -19,11 +19,6 @@
</properties>
<repositories>
<!--<repository>
<id>central</id>
<name>Maven Central</name>
<url>https://repo1.maven.org/maven2/</url>
</repository>-->
<repository>
<id>jogamp-remote</id>
<name>jogamp mirror</name>
@ -34,21 +29,6 @@
<name>freehep</name>
<url>https://java.freehep.org/maven2/</url>
</repository>
<!--<repository>
<id>boundless</id>
<name>boundlessgeo</name>
<url>https://repo.boundlessgeo.com/main/</url>
</repository>-->
<!--<repository>
<id>jzy3d-snapshots</id>
<name>Jzy3d Snapshots</name>
<url>https://maven.jzy3d.org/snapshots/</url>
</repository>
<repository>
<id>jzy3d-releases</id>
<name>Jzy3d Releases</name>
<url>https://maven.jzy3d.org/releases/</url>
</repository>-->
</repositories>
<dependencies>
@ -92,93 +72,6 @@
<artifactId>jogl-all-main</artifactId>
<version>${jogl.version}</version>
</dependency>
<!--<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-natives-linux-aarch64</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-natives-linux-amd64</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-natives-linux-armv6hf</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-natives-linux-i586</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-natives-macosx-universal</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-natives-windows-amd64</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-natives-windows-i586 </artifactId>
<version>${jogl.version}</version>
</dependency>
&lt;!&ndash; GLUEGEN &ndash;&gt;
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-natives-macosx-universal</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-natives-linux-aarch64</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-natives-linux-amd64</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-natives-linux-armv6hf</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-natives-linux-i586</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-natives-macosx-universal</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-natives-windows-amd64</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-natives-windows-i586</artifactId>
<version>${jogl.version}</version>
</dependency>-->
<dependency>
<groupId>org.joml</groupId>
<artifactId>joml</artifactId>

View File

@ -87,7 +87,6 @@ float calculateDepth(vec3 pos)
vec4 ndc = MVP * vec4(pos, 1.0);
ndc.xyz /= ndc.w;
float depth = 0.5 * (gl_DepthRange.diff * ndc.z + (gl_DepthRange.near + gl_DepthRange.far));
//return depth;
return depth + 0.005;
return depth;
//return ndc.z * 0.5 + 0.5;
}

View File

@ -67,7 +67,7 @@ import java.util.zip.ZipInputStream;
public static String getVersion(){
String version = GlobalUtil.class.getPackage().getImplementationVersion();
if (version == null || version.equals("")) {
version = "3.5.11";
version = "3.5.12";
}
return version;
}

View File

@ -29,11 +29,6 @@
<name>freehep</name>
<url>https://java.freehep.org/maven2/</url>
</repository>
<!--<repository>
<id>boundless</id>
<name>boundlessgeo</name>
<url>https://repo.boundlessgeo.com/main/</url>
</repository>-->
</repositories>
<dependencies>
@ -122,6 +117,11 @@
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<!--<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.30</version>
</dependency>-->
</dependencies>
<build>

View File

@ -1,34 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\common_math\interpolate">
<RecentFolder Folder="D:\Working\MIScript\cuace_dust\py\plot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\grib"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\LaSW"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\LaSW\airship"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\dataframe">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\text"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\model"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\slice"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\linalg"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\interpolate"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite\FY"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\weather"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot\air_path_model_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow\typhoon_map_volume_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\common_math\interpolate\interp1d_kriging.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\common_math\interpolate\griddata_kriging.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\dataframe\dataframe_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\dataframe\reindex_1.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot\air_path_model_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow\typhoon_map_volume_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\common_math\interpolate\interp1d_kriging.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\common_math\interpolate\griddata_kriging.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\dataframe\dataframe_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\dataframe\reindex_1.py"/>
</RecentFiles>
</File>
<Font>

View File

@ -0,0 +1,101 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
/**
* Chebyshev distance (or Tchebychev distance), or L<sub>&infin;</sub> metric
* is a metric defined on a vector space where the distance between two vectors
* is the greatest of their differences along any coordinate dimension.
*
* @author Haifeng Li
*/
public class ChebyshevDistance implements Metric<double[]> {
private static final long serialVersionUID = 1L;
/**
* Constructor.
*/
public ChebyshevDistance() {
}
@Override
public String toString() {
return "Chebyshev Distance";
}
/**
* Chebyshev distance between the two arrays of type integer.
*/
public static double d(int[] x, int[] y) {
if (x.length != y.length) {
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
}
double dist = 0.0;
for (int i = 0; i < x.length; i++) {
double d = Math.abs(x[i] - y[i]);
if (dist < d)
dist = d;
}
return dist;
}
/**
* Chebyshev distance between the two arrays of type float.
* NaN will be treated as missing values and will be excluded from the
* calculation.
*/
public static double d(float[] x, float[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
double dist = 0.0;
for (int i = 0; i < x.length; i++) {
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
double d = Math.abs(x[i] - y[i]);
if (dist < d)
dist = d;
}
}
return dist;
}
/**
* Chebyshev distance between the two arrays of type double.
* NaN will be treated as missing values and will be excluded from the
* calculation.
*/
@Override
public double d(double[] x, double[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
double dist = 0.0;
for (int i = 0; i < x.length; i++) {
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
double d = Math.abs(x[i] - y[i]);
if (dist < d)
dist = d;
}
}
return dist;
}
}

View File

@ -0,0 +1,77 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
import org.meteoinfo.math.MathEx;
import java.util.function.ToDoubleBiFunction;
/**
* Correlation distance is defined as 1 - correlation coefficient.
*
* @author Haifeng Li
*/
public class CorrelationDistance implements Distance<double[]> {
private static final long serialVersionUID = 1L;
/** A character string indicating what type of correlation is employed. */
private String method;
/** Correlation lambda. */
private ToDoubleBiFunction<double[], double[]> cor;
/**
* Constructor of Pearson correlation distance.
*/
public CorrelationDistance() {
this("pearson");
}
/**
* Constructor.
*/
public CorrelationDistance(String method) {
this.method = method.trim().toLowerCase();
switch (this.method) {
case "pearson":
cor = (x, y) -> 1 - MathEx.cor(x, y);
break;
case "spearman":
cor = (x, y) -> 1 - MathEx.spearman(x, y);
break;
case "kendall":
cor = (x, y) -> 1 - MathEx.kendall(x, y);
break;
default:
throw new IllegalArgumentException("Invalid correlation: " + method);
}
}
@Override
public String toString() {
return String.format("Correlation Distance(%s)", method);
}
/**
* Pearson correlation distance between the two arrays of type double.
*/
@Override
public double d(double[] x, double[] y) {
return cor.applyAsDouble(x, y);
}
}

View File

@ -0,0 +1,104 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
import java.io.Serializable;
import java.util.function.ToDoubleBiFunction;
import java.util.stream.IntStream;
import org.meteoinfo.math.blas.UPLO;
import org.meteoinfo.math.matrix.Matrix;
/**
* An interface to calculate a distance measure between two objects. A distance
* function maps pairs of points into the nonnegative reals and has to satisfy
* <ul>
* <li> non-negativity: <code>d(x, y) &ge; 0</code>
* <li> isolation: <code>d(x, y) = 0</code> if and only if <code>x = y</code>
* <li> symmetry: <code>d(x, y) = d(x, y)</code>
* </ul>
* Note that a distance function is not required to satisfy triangular inequality
* <code>|x - y| + |y - z| &ge; |x - z|</code>, which is necessary for a metric.
*
* @author Haifeng Li
*/
public interface Distance<T> extends ToDoubleBiFunction<T,T>, Serializable {
/**
* Returns the distance measure between two objects.
*/
double d(T x, T y);
/**
* Returns the distance measure between two objects.
* This is simply for Scala convenience.
*/
default double apply(T x, T y) {
return d(x, y);
}
@Override
default double applyAsDouble(T x, T y) {
return d(x, y);
}
/**
* Returns the pairwise distance matrix.
*
* @param x samples.
* @return the pairwise distance matrix.
*/
default Matrix D(T[] x) {
int n = x.length;
int N = n * (n - 1) / 2;
Matrix D = new Matrix(n, n);
IntStream.range(0, N).parallel().forEach(k -> {
int j = n - 2 - (int) Math.floor(Math.sqrt(-8*k + 4*n*(n-1)-7)/2.0 - 0.5);
int i = k + j + 1 - n*(n-1)/2 + (n-j)*((n-j)-1)/2;
D.set(i, j, d(x[i], x[j]));
});
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
D.set(i, j, D.get(j, i));
}
}
D.uplo(UPLO.LOWER);
return D;
}
/**
* Returns the pairwise distance matrix.
*
* @param x samples.
* @param y samples.
* @return the pairwise distance matrix.
*/
default Matrix D(T[] x, T[] y) {
int m = x.length;
int n = y.length;
Matrix D = new Matrix(m, n);
IntStream.range(0, m).parallel().forEach(i -> {
T xi = x[i];
for (int j = 0; j < n; j++) {
D.set(i, j, d(xi, y[j]));
}
});
return D;
}
}

View File

@ -0,0 +1,185 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
import java.util.Arrays;
/**
* Euclidean distance. For float or double arrays, missing values (i.e. NaN)
* are also handled.
*
* @see SparseEuclideanDistance
*
* @author Haifeng Li
*/
public class EuclideanDistance implements Metric<double[]> {
private static final long serialVersionUID = 1L;
/**
* The weights used in weighted distance.
*/
private double[] weight = null;
/**
* Constructor. Standard (unweighted) Euclidean distance.
*/
public EuclideanDistance() {
}
/**
* Constructor with a given weight vector.
*
* @param weight the weight vector.
*/
public EuclideanDistance(double[] weight) {
for (int i = 0; i < weight.length; i++) {
if (weight[i] < 0) {
throw new IllegalArgumentException(String.format("Weight has to be nonnegative: %f", weight[i]));
}
}
this.weight = weight;
}
@Override
public String toString() {
if (weight != null) {
return String.format("Weighted Euclidean Distance(%s)", Arrays.toString(weight));
} else {
return "Euclidean Distance";
}
}
/**
* Euclidean distance between the two arrays of type integer. No missing
* value handling in this method.
*/
public double d(int[] x, int[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < x.length; i++) {
double d = x[i] - y[i];
dist += d * d;
}
} else {
if (x.length != weight.length)
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
for (int i = 0; i < x.length; i++) {
double d = x[i] - y[i];
dist += weight[i] * d * d;
}
}
return Math.sqrt(dist);
}
/**
* Euclidean distance between the two arrays of type float.
* NaN will be treated as missing values and will be excluded from the
* calculation. Let m be the number nonmissing values, and n be the
* number of all values. The returned distance is sqrt(n * d / m),
* where d is the square of distance between nonmissing values.
*/
public double d(float[] x, float[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
int n = x.length;
int m = 0;
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < n; i++) {
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
m++;
double d = x[i] - y[i];
dist += d * d;
}
}
} else {
if (x.length != weight.length)
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
for (int i = 0; i < n; i++) {
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
m++;
double d = x[i] - y[i];
dist += weight[i] * d * d;
}
}
}
if (m == 0)
dist = Double.NaN;
else
dist = n * dist / m;
return Math.sqrt(dist);
}
/**
* Euclidean distance between the two arrays of type double.
* NaN will be treated as missing values and will be excluded from the
* calculation. Let m be the number nonmissing values, and n be the
* number of all values. The returned distance is sqrt(n * d / m),
* where d is the square of distance between nonmissing values.
*/
@Override
public double d(double[] x, double[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
int n = x.length;
int m = 0;
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < n; i++) {
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
m++;
double d = x[i] - y[i];
dist += d * d;
}
}
} else {
if (x.length != weight.length)
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
for (int i = 0; i < n; i++) {
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
m++;
double d = x[i] - y[i];
dist += weight[i] * d * d;
}
}
}
if (m == 0)
dist = Double.NaN;
else
dist = n * dist / m;
return Math.sqrt(dist);
}
}

View File

@ -0,0 +1,152 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
import java.util.BitSet;
/**
* In information theory, the Hamming distance between two strings of equal
* length is the number of positions for which the corresponding symbols are
* different. Put another way, it measures the minimum number of substitutions
* required to change one into the other, or the number of errors that
* transformed one string into the other. For a fixed length n, the Hamming
* distance is a metric on the vector space of the words of that length.
*
* @author Haifeng Li
*/
public class HammingDistance implements Distance<BitSet> {
/** Constructor. */
public HammingDistance() {
}
@Override
public String toString() {
return "Hamming Distance";
}
@Override
public double d(BitSet x, BitSet y) {
if (x.size() != y.size()) {
throw new IllegalArgumentException(String.format("BitSets have different length: x[%d], y[%d]", x.size(), y.size()));
}
int dist = 0;
for (int i = 0; i < x.size(); i++) {
if (x.get(i) != y.get(i))
dist++;
}
return dist;
}
/**
* Returns Hamming distance between the two bytes.
*/
public static int d(byte x, byte y) {
return d((int)x, (int)y);
}
/**
* Returns Hamming distance between the two shorts.
*/
public static int d(short x, short y) {
return d((int)x, (int)y);
}
/**
* Returns Hamming distance between the two integers.
*/
public static int d(int x, int y) {
int dist = 0;
int val = x ^ y;
// Count the number of set bits (Knuth's algorithm)
while (val != 0) {
++dist;
val &= val - 1;
}
return dist;
}
/**
* Returns Hamming distance between the two long integers.
*/
public static int d(long x, long y) {
int dist = 0;
long val = x ^ y;
// Count the number of set bits (Knuth's algorithm)
while (val != 0) {
++dist;
val &= val - 1;
}
return dist;
}
/**
* Returns Hamming distance between the two byte arrays.
*/
public static int d(byte[] x, byte[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
int dist = 0;
for (int i = 0; i < x.length; i++) {
if (x[i] != y[i])
dist++;
}
return dist;
}
/**
* Returns Hamming distance between the two short arrays.
*/
public static int d(short[] x, short[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
int dist = 0;
for (int i = 0; i < x.length; i++) {
if (x[i] != y[i])
dist++;
}
return dist;
}
/**
* Returns Hamming distance between the two integer arrays.
*/
public static int d(int[] x, int[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
int dist = 0;
for (int i = 0; i < x.length; i++) {
if (x[i] != y[i])
dist++;
}
return dist;
}
}

View File

@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
import java.util.HashSet;
import java.util.Set;
/**
* The Jaccard index, also known as the Jaccard similarity coefficient is a
* statistic used for comparing the similarity and diversity of sample sets.
* <p>
* The Jaccard coefficient measures similarity between sample sets, and is
* defined as the size of the intersection divided by the size of the union
* of the sample sets.
* <p>
* The Jaccard distance, which measures dissimilarity between sample sets,
* is complementary to the Jaccard coefficient and is obtained by subtracting
* the Jaccard coefficient from 1, or, equivalently, by dividing the difference
* of the sizes of the union and the intersection of two sets by the size of
* the union.
*
* @author Haifeng Li
*/
public class JaccardDistance<T> implements Distance<T[]> {
private static final long serialVersionUID = 1L;
/**
* Constructor.
*/
public JaccardDistance() {
}
@Override
public String toString() {
return "Jaccard Distance";
}
@Override
public double d(T[] a, T[] b) {
Set<T> union = new HashSet<>();
Set<T> intersection = new HashSet<>();
for (int i = 0; i < b.length; i++) {
union.add(b[i]);
}
for (int i = 0; i < a.length; i++) {
intersection.add(a[i]);
}
intersection.retainAll(union);
for (int i = 0; i < a.length; i++) {
union.add(a[i]);
}
return 1.0 - (double) intersection.size() / union.size();
}
/**
* Returns the Jaccard distance between sets.
*/
public static <T> double d(Set<T> a, Set<T> b) {
Set<T> union = new HashSet<>(a);
union.addAll(b);
Set<T> intersection = new HashSet<>(a);
intersection.retainAll(b);
return 1.0 - (double) intersection.size() / union.size();
}
}

View File

@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
import org.meteoinfo.math.MathEx;
/**
* The Jensen-Shannon divergence is a popular method of measuring the
* similarity between two probability distributions. It is also known
* as information radius or total divergence to the average.
* <p>
* The Jensen-Shannon divergence is a symmetrized and smoothed version of the
* Kullback-Leibler divergence . It is defined by
* <p>
* <pre>
* J(P||Q) = (D(P||M) + D(Q||M)) / 2
* </pre>
* where M = (P+Q)/2 and D(&middot;||&middot;) is KL divergence.
* Different from the Kullback-Leibler divergence, it is always a finite value.
* <p>
* The square root of the Jensen-Shannon divergence is a metric, which is
* calculated by this class.
*
* @author Haifeng Li
*/
public class JensenShannonDistance implements Metric<double[]> {
private static final long serialVersionUID = 1L;
/**
* Constructor.
*/
public JensenShannonDistance() {
}
@Override
public String toString() {
return "Jensen-Shannon Distance";
}
@Override
public double d(double[] x, double[] y) {
if (x.length != y.length) {
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
}
return Math.sqrt(MathEx.JensenShannonDivergence(x, y));
}
}

View File

@ -0,0 +1,174 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
import java.util.Arrays;
/**
* Manhattan distance, also known as L<sub>1</sub> distance or L<sub>1</sub>
* norm, is the sum of the (absolute) differences of their coordinates. Use
* getInstance() to get the standard unweighted Manhattan distance. Or create
* an instance with a specified weight vector. For float or double arrays,
* missing values (i.e. NaN) are also handled.
*
* @see SparseManhattanDistance
*
* @author Haifeng Li
*/
public class ManhattanDistance implements Metric<double[]> {
private static final long serialVersionUID = 1L;
/**
* The weights used in weighted distance.
*/
private double[] weight = null;
/**
* Constructor.
*/
public ManhattanDistance() {
}
/**
* Constructor.
*
* @param weight the weight vector.
*/
public ManhattanDistance(double[] weight) {
for (int i = 0; i < weight.length; i++) {
if (weight[i] < 0) {
throw new IllegalArgumentException(String.format("Weight has to be nonnegative: %f", weight[i]));
}
}
this.weight = weight;
}
@Override
public String toString() {
if (weight != null) {
return String.format("Weighted Manhattan Distance(%s)", Arrays.toString(weight));
} else {
return "Manhattan Distance";
}
}
/**
* Manhattan distance between two arrays of type integer.
*/
public double d(int[] x, int[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < x.length; i++) {
dist += Math.abs(x[i] - y[i]);
}
} else {
if (x.length != weight.length)
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
for (int i = 0; i < x.length; i++) {
dist += weight[i] * Math.abs(x[i] - y[i]);
}
}
return dist;
}
/**
* Manhattan distance between two arrays of type float.
* NaN will be treated as missing values and will be excluded from the
* calculation. Let m be the number non-missing values, and n be the
* number of all values. The returned distance is n * d / m,
* where d is the distance between non-missing values.
*/
public double d(float[] x, float[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
int n = x.length;
int m = 0;
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < n; i++) {
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
m++;
dist += Math.abs(x[i] - y[i]);
}
}
} else {
if (x.length != weight.length)
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
for (int i = 0; i < n; i++) {
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
m++;
dist += weight[i] * Math.abs(x[i] - y[i]);
}
}
}
dist = n * dist / m;
return dist;
}
/**
* Manhattan distance between two arrays of type double.
* NaN will be treated as missing values and will be excluded from the
* calculation. Let m be the number non-missing values, and n be the
* number of all values. The returned distance is n * d / m,
* where d is the distance between non-missing values.
*/
@Override
public double d(double[] x, double[] y) {
if (x.length != y.length)
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
int n = x.length;
int m = 0;
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < n; i++) {
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
m++;
dist += Math.abs(x[i] - y[i]);
}
}
} else {
if (x.length != weight.length)
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
for (int i = 0; i < n; i++) {
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
m++;
dist += weight[i] * Math.abs(x[i] - y[i]);
}
}
}
dist = n * dist / m;
return dist;
}
}

View File

@ -0,0 +1,35 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
/**
* A metric function defines a distance between elements of a set. Besides
* non-negativity, isolation, and symmetry, it also has to satisfy triangular
* inequality.
* <ul>
* <li> non-negativity: <code>d(x, y) &ge; 0</code>
* <li> isolation: <code>d(x, y) = 0</code> if and only if <code>x = y</code>
* <li> symmetry: <code>d(x, y) = d(x, y)</code>
* <li> triangular inequality: <code>d(x, y) + d(y, z) &ge; d(x, z)</code>.
* </ul>
*
* @author Haifeng Li
*/
public interface Metric<T> extends Distance<T> {
}

View File

@ -0,0 +1,200 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.distance;
import java.util.Arrays;
/**
* Minkowski distance of order p or L<sub>p</sub>-norm, is a generalization of
* Euclidean distance that is actually L<sub>2</sub>-norm. You may also provide
* a specified weight vector. For float or double arrays, missing values (i.e. NaN)
* are also handled.
*
* @see SparseMinkowskiDistance
*
* @author Haifeng Li
*/
public class MinkowskiDistance implements Metric<double[]> {
private static final long serialVersionUID = 1L;
/**
* The order of Minkowski distance.
*/
private int p;
/**
* The weights used in weighted distance.
*/
private double[] weight = null;
/**
* Constructor.
*/
public MinkowskiDistance(int p) {
if (p <= 0) {
throw new IllegalArgumentException(String.format("The order p has to be larger than 0: p = d", p));
}
this.p = p;
}
/**
* Constructor.
*
* @param weight the weight vector.
*/
public MinkowskiDistance(int p, double[] weight) {
if (p <= 0) {
throw new IllegalArgumentException(String.format("The order p has to be larger than 0: p = d", p));
}
for (int i = 0; i < weight.length; i++) {
if (weight[i] < 0) {
throw new IllegalArgumentException(String.format("Weight has to be nonnegative: %f", weight[i]));
}
}
this.p = p;
this.weight = weight;
}
@Override
public String toString() {
if (weight != null) {
return String.format("Weighted Minkowski Distance(p = %d, weight = %s)", p, Arrays.toString(weight));
} else {
return String.format("Minkowski Distance(p = %d)", p);
}
}
/**
* Minkowski distance between the two arrays of type integer.
*/
public double d(int[] x, int[] y) {
if (x.length != y.length) {
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
}
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < x.length; i++) {
double d = Math.abs(x[i] - y[i]);
dist += Math.pow(d, p);
}
} else {
if (x.length != weight.length) {
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
}
for (int i = 0; i < x.length; i++) {
double d = Math.abs(x[i] - y[i]);
dist += weight[i] * Math.pow(d, p);
}
}
return Math.pow(dist, 1.0/p);
}
/**
* Minkowski distance between the two arrays of type float.
* NaN will be treated as missing values and will be excluded from the
* calculation. Let m be the number non-missing values, and n be the
* number of all values. The returned distance is pow(n * d / m, 1/p),
* where d is the p-pow of distance between non-missing values.
*/
public double d(float[] x, float[] y) {
if (x.length != y.length) {
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
}
int n = x.length;
int m = 0;
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < x.length; i++) {
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
m++;
double d = Math.abs(x[i] - y[i]);
dist += Math.pow(d, p);
}
}
} else {
if (x.length != weight.length) {
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
}
for (int i = 0; i < x.length; i++) {
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
m++;
double d = Math.abs(x[i] - y[i]);
dist += weight[i] * Math.pow(d, p);
}
}
}
dist = n * dist / m;
return Math.pow(dist, 1.0/p);
}
/**
* Minkowski distance between the two arrays of type double.
* NaN will be treated as missing values and will be excluded from the
* calculation. Let m be the number non-missing values, and n be the
* number of all values. The returned distance is pow(n * d / m, 1/p),
* where d is the p-pow of distance between non-missing values.
*/
@Override
public double d(double[] x, double[] y) {
if (x.length != y.length) {
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
}
int n = x.length;
int m = 0;
double dist = 0.0;
if (weight == null) {
for (int i = 0; i < x.length; i++) {
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
m++;
double d = Math.abs(x[i] - y[i]);
dist += Math.pow(d, p);
}
}
} else {
if (x.length != weight.length) {
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
}
for (int i = 0; i < x.length; i++) {
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
m++;
double d = Math.abs(x[i] - y[i]);
dist += weight[i] * Math.pow(d, p);
}
}
}
dist = n * dist / m;
return Math.pow(dist, 1.0/p);
}
}

View File

@ -0,0 +1,363 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.sort;
/**
* Selection is asking for the k-th smallest element out of n elements.
* This class implements the fastest general method for selection based on
* partitioning, exactly as done in the Quicksort algorithm.
* <p>
* The most common use of selection is in the statistical characterization of
* a set of data. One often wants to know the median element (quantile p = 1/2)
* in an array or the top and bottom quartile elements (quantile p = 1/4, 3/4).
*
* @author Haifeng Li
*/
public interface QuickSelect {
/**
* Given k in [0, n-1], returns an array value from arr such that k array
* values are less than or equal to the one returned. The input array will
* be rearranged to have this value in location arr[k], with all smaller
* elements moved to arr[0, k-1] (in arbitrary order) and all larger elements
* in arr[k+1, n-1] (also in arbitrary order).
*/
static int select(int[] arr, int k) {
int n = arr.length;
int l = 0;
int ir = n - 1;
int a;
int i, j, mid;
for (;;) {
if (ir <= l + 1) {
if (ir == l + 1 && arr[ir] < arr[l]) {
Sort.swap(arr, l, ir);
}
return arr[k];
} else {
mid = (l + ir) >> 1;
Sort.swap(arr, mid, l + 1);
if (arr[l] > arr[ir]) {
Sort.swap(arr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
Sort.swap(arr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
Sort.swap(arr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
Sort.swap(arr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
if (j >= k) {
ir = j - 1;
}
if (j <= k) {
l = i;
}
}
}
}
/**
* Given k in [0, n-1], returns an array value from arr such that k array
* values are less than or equal to the one returned. The input array will
* be rearranged to have this value in location arr[k], with all smaller
* elements moved to arr[0, k-1] (in arbitrary order) and all larger elements
* in arr[k+1, n-1] (also in arbitrary order).
*/
static float select(float[] arr, int k) {
int n = arr.length;
int l = 0;
int ir = n - 1;
float a;
int i, j, mid;
for (;;) {
if (ir <= l + 1) {
if (ir == l + 1 && arr[ir] < arr[l]) {
Sort.swap(arr, l, ir);
}
return arr[k];
} else {
mid = (l + ir) >> 1;
Sort.swap(arr, mid, l + 1);
if (arr[l] > arr[ir]) {
Sort.swap(arr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
Sort.swap(arr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
Sort.swap(arr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
Sort.swap(arr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
if (j >= k) {
ir = j - 1;
}
if (j <= k) {
l = i;
}
}
}
}
/**
* Given k in [0, n-1], returns an array value from arr such that k array
* values are less than or equal to the one returned. The input array will
* be rearranged to have this value in location arr[k], with all smaller
* elements moved to arr[0, k-1] (in arbitrary order) and all larger elements
* in arr[k+1, n-1] (also in arbitrary order).
*/
static double select(double[] arr, int k) {
int n = arr.length;
int l = 0;
int ir = n - 1;
double a;
int i, j, mid;
for (;;) {
if (ir <= l + 1) {
if (ir == l + 1 && arr[ir] < arr[l]) {
Sort.swap(arr, l, ir);
}
return arr[k];
} else {
mid = (l + ir) >> 1;
Sort.swap(arr, mid, l + 1);
if (arr[l] > arr[ir]) {
Sort.swap(arr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
Sort.swap(arr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
Sort.swap(arr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
Sort.swap(arr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
if (j >= k) {
ir = j - 1;
}
if (j <= k) {
l = i;
}
}
}
}
/**
* Given k in [0, n-1], returns an array value from arr such that k array
* values are less than or equal to the one returned. The input array will
* be rearranged to have this value in location arr[k], with all smaller
* elements moved to arr[0, k-1] (in arbitrary order) and all larger elements
* in arr[k+1, n-1] (also in arbitrary order).
*/
static <T extends Comparable<? super T>> T select(T[] arr, int k) {
int n = arr.length;
int l = 0;
int ir = n - 1;
T a;
int i, j, mid;
for (;;) {
if (ir <= l + 1) {
if (ir == l + 1 && arr[ir].compareTo(arr[l]) < 0) {
Sort.swap(arr, l, ir);
}
return arr[k];
} else {
mid = (l + ir) >> 1;
Sort.swap(arr, mid, l + 1);
if (arr[l].compareTo(arr[ir]) > 0) {
Sort.swap(arr, l, ir);
}
if (arr[l + 1].compareTo(arr[ir]) > 0) {
Sort.swap(arr, l + 1, ir);
}
if (arr[l].compareTo(arr[l + 1]) > 0) {
Sort.swap(arr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
for (;;) {
do {
i++;
} while (arr[i].compareTo(a) < 0);
do {
j--;
} while (arr[j].compareTo(a) > 0);
if (j < i) {
break;
}
Sort.swap(arr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
if (j >= k) {
ir = j - 1;
}
if (j <= k) {
l = i;
}
}
}
}
/**
* Find the median of an array of type integer.
*/
static int median(int[] a) {
int k = a.length / 2;
return select(a, k);
}
/**
* Find the median of an array of type float.
*/
static float median(float[] a) {
int k = a.length / 2;
return select(a, k);
}
/**
* Find the median of an array of type double.
*/
static double median(double[] a) {
int k = a.length / 2;
return select(a, k);
}
/**
* Find the median of an array of type double.
*/
static <T extends Comparable<? super T>> T median(T[] a) {
int k = a.length / 2;
return select(a, k);
}
/**
* Find the first quantile (p = 1/4) of an array of type integer.
*/
static int q1(int[] a) {
int k = a.length / 4;
return select(a, k);
}
/**
* Find the first quantile (p = 1/4) of an array of type float.
*/
static float q1(float[] a) {
int k = a.length / 4;
return select(a, k);
}
/**
* Find the first quantile (p = 1/4) of an array of type double.
*/
static double q1(double[] a) {
int k = a.length / 4;
return select(a, k);
}
/**
* Find the first quantile (p = 1/4) of an array of type double.
*/
static <T extends Comparable<? super T>> T q1(T[] a) {
int k = a.length / 4;
return select(a, k);
}
/**
* Find the third quantile (p = 3/4) of an array of type integer.
*/
static int q3(int[] a) {
int k = 3 * a.length / 4;
return select(a, k);
}
/**
* Find the third quantile (p = 3/4) of an array of type float.
*/
static float q3(float[] a) {
int k = 3 * a.length / 4;
return select(a, k);
}
/**
* Find the third quantile (p = 3/4) of an array of type double.
*/
static double q3(double[] a) {
int k = 3 * a.length / 4;
return select(a, k);
}
/**
* Find the third quantile (p = 3/4) of an array of type double.
*/
static <T extends Comparable<? super T>> T q3(T[] a) {
int k = 3 * a.length / 4;
return select(a, k);
}
}

View File

@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
*
* Smile is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Smile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
package org.meteoinfo.math.util;
/** A pair of integer. */
public class IntPair {
public final int i;
public final int j;
/** Constructor. */
public IntPair(int i, int j) {
this.i = i;
this.j = j;
}
@Override
public int hashCode() {
return i * 31 + j;
}
@Override
public String toString() {
return String.format("(%d, %d)", i, j);
}
@Override
public boolean equals(Object o) {
if (o != null && o instanceof IntPair) {
IntPair p = (IntPair) o;
return i == p.i && j == p.j;
}
return false;
}
}

View File

@ -23,20 +23,23 @@ public class MatrixTest {
@Test
public void testMv() {
matrix = new Matrix(A);
double[] d = matrix.mv(b);
assertEquals(0.65, d[0], 1E-7);
}
@Test
public void testTv() {
matrix = new Matrix(A);
double[] d = matrix.tv(b);
assertEquals(d[0], 0.65, 1E-7);
assertEquals(0.65, d[0], 1E-7);
}
@Test
public void testSVDSolve() {
matrix = new Matrix(A);
Matrix.SVD svd = matrix.svd(true, true);
double[] d = svd.solve(b);
assertEquals(d[0], 0.3642384179155737, 1E-7);
assertEquals(0.3642384179155737, d[0], 1E-7);
}
}

View File

@ -16,6 +16,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<commons-math.version>4.0-beta1</commons-math.version>
<commons-numbers.version>1.1</commons-numbers.version>
<commons-rng.version>1.5</commons-rng.version>
</properties>
@ -34,15 +35,10 @@
<artifactId>meteoinfo-common</artifactId>
<version>${project.version}</version>
</dependency>
<!--<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math4-legacy</artifactId>
<version>4.0-beta1</version>
<version>${commons-math.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>