/* * Copyright 2012 Benjamin Glatzel <benjamin.glatzel@me.com> * * 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. */ package org.terasology.utilities; import org.terasology.math.TeraMath; import javax.vecmath.Vector3f; /** * Random number generator based on the Xorshift generator by George Marsaglia. * * @author Benjamin Glatzel <benjamin.glatzel@me.com> */ public class FastRandom { private long _seed = System.currentTimeMillis(); /** * Initializes a new instance of the random number generator using * a specified seed. * * @param seed The seed to use */ public FastRandom(long seed) { this._seed = seed; } /** * Initializes a new instance of the random number generator using * "System.currentTimeMillis()" as seed. */ public FastRandom() { } /** * Returns a random long value. * * @return Random value */ long randomLong() { _seed ^= (_seed << 21); _seed ^= (_seed >>> 35); _seed ^= (_seed << 4); return _seed; } /** * Returns a random int value. * * @return Random value */ public int randomInt() { return (int) randomLong(); } public int randomInt(int range) { return (int) randomLong() % range; } public int randomIntAbs() { return TeraMath.fastAbs(randomInt()); } public int randomIntAbs(int range) { return TeraMath.fastAbs(randomInt() % range); } /** * Returns a random double value. * * @return Random value between -1.0 and 1.0 */ public double randomDouble() { return randomLong() / ((double) Long.MAX_VALUE - 1d); } /** * @return Random value between -1f and 1f */ public float randomFloat() { return randomLong() / ((float) Long.MAX_VALUE - 1f); } /** * @return A random vector3f with each value between -1f and 1f */ //TODO: Produce a unit vector public Vector3f randomVector3f() { return new Vector3f(randomFloat(), randomFloat(), randomFloat()); } /** * @return Random value between 0f and 1f */ public float randomPosFloat() { return 0.5f * (randomFloat() + 1.0f); } /** * Returns a random bool. * * @return Random value */ public boolean randomBoolean() { return randomLong() > 0; } /** * Returns a random character string with a specified length. * * @param length The length of the generated string * @return Random character string */ public String randomCharacterString(int length) { StringBuilder s = new StringBuilder(); for (int i = 0; i < length / 2; i++) { s.append((char) ('a' + TeraMath.fastAbs(randomDouble()) * 26d)); s.append((char) ('A' + TeraMath.fastAbs(randomDouble()) * 26d)); } return s.toString(); } /** * Calculates a standardized normal distributed value (using the polar method). * * @return The value */ public double standNormalDistrDouble() { double q = Double.MAX_VALUE; double u1 = 0; double u2; while (q >= 1d || q == 0) { u1 = randomDouble(); u2 = randomDouble(); q = java.lang.Math.pow(u1, 2) + java.lang.Math.pow(u2, 2); } double p = java.lang.Math.sqrt((-2d * (java.lang.Math.log(q))) / q); return u1 * p; // or u2 * p } }