Java tutorial
/* Copyright 2009 - 2010 The Stajistics Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package nars.util.data; import com.google.common.base.Charsets; import com.google.common.io.CharStreams; import com.google.common.io.Closeables; import com.google.common.primitives.Bytes; import com.google.common.primitives.Longs; import com.gs.collections.impl.list.mutable.primitive.IntArrayList; import nars.util.Texts; import org.jetbrains.annotations.NotNull; import sun.misc.Unsafe; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.locks.LockSupport; import java.util.function.Consumer; import static java.util.Arrays.stream; /** * * * */ public enum Util { ; public static final int PRIME3 = 524287; public static final int PRIME2 = 92821; public static final int PRIME1 = 31; /** * It is basically the same as a lookup table with 2048 entries and linear interpolation between the entries, but all this with IEEE floating point tricks. * http://stackoverflow.com/questions/412019/math-optimization-in-c-sharp#412988 */ public static double expFast(double val) { long tmp = (long) (1512775 * val + (1072693248 - 60801)); return Double.longBitsToDouble(tmp << 32); } /** * Fetch the Unsafe. Use With Caution. */ public static Unsafe getUnsafe() { // Not on bootclasspath if (Util.class.getClassLoader() == null) return Unsafe.getUnsafe(); try { Field fld = Unsafe.class.getDeclaredField("theUnsafe"); fld.setAccessible(true); return (Unsafe) fld.get(Util.class); } catch (Exception e) { throw new RuntimeException("Could not obtain access to sun.misc.Unsafe", e); } } public static String UUIDbase64() { long low = UUID.randomUUID().getLeastSignificantBits(); long high = UUID.randomUUID().getMostSignificantBits(); return new String( Base64.getEncoder().encode(Bytes.concat(Longs.toByteArray(low), Longs.toByteArray(high)))); } // public static int hash(int a, int b) { // return PRIME2 * (PRIME2 + a) + b; // } // // public static int hash(int a, int b, int c) { // return PRIME2 * (PRIME2 * (PRIME2 + a) + b) + c; // } // public final static int hash(int a, int b, int c, int d) { // return PRIME2 * (PRIME2 * (PRIME2 * (PRIME2 + a) + b) + c) + d; // } // public final static int hash(int a, int b, int c, int d, long e) { // long x = PRIME2 * (PRIME2 * (PRIME2 * (PRIME2 * (PRIME2 + a) + b) + c) + d) + e; // return (int)x; // } public static int hash(Object a, Object b) { return hashCombine(a.hashCode(), b.hashCode()); } public static int hash(Object a, Object b, Object c) { return hashCombine(a.hashCode(), b.hashCode(), c.hashCode()); } // public final static int hash(Object a, Object b, Object c, Object d) { // return hash(a.hashCode(), b.hashCode(), c.hashCode(), d.hashCode()); // } public static void assertNotNull(Object test, String varName) { if (test == null) { throw new NullPointerException(varName); } } public static void assertNotEmpty(Object[] test, String varName) { if (test == null) { throw new NullPointerException(varName); } if (test.length == 0) { throw new IllegalArgumentException("empty " + varName); } } public static void assertNotEmpty(CharSequence test, String varName) { if (test == null) { throw new NullPointerException(varName); } if (test.length() == 0) { throw new IllegalArgumentException("empty " + varName); } } public static void assertNotBlank(CharSequence test, String varName) { if (test != null) { test = test.toString().trim(); } assertNotEmpty(test, varName); } public static <E> void assertNotEmpty(Collection<E> test, String varName) { if (test == null) { throw new NullPointerException(varName); } if (test.isEmpty()) { throw new IllegalArgumentException("empty " + varName); } } public static <K, V> void assertNotEmpty(Map<K, V> test, String varName) { if (test == null) { throw new NullPointerException(varName); } if (test.isEmpty()) { throw new IllegalArgumentException("empty " + varName); } } public static boolean equalsNullAware(Object obj1, Object obj2) { if (obj1 == null) { return obj2 == null; } if (obj2 == null) { return false; } return obj1.equals(obj2); } public static String globToRegEx(String line) { line = line.trim(); int strLen = line.length(); StringBuilder sb = new StringBuilder(strLen); // Remove beginning and ending * globs because they're useless if (line.length() > 0 && line.charAt(0) == '*') { line = line.substring(1); strLen--; } if (line.length() > 0 && line.charAt(line.length() - 1) == '*') { line = line.substring(0, strLen - 1); strLen--; } boolean escaping = false; int inCurlies = 0; for (char currentChar : line.toCharArray()) { switch (currentChar) { case '*': if (escaping) sb.append("\\*"); else sb.append(".*"); escaping = false; break; case '?': if (escaping) sb.append("\\?"); else sb.append('.'); escaping = false; break; case '.': case '(': case ')': case '+': case '|': case '^': case '$': case '@': case '%': sb.append('\\'); sb.append(currentChar); escaping = false; break; case '\\': if (escaping) { sb.append("\\\\"); escaping = false; } else escaping = true; break; case '{': if (escaping) { sb.append("\\{"); } else { sb.append('('); inCurlies++; } escaping = false; break; case '}': if (inCurlies > 0 && !escaping) { sb.append(')'); inCurlies--; } else if (escaping) sb.append("\\}"); else sb.append('}'); escaping = false; break; case ',': if (inCurlies > 0 && !escaping) { sb.append('|'); } else if (escaping) sb.append("\\,"); else sb.append(','); break; default: escaping = false; sb.append(currentChar); } } return sb.toString(); } /* ************************************************************************** * * * General Purpose Hash Function Algorithms Library * * * * Author: Arash Partow - 2002 * * URL: http://www.partow.net * * URL: http://www.partow.net/programming/hashfunctions/index.html * * * * Copyright notice: * * Free use of the General Purpose Hash Function Algorithms Library is * * permitted under the guidelines and in accordance with the most current * * version of the Common Public License. * * http://www.opensource.org/licenses/cpl1.0.php * * * ************************************************************************** */ /*class GeneralHashFunctionLibrary {*/ public static long RSHash(String str) { int b = 378551; int a = 63689; long hash = 0; for (int i = 0; i < str.length(); i++) { hash = hash * a + str.charAt(i); a = a * b; } return hash; } /* End Of RS Hash Function */ public static long JSHash(String str) { long hash = 1315423911; for (int i = 0; i < str.length(); i++) { hash ^= ((hash << 5) + str.charAt(i) + (hash >> 2)); } return hash; } /* End Of JS Hash Function */ public static long PJWHash(String str) { long BitsInUnsignedInt = (4 * 8); long ThreeQuarters = (BitsInUnsignedInt * 3) / 4; long OneEighth = BitsInUnsignedInt / 8; long HighBits = (0xFFFFFFFFL) << (BitsInUnsignedInt - OneEighth); long hash = 0; long test = 0; for (int i = 0; i < str.length(); i++) { hash = (hash << OneEighth) + str.charAt(i); if ((test = hash & HighBits) != 0) { hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits)); } } return hash; } /* End Of P. J. Weinberger Hash Function */ public static long ELFHash(String str) { long hash = 0; long x = 0; for (int i = 0; i < str.length(); i++) { hash = (hash << 4) + str.charAt(i); if ((x = hash & 0xF0000000L) != 0) { hash ^= (x >> 24); } hash &= ~x; } return hash; } /** from clojure.Util */ public static int hashCombine(int seed, int hash) { return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2)); //return seed * 31 + hash; } public static int hashCombine(int a, int b, int c) { //TODO decide if this is efficient and hashes well return hashCombine(hashCombine(a, b), c); } public static int ELFHashNonZero(byte[] str, int seed) { int i = (int) ELFHash(str, seed); if (i == 0) i = 1; return i; } public static long ELFHash(byte[] str, long seed) { long hash = seed; int len = str.length; for (byte aStr : str) { hash = (hash << 4) + aStr; long x; if ((x = hash & 0xF0000000L) != 0) { hash ^= (x >> 24); } hash &= ~x; } return hash; } public static long BKDRHash(String str) { long seed = 131; // 31 131 1313 13131 131313 etc.. long hash = 0; for (int i = 0; i < str.length(); i++) { hash = (hash * seed) + str.charAt(i); } return hash; } /* End Of BKDR Hash Function */ public static long SDBMHash(String str) { long hash = 0; for (int i = 0; i < str.length(); i++) { hash = str.charAt(i) + (hash << 6) + (hash << 16) - hash; } return hash; } /* End Of SDBM Hash Function */ public static long DJBHash(String str) { long hash = 5381; for (int i = 0; i < str.length(); i++) { hash = ((hash << 5) + hash) + str.charAt(i); } return hash; } /* End Of DJB Hash Function */ public static long DEKHash(String str) { long hash = str.length(); for (int i = 0; i < str.length(); i++) { hash = ((hash << 5) ^ (hash >> 27)) ^ str.charAt(i); } return hash; } /* End Of DEK Hash Function */ public static long BPHash(String str) { long hash = 0; for (int i = 0; i < str.length(); i++) { hash = hash << 7 ^ str.charAt(i); } return hash; } /* End Of BP Hash Function */ public static long FNVHash(String str) { long fnv_prime = 0x811C9DC5; long hash = 0; for (int i = 0; i < str.length(); i++) { hash *= fnv_prime; hash ^= str.charAt(i); } return hash; } /* End Of FNV Hash Function */ public static long APHash(String str) { long hash = 0xAAAAAAAA; for (int i = 0; i < str.length(); i++) { hash ^= (i & 1) == 0 ? (hash << 7) ^ str.charAt(i) * (hash >> 3) : ~((hash << 11) + str.charAt(i) ^ (hash >> 5)); } return hash; } /* End Of AP Hash Function */ // } /** * returns the next index */ public static int long2Bytes(long l, byte[] target, int offset) { for (int i = offset + 7; i >= offset; i--) { target[i] = (byte) (l & 0xFF); l >>= 8; } return offset + 8; } /** * returns the next index */ public static int int2Bytes(int l, byte[] target, int offset) { for (int i = offset + 3; i >= offset; i--) { target[i] = (byte) (l & 0xFF); l >>= 8; } return offset + 4; } /** * http://www.java-gaming.org/index.php?topic=24194.0 */ public static int floorInt(float x) { return (int) (x + BIG_ENOUGH_FLOOR) - BIG_ENOUGH_INT; } private static final int BIG_ENOUGH_INT = 16 * 1024; private static final double BIG_ENOUGH_FLOOR = BIG_ENOUGH_INT; private static final double BIG_ENOUGH_ROUND = BIG_ENOUGH_INT + 0.5; /** * linear interpolate between target & current, factor is between 0 and 1.0 */ public static float lerp(float target, float current, float factor) { return target * factor + current * (1.0f - factor); } public static double lerp(double target, double current, double factor) { return target * factor + current * (1.0f - factor); } /** * maximum, simpler and faster than Math.max without its additional tests */ public static float max(float a, float b) { return (a > b) ? a : b; } public static float mean(float a, float b) { return (a + b) * 0.5f; } public static short f2s(float conf) { return (short) (conf * Short.MAX_VALUE); } public static byte f2b(float conf) { return (byte) (conf * Byte.MAX_VALUE); } /** * removal rates are approximately monotonically increasing function; * tests first, mid and last for this ordering * first items are highest, so it is actually descending order * TODO improve accuracy */ public static boolean isSemiMonotonicallyDec(double[] count) { int cl = count.length; return (count[0] >= count[cl - 1]) && (count[cl / 2] >= count[cl - 1]); } /* TODO improve accuracy */ public static boolean isSemiMonotonicallyInc(int[] count) { int cl = count.length; return (count[0] <= count[cl - 1]) && (count[cl / 2] <= count[cl - 1]); } /** * Generic utility method for running a list of tasks in current thread */ public static void run(Deque<Runnable> tasks) { run(tasks, tasks.size(), Runnable::run); } public static void run(Deque<Runnable> tasks, int maxTasksToRun, Consumer<Runnable> runner) { while (!tasks.isEmpty() && maxTasksToRun-- > 0) { runner.accept(tasks.removeFirst()); } } /** * Generic utility method for running a list of tasks in current thread (concurrency == 1) or in multiple threads (> 1, in which case it will block until they finish) */ public static void run(Deque<Runnable> tasks, int maxTasksToRun, int threads) { //int concurrency = Math.min(threads, maxTasksToRun); //if (concurrency == 1) { tasks.forEach(Runnable::run); // return; // } // // ConcurrentContext ctx = ConcurrentContext.enter(); // ctx.setConcurrency(concurrency); // // try { // run(tasks, maxTasksToRun, ctx::execute); // } finally { // // Waits for all concurrent executions to complete. // // Re-exports any exception raised during concurrent executions. // if (ctx != null) // ctx.exit(); // } } /** * clamps a value to 0..1 range */ public static float clamp(float p) { if (p > 1.0f) return 1.0f; if (p < 0.0f) return 0.0f; return p; } /** * discretizes values to nearest finite resolution real number determined by epsilon spacing */ public static float round(float value, float epsilon) { return clamp(Math.round(value / epsilon) * epsilon); } public static int hash(float f, int discretness) { return (int) (f * discretness); } public static boolean equals(double a, double b) { return equals(a, b, Double.MIN_VALUE * 2); } public static boolean equals(float a, float b) { return equals(a, b, Float.MIN_VALUE * 2); } /** * tests equivalence (according to epsilon precision) */ public static boolean equals(float a, float b, float epsilon) { return Math.abs(a - b) < epsilon; } /** * tests equivalence (according to epsilon precision) */ public static boolean equals(double a, double b, double epsilon) { return Math.abs(a - b) < epsilon; } public static void pause(long milli) { pauseWait(milli); } private final static Object waitLock = new Object(); public static long pauseWaitUntil(long untilTargetTime) { long now = System.currentTimeMillis(); long dt = untilTargetTime - now; if (dt > 0) { synchronized (waitLock) { try { waitLock.wait(dt); } catch (InterruptedException e) { } } now = System.currentTimeMillis(); } return now; } // /** from: http://stackoverflow.com/a/1205300 */ // public static long pauseLockUntil(long untilTargetTime) { // // // Wait until the desired next time arrives using nanosecond // // accuracy timer (wait(time) isn't accurate enough on most platforms) // long now = System.currentTimeMillis(); // long dt = (untilTargetTime-now) * 1000000; // if (dt > 0) { // LockSupport.parkNanos(dt); // now = System.currentTimeMillis(); // } // return now; // } /** from boofcv: */ static void pauseWait(long milli) { if (milli <= 0) return; Thread t = Thread.currentThread(); long start = System.currentTimeMillis(); long now; while ((now = System.currentTimeMillis()) - start < milli) { synchronized (t) { try { long ignore = milli - (now - start); if (ignore > 0L) { t.wait(ignore); } } catch (InterruptedException var9) { } } } } /** applies a quick, non-lexicographic ordering compare * by first testing their lengths */ public static int compare(long[] x, long[] y) { if (x == y) return 0; int xlen = x.length; int yLen = y.length; if (xlen != yLen) { return Integer.compare(xlen, yLen); } else { for (int i = 0; i < xlen; i++) { int c = Long.compare(x[i], y[i]); if (c != 0) return c; //first different chra } return 0; //equal } } public static byte[] intAsByteArray(int index) { if (index < 36) { byte x = base36(index); return new byte[] { x }; } else if (index < (36 * 36)) { byte x1 = base36(index % 36); byte x2 = base36(index / 36); return new byte[] { x2, x1 }; } else { throw new RuntimeException("variable index out of range for this method"); } // int digits = (index >= 256 ? 3 : ((index >= 16) ? 2 : 1)); // StringBuilder cb = new StringBuilder(1 + digits).append(type); // do { // cb.append( Character.forDigit(index % 16, 16) ); index /= 16; // } while (index != 0); // return cb.toString(); } public static int bin(float x, int bins) { return (int) Math.floor((x + (0.5f / bins)) * bins); } /** bins a priority value to an integer */ public static int decimalize(float v) { return bin(v, 10); } /** finds the mean value of a given bin */ public static float unbinCenter(int b, int bins) { return ((float) b) / bins; } public static <D> D runProbability(Random rng, float[] probs, D[] choices) { float tProb = 0; for (int i = 0; i < probs.length; i++) { tProb += probs[i]; } float s = rng.nextFloat() * tProb; int c = 0; for (int i = 0; i < probs.length; i++) { s -= probs[i]; if (s <= 0) { c = i; break; } } return choices[c]; } public static MethodHandle mhRef(Class<?> type, String name) { try { return MethodHandles.lookup() //.publicLookup( .unreflect(stream(type.getMethods()).filter(m -> m.getName().equals(name)).findFirst().get()); } catch (IllegalAccessException e) { throw new Error(e); } } public static <F> MethodHandle mh(String name, F fun) { return mh(name, fun.getClass(), fun); } public static <F> MethodHandle mh(String name, Class<? extends F> type, F fun) { return mhRef(type, name).bindTo(fun); } public static <F> MethodHandle mh(String name, F... fun) { F fun0 = fun[0]; MethodHandle m = mh(name, fun0.getClass(), fun0); for (int i = 1; i < fun.length; i++) { m = m.bindTo(fun[i]); } return m; } public static byte base36(int index) { if (index < 10) return (byte) ('0' + index); else if (index < (10 + 26)) return (byte) ((index - 10) + 'a'); else throw new RuntimeException("out of bounds"); } /** clamps output to 0..+1. y=0.5 at x=0 */ public static float sigmoid(float v) { return 1f / (1f + (float) Math.exp(-v)); } public static float sigmoidDiff(float a, float b) { float sum = a + b; float delta = a - b; float deltaNorm = delta / sum; return sigmoid(deltaNorm); } public static float sigmoidDiffAbs(float a, float b) { float sum = a + b; float delta = Math.abs(a - b); float deltaNorm = delta / sum; return sigmoid(deltaNorm); } /** * 2 decimal representation of values between 0 and 1. only the tens and hundredth * decimal point are displayed - not the ones, and not a decimal point. * for compact display. * if the value=1.0, then 'aa' is the result */ @NotNull public static String n2u(float x) { if ((x < 0) || (x > 1)) throw new RuntimeException("values >=0 and <=1"); int hundreds = (int) Texts.hundredths(x); if (x == 100) return "aa"; return hundreds < 10 ? "0" + hundreds : Integer.toString(hundreds); } public static List<String> inputToStrings(InputStream is) throws IOException { List<String> x = CharStreams.readLines(new InputStreamReader(is, Charsets.UTF_8)); Closeables.closeQuietly(is); return x; } public static String inputToString(InputStream is) throws IOException { String s = CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8)); Closeables.closeQuietly(is); return s; } public static int[] reverse(IntArrayList l) { switch (l.size()) { case 0: throw new UnsupportedOperationException(); //should never happen case 1: return new int[] { l.get(0) }; case 2: return new int[] { l.get(1), l.get(0) }; case 3: return new int[] { l.get(2), l.get(1), l.get(0) }; default: //reverse the array since it has been constructed in reverse //TODO use more efficient array reversal return l.asReversed().toArray();//toReversed().toArray(); } } public static String s(String s, int maxLen) { if (s.length() < maxLen) return s; return s.substring(0, maxLen - 2) + ".."; } public static void writeBits(int x, int numBits, float[] y, int offset) { for (int i = 0, j = offset; i < numBits; i++, j++) { int mask = 1 << i; y[j] = ((x & mask) == 1) ? 1f : 0f; } } /** a and b must be instances of input, and output must be of size input.length-2 */ public static <X> X[] except(X[] input, X a, X b, X[] output) { int targetLen = input.length - 2; if (output.length != targetLen) { throw new RuntimeException("wrong size"); } int j = 0; for (X x : input) { if ((x != a) && (x != b)) output[j++] = x; } return output; } }