|
| 1 | +package com.falsepattern.lib.compat; |
| 2 | + |
| 3 | +import java.util.Random; |
| 4 | + |
| 5 | +/** |
| 6 | + * This is here because the real MathHelper has some of its methods only present in clientside, some of which we |
| 7 | + * actually DO need in serverside. |
| 8 | + */ |
| 9 | +public class MathHelper { |
| 10 | + /** |
| 11 | + * Though it looks like an array, this is really more like a mapping. Key (index of this array) is the upper 5 bits |
| 12 | + * of the result of multiplying a 32-bit unsigned integer by the B(2, 5) De Bruijn sequence 0x077CB531. Value |
| 13 | + * (value stored in the array) is the unique index (from the right) of the leftmost one-bit in a 32-bit unsigned |
| 14 | + * integer that can cause the upper 5 bits to get that value. Used for highly optimized "find the log-base-2 of |
| 15 | + * this number" calculations. |
| 16 | + */ |
| 17 | + private static final int[] multiplyDeBruijnBitPosition; |
| 18 | + private static final float[] SIN_TABLE = new float[65536]; |
| 19 | + |
| 20 | + static { |
| 21 | + for (int i = 0; i < 65536; ++i) { |
| 22 | + SIN_TABLE[i] = (float) Math.sin((double) i * Math.PI * 2.0D / 65536.0D); |
| 23 | + } |
| 24 | + |
| 25 | + multiplyDeBruijnBitPosition = |
| 26 | + new int[]{0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, |
| 27 | + 12, 18, 6, 11, 5, 10, 9}; |
| 28 | + } |
| 29 | + |
| 30 | + /** |
| 31 | + * sin looked up in a table |
| 32 | + */ |
| 33 | + public static float sin(float a) { |
| 34 | + return SIN_TABLE[(int) (a * 10430.378F) & 65535]; |
| 35 | + } |
| 36 | + |
| 37 | + /** |
| 38 | + * cos looked up in the sin table with the appropriate offset |
| 39 | + */ |
| 40 | + public static float cos(float a) { |
| 41 | + return SIN_TABLE[(int) (a * 10430.378F + 16384.0F) & 65535]; |
| 42 | + } |
| 43 | + |
| 44 | + public static float sqrt_float(float a) { |
| 45 | + return (float) Math.sqrt(a); |
| 46 | + } |
| 47 | + |
| 48 | + public static float sqrt_double(double a) { |
| 49 | + return (float) Math.sqrt(a); |
| 50 | + } |
| 51 | + |
| 52 | + /** |
| 53 | + * Returns the greatest integer less than or equal to the float argument |
| 54 | + */ |
| 55 | + public static int floor_float(float a) { |
| 56 | + int i = (int) a; |
| 57 | + return a < (float) i ? i - 1 : i; |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * returns par0 cast as an int, and no greater than Integer.MAX_VALUE-1024 |
| 62 | + */ |
| 63 | + public static int truncateDoubleToInt(double a) { |
| 64 | + return (int) (a + 1024.0D) - 1024; |
| 65 | + } |
| 66 | + |
| 67 | + /** |
| 68 | + * Returns the greatest integer less than or equal to the double argument |
| 69 | + */ |
| 70 | + public static int floor_double(double a) { |
| 71 | + int i = (int) a; |
| 72 | + return a < (double) i ? i - 1 : i; |
| 73 | + } |
| 74 | + |
| 75 | + /** |
| 76 | + * Long version of floor_double |
| 77 | + */ |
| 78 | + public static long floor_double_long(double a) { |
| 79 | + long i = (long) a; |
| 80 | + return a < (double) i ? i - 1L : i; |
| 81 | + } |
| 82 | + |
| 83 | + public static int absFloor(double a) { |
| 84 | + return (int) (a >= 0.0D ? a : -a + 1.0D); |
| 85 | + } |
| 86 | + |
| 87 | + public static float abs(float a) { |
| 88 | + return a >= 0.0F ? a : -a; |
| 89 | + } |
| 90 | + |
| 91 | + /** |
| 92 | + * Returns the unsigned value of an int. |
| 93 | + */ |
| 94 | + public static int abs_int(int a) { |
| 95 | + return a >= 0 ? a : -a; |
| 96 | + } |
| 97 | + |
| 98 | + public static int ceiling_float_int(float a) { |
| 99 | + int i = (int) a; |
| 100 | + return a > (float) i ? i + 1 : i; |
| 101 | + } |
| 102 | + |
| 103 | + public static int ceiling_double_int(double a) { |
| 104 | + int i = (int) a; |
| 105 | + return a > (double) i ? i + 1 : i; |
| 106 | + } |
| 107 | + |
| 108 | + /** |
| 109 | + * Returns the value of the first parameter, clamped to be within the lower and upper limits given by the second and |
| 110 | + * third parameters. |
| 111 | + */ |
| 112 | + public static int clamp_int(int a, int min, int max) { |
| 113 | + return a < min ? min : (Math.min(a, max)); |
| 114 | + } |
| 115 | + |
| 116 | + /** |
| 117 | + * Returns the value of the first parameter, clamped to be within the lower and upper limits given by the second and |
| 118 | + * third parameters |
| 119 | + */ |
| 120 | + public static float clamp_float(float a, float min, float max) { |
| 121 | + return a < min ? min : Math.min(a, max); |
| 122 | + } |
| 123 | + |
| 124 | + public static double clamp_double(double a, double min, double max) { |
| 125 | + return a < min ? min : Math.min(a, max); |
| 126 | + } |
| 127 | + |
| 128 | + public static double denormalizeClamp(double min, double max, double normalized) { |
| 129 | + return normalized < 0.0D ? min : (normalized > 1.0D ? max : min + (max - min) * normalized); |
| 130 | + } |
| 131 | + |
| 132 | + /** |
| 133 | + * Maximum of the absolute value of two numbers. |
| 134 | + */ |
| 135 | + public static double abs_max(double a, double b) { |
| 136 | + if (a < 0.0D) { |
| 137 | + a = -a; |
| 138 | + } |
| 139 | + |
| 140 | + if (b < 0.0D) { |
| 141 | + b = -b; |
| 142 | + } |
| 143 | + |
| 144 | + return Math.max(a, b); |
| 145 | + } |
| 146 | + |
| 147 | + /** |
| 148 | + * Buckets an integer with specifed bucket sizes. Args: i, bucketSize |
| 149 | + */ |
| 150 | + public static int bucketInt(int i, int bucketSize) { |
| 151 | + return i < 0 ? -((-i - 1) / bucketSize) - 1 : i / bucketSize; |
| 152 | + } |
| 153 | + |
| 154 | + /** |
| 155 | + * Tests if a string is null or of length zero |
| 156 | + */ |
| 157 | + public static boolean stringNullOrLengthZero(String str) { |
| 158 | + return str == null || str.length() == 0; |
| 159 | + } |
| 160 | + |
| 161 | + public static int getRandomIntegerInRange(Random rng, int min, int max) { |
| 162 | + return min >= max ? min : rng.nextInt(max - min + 1) + min; |
| 163 | + } |
| 164 | + |
| 165 | + public static float randomFloatClamp(Random rng, float min, float max) { |
| 166 | + return min >= max ? min : rng.nextFloat() * (max - min) + min; |
| 167 | + } |
| 168 | + |
| 169 | + public static double getRandomDoubleInRange(Random rng, double min, double max) { |
| 170 | + return min >= max ? min : rng.nextDouble() * (max - min) + min; |
| 171 | + } |
| 172 | + |
| 173 | + public static double average(long[] values) { |
| 174 | + long i = 0L; |
| 175 | + long[] along1 = values; |
| 176 | + int j = values.length; |
| 177 | + |
| 178 | + for (int k = 0; k < j; ++k) { |
| 179 | + long l = along1[k]; |
| 180 | + i += l; |
| 181 | + } |
| 182 | + |
| 183 | + return (double) i / (double) values.length; |
| 184 | + } |
| 185 | + |
| 186 | + /** |
| 187 | + * the angle is reduced to an angle between -180 and +180 by mod, and a 360 check |
| 188 | + */ |
| 189 | + public static float wrapAngleTo180_float(float angle) { |
| 190 | + angle %= 360.0F; |
| 191 | + |
| 192 | + if (angle >= 180.0F) { |
| 193 | + angle -= 360.0F; |
| 194 | + } |
| 195 | + |
| 196 | + if (angle < -180.0F) { |
| 197 | + angle += 360.0F; |
| 198 | + } |
| 199 | + |
| 200 | + return angle; |
| 201 | + } |
| 202 | + |
| 203 | + /** |
| 204 | + * the angle is reduced to an angle between -180 and +180 by mod, and a 360 check |
| 205 | + */ |
| 206 | + public static double wrapAngleTo180_double(double angle) { |
| 207 | + angle %= 360.0D; |
| 208 | + |
| 209 | + if (angle >= 180.0D) { |
| 210 | + angle -= 360.0D; |
| 211 | + } |
| 212 | + |
| 213 | + if (angle < -180.0D) { |
| 214 | + angle += 360.0D; |
| 215 | + } |
| 216 | + |
| 217 | + return angle; |
| 218 | + } |
| 219 | + |
| 220 | + /** |
| 221 | + * parses the string as integer or returns the second parameter if it fails |
| 222 | + */ |
| 223 | + public static int parseIntWithDefault(String str, int def) { |
| 224 | + int j = def; |
| 225 | + |
| 226 | + try { |
| 227 | + j = Integer.parseInt(str); |
| 228 | + } catch (Throwable throwable) { |
| 229 | + } |
| 230 | + |
| 231 | + return j; |
| 232 | + } |
| 233 | + |
| 234 | + /** |
| 235 | + * parses the string as integer or returns the second parameter if it fails. this value is capped to par2 |
| 236 | + */ |
| 237 | + public static int parseIntWithDefaultAndMax(String str, int def, int min) { |
| 238 | + int k = def; |
| 239 | + |
| 240 | + try { |
| 241 | + k = Integer.parseInt(str); |
| 242 | + } catch (Throwable throwable) { |
| 243 | + } |
| 244 | + |
| 245 | + if (k < min) { |
| 246 | + k = min; |
| 247 | + } |
| 248 | + |
| 249 | + return k; |
| 250 | + } |
| 251 | + |
| 252 | + /** |
| 253 | + * parses the string as double or returns the second parameter if it fails. |
| 254 | + */ |
| 255 | + public static double parseDoubleWithDefault(String str, double def) { |
| 256 | + double d1 = def; |
| 257 | + |
| 258 | + try { |
| 259 | + d1 = Double.parseDouble(str); |
| 260 | + } catch (Throwable ignored) { |
| 261 | + } |
| 262 | + |
| 263 | + return d1; |
| 264 | + } |
| 265 | + |
| 266 | + public static double parseDoubleWithDefaultAndMin(String str, double def, double min) { |
| 267 | + double d2 = def; |
| 268 | + |
| 269 | + try { |
| 270 | + d2 = Double.parseDouble(str); |
| 271 | + } catch (Throwable throwable) { |
| 272 | + } |
| 273 | + |
| 274 | + if (d2 < min) { |
| 275 | + d2 = min; |
| 276 | + } |
| 277 | + |
| 278 | + return d2; |
| 279 | + } |
| 280 | + |
| 281 | + /** |
| 282 | + * Returns the input value rounded up to the next highest power of two. |
| 283 | + */ |
| 284 | + public static int roundUpToPowerOfTwo(int a) { |
| 285 | + int j = a - 1; |
| 286 | + j |= j >> 1; |
| 287 | + j |= j >> 2; |
| 288 | + j |= j >> 4; |
| 289 | + j |= j >> 8; |
| 290 | + j |= j >> 16; |
| 291 | + return j + 1; |
| 292 | + } |
| 293 | + |
| 294 | + /** |
| 295 | + * Is the given value a power of two? (1, 2, 4, 8, 16, ...) |
| 296 | + */ |
| 297 | + private static boolean isPowerOfTwo(int a) { |
| 298 | + return a != 0 && (a & a - 1) == 0; |
| 299 | + } |
| 300 | + |
| 301 | + /** |
| 302 | + * Uses a B(2, 5) De Bruijn sequence and a lookup table to efficiently calculate the log-base-two of the given |
| 303 | + * value. Optimized for cases where the input value is a power-of-two. If the input value is not a power-of-two, |
| 304 | + * then subtract 1 from the return value. |
| 305 | + */ |
| 306 | + private static int calculateLogBaseTwoDeBruijn(int a) { |
| 307 | + a = isPowerOfTwo(a) ? a : roundUpToPowerOfTwo(a); |
| 308 | + return multiplyDeBruijnBitPosition[(int) ((long) a * 125613361L >> 27) & 31]; |
| 309 | + } |
| 310 | + |
| 311 | + /** |
| 312 | + * Efficiently calculates the floor of the base-2 log of an integer value. This is effectively the index of the |
| 313 | + * highest bit that is set. For example, if the number in binary is 0...100101, this will return 5. |
| 314 | + */ |
| 315 | + public static int calculateLogBaseTwo(int a) { |
| 316 | + /** |
| 317 | + * Uses a B(2, 5) De Bruijn sequence and a lookup table to efficiently calculate the log-base-two of the given |
| 318 | + * value. Optimized for cases where the input value is a power-of-two. If the input value is not a power-of- |
| 319 | + * two, then subtract 1 from the return value. |
| 320 | + */ |
| 321 | + return calculateLogBaseTwoDeBruijn(a) - (isPowerOfTwo(a) ? 0 : 1); |
| 322 | + } |
| 323 | + |
| 324 | + public static int roundUp(int a, int b) { |
| 325 | + if (b == 0) { |
| 326 | + return 0; |
| 327 | + } else { |
| 328 | + if (a < 0) { |
| 329 | + b *= -1; |
| 330 | + } |
| 331 | + |
| 332 | + int k = a % b; |
| 333 | + return k == 0 ? a : a + b - k; |
| 334 | + } |
| 335 | + } |
| 336 | +} |
0 commit comments