// Copyright 2013 Thomas Müller
// This file is part of MarMoT, which is licensed under GPLv3.
package marmot.util;
public class Numerics {
public final static double EPSILON = 1e-5;
/**
* Determines whether two 1d jagged arrays are approximately equal
* @param array1
* @param array2
* @param eps
* @return
*/
public static boolean approximatelyEqual(double[] array1, double[] array2, double eps) {
boolean approxEqual = true;
for (int i = 0; i < array1.length; ++i) {
if (Math.abs(array1[i] - array2[i]) > eps) {
approxEqual = false;
break;
}
}
return approxEqual;
}
/**
* Determines whether two 2d jagged arrays are approximately equal
* @param array1
* @param array2
* @param eps
* @return
*/
public static boolean approximatelyEqual(double[][] array1, double[][] array2, double eps) {
boolean approxEqual = true;
for (int i = 0; i < array1.length; ++i) {
for (int j = 0; j < array1[i].length; ++j) {
if (Math.abs(array1[i][j] - array2[i][j]) > eps) {
approxEqual = false;
break;
}
}
}
return approxEqual;
}
/**
* Determines whether two 3d jagged arrays are approximately equal
* @param array1
* @param array2
* @param eps
* @return
*/
public static boolean approximatelyEqual(double[][][] array1, double[][][] array2, double eps) {
boolean approxEqual = true;
for (int i = 0; i < array1.length; ++i) {
for (int j = 0; j < array1[i].length; ++j) {
for (int k = 0; k < array1[i][j].length; ++k) {
if (Math.abs(array1[i][j][k] - array2[i][j][k]) > eps) {
approxEqual = false;
break;
}
}
}
}
return approxEqual;
}
// The following code is based on a similar function in MALLET.
// (http://www.cs.umass.edu/~mccallum/mallet)
// But was modified using the thresholds from log1pexp.
public static double sumLogProb(double a, double b) {
if (a == Double.NEGATIVE_INFINITY) {
if (b == Double.NEGATIVE_INFINITY)
return Double.NEGATIVE_INFINITY;
return b;
}
if (b == Double.NEGATIVE_INFINITY) {
return a;
}
if (a > b) {
return a + Math.log1p(Math.exp(b - a));
}
return b + Math.log1p(Math.exp(a - b));
}
// Adapted from http://web.science.mq.edu.au/~mjohnson/code/digamma.c
// Written by Mark Johnson
public static double digamma(double x) {
double result, xx, xx2, xx4;
if (x == 0.) {
return 0;
} else if (x < 0.) {
throw new IllegalArgumentException("x <= 0 : x =" + x);
}
result = 0;
for (; x < 7; ++x) {
result -= 1 / x;
}
x -= 0.5;
xx = 1.0 / x;
xx2 = xx * xx;
xx4 = xx2 * xx2;
result += Math.log(x) + (1. / 24.) * xx2 - (7.0 / 960.0) * xx4
+ (31.0 / 8064.0) * xx4 * xx2 - (127.0 / 30720.0) * xx4 * xx4;
return result;
}
public static double exp_digamma(double x) {
return Math.exp(digamma(x));
}
public static boolean approximatelyGreaterEqual(double a,
double b, double epsilon) {
return a + epsilon > b;
}
public static boolean approximatelyGreaterEqual(double a,
double b) {
return approximatelyGreaterEqual(a, b, EPSILON);
}
public static boolean approximatelyLesserEqual(double a, double b) {
return approximatelyGreaterEqual(b, a);
}
public static boolean approximatelyEqual(double a,
double b) {
return Math.abs(a - b) < EPSILON;
}
}