ucar.nc2.util.Misc Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.nc2.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Formatter;
import java.util.List;
/**
* Miscellaneous static routines.
*
* @author caron
*/
public class Misc {
public static final int referenceSize = 4; // estimates pointer size, in principle JVM dependent
public static final int objectSize = 16; // estimates pointer size, in principle JVM dependent
/**
* The default maximum {@link #relativeDifference(float, float) relative difference} that two floats can have in
* order to be deemed {@link #nearlyEquals(float, float) nearly equal}.
*/
public static final float defaultMaxRelativeDiffFloat = 1.0e-5f;
/**
* The default maximum {@link #relativeDifference(double, double) relative difference} that two doubles can have in
* order to be deemed {@link #nearlyEquals(double, double) nearly equal}.
*/
public static final double defaultMaxRelativeDiffDouble = 1.0e-8;
/**
* Returns the absolute difference between two numbers, i.e. {@code |a - b|}.
*
* @param a first number.
* @param b second number.
* @return the absolute difference.
*/
public static float absoluteDifference(float a, float b) {
if (Float.compare(a, b) == 0) { // Shortcut: handles infinities and NaNs.
return 0;
} else {
return Math.abs(a - b);
}
}
/** Same as {@link #absoluteDifference(float, float)}, but for doubles. */
public static double absoluteDifference(double a, double b) {
if (Double.compare(a, b) == 0) { // Shortcut: handles infinities and NaNs.
return 0;
} else {
return Math.abs(a - b);
}
}
/**
* Returns the relative difference between two numbers, i.e. {@code |a - b| / max(|a|, |b|)}.
*
* For cases where {@code a == 0}, {@code b == 0}, or {@code a} and {@code b} are extremely close, traditional
* relative difference calculation breaks down. So, in those instances, we compute the difference relative to
* {@link Float#MIN_NORMAL}, i.e. {@code |a - b| / Float.MIN_NORMAL}.
*
* @param a first number.
* @param b second number.
* @return the relative difference.
* @see The Floating-Point Guide
* @see
* Comparing Floating Point Numbers, 2012 Edition
*/
public static float relativeDifference(float a, float b) {
float absDiff = absoluteDifference(a, b);
if (Float.compare(a, b) == 0) { // Shortcut: handles infinities and NaNs.
return 0;
} else if (a == 0 || b == 0 || absDiff < Float.MIN_NORMAL) {
return absDiff / Float.MIN_NORMAL;
} else {
float maxAbsValue = Math.max(Math.abs(a), Math.abs(b));
return absDiff / maxAbsValue;
}
}
/** Same as {@link #relativeDifference(float, float)}, but for doubles. */
public static double relativeDifference(double a, double b) {
double absDiff = absoluteDifference(a, b);
if (Double.compare(a, b) == 0) { // Shortcut: handles infinities and NaNs.
return 0;
} else if (a == 0 || b == 0 || absDiff < Double.MIN_NORMAL) {
return absDiff / Double.MIN_NORMAL;
} else {
double maxAbsValue = Math.max(Math.abs(a), Math.abs(b));
return absDiff / maxAbsValue;
}
}
/** Returns the result of {@link #nearlyEquals(float, float, float)}, with {@link #defaultMaxRelativeDiffFloat}. */
public static boolean nearlyEquals(float a, float b) {
return nearlyEquals(a, b, defaultMaxRelativeDiffFloat);
}
/**
* Returns {@code true} if {@code a} and {@code b} are nearly equal. Specifically, it checks whether the
* {@link #relativeDifference(float, float) relative difference} of the two numbers is less than {@code maxRelDiff}.
*
* @param a first number.
* @param b second number.
* @param maxRelDiff the maximum {@link #relativeDifference relative difference} the two numbers may have.
* @return {@code true} if {@code a} and {@code b} are nearly equal.
*/
public static boolean nearlyEquals(float a, float b, float maxRelDiff) {
return relativeDifference(a, b) < maxRelDiff;
}
/**
* Returns the result of {@link #nearlyEquals(double, double, double)}, with {@link #defaultMaxRelativeDiffDouble}.
*/
public static boolean nearlyEquals(double a, double b) {
return nearlyEquals(a, b, defaultMaxRelativeDiffDouble);
}
/** Same as {@link #nearlyEquals(float, float, float)}, but for doubles. */
public static boolean nearlyEquals(double a, double b, double maxRelDiff) {
return relativeDifference(a, b) < maxRelDiff;
}
/**
* Check if two numbers are nearly equal with given absolute tolerance.
*
* @param a first number.
* @param b second number.
* @param maxAbsDiff the maximum {@link #absoluteDifference absolute difference} the two numbers may have.
* @return true if within tolerance.
*/
public static boolean nearlyEqualsAbs(float a, float b, float maxAbsDiff) {
return absoluteDifference(a, b) <= Math.abs(maxAbsDiff);
}
/** Same as {@link #nearlyEqualsAbs(float, float, float)}, but with doubles. */
public static boolean nearlyEqualsAbs(double a, double b, double maxAbsDiff) {
return absoluteDifference(a, b) <= Math.abs(maxAbsDiff);
}
static public String showInts(int[] inta) {
if (inta == null) return "null";
Formatter f = new Formatter();
for (int i : inta) f.format("%d,", i);
return f.toString();
}
static public String showInts(List intList) {
if (intList == null) return "null";
Formatter f = new Formatter();
for (int i : intList) f.format("%d,", i);
return f.toString();
}
static public void showInts(int[] inta, Formatter f) {
if (inta == null) {
f.format("null");
return;
}
for (int i : inta) f.format("%d, ", i);
}
static public String showLongs(long[] longa) {
if (longa == null) return "null";
Formatter f = new Formatter();
for (long i : longa) f.format("%d,", i);
return f.toString();
}
static public String showBytes(byte[] buff) {
StringBuilder sbuff = new StringBuilder();
for (int i = 0; i < buff.length; i++) {
byte b = buff[i];
int ub = (b < 0) ? b + 256 : b;
if (i > 0) sbuff.append(" ");
sbuff.append(ub);
}
return sbuff.toString();
}
static public void showBytes(byte[] buff, Formatter f) {
for (byte b : buff) {
int ub = (b < 0) ? b + 256 : b;
f.format("%3d ", ub);
}
}
static public int getSize(Iterable ii) {
if (ii instanceof Collection)
return ((Collection) ii).size();
int count = 0;
for (Object i : ii) count++;
return count;
}
static public List getList(Iterable ii) {
if (ii instanceof List)
return (List) ii;
List