Commons/src/main/java/eu/univento/commons/utils/Maths.java

285 lines
8.1 KiB
Java

package eu.univento.commons.utils;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author joethei
* @version 1.5
*/
final class Maths {
public static final float nanoToSec = 1.0E-009F;
public static final float FLOAT_ROUNDING_ERROR = 1.0E-006F;
public static final float PI = 3.141593F;
public static final float PI2 = 6.283186F;
public static final float SQRT_3 = 1.73205F;
public static final float E = 2.718282F;
public static final float radiansToDegrees = 57.295776F;
public static final float radDeg = 57.295776F;
public static final float degreesToRadians = 0.01745329F;
public static final float degRad = 0.01745329F;
private static final int ATAN2_DIM = (int)Math.sqrt(16384.0D);
private static final float INV_ATAN2_DIM_MINUS_1 = 1.0F / (ATAN2_DIM - 1);
private static final Random random = new Random();
public static float sin(float radians) {
return Sin.table[((int)(radians * 2607.5945F) & 0x3FFF)];
}
public static float cos(float radians)
{
return Sin.table[((int)((radians + 1.570796F) * 2607.5945F) & 0x3FFF)];
}
public static float sinDeg(float degrees)
{
return Sin.table[((int)(degrees * 45.511112F) & 0x3FFF)];
}
public static float cosDeg(float degrees)
{
return Sin.table[((int)((degrees + 90.0F) * 45.511112F) & 0x3FFF)];
}
public static float atan2(float y, float x)
{
float mul;
float add;
if (x < 0.0F)
{
if (y < 0.0F) {
y = -y;
mul = 1.0F;
} else {
mul = -1.0F;
}x = -x;
add = -3.141593F;
}
else
{
if (y < 0.0F) {
y = -y;
mul = -1.0F;
} else {
mul = 1.0F;
}add = 0.0F;
}
float invDiv = 1.0F / ((x < y ? y : x) * INV_ATAN2_DIM_MINUS_1);
if (invDiv == 1.0F) return ((float)Math.atan2(y, x) + add) * mul;
int xi = (int)(x * invDiv);
int yi = (int)(y * invDiv);
return (Atan2.table[(yi * ATAN2_DIM + xi)] + add) * mul;
}
public static int random(int range)
{
return random.nextInt(range + 1);
}
public static int random(int start, int end)
{
return start + random.nextInt(end - start + 1);
}
public static boolean randomBoolean()
{
return random.nextBoolean();
}
public static boolean randomBoolean(float chance)
{
return random() < chance;
}
private static float random()
{
return random.nextFloat();
}
public static float random(float range)
{
return random.nextFloat() * range;
}
public static float random(float start, float end)
{
return start + random.nextFloat() * (end - start);
}
public static int nextPowerOfTwo(int value)
{
if (value == 0) return 1;
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return value + 1;
}
public static boolean isPowerOfTwo(int value) {
return (value != 0) && ((value & value - 1) == 0);
}
public static int clamp(int value, int min, int max)
{
if (value < min) return min;
if (value > max) return max;
return value;
}
public static short clamp(short value, short min, short max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
public static float clamp(float value, float min, float max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
public static int floor(float x)
{
return (int)(x + 16384.0D) - 16384;
}
public static int floorPositive(float x)
{
return (int)x;
}
public static int ceil(float x)
{
return (int)(x + 16384.999999999996D) - 16384;
}
public static int ceilPositive(float x)
{
return (int)(x + 0.9999999000000001D);
}
public static int round(float x)
{
return (int)(x + 16384.5D) - 16384;
}
public static int roundPositive(float x)
{
return (int)(x + 0.5F);
}
public static boolean isZero(float value)
{
return Math.abs(value) <= 1.0E-006F;
}
public static boolean isZero(float value, float tolerance)
{
return Math.abs(value) <= tolerance;
}
public static boolean isEqual(float a, float b)
{
return Math.abs(a - b) <= 1.0E-006F;
}
public static boolean isEqual(float a, float b, float tolerance)
{
return Math.abs(a - b) <= tolerance;
}
public static long parseDateDiff(String time, boolean future)
throws Exception
{
Pattern timePattern = Pattern.compile("(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?(?:([0-9]+)\\s*(?:s[a-z]*)?)?", 2);
Matcher m = timePattern.matcher(time);
int years = 0;
int months = 0;
int weeks = 0;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
boolean found = false;
while (m.find()) {
if ((m.group() == null) || (m.group().isEmpty())) {
continue;
}
for (int i = 0; i < m.groupCount(); i++) {
if ((m.group(i) != null) && (!m.group(i).isEmpty())) {
found = true;
break;
}
}
if (found) {
if ((m.group(1) != null) && (!m.group(1).isEmpty()))
years = Integer.parseInt(m.group(1));
if ((m.group(2) != null) && (!m.group(2).isEmpty()))
months = Integer.parseInt(m.group(2));
if ((m.group(3) != null) && (!m.group(3).isEmpty()))
weeks = Integer.parseInt(m.group(3));
if ((m.group(4) != null) && (!m.group(4).isEmpty()))
days = Integer.parseInt(m.group(4));
if ((m.group(5) != null) && (!m.group(5).isEmpty()))
hours = Integer.parseInt(m.group(5));
if ((m.group(6) != null) && (!m.group(6).isEmpty()))
minutes = Integer.parseInt(m.group(6));
if ((m.group(7) == null) || (m.group(7).isEmpty())) break;
seconds = Integer.parseInt(m.group(7));
break;
}
}
if (!found)
throw new Exception("Illegal Date");
Calendar c = new GregorianCalendar();
if (years > 0)
c.add(1, years * (future ? 1 : -1));
if (months > 0)
c.add(2, months * (future ? 1 : -1));
if (weeks > 0)
c.add(3, weeks * (future ? 1 : -1));
if (days > 0)
c.add(5, days * (future ? 1 : -1));
if (hours > 0)
c.add(11, hours * (future ? 1 : -1));
if (minutes > 0)
c.add(12, minutes * (future ? 1 : -1));
if (seconds > 0)
c.add(13, seconds * (future ? 1 : -1));
return c.getTimeInMillis();
}
private static class Atan2
{
static final float[] table = new float[16384];
static { for (int i = 0; i < Maths.ATAN2_DIM; i++)
for (int j = 0; j < Maths.ATAN2_DIM; j++) {
float x0 = i / Maths.ATAN2_DIM;
float y0 = j / Maths.ATAN2_DIM;
table[(j * Maths.ATAN2_DIM + i)] = (float)Math.atan2(y0, x0);
}
}
}
private static class Sin
{
static final float[] table = new float[16384];
static { for (int i = 0; i < 16384; i++)
table[i] = (float)Math.sin((i + 0.5F) / 16384.0F * 6.283186F);
for (int i = 0; i < 360; i += 90)
table[((int)(i * 45.511112F) & 0x3FFF)] = (float)Math.sin(i * 0.01745329F);
}
}
}