/* * Copyright 2016 higherfrequencytrading.com * * 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 net.openhft.lang; /** * @author peter.lawrey */ public class Maths { /** * Numbers larger than this are whole numbers due to representation error. */ private static final double WHOLE_NUMBER = 1L << 53; private static final long[] TENS = new long[19]; static { TENS[0] = 1; for (int i = 1; i < TENS.length; i++) TENS[i] = TENS[i - 1] * 10; } /** * Performs a round which is accurate to within 1 ulp. i.e. for values very close to 0.5 it might be rounded up or * down. This is a pragmatic choice for performance reasons as it is assumed you are not working on the edge of the * precision of double. * * @param d value to round * @return rounded value */ public static double round2(double d) { final double factor = 1e2; return d > WHOLE_NUMBER || d < -WHOLE_NUMBER ? d : (long) (d < 0 ? d * factor - 0.5 : d * factor + 0.5) / factor; } /** * Performs a round which is accurate to within 1 ulp. i.e. for values very close to 0.5 it might be rounded up or * down. This is a pragmatic choice for performance reasons as it is assumed you are not working on the edge of the * precision of double. * * @param d value to round * @return rounded value */ public static double round4(double d) { final double factor = 1e4; return d > Long.MAX_VALUE / factor || d < -Long.MAX_VALUE / factor ? d : (long) (d < 0 ? d * factor - 0.5 : d * factor + 0.5) / factor; } /** * Performs a round which is accurate to within 1 ulp. i.e. for values very close to 0.5 it might be rounded up or * down. This is a pragmatic choice for performance reasons as it is assumed you are not working on the edge of the * precision of double. * * @param d value to round * @return rounded value */ public static double round6(double d) { final double factor = 1e6; return d > Long.MAX_VALUE / factor || d < -Long.MAX_VALUE / factor ? d : (long) (d < 0 ? d * factor - 0.5 : d * factor + 0.5) / factor; } /** * Performs a round which is accurate to within 1 ulp. i.e. for values very close to 0.5 it might be rounded up or * down. This is a pragmatic choice for performance reasons as it is assumed you are not working on the edge of the * precision of double. * * @param d value to round * @return rounded value */ public static double round8(double d) { final double factor = 1e8; return d > Long.MAX_VALUE / factor || d < -Long.MAX_VALUE / factor ? d : (long) (d < 0 ? d * factor - 0.5 : d * factor + 0.5) / factor; } public static long power10(int n) { if (n < 0 || n >= TENS.length) return -1; return TENS[n]; } public static int nextPower2(int n, int min) { if (!isPowerOf2(min)) throw new IllegalArgumentException(); if (n < min) return min; if (isPowerOf2(n)) return n; int i = min; while (i < n) { i *= 2; if (i <= 0) return 1 << 30; } return i; } public static long nextPower2(long n, long min) { if (!isPowerOf2(min)) throw new IllegalArgumentException(); if (n < min) return min; if (isPowerOf2(n)) return n; long i = min; while (i < n) { i *= 2; if (i <= 0) return 1L << 62; } return i; } public static boolean isPowerOf2(int n) { return (n & (n - 1)) == 0; } public static boolean isPowerOf2(long n) { return (n & (n - 1L)) == 0L; } public static int hash(int n) { n ^= (n >>> 21) - (n >>> 11); n ^= (n >>> 7) + (n >>> 4); return n; } public static long hash(long n) { n ^= (n >>> 41) - (n >>> 21); n ^= (n >>> 15) + (n >>> 7); return n; } public static long hash(CharSequence cs) { long hash = 0; for (int i = 0; i < cs.length(); i++) hash = hash * 131 + cs.charAt(i); return hash; } /** * Compares two {@code long} values numerically. The value returned is identical to what would be returned by: * <pre> * Long.valueOf(x).compareTo(Long.valueOf(y)) * </pre> * * @param x the first {@code long} to compare * @param y the second {@code long} to compare * @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y}; and a value greater * than {@code 0} if {@code x > y} */ public static int compare(long x, long y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); } public static int intLog2(long num) { long l = Double.doubleToRawLongBits(num); return (int) ((l >> 52) - 1023); } public static int toInt(long l, String error) { if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) throw new IllegalStateException(String.format(error, l)); return (int) l; } public static long agitate(long l) { l ^= l >> 23; l += Long.rotateRight(l, 18); return l; } }