001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.util; 020 021public class MathMan { 022 023 private static final int ATAN2_BITS = 7; 024 private static final int ATAN2_BITS2 = ATAN2_BITS << 1; 025 private static final int ATAN2_MASK = ~(-1 << ATAN2_BITS2); 026 private static final int ATAN2_COUNT = ATAN2_MASK + 1; 027 private static final int ATAN2_DIM = (int) Math.sqrt(ATAN2_COUNT); 028 private static final float INV_ATAN2_DIM_MINUS_1 = 1.0f / (ATAN2_DIM - 1); 029 private static final float[] atan2 = new float[ATAN2_COUNT]; 030 private static final int[] table = 031 {0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, 64, 65, 67, 69, 71, 73, 75, 032 76, 78, 80, 81, 83, 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 033 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 034 124, 125, 126, 128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 035 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 036 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, 037 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 038 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 039 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 203, 203, 040 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 041 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223, 224, 042 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 043 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, 241, 241, 242, 242, 044 243, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 045 251, 252, 252, 253, 253, 254, 254, 255}; 046 047 static { 048 for (int i = 0; i < ATAN2_DIM; i++) { 049 for (int j = 0; j < ATAN2_DIM; j++) { 050 float x0 = (float) i / ATAN2_DIM; 051 float y0 = (float) j / ATAN2_DIM; 052 053 atan2[(j * ATAN2_DIM) + i] = (float) Math.atan2(y0, x0); 054 } 055 } 056 } 057 058 public static final int gcd(int a, int b) { 059 if (b == 0) { 060 return a; 061 } 062 return gcd(b, a % b); 063 } 064 065 public static final int gcd(int[] a) { 066 int result = a[0]; 067 for (int i = 1; i < a.length; i++) { 068 result = gcd(result, a[i]); 069 } 070 return result; 071 } 072 073 public static long pairInt(int x, int y) { 074 return (((long) x) << 32) | (y & 0xffffffffL); 075 } 076 077 public static int unpairIntX(long pair) { 078 return (int) (pair >> 32); 079 } 080 081 public static int unpairIntY(long pair) { 082 return (int) pair; 083 } 084 085 public static byte pair16(byte x, byte y) { 086 return (byte) (x + (y << 4)); 087 } 088 089 public static byte unpair16x(byte value) { 090 return (byte) (value & 0xF); 091 } 092 093 public static byte unpair16y(byte value) { 094 return (byte) ((value >> 4) & 0xF); 095 } 096 097 public static long inverseRound(double val) { 098 long round = Math.round(val); 099 return (long) (round + Math.signum(val - round)); 100 } 101 102 public static int sqrt(int x) { 103 int xn; 104 105 if (x >= 0x10000) { 106 if (x >= 0x1000000) { 107 if (x >= 0x10000000) { 108 if (x >= 0x40000000) { 109 xn = table[x >> 24] << 8; 110 } else { 111 xn = table[x >> 22] << 7; 112 } 113 } else { 114 if (x >= 0x4000000) { 115 xn = table[x >> 20] << 6; 116 } else { 117 xn = table[x >> 18] << 5; 118 } 119 } 120 121 xn = (xn + 1 + (x / xn)) >> 1; 122 xn = (xn + 1 + (x / xn)) >> 1; 123 return ((xn * xn) > x) ? --xn : xn; 124 } else { 125 if (x >= 0x100000) { 126 if (x >= 0x400000) { 127 xn = table[x >> 16] << 4; 128 } else { 129 xn = table[x >> 14] << 3; 130 } 131 } else { 132 if (x >= 0x40000) { 133 xn = table[x >> 12] << 2; 134 } else { 135 xn = table[x >> 10] << 1; 136 } 137 } 138 139 xn = (xn + 1 + (x / xn)) >> 1; 140 141 return ((xn * xn) > x) ? --xn : xn; 142 } 143 } else { 144 if (x >= 0x100) { 145 if (x >= 0x1000) { 146 if (x >= 0x4000) { 147 xn = (table[x >> 8]) + 1; 148 } else { 149 xn = (table[x >> 6] >> 1) + 1; 150 } 151 } else { 152 if (x >= 0x400) { 153 xn = (table[x >> 4] >> 2) + 1; 154 } else { 155 xn = (table[x >> 2] >> 3) + 1; 156 } 157 } 158 159 return ((xn * xn) > x) ? --xn : xn; 160 } else { 161 if (x >= 0) { 162 return table[x] >> 4; 163 } 164 } 165 } 166 throw new IllegalArgumentException("Invalid number:" + x); 167 } 168 169 170 public static double getMean(int[] array) { 171 double count = 0; 172 for (int i : array) { 173 count += i; 174 } 175 return count / array.length; 176 } 177 178 public static double getMean(double[] array) { 179 double count = 0; 180 for (double i : array) { 181 count += i; 182 } 183 return count / array.length; 184 } 185 186 public static int pair(short x, short y) { 187 return (x << 16) | (y & 0xFFFF); 188 } 189 190 public static final int average(int a, int b) { 191 return (a & b) + (a ^ b) / 2; 192 } 193 194 public static short unpairX(int hash) { 195 return (short) (hash >> 16); 196 } 197 198 public static short unpairY(int hash) { 199 return (short) (hash & 0xFFFF); 200 } 201 202 /** 203 * get the x,y,z unit vector from pitch and yaw specified 204 * 205 * @param yaw yaw 206 * @param pitch pitch 207 * @return x, y, z unit vector 208 */ 209 public static float[] getDirection(float yaw, float pitch) { 210 double pitch_sin = Math.sin(pitch); 211 return new float[]{(float) (pitch_sin * Math.cos(yaw)), 212 (float) (pitch_sin * Math.sin(yaw)), (float) Math.cos(pitch)}; 213 } 214 215 public static int floorMod(int x, int y) { 216 int i = x % y; 217 if (i < 0) { 218 i += y; 219 } 220 return i; 221 } 222 223 public static int roundInt(double value) { 224 return (int) (value < 0 ? (value == (int) value) ? value : value - 1 : value); 225 } 226 227 /** 228 * Returns [ pitch, yaw ] 229 * 230 * @param x x 231 * @param y y 232 * @param z z 233 * @return pitch and yaw of x,y,z from 0,0,0 234 */ 235 public static float[] getPitchAndYaw(float x, float y, float z) { 236 float distance = sqrtApprox((z * z) + (x * x)); 237 return new float[]{atan2(y, distance), atan2(x, z)}; 238 } 239 240 public static final float atan2(float y, float x) { 241 float add; 242 float mul; 243 244 if (x < 0.0f) { 245 if (y < 0.0f) { 246 x = -x; 247 y = -y; 248 249 mul = 1.0f; 250 } else { 251 x = -x; 252 mul = -1.0f; 253 } 254 255 add = -3.141592653f; 256 } else { 257 if (y < 0.0f) { 258 y = -y; 259 mul = -1.0f; 260 } else { 261 mul = 1.0f; 262 } 263 264 add = 0.0f; 265 } 266 267 float invDiv = 1.0f / (((x < y) ? y : x) * INV_ATAN2_DIM_MINUS_1); 268 269 int xi = (int) (x * invDiv); 270 int yi = (int) (y * invDiv); 271 272 return (atan2[(yi * ATAN2_DIM) + xi] + add) * mul; 273 } 274 275 public static float sqrtApprox(float f) { 276 return f * Float.intBitsToFloat(0x5f375a86 - (Float.floatToIntBits(f) >> 1)); 277 } 278 279 public static double sqrtApprox(double d) { 280 return Double 281 .longBitsToDouble(((Double.doubleToLongBits(d) - (1L << 52)) >> 1) + (1L << 61)); 282 } 283 284 public static float invSqrt(float x) { 285 float xhalf = 0.5f * x; 286 int i = Float.floatToIntBits(x); 287 i = 0x5f3759df - (i >> 1); 288 x = Float.intBitsToFloat(i); 289 x = x * (1.5f - (xhalf * x * x)); 290 return x; 291 } 292 293 public static int getPositiveId(int i) { 294 if (i < 0) { 295 return (-i * 2) - 1; 296 } 297 return i * 2; 298 } 299 300 public static boolean isInteger(String str) { 301 if (str == null) { 302 return false; 303 } 304 int length = str.length(); 305 if (length == 0) { 306 return false; 307 } 308 int i = 0; 309 if (str.charAt(0) == '-') { 310 if (length == 1) { 311 return false; 312 } 313 i = 1; 314 } 315 for (; i < length; i++) { 316 char c = str.charAt(i); 317 if ((c <= '/') || (c >= ':')) { 318 return false; 319 } 320 } 321 return true; 322 } 323 324 public static double getSD(double[] array, double av) { 325 double sd = 0; 326 for (double element : array) { 327 sd += Math.pow(Math.abs(element - av), 2); 328 } 329 return Math.sqrt(sd / array.length); 330 } 331 332 public static double getSD(int[] array, double av) { 333 double sd = 0; 334 for (int element : array) { 335 sd += Math.pow(Math.abs(element - av), 2); 336 } 337 return Math.sqrt(sd / array.length); 338 } 339 340 public static int mod(int x, int y) { 341 if (isPowerOfTwo(y)) { 342 return x & (y - 1); 343 } 344 return x % y; 345 } 346 347 public static int unsignedmod(int x, int y) { 348 if (isPowerOfTwo(y)) { 349 return x & (y - 1); 350 } 351 return x % y; 352 } 353 354 public static boolean isPowerOfTwo(int number) { 355 return (number & (number - 1)) == 0; 356 } 357 358}