package net.seninp.jmotif.distance;
/**
* The Euclidean distance implementation.
*
* @author Pavel Senin
*
*/
public final class EuclideanDistance {
/**
* Constructor.
*/
public EuclideanDistance() {
super();
}
/**
* Calculates the Euclidean distance between two points.
*
* @param p1 The first point.
* @param p2 The second point.
* @return The Euclidean distance.
*/
public double distance(double p1, double p2) {
double d = (p1 - p2) * (p1 - p2);
return Math.sqrt(d);
}
/**
* Calculates the Euclidean distance between two points.
*
* @param point1 The first point.
* @param point2 The second point.
* @return The Euclidean distance.
* @throws Exception In the case of error.
*/
public double distance(double[] point1, double[] point2) throws Exception {
return Math.sqrt(distance2(point1, point2));
}
/**
* Calculates the Euclidean distance between two points.
*
* @param point1 The first point.
* @param point2 The second point.
* @return The Euclidean distance.
* @throws Exception In the case of error.
*/
public double distance(int[] point1, int[] point2) throws Exception {
return Math.sqrt(Long.valueOf(distance2(point1, point2)).doubleValue());
}
/**
* Calculates the square of the Euclidean distance between two 1D points represented by real
* values.
*
* @param p1 The first point.
* @param p2 The second point.
* @return The Square of Euclidean distance.
*/
public double distance2(double p1, double p2) {
return (p1 - p2) * (p1 - p2);
}
/**
* Calculates the square of the Euclidean distance between two multidimensional points represented
* by the rational vectors.
*
* @param point1 The first point.
* @param point2 The second point.
* @return The Euclidean distance.
* @throws Exception In the case of error.
*/
public double distance2(double[] point1, double[] point2) throws Exception {
if (point1.length == point2.length) {
Double sum = 0D;
for (int i = 0; i < point1.length; i++) {
double tmp = point2[i] - point1[i];
sum = sum + tmp * tmp;
}
return sum;
}
else {
throw new Exception("Exception in Euclidean distance: array lengths are not equal");
}
}
/**
* Calculates the square of the Euclidean distance between two multidimensional points represented
* by integer vectors.
*
* @param point1 The first point.
* @param point2 The second point.
* @return The Euclidean distance.
* @throws Exception In the case of error.
*/
public long distance2(int[] point1, int[] point2) throws Exception {
if (point1.length == point2.length) {
long sum = 0;
for (int i = 0; i < point1.length; i++) {
sum = sum + (point2[i] - point1[i]) * (point2[i] - point1[i]);
}
return sum;
}
else {
throw new Exception("Exception in Euclidean distance: array lengths are not equal");
}
}
/**
* Calculates Euclidean distance between two multi-dimensional time-series of equal length.
*
* @param series1 The first series.
* @param series2 The second series.
* @return The eclidean distance.
* @throws Exception if error occures.
*/
public double seriesDistance(double[][] series1, double[][] series2) throws Exception {
if (series1.length == series2.length) {
Double res = 0D;
for (int i = 0; i < series1.length; i++) {
res = res + distance2(series1[i], series2[i]);
}
return Math.sqrt(res);
}
else {
throw new Exception("Exception in Euclidean distance: array lengths are not equal");
}
}
/**
* Calculates the Normalized Euclidean distance between two points.
*
* @param point1 The first point.
* @param point2 The second point.
* @return The Euclidean distance.
* @throws Exception In the case of error.
*/
public double normalizedDistance(double[] point1, double[] point2) throws Exception {
return Math.sqrt(distance2(point1, point2)) / point1.length;
}
/**
* Implements Euclidean distance with early abandoning.
*
* @param series1 the first series.
* @param series2 the second series.
* @param cutoff the cut-off threshold
* @return the distance if it is less than cutoff or Double.NAN if it is above.
*
* @throws Exception if error occurs.
*/
public Double earlyAbandonedDistance(double[] series1, double[] series2, double cutoff)
throws Exception {
if (series1.length == series2.length) {
double cutOff2 = cutoff;
if (Double.MAX_VALUE != cutoff) {
cutOff2 = cutoff * cutoff;
}
Double res = 0D;
for (int i = 0; i < series1.length; i++) {
res = res + distance2(series1[i], series2[i]);
if (res > cutOff2) {
return Double.NaN;
}
}
return Math.sqrt(res);
}
else {
throw new Exception("Exception in Euclidean distance: array lengths are not equal");
}
}
}