1 /* 2 SPDX-FileCopyrightText: 2011 See AUTHORS file. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package org.kde.kstars.math; 8 9 /** from libgdx: https://github.com/libgdx/libgdx */ 10 11 import java.util.Random; 12 13 /** Utility and fast math functions. 14 * <p> 15 * Thanks to Riven on JavaGaming.org for the basis of sin/cos/atan2/floor/ceil. 16 * @author Nathan Sweet */ 17 public class MathUtils { 18 static public final float nanoToSec = 1 / 1000000000f; 19 20 // --- 21 22 static public final float PI = 3.1415927f; 23 24 static private final int SIN_BITS = 13; // Adjust for accuracy. 25 static private final int SIN_MASK = ~(-1 << SIN_BITS); 26 static private final int SIN_COUNT = SIN_MASK + 1; 27 28 static private final float radFull = PI * 2; 29 static private final float degFull = 360; 30 static private final float radToIndex = SIN_COUNT / radFull; 31 static private final float degToIndex = SIN_COUNT / degFull; 32 33 static public final float radiansToDegrees = 180f / PI; 34 static public final float radDeg = radiansToDegrees; 35 static public final float degreesToRadians = PI / 180; 36 static public final float degRad = degreesToRadians; 37 38 static private class Sin { 39 static final float[] table = new float[SIN_COUNT]; 40 static { 41 for (int i = 0; i < SIN_COUNT; i++) 42 table[i] = (float)Math.sin((i + 0.5f) / SIN_COUNT * radFull); 43 for (int i = 0; i < 360; i += 90) 44 table[(int)(i * degToIndex) & SIN_MASK] = (float)Math.sin(i * degreesToRadians); 45 } 46 } 47 48 static private class Cos { 49 static final float[] table = new float[SIN_COUNT]; 50 static { 51 for (int i = 0; i < SIN_COUNT; i++) 52 table[i] = (float)Math.cos((i + 0.5f) / SIN_COUNT * radFull); 53 for (int i = 0; i < 360; i += 90) 54 table[(int)(i * degToIndex) & SIN_MASK] = (float)Math.cos(i * degreesToRadians); 55 } 56 } 57 58 /** Returns the sine in radians. */ sin(float radians)59 static public final float sin (float radians) { 60 return Sin.table[(int)(radians * radToIndex) & SIN_MASK]; 61 } 62 63 /** Returns the cosine in radians. */ cos(float radians)64 static public final float cos (float radians) { 65 return Cos.table[(int)(radians * radToIndex) & SIN_MASK]; 66 } 67 68 /** Returns the sine in radians. */ sinDeg(float degrees)69 static public final float sinDeg (float degrees) { 70 return Sin.table[(int)(degrees * degToIndex) & SIN_MASK]; 71 } 72 73 /** Returns the cosine in radians. */ cosDeg(float degrees)74 static public final float cosDeg (float degrees) { 75 return Cos.table[(int)(degrees * degToIndex) & SIN_MASK]; 76 } 77 78 // --- 79 80 static private final int ATAN2_BITS = 7; // Adjust for accuracy. 81 static private final int ATAN2_BITS2 = ATAN2_BITS << 1; 82 static private final int ATAN2_MASK = ~(-1 << ATAN2_BITS2); 83 static private final int ATAN2_COUNT = ATAN2_MASK + 1; 84 static final int ATAN2_DIM = (int)Math.sqrt(ATAN2_COUNT); 85 static private final float INV_ATAN2_DIM_MINUS_1 = 1.0f / (ATAN2_DIM - 1); 86 87 static private class Atan2 { 88 static final float[] table = new float[ATAN2_COUNT]; 89 static { 90 for (int i = 0; i < ATAN2_DIM; i++) { 91 for (int j = 0; j < ATAN2_DIM; j++) { 92 float x0 = (float)i / ATAN2_DIM; 93 float y0 = (float)j / ATAN2_DIM; 94 table[j * ATAN2_DIM + i] = (float)Math.atan2(y0, x0); 95 } 96 } 97 } 98 } 99 100 /** Returns atan2 in radians from a lookup table. */ atan2(float y, float x)101 static public final float atan2 (float y, float x) { 102 float add, mul; 103 if (x < 0) { 104 if (y < 0) { 105 y = -y; 106 mul = 1; 107 } else 108 mul = -1; 109 x = -x; 110 add = -PI; 111 } else { 112 if (y < 0) { 113 y = -y; 114 mul = -1; 115 } else 116 mul = 1; 117 add = 0; 118 } 119 float invDiv = 1 / ((x < y ? y : x) * INV_ATAN2_DIM_MINUS_1); 120 int xi = (int)(x * invDiv); 121 int yi = (int)(y * invDiv); 122 return (Atan2.table[yi * ATAN2_DIM + xi] + add) * mul; 123 } 124 125 // --- 126 127 static public Random random = new Random(); 128 129 /** Returns a random number between 0 (inclusive) and the specified value (inclusive). */ random(int range)130 static public final int random (int range) { 131 return random.nextInt(range + 1); 132 } 133 134 /** Returns a random number between start (inclusive) and end (inclusive). */ random(int start, int end)135 static public final int random (int start, int end) { 136 return start + random.nextInt(end - start + 1); 137 } 138 randomBoolean()139 static public final boolean randomBoolean () { 140 return random.nextBoolean(); 141 } 142 random()143 static public final float random () { 144 return random.nextFloat(); 145 } 146 147 /** Returns a random number between 0 (inclusive) and the specified value (inclusive). */ random(float range)148 static public final float random (float range) { 149 return random.nextFloat() * range; 150 } 151 152 /** Returns a random number between start (inclusive) and end (inclusive). */ random(float start, float end)153 static public final float random (float start, float end) { 154 return start + random.nextFloat() * (end - start); 155 } 156 157 // --- 158 159 /** Returns the next power of two. Returns the specified value if the value is already a power of two. */ nextPowerOfTwo(int value)160 static public int nextPowerOfTwo (int value) { 161 if (value == 0) return 1; 162 value--; 163 value |= value >> 1; 164 value |= value >> 2; 165 value |= value >> 4; 166 value |= value >> 8; 167 value |= value >> 16; 168 return value + 1; 169 } 170 isPowerOfTwo(int value)171 static public boolean isPowerOfTwo (int value) { 172 return value != 0 && (value & value - 1) == 0; 173 } 174 175 // --- 176 clamp(int value, int min, int max)177 static public int clamp (int value, int min, int max) { 178 if (value < min) return min; 179 if (value > max) return max; 180 return value; 181 } 182 clamp(short value, short min, short max)183 static public short clamp (short value, short min, short max) { 184 if (value < min) return min; 185 if (value > max) return max; 186 return value; 187 } 188 clamp(float value, float min, float max)189 static public float clamp (float value, float min, float max) { 190 if (value < min) return min; 191 if (value > max) return max; 192 return value; 193 } 194 195 // --- 196 197 static private final int BIG_ENOUGH_INT = 16 * 1024; 198 static private final double BIG_ENOUGH_FLOOR = BIG_ENOUGH_INT; 199 static private final double CEIL = 0.9999999; 200 static private final double BIG_ENOUGH_CEIL = NumberUtils 201 .longBitsToDouble(NumberUtils.doubleToLongBits(BIG_ENOUGH_INT + 1) - 1); 202 static private final double BIG_ENOUGH_ROUND = BIG_ENOUGH_INT + 0.5f; 203 204 /** Returns the largest integer less than or equal to the specified float. This method will only properly floor floats from 205 * -(2^14) to (Float.MAX_VALUE - 2^14). */ floor(float x)206 static public int floor (float x) { 207 return (int)(x + BIG_ENOUGH_FLOOR) - BIG_ENOUGH_INT; 208 } 209 210 /** Returns the largest integer less than or equal to the specified float. This method will only properly floor floats that are 211 * positive. Note this method simply casts the float to int. */ floorPositive(float x)212 static public int floorPositive (float x) { 213 return (int)x; 214 } 215 216 /** Returns the smallest integer greater than or equal to the specified float. This method will only properly ceil floats from 217 * -(2^14) to (Float.MAX_VALUE - 2^14). */ ceil(float x)218 static public int ceil (float x) { 219 return (int)(x + BIG_ENOUGH_CEIL) - BIG_ENOUGH_INT; 220 } 221 222 /** Returns the smallest integer greater than or equal to the specified float. This method will only properly ceil floats that 223 * are positive. */ ceilPositive(float x)224 static public int ceilPositive (float x) { 225 return (int)(x + CEIL); 226 } 227 228 /** Returns the closest integer to the specified float. This method will only properly round floats from -(2^14) to 229 * (Float.MAX_VALUE - 2^14). */ round(float x)230 static public int round (float x) { 231 return (int)(x + BIG_ENOUGH_ROUND) - BIG_ENOUGH_INT; 232 } 233 234 /** Returns the closest integer to the specified float. This method will only properly round floats that are positive. */ roundPositive(float x)235 static public int roundPositive (float x) { 236 return (int)(x + 0.5f); 237 } 238 } 239