/**
* Copyright 2008 - 2012
*
* 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.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.3.3
*/
package loon.utils;
import java.util.Random;
import loon.LSystem;
import loon.geom.RectBox;
public class MathUtils {
final static public Random random = new Random();
private static final int[] SHIFT = { 0, 1144, 2289, 3435, 4583, 5734, 6888, 8047, 9210, 10380, 11556, 12739, 13930,
15130, 16340, 17560, 18792, 20036, 21294, 22566, 23853, 25157, 26478, 27818, 29179, 30560, 31964, 33392,
34846, 36327, 37837, 39378, 40951, 42560, 44205, 45889, 47615, 49385, 51202, 53070, 54991, 56970, 59009,
61113, 63287, 65536 };
public static int ifloor(float v) {
int iv = (int) v;
return (v >= 0f || iv == v || iv == Integer.MIN_VALUE) ? iv : (iv - 1);
}
public static int iceil(float v) {
int iv = (int) v;
return (v <= 0f || iv == v || iv == Integer.MAX_VALUE) ? iv : (iv + 1);
}
public static RectBox getBounds(float x, float y, float width, float height, float rotate, RectBox result) {
if (rotate == 0) {
if (result == null) {
result = new RectBox(x, y, width, height);
} else {
result.setBounds(x, y, width, height);
}
return result;
}
int[] rect = getLimit(x, y, width, height, rotate);
if (result == null) {
result = new RectBox(rect[0], rect[1], rect[2], rect[3]);
} else {
result.setBounds(rect[0], rect[1], rect[2], rect[3]);
}
return result;
}
public static RectBox getBounds(float x, float y, float width, float height, float rotate) {
return getBounds(x, y, width, height, rotate, null);
}
static public boolean isZero(float value, float tolerance) {
return Math.abs(value) <= tolerance;
}
static public boolean isEqual(float a, float b) {
return Math.abs(a - b) <= FLOAT_ROUNDING_ERROR;
}
static public boolean isEqual(float a, float b, float tolerance) {
return Math.abs(a - b) <= tolerance;
}
static public final float FLOAT_ROUNDING_ERROR = 0.000001f;
static public 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 int[] getLimit(float x, float y, float width, float height, float rotate) {
float rotation = MathUtils.toRadians(rotate);
float angSin = MathUtils.sin(rotation);
float angCos = MathUtils.cos(rotation);
int newW = MathUtils.floor((width * MathUtils.abs(angCos)) + (height * MathUtils.abs(angSin)));
int newH = MathUtils.floor((height * MathUtils.abs(angCos)) + (width * MathUtils.abs(angSin)));
int centerX = (int) (x + (width / 2));
int centerY = (int) (y + (height / 2));
int newX = (centerX - (newW / 2));
int newY = (centerY - (newH / 2));
return new int[] { newX, newY, newW, newH };
}
final static private String[] zeros = { "", "0", "00", "000", "0000", "00000", "000000", "0000000", "00000000",
"000000000", "0000000000" };
/**
* 为指定数值补足位数
*
* @param number
* @param numDigits
* @return
*/
public static String addZeros(long number, int numDigits) {
return addZeros(String.valueOf(number), numDigits);
}
/**
* 为指定数值补足位数
*
* @param number
* @param numDigits
* @return
*/
public static String addZeros(String number, int numDigits) {
int length = numDigits - number.length();
if (length > -1) {
number = zeros[length] + number;
}
return number;
}
/**
* 返回数字的位数长度
*
* @param num
* @return
*/
public static int getBitSize(int num) {
int numBits = 0;
if (num < 10l) {
numBits = 1;
} else if (num < 100l) {
numBits = 2;
} else if (num < 1000l) {
numBits = 3;
} else if (num < 10000l) {
numBits = 4;
} else if (num < 100000l) {
numBits = 5;
} else if (num < 1000000l) {
numBits = 6;
} else if (num < 10000000l) {
numBits = 7;
} else if (num < 100000000l) {
numBits = 8;
} else if (num < 1000000000l) {
numBits = 9;
} else {
numBits = (String.valueOf(num).length() - 1);
}
return numBits;
}
/**
* 判断是否为数字
*
* @param param
* @return
*/
public static boolean isNan(String str) {
if (StringUtils.isEmpty(str)) {
return false;
}
char[] chars = str.toCharArray();
int sz = chars.length;
boolean hasExp = false;
boolean hasDecPoint = false;
boolean allowSigns = false;
boolean foundDigit = false;
int start = (chars[0] == '-') ? 1 : 0;
if (sz > start + 1) {
if (chars[start] == '0' && chars[start + 1] == 'x') {
int i = start + 2;
if (i == sz) {
return false;
}
for (; i < chars.length; i++) {
if ((chars[i] < '0' || chars[i] > '9') && (chars[i] < 'a' || chars[i] > 'f')
&& (chars[i] < 'A' || chars[i] > 'F')) {
return false;
}
}
return true;
}
}
sz--;
int i = start;
while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
if (chars[i] >= '0' && chars[i] <= '9') {
foundDigit = true;
allowSigns = false;
} else if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
return false;
}
hasDecPoint = true;
} else if (chars[i] == 'e' || chars[i] == 'E') {
if (hasExp) {
return false;
}
if (!foundDigit) {
return false;
}
hasExp = true;
allowSigns = true;
} else if (chars[i] == '+' || chars[i] == '-') {
if (!allowSigns) {
return false;
}
allowSigns = false;
foundDigit = false;
} else {
return false;
}
i++;
}
if (i < chars.length) {
if (chars[i] >= '0' && chars[i] <= '9') {
return true;
}
if (chars[i] == 'e' || chars[i] == 'E') {
return false;
}
if (!allowSigns && (chars[i] == 'd' || chars[i] == 'D' || chars[i] == 'f' || chars[i] == 'F')) {
return foundDigit;
}
if (chars[i] == 'l' || chars[i] == 'L') {
return foundDigit && !hasExp;
}
return false;
}
return !allowSigns && foundDigit;
}
public static final float PI_OVER2 = 1.5708f;
public static final float PI_OVER4 = 0.785398f;
static private final int BIG_ENOUGH_INT = 16 * 1024;
static private final float BIG_ENOUGH_FLOOR = BIG_ENOUGH_INT;
static private final float CEIL = 0.9999999f;
static private final float BIG_ENOUGH_CEIL = NumberUtils
.intBitsToFloat(NumberUtils.floatToRawIntBits(BIG_ENOUGH_INT + 1) - 1);
static private final float BIG_ENOUGH_ROUND = BIG_ENOUGH_INT + 0.5f;
static private final int ATAN2_BITS = 7;
static private final int ATAN2_BITS2 = ATAN2_BITS << 1;
static private final int ATAN2_MASK = ~(-1 << ATAN2_BITS2);
static private final int ATAN2_COUNT = ATAN2_MASK + 1;
static private final int ATAN2_DIM = (int) Math.sqrt(ATAN2_COUNT);
static private final float INV_ATAN2_DIM_MINUS_1 = 1.0f / (ATAN2_DIM - 1);
static private final float[] atan2 = new float[ATAN2_COUNT];
public static final float PI = 3.1415927f;
public static final float TWO_PI = 6.28319f;
static private final int SIN_BITS = 13;
static private final int SIN_MASK = ~(-1 << SIN_BITS);
static private final int SIN_COUNT = SIN_MASK + 1;
static private final float radFull = PI * 2;
static private final float degFull = 360;
static private final float radToIndex = SIN_COUNT / radFull;
static private final float degToIndex = SIN_COUNT / degFull;
public static final float RAD_TO_DEG = 180.0f / PI;
public static final float DEG_TO_RAD = PI / 180.0f;
public static final float[] sin = new float[SIN_COUNT];
public static final float[] cos = new float[SIN_COUNT];
static {
for (int i = 0; i < SIN_COUNT; i++) {
float a = (i + 0.5f) / SIN_COUNT * radFull;
sin[i] = (float) Math.sin(a);
cos[i] = (float) Math.cos(a);
}
for (int i = 0; i < 360; i += 90) {
sin[(int) (i * degToIndex) & SIN_MASK] = (float) Math.sin(i * DEG_TO_RAD);
cos[(int) (i * degToIndex) & SIN_MASK] = (float) Math.cos(i * DEG_TO_RAD);
}
for (int i = 0; i < ATAN2_DIM; i++) {
for (int j = 0; j < ATAN2_DIM; j++) {
float x0 = (float) i / ATAN2_DIM;
float y0 = (float) j / ATAN2_DIM;
atan2[j * ATAN2_DIM + i] = (float) Math.atan2(y0, x0);
}
}
}
public static final int ZERO_FIXED = 0;
public static final int ONE_FIXED = 1 << 16;
public static final float EPSILON = 0.001f;
public static final int PI_FIXED = 205887;
public static final int PI_OVER_2_FIXED = PI_FIXED / 2;
public static final int E_FIXED = 178145;
public static final int HALF_FIXED = 2 << 15;
public static boolean isZero(float value) {
return Math.abs(value) <= 0.00000001;
}
public static int mul(int x, int y) {
long z = (long) x * (long) y;
return ((int) (z >> 16));
}
public static float mul(float x, float y) {
long z = (long) x * (long) y;
return ((float) (z >> 16));
}
public static final int mulDiv(int f1, int f2, int f3) {
return (int) ((long) f1 * f2 / f3);
}
public static final long mulDiv(long f1, long f2, long f3) {
return f1 * f2 / f3;
}
public static int mid(int i, int min, int max) {
return MathUtils.max(i, MathUtils.min(min, max));
}
public static int div(int x, int y) {
long z = (((long) x) << 32);
return (int) ((z / y) >> 16);
}
public static float div(float x, float y) {
long z = (((long) x) << 32);
return (float) ((z / (long) y) >> 16);
}
public static int sqrt(int n) {
int s = (n + 65536) >> 1;
for (int i = 0; i < 8; i++) {
s = (s + div(n, s)) >> 1;
}
return s;
}
public static int round(int n) {
if (n > 0) {
if ((n & 0x8000) != 0) {
return (((n + 0x10000) >> 16) << 16);
} else {
return (((n) >> 16) << 16);
}
} else {
int k;
n = -n;
if ((n & 0x8000) != 0) {
k = (((n + 0x10000) >> 16) << 16);
} else {
k = (((n) >> 16) << 16);
}
return -k;
}
}
public static boolean equal(int a, int b) {
if (a > b)
return a - b <= EPSILON;
else
return b - a <= EPSILON;
}
public static boolean equal(float a, float b) {
if (a > b)
return a - b <= EPSILON;
else
return b - a <= EPSILON;
}
static final int SK1 = 498;
static final int SK2 = 10882;
public static int sin(int f) {
int sign = 1;
if ((f > PI_OVER_2_FIXED) && (f <= PI_FIXED)) {
f = PI_FIXED - f;
} else if ((f > PI_FIXED) && (f <= (PI_FIXED + PI_OVER_2_FIXED))) {
f = f - PI_FIXED;
sign = -1;
} else if (f > (PI_FIXED + PI_OVER_2_FIXED)) {
f = (PI_FIXED << 1) - f;
sign = -1;
}
int sqr = mul(f, f);
int result = SK1;
result = mul(result, sqr);
result -= SK2;
result = mul(result, sqr);
result += ONE_FIXED;
result = mul(result, f);
return sign * result;
}
static final int CK1 = 2328;
static final int CK2 = 32551;
public static int cos(int f) {
int sign = 1;
if ((f > PI_OVER_2_FIXED) && (f <= PI_FIXED)) {
f = PI_FIXED - f;
sign = -1;
} else if ((f > PI_OVER_2_FIXED) && (f <= (PI_FIXED + PI_OVER_2_FIXED))) {
f = f - PI_FIXED;
sign = -1;
} else if (f > (PI_FIXED + PI_OVER_2_FIXED)) {
f = (PI_FIXED << 1) - f;
}
int sqr = mul(f, f);
int result = CK1;
result = mul(result, sqr);
result -= CK2;
result = mul(result, sqr);
result += ONE_FIXED;
return result * sign;
}
static final int TK1 = 13323;
static final int TK2 = 20810;
public static int tan(int f) {
int sqr = mul(f, f);
int result = TK1;
result = mul(result, sqr);
result += TK2;
result = mul(result, sqr);
result += ONE_FIXED;
result = mul(result, f);
return result;
}
public static int atan(int f) {
int sqr = mul(f, f);
int result = 1365;
result = mul(result, sqr);
result -= 5579;
result = mul(result, sqr);
result += 11805;
result = mul(result, sqr);
result -= 21646;
result = mul(result, sqr);
result += 65527;
result = mul(result, f);
return result;
}
static final int AS1 = -1228;
static final int AS2 = 4866;
static final int AS3 = 13901;
static final int AS4 = 102939;
public static int asin(int f) {
int fRoot = sqrt(ONE_FIXED - f);
int result = AS1;
result = mul(result, f);
result += AS2;
result = mul(result, f);
result -= AS3;
result = mul(result, f);
result += AS4;
result = PI_OVER_2_FIXED - (mul(fRoot, result));
return result;
}
public static int acos(int f) {
int fRoot = sqrt(ONE_FIXED - f);
int result = AS1;
result = mul(result, f);
result += AS2;
result = mul(result, f);
result -= AS3;
result = mul(result, f);
result += AS4;
result = mul(fRoot, result);
return result;
}
static int log2arr[] = { 26573, 14624, 7719, 3973, 2017, 1016, 510, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0, 0, 0 };
static int lnscale[] = { 0, 45426, 90852, 136278, 181704, 227130, 272557, 317983, 363409, 408835, 454261, 499687,
545113, 590539, 635965, 681391, 726817 };
public static int ln(int x) {
int shift = 0;
while (x > 1 << 17) {
shift++;
x >>= 1;
}
int g = 0;
int d = HALF_FIXED;
for (int i = 1; i < 16; i++) {
if (x > (ONE_FIXED + d)) {
x = div(x, (ONE_FIXED + d));
g += log2arr[i - 1];
}
d >>= 1;
}
return g + lnscale[shift];
}
static public final float tan(float angle) {
return (float) Math.tan(angle);
}
static public final float asin(float value) {
return (float) Math.asin(value);
}
static public final float acos(float value) {
return (float) Math.acos(value);
}
static public final float atan(float value) {
return (float) Math.atan(value);
}
static public final float mag(float a, float b) {
return (float) Math.sqrt(a * a + b * b);
}
static public final float mag(float a, float b, float c) {
return (float) Math.sqrt(a * a + b * b + c * c);
}
static public final float dist(float x1, float y1, float x2, float y2) {
return sqrt(sq(x2 - x1) + sq(y2 - y1));
}
static public final float dist(float x1, float y1, float z1, float x2, float y2, float z2) {
return sqrt(sq(x2 - x1) + sq(y2 - y1) + sq(z2 - z1));
}
static public final float abs(float n) {
return (n < 0) ? -n : n;
}
static public final int abs(int n) {
return (n < 0) ? -n : n;
}
static public final float sq(float a) {
return a * a;
}
static public final float sqrt(float a) {
return (float) Math.sqrt(a);
}
static public final float log(float a) {
return (float) Math.log(a);
}
static public final float exp(float a) {
return (float) Math.exp(a);
}
static public final float pow(float a, float b) {
return (float) Math.pow(a, b);
}
static public final int max(int a, int b) {
return (a > b) ? a : b;
}
static public final float max(float a, float b) {
return (a > b) ? a : b;
}
static public final long max(long a, long b) {
return (a > b) ? a : b;
}
static public final int max(int a, int b, int c) {
return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
}
static public final float max(float a, float b, float c) {
return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
}
static public final int min(int a, int b, int c) {
return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
}
static public final float min(float a, float b, float c) {
return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
}
static public final float min(float a, float b) {
return (a <= b) ? a : b;
}
public static int min(int a, int b) {
return (a <= b) ? a : b;
}
public static float mix(final float x, final float y, final float m) {
return x * (1 - m) + y * m;
}
public static int mix(final int x, final int y, final float m) {
return Math.round(x * (1 - m) + y * m);
}
static public final float norm(float value, float start, float stop) {
return (value - start) / (stop - start);
}
static public final float map(float value, float istart, float istop, float ostart, float ostop) {
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}
public static final float sin(float rad) {
return sin[(int) (rad * radToIndex) & SIN_MASK];
}
public static final float cos(float rad) {
return cos[(int) (rad * radToIndex) & SIN_MASK];
}
public static final float sinDeg(float deg) {
return sin[(int) (deg * degToIndex) & SIN_MASK];
}
public static final float cosDeg(float deg) {
return cos[(int) (deg * degToIndex) & SIN_MASK];
}
public static final float atan2(float y, float x) {
float add, mul;
if (x < 0) {
if (y < 0) {
y = -y;
mul = 1;
} else
mul = -1;
x = -x;
add = -3.141592653f;
} else {
if (y < 0) {
y = -y;
mul = -1;
} else
mul = 1;
add = 0;
}
float invDiv = 1 / ((x < y ? y : x) * INV_ATAN2_DIM_MINUS_1);
int xi = (int) (x * invDiv);
int yi = (int) (y * invDiv);
return (atan2[yi * ATAN2_DIM + xi] + add) * mul;
}
public static float toDegrees(final float radians) {
return radians * RAD_TO_DEG;
}
public static float toRadians(final float degrees) {
return degrees * DEG_TO_RAD;
}
public static final float degToRad(float deg) {
return deg * 360 / TWO_PI;
}
public static final int bringToBounds(final int minValue, final int maxValue, final int v) {
return Math.max(minValue, Math.min(maxValue, v));
}
public static final float bringToBounds(final float minValue, final float maxValue, final float v) {
return Math.max(minValue, Math.min(maxValue, v));
}
public static final boolean nextBoolean() {
return randomBoolean();
}
public static final int nextInt(int range) {
return range <= 0 ? 0 : random.nextInt(range);
}
public static final int nextInt(int start, int end) {
return end <= 0 ? 0 : start + random.nextInt(end - start);
}
public static final int random(int range) {
return random.nextInt(range + 1);
}
public static final int random(int start, int end) {
return start + random.nextInt(end - start + 1);
}
public static final boolean randomBoolean() {
return random.nextBoolean();
}
public static final float random() {
return random.nextFloat();
}
public static final float random(float range) {
return random.nextFloat() * range;
}
public static final float random(float start, float end) {
return start + random.nextFloat() * (end - start);
}
public static int floor(float x) {
return (int) (x + BIG_ENOUGH_FLOOR) - BIG_ENOUGH_INT;
}
public static int floorPositive(float x) {
return (int) x;
}
public static int ceil(float x) {
return (int) (x + BIG_ENOUGH_CEIL) - BIG_ENOUGH_INT;
}
public static int ceilPositive(float x) {
return (int) (x + CEIL);
}
public static int round(float x) {
return (int) (x + BIG_ENOUGH_ROUND) - BIG_ENOUGH_INT;
}
public static int roundPositive(float x) {
return (int) (x + 0.5f);
}
public static float barycentric(float value1, float value2, float value3, float amount1, float amount2) {
return value1 + (value2 - value1) * amount1 + (value3 - value1) * amount2;
}
public static float catmullRom(float value1, float value2, float value3, float value4, float amount) {
double amountSquared = amount * amount;
double amountCubed = amountSquared * amount;
return (float) (0.5 * (2.0 * value2 + (value3 - value1) * amount
+ (2.0 * value1 - 5.0 * value2 + 4.0 * value3 - value4) * amountSquared
+ (3.0 * value2 - value1 - 3.0 * value3 + value4) * amountCubed));
}
public static final int clamp(int value, int min, int max) {
value = (value > max) ? max : value;
value = (value < min) ? min : value;
return value;
}
public static float clamp(float value, float min, float max) {
value = (value > max) ? max : value;
value = (value < min) ? min : value;
return value;
}
public static float clamp(final float v) {
return v < 0f ? 0f : (v > 1f ? 1f : v);
}
public static float distance(float value1, float value2) {
return Math.abs(value1 - value2);
}
public static float hermite(float value1, float tangent1, float value2, float tangent2, float amount) {
double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result;
double sCubed = s * s * s;
double sSquared = s * s;
if (amount == 0f) {
result = value1;
} else if (amount == 1f) {
result = value2;
} else {
result = (2 * v1 - 2 * v2 + t2 + t1) * sCubed + (3 * v2 - 3 * v1 - 2 * t1 - t2) * sSquared + t1 * s + v1;
}
return (float) result;
}
public static float lerp(float value1, float value2, float amount) {
return value1 + (value2 - value1) * amount;
}
public static float smoothStep(float value1, float value2, float amount) {
float result = clamp(amount, 0f, 1f);
result = hermite(value1, 0f, value2, 0f, result);
return result;
}
public static float wrapAngle(float angle) {
angle = (float) IEEEremainder((double) angle, 6.2831854820251465d);
if (angle <= -3.141593f) {
angle += 6.283185f;
return angle;
}
if (angle > 3.141593f) {
angle -= 6.283185f;
}
return angle;
}
public static double normalizeLon(double lon) {
if (lon == lon) {
while ((lon < -180d) || (lon > 180d)) {
lon = IEEEremainder(lon, 360d);
}
}
return lon;
}
public static double IEEEremainder(double f1, double f2) {
double r = Math.abs(f1 % f2);
if (Double.isNaN(r) || r == f2 || r <= Math.abs(f2) / 2.0) {
return r;
} else {
return Math.signum(f1) * (r - f2);
}
}
public static final int sum(final int[] values) {
int sum = 0;
for (int i = values.length - 1; i >= 0; i--) {
sum += values[i];
}
return sum;
}
public static final void arraySumInternal(final int[] values) {
final int valueCount = values.length;
for (int i = 1; i < valueCount; i++) {
values[i] = values[i - 1] + values[i];
}
}
public static final void arraySumInternal(final long[] values) {
final int valueCount = values.length;
for (int i = 1; i < valueCount; i++) {
values[i] = values[i - 1] + values[i];
}
}
public static final void arraySumInternal(final long[] values, final long factor) {
values[0] = values[0] * factor;
final int valueCount = values.length;
for (int i = 1; i < valueCount; i++) {
values[i] = values[i - 1] + values[i] * factor;
}
}
public static final void arraySumInto(final long[] values, final long[] targetValues, final long factor) {
targetValues[0] = values[0] * factor;
final int valueCount = values.length;
for (int i = 1; i < valueCount; i++) {
targetValues[i] = targetValues[i - 1] + values[i] * factor;
}
}
public static final float arraySum(final float[] values) {
float sum = 0;
final int valueCount = values.length;
for (int i = 0; i < valueCount; i++) {
sum += values[i];
}
return sum;
}
public static final float arrayAverage(final float[] values) {
return MathUtils.arraySum(values) / values.length;
}
public static float[] scaleAroundCenter(final float[] vertices, final float scaleX, final float scaleY,
final float scaleCenterX, final float scaleCenterY) {
if (scaleX != 1 || scaleY != 1) {
for (int i = vertices.length - 2; i >= 0; i -= 2) {
vertices[i] = scaleCenterX + (vertices[i] - scaleCenterX) * scaleX;
vertices[i + 1] = scaleCenterY + (vertices[i + 1] - scaleCenterY) * scaleY;
}
}
return vertices;
}
public static final boolean isInBounds(final int minValue, final int maxValue, final int val) {
return val >= minValue && val <= maxValue;
}
public static final boolean isInBounds(final float minValue, final float maxValue, final float val) {
return val >= minValue && val <= maxValue;
}
protected static int TO_STRING_DECIMAL_PLACES = 3;
public static String toString(float value) {
return toString(value, TO_STRING_DECIMAL_PLACES);
}
public static String toString(float value, int decimalPlaces) {
if (Float.isNaN(value))
return "NaN";
StringBuilder buf = new StringBuilder();
if (value >= 0)
buf.append("+");
else {
buf.append("-");
value = -value;
}
int ivalue = (int) value;
buf.append(ivalue);
if (decimalPlaces > 0) {
buf.append(".");
for (int ii = 0; ii < decimalPlaces; ii++) {
value = (value - ivalue) * 10;
ivalue = (int) value;
buf.append(ivalue);
}
// trim trailing zeros
for (int ii = 0; ii < decimalPlaces - 1; ii++) {
if (buf.charAt(buf.length() - 1) == '0') {
buf.setLength(buf.length() - 1);
}
}
}
return buf.toString();
}
public final static int round(int div1, int div2) {
final int remainder = div1 % div2;
if (MathUtils.abs(remainder) * 2 <= MathUtils.abs(div2)) {
return div1 / div2;
} else if (div1 * div2 < 0) {
return div1 / div2 - 1;
} else {
return div1 / div2 + 1;
}
}
public final static float round(float div1, float div2) {
final float remainder = div1 % div2;
if (MathUtils.abs(remainder) * 2 <= MathUtils.abs(div2)) {
return div1 / div2;
} else if (div1 * div2 < 0) {
return div1 / div2 - 1;
} else {
return div1 / div2 + 1;
}
}
public final static long round(long div1, long div2) {
final long remainder = div1 % div2;
if (MathUtils.abs(remainder) * 2 <= MathUtils.abs(div2)) {
return div1 / div2;
} else if (div1 * div2 < 0) {
return div1 / div2 - 1;
} else {
return div1 / div2 + 1;
}
}
public final static int toShift(int angle) {
if (angle <= 45) {
return SHIFT[angle];
} else if (angle >= 315) {
return -SHIFT[360 - angle];
} else if (angle >= 135 && angle <= 180) {
return -SHIFT[180 - angle];
} else if (angle >= 180 && angle <= 225) {
return SHIFT[angle - 180];
} else if (angle >= 45 && angle <= 90) {
return SHIFT[90 - angle];
} else if (angle >= 90 && angle <= 135) {
return -SHIFT[angle - 90];
} else if (angle >= 225 && angle <= 270) {
return SHIFT[270 - angle];
} else {
return -SHIFT[angle - 270];
}
}
public static float bezierAt(float a, float b, float c, float d, float t) {
return (MathUtils.pow(1 - t, 3) * a + 3 * t * (MathUtils.pow(1 - t, 2)) * b
+ 3 * MathUtils.pow(t, 2) * (1 - t) * c + MathUtils.pow(t, 3) * d);
}
public final static int parseUnsignedInt(String s) {
return parseUnsignedInt(s, 10);
}
public final static int parseUnsignedInt(String s, int radix) {
if (s == null) {
throw LSystem.runThrow("null");
}
int len = s.length();
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar == '-') {
throw LSystem.runThrow("on unsigned string %s.");
} else {
if (len <= 5 || (radix == 10 && len <= 9)) {
return Integer.parseInt(s, radix);
} else {
long ell = Long.parseLong(s, radix);
if ((ell & 0xffff_ffff_0000_0000L) == 0) {
return (int) ell;
} else {
throw LSystem.runThrow("range of unsigned int.");
}
}
}
} else {
throw LSystem.runThrow(s);
}
}
public static int numberOfTrailingZeros(long i) {
int x, y;
if (i == 0) {
return 64;
}
int n = 63;
y = (int) i;
if (y != 0) {
n = n - 32;
x = y;
} else
x = (int) (i >>> 32);
y = x << 16;
if (y != 0) {
n = n - 16;
x = y;
}
y = x << 8;
if (y != 0) {
n = n - 8;
x = y;
}
y = x << 4;
if (y != 0) {
n = n - 4;
x = y;
}
y = x << 2;
if (y != 0) {
n = n - 2;
x = y;
}
return n - ((x << 1) >>> 31);
}
public static float maxAbs(float x, float y) {
return MathUtils.abs(x) >= MathUtils.abs(y) ? x : y;
}
public static float minAbs(float x, float y) {
return MathUtils.abs(x) <= MathUtils.abs(y) ? x : y;
}
public final static float lerpCut(float progress, float progressLowCut, float progressHighCut, float fromValue,
float toValue) {
progress = MathUtils.clamp(progress, progressLowCut, progressHighCut);
float a = (progress - progressLowCut) / (progressHighCut - progressLowCut);
return MathUtils.lerp(fromValue, toValue, a);
}
public final static float scale(float value, float maxValue, float maxScale) {
return (maxScale / maxValue) * value;
}
public final static float percent(float value, float percent) {
return value * (percent * 0.01f);
}
public final static int percent(int value, int percent) {
return (int) (value * (percent * 0.01f));
}
}