aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gtPlusPlus/api/objects/random
diff options
context:
space:
mode:
authorJakub <53441451+kuba6000@users.noreply.github.com>2022-08-29 16:04:28 +0200
committerGitHub <noreply@github.com>2022-08-29 16:04:28 +0200
commit7d1f51a8937e0a86486267437d444696e81e8aa0 (patch)
treea5b145e7271998f7b4b968a2212ed487e54a92b5 /src/main/java/gtPlusPlus/api/objects/random
parent5267969156d30b4bb5f4cb2279ebb49db6bd40e2 (diff)
downloadGT5-Unofficial-7d1f51a8937e0a86486267437d444696e81e8aa0.tar.gz
GT5-Unofficial-7d1f51a8937e0a86486267437d444696e81e8aa0.tar.bz2
GT5-Unofficial-7d1f51a8937e0a86486267437d444696e81e8aa0.zip
Buildscript + Spotless (#318)
* Convert AES.java to readable class * Buildscript * Spotless
Diffstat (limited to 'src/main/java/gtPlusPlus/api/objects/random')
-rw-r--r--src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java136
-rw-r--r--src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java761
-rw-r--r--src/main/java/gtPlusPlus/api/objects/random/XSTR.java441
3 files changed, 661 insertions, 677 deletions
diff --git a/src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java b/src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java
index b2dc984456..86ea4b4ad6 100644
--- a/src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java
+++ b/src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java
@@ -34,12 +34,12 @@
*/
package gtPlusPlus.api.objects.random;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.Random;
import gtPlusPlus.api.interfaces.IRandomGenerator;
import gtPlusPlus.core.util.Utils;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Random;
/**
* The Blum-Blum-Shub random number generator.
@@ -112,13 +112,12 @@ public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
* @param rand A source of randomness
*/
private static BigInteger getPrime(int bits, Random rand) {
- BigInteger p;
- while (true) {
- p = new BigInteger(bits, 100, rand);
- if (p.mod(four).equals(three))
- break;
- }
- return p;
+ BigInteger p;
+ while (true) {
+ p = new BigInteger(bits, 100, rand);
+ if (p.mod(four).equals(three)) break;
+ }
+ return p;
}
/**
@@ -132,14 +131,14 @@ public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
* @return A BigInteger, the <i>n</i>.
*/
public static BigInteger generateN(int bits, Random rand) {
- BigInteger p = getPrime(bits/2, rand);
- BigInteger q = getPrime(bits/2, rand);
+ BigInteger p = getPrime(bits / 2, rand);
+ BigInteger q = getPrime(bits / 2, rand);
- // make sure p != q (almost always true, but just in case, check)
- while (p.equals(q)) {
- q = getPrime(bits, rand);
- }
- return p.multiply(q);
+ // make sure p != q (almost always true, but just in case, check)
+ while (p.equals(q)) {
+ q = getPrime(bits, rand);
+ }
+ return p.multiply(q);
}
/**
@@ -148,7 +147,7 @@ public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
* @param bits number of bits
*/
public CSPRNG_DO_NOT_USE(int bits) {
- this(bits, new Random());
+ this(bits, new Random());
}
/**
@@ -158,7 +157,7 @@ public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
* @param rand
*/
public CSPRNG_DO_NOT_USE(int bits, Random rand) {
- this(generateN(bits, rand));
+ this(generateN(bits, rand));
}
/**
@@ -170,7 +169,7 @@ public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
* The n-value.
*/
public CSPRNG_DO_NOT_USE(BigInteger n) {
- this(n, SecureRandom.getSeed(n.bitLength() / 8));
+ this(n, SecureRandom.getSeed(n.bitLength() / 8));
}
/**
@@ -183,8 +182,8 @@ public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
* The seed value using a byte[] array.
*/
public CSPRNG_DO_NOT_USE(BigInteger n, byte[] seed) {
- this.n = n;
- setSeed(seed);
+ this.n = n;
+ setSeed(seed);
}
/**
@@ -194,9 +193,9 @@ public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
* The new seed.
*/
public void setSeed(byte[] seedBytes) {
- // ADD: use hardwired default for n
- BigInteger seed = new BigInteger(1, seedBytes);
- state = seed.mod(n);
+ // ADD: use hardwired default for n
+ BigInteger seed = new BigInteger(1, seedBytes);
+ state = seed.mod(n);
}
/**
@@ -205,67 +204,64 @@ public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
* @return int
*/
@Override
- public int next(int numBits) {
- // TODO: find out how many LSB one can extract per cycle.
- // it is more than one.
- int result = 0;
- for (int i = numBits; i != 0; --i) {
- state = state.modPow(two, n);
- result = (result << 1) | (state.testBit(0) == true ? 1 : 0);
- }
- return result;
+ public int next(int numBits) {
+ // TODO: find out how many LSB one can extract per cycle.
+ // it is more than one.
+ int result = 0;
+ for (int i = numBits; i != 0; --i) {
+ state = state.modPow(two, n);
+ result = (result << 1) | (state.testBit(0) == true ? 1 : 0);
+ }
+ return result;
}
-
- public static CSPRNG_DO_NOT_USE generate(){
- return generate(512);
+ public static CSPRNG_DO_NOT_USE generate() {
+ return generate(512);
}
-
+
/**
* @return CSPRNG_DO_NOT_USE
* @Author Draknyte1/Alkalus
*/
- public static CSPRNG_DO_NOT_USE generate(int bitsize){
- // First use the internal, stock "true" random number
- // generator to get a "true random seed"
- SecureRandom r = Utils.generateSecureRandom();
- r.nextInt(); // need to do something for SR to be triggered.
- // Use this seed to generate a n-value for Blum-Blum-Shub
- // This value can be re-used if desired.
- BigInteger nval = CSPRNG_DO_NOT_USE.generateN(bitsize, r);
- // now get a seed
- byte[] seed = new byte[bitsize/8];
- r.nextBytes(seed);
- // now create an instance of BlumBlumShub
- CSPRNG_DO_NOT_USE bbs = new CSPRNG_DO_NOT_USE(nval, seed);
- return bbs;
+ public static CSPRNG_DO_NOT_USE generate(int bitsize) {
+ // First use the internal, stock "true" random number
+ // generator to get a "true random seed"
+ SecureRandom r = Utils.generateSecureRandom();
+ r.nextInt(); // need to do something for SR to be triggered.
+ // Use this seed to generate a n-value for Blum-Blum-Shub
+ // This value can be re-used if desired.
+ BigInteger nval = CSPRNG_DO_NOT_USE.generateN(bitsize, r);
+ // now get a seed
+ byte[] seed = new byte[bitsize / 8];
+ r.nextBytes(seed);
+ // now create an instance of BlumBlumShub
+ CSPRNG_DO_NOT_USE bbs = new CSPRNG_DO_NOT_USE(nval, seed);
+ return bbs;
}
-
-
+
/**
* @return CSPRNG_DO_NOT_USE
* @Author Draknyte1/Alkalus
*/
- public static CSPRNG_DO_NOT_USE generate(Random aRandom){
- return generate(512, aRandom);
+ public static CSPRNG_DO_NOT_USE generate(Random aRandom) {
+ return generate(512, aRandom);
}
-
+
/**
* @return CSPRNG_DO_NOT_USE
* @Author Draknyte1/Alkalus
*/
- public static CSPRNG_DO_NOT_USE generate(int aBitSize, Random aRandom){
- // First use the internal, stock "true" random number
- // generator to get a "true random seed"
- SecureRandom r = Utils.generateSecureRandom();
- r.nextInt(); // need to do something for SR to be triggered.
- // Use this seed to generate a n-value for Blum-Blum-Shub
- // This value can be re-used if desired.
- int bitsize = aBitSize;
- // now create an instance of BlumBlumShub
- // do everything almost automatically
- CSPRNG_DO_NOT_USE bbs = new CSPRNG_DO_NOT_USE(bitsize, aRandom);
- return bbs;
+ public static CSPRNG_DO_NOT_USE generate(int aBitSize, Random aRandom) {
+ // First use the internal, stock "true" random number
+ // generator to get a "true random seed"
+ SecureRandom r = Utils.generateSecureRandom();
+ r.nextInt(); // need to do something for SR to be triggered.
+ // Use this seed to generate a n-value for Blum-Blum-Shub
+ // This value can be re-used if desired.
+ int bitsize = aBitSize;
+ // now create an instance of BlumBlumShub
+ // do everything almost automatically
+ CSPRNG_DO_NOT_USE bbs = new CSPRNG_DO_NOT_USE(bitsize, aRandom);
+ return bbs;
}
-
}
diff --git a/src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java b/src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java
index fec92368f8..8b70955e63 100644
--- a/src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java
+++ b/src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java
@@ -6,16 +6,16 @@ import java.util.Random;
import java.util.UUID;
/**
- *
+ *
* Implement modified version of Apache's OpenJPA UUID generator.
* This UUID generator is paired with a Blum-Blum-Shub random number generator
* which in itself is seeded by custom SecureRandom.
- *
+ *
* The UUID generator class has been converted from a static factory to an instanced factory.
- *
+ *
*/
-//========================================= APACHE BLOCK =========================================
+// ========================================= APACHE BLOCK =========================================
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -33,7 +33,7 @@ import java.util.UUID;
* "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.
+ * under the License.
*/
/**
@@ -41,8 +41,8 @@ import java.util.UUID;
* in the Apache Commons Id project: http://jakarta.apache.org/commons/sandbox
* /id/uuid.html The type 4 generator uses the standard Java UUID generator.
*
- * The type 1 code has been vastly simplified and modified to replace the
- * ethernet address of the host machine with the IP, since we do not want to
+ * The type 1 code has been vastly simplified and modified to replace the
+ * ethernet address of the host machine with the IP, since we do not want to
* require native libs and Java cannot access the MAC address directly.
*
* In spirit, implements the IETF UUID draft specification, found here:<br />
@@ -54,396 +54,383 @@ import java.util.UUID;
*/
public class UUIDGenerator {
- // supported UUID types
- public static final int TYPE1 = 1;
- public static final int TYPE4 = 4;
- // indexes within the uuid array for certain boundaries
- private static final byte IDX_TIME_HI = 6;
- private static final byte IDX_TYPE = 6; // multiplexed
- private static final byte IDX_TIME_MID = 4;
- private static final byte IDX_TIME_LO = 0;
- private static final byte IDX_TIME_SEQ = 8;
- private static final byte IDX_VARIATION = 8; // multiplexed
- // indexes and lengths within the timestamp for certain boundaries
- private static final byte TS_TIME_LO_IDX = 4;
- private static final byte TS_TIME_LO_LEN = 4;
- private static final byte TS_TIME_MID_IDX = 2;
- private static final byte TS_TIME_MID_LEN = 2;
- private static final byte TS_TIME_HI_IDX = 0;
- private static final byte TS_TIME_HI_LEN = 2;
- // offset to move from 1/1/1970, which is 0-time for Java, to gregorian
- // 0-time 10/15/1582, and multiplier to go from 100nsec to msec units
- private static final long GREG_OFFSET = 0xB1D069B5400L;
- private static final long MILLI_MULT = 10000L;
- // type of UUID -- time based
- private final static byte TYPE_TIME_BASED = 0x10;
- // random number generator used to reduce conflicts with other JVMs, and
- // hasher for strings.
- private Random RANDOM;
- // 4-byte IP address + 2 random bytes to compensate for the fact that
- // the MAC address is usually 6 bytes
- private byte[] IP;
- // counter is initialized to 0 and is incremented for each uuid request
- // within the same timestamp window.
- private int _counter;
- // current timestamp (used to detect multiple uuid requests within same
- // timestamp)
- private long _currentMillis;
- // last used millis time, and a semi-random sequence that gets reset
- // when it overflows
- private long _lastMillis = 0L;
- private static final int MAX_14BIT = 0x3FFF;
- private short _seq = 0;
- private boolean type1Initialized = false; /*
+ // supported UUID types
+ public static final int TYPE1 = 1;
+ public static final int TYPE4 = 4;
+ // indexes within the uuid array for certain boundaries
+ private static final byte IDX_TIME_HI = 6;
+ private static final byte IDX_TYPE = 6; // multiplexed
+ private static final byte IDX_TIME_MID = 4;
+ private static final byte IDX_TIME_LO = 0;
+ private static final byte IDX_TIME_SEQ = 8;
+ private static final byte IDX_VARIATION = 8; // multiplexed
+ // indexes and lengths within the timestamp for certain boundaries
+ private static final byte TS_TIME_LO_IDX = 4;
+ private static final byte TS_TIME_LO_LEN = 4;
+ private static final byte TS_TIME_MID_IDX = 2;
+ private static final byte TS_TIME_MID_LEN = 2;
+ private static final byte TS_TIME_HI_IDX = 0;
+ private static final byte TS_TIME_HI_LEN = 2;
+ // offset to move from 1/1/1970, which is 0-time for Java, to gregorian
+ // 0-time 10/15/1582, and multiplier to go from 100nsec to msec units
+ private static final long GREG_OFFSET = 0xB1D069B5400L;
+ private static final long MILLI_MULT = 10000L;
+ // type of UUID -- time based
+ private static final byte TYPE_TIME_BASED = 0x10;
+ // random number generator used to reduce conflicts with other JVMs, and
+ // hasher for strings.
+ private Random RANDOM;
+ // 4-byte IP address + 2 random bytes to compensate for the fact that
+ // the MAC address is usually 6 bytes
+ private byte[] IP;
+ // counter is initialized to 0 and is incremented for each uuid request
+ // within the same timestamp window.
+ private int _counter;
+ // current timestamp (used to detect multiple uuid requests within same
+ // timestamp)
+ private long _currentMillis;
+ // last used millis time, and a semi-random sequence that gets reset
+ // when it overflows
+ private long _lastMillis = 0L;
+ private static final int MAX_14BIT = 0x3FFF;
+ private short _seq = 0;
+ private boolean type1Initialized = false; /*
* Initializer for type 1 UUIDs. Creates random generator and genenerates
* the node portion of the UUID using the IP address.
*/
- private synchronized void initializeForType1() {
- if (type1Initialized == true) {
- return;
- }
- // note that secure random is very slow the first time
- // it is used; consider switching to a standard random
- RANDOM = CSPRNG_DO_NOT_USE.generate();
- _seq = (short) RANDOM.nextInt(MAX_14BIT);
- byte[] ip = null;
- try {
- ip = InetAddress.getLocalHost().getAddress();
- } catch (IOException ioe) {
- throw new RuntimeException(ioe);
- }
- IP = new byte[6];
- RANDOM.nextBytes(IP);
- //OPENJPA-2055: account for the fact that 'getAddress'
- //may return an IPv6 address which is 16 bytes wide.
- for( int i = 0 ; i < ip.length; ++i ) {
- IP[2+(i%4)] ^= ip[i];
- }
- type1Initialized = true;
- }
- /**
- * Return a unique UUID value.
- */
- public byte[] next(int type) {
- if (type == TYPE4) {
- return createType4();
- }
- return createType1();
- }
- /*
- * Creates a type 1 UUID
- */
- public byte[] createType1() {
- if (type1Initialized == false) {
- initializeForType1();
- }
- // set ip addr
- byte[] uuid = new byte[16];
- System.arraycopy(IP, 0, uuid, 10, IP.length);
- // Set time info. Have to do this processing within a synchronized
- // block because of the statics...
- long now = 0;
- synchronized (UUIDGenerator.class) {
- // Get the time to use for this uuid. This method has the side
- // effect of modifying the clock sequence, as well.
- now = getTime();
- // Insert the resulting clock sequence into the uuid
- uuid[IDX_TIME_SEQ] = (byte) ((_seq & 0x3F00) >>> 8);
- uuid[IDX_VARIATION] |= 0x80;
- uuid[IDX_TIME_SEQ+1] = (byte) (_seq & 0xFF);
- }
- // have to break up time because bytes are spread through uuid
- byte[] timeBytes = Bytes.toBytes(now);
- // Copy time low
- System.arraycopy(timeBytes, TS_TIME_LO_IDX, uuid, IDX_TIME_LO,
- TS_TIME_LO_LEN);
- // Copy time mid
- System.arraycopy(timeBytes, TS_TIME_MID_IDX, uuid, IDX_TIME_MID,
- TS_TIME_MID_LEN);
- // Copy time hi
- System.arraycopy(timeBytes, TS_TIME_HI_IDX, uuid, IDX_TIME_HI,
- TS_TIME_HI_LEN);
- //Set version (time-based)
- uuid[IDX_TYPE] |= TYPE_TIME_BASED; // 0001 0000
- return uuid;
- }
- /*
- * Creates a type 4 UUID
- */
- private byte[] createType4() {
- UUID type4 = UUID.randomUUID();
- byte[] uuid = new byte[16];
- longToBytes(type4.getMostSignificantBits(), uuid, 0);
- longToBytes(type4.getLeastSignificantBits(), uuid, 8);
- return uuid;
- }
- /*
- * Converts a long to byte values, setting them in a byte array
- * at a given starting position.
- */
- private void longToBytes(long longVal, byte[] buf, int sPos) {
- sPos += 7;
- for(int i = 0; i < 8; i++)
- buf[sPos-i] = (byte)(longVal >>> (i * 8));
- }
+ private synchronized void initializeForType1() {
+ if (type1Initialized == true) {
+ return;
+ }
+ // note that secure random is very slow the first time
+ // it is used; consider switching to a standard random
+ RANDOM = CSPRNG_DO_NOT_USE.generate();
+ _seq = (short) RANDOM.nextInt(MAX_14BIT);
- /**
- * Return the next unique uuid value as a 16-character string.
- */
- public String nextString(int type) {
- byte[] bytes = next(type);
- try {
- return new String(bytes, "ISO-8859-1");
- } catch (Exception e) {
- return new String(bytes);
- }
- }
- /**
- * Return the next unique uuid value as a 32-character hex string.
- */
- public String nextHex(int type) {
- return Base16Encoder.encode(next(type));
- }
- /**
- * Get the timestamp to be used for this uuid. Must be called from
- * a synchronized block.
- *
- * @return long timestamp
- */
- // package-visibility for testing
- private long getTime() {
- if (RANDOM == null)
- initializeForType1();
- long newTime = getUUIDTime();
- if (newTime <= _lastMillis) {
- incrementSequence();
- newTime = getUUIDTime();
- }
- _lastMillis = newTime;
- return newTime;
- }
- /**
- * Gets the appropriately modified timestamep for the UUID. Must be called
- * from a synchronized block.
- *
- * @return long timestamp in 100ns intervals since the Gregorian change
- * offset
- */
- private long getUUIDTime() {
- if (_currentMillis != System.currentTimeMillis()) {
- _currentMillis = System.currentTimeMillis();
- _counter = 0; // reset counter
- }
- // check to see if we have created too many uuid's for this timestamp
- if (_counter + 1 >= MILLI_MULT) {
- // Original algorithm threw exception. Seemed like overkill.
- // Let's just increment the timestamp instead and start over...
- _currentMillis++;
- _counter = 0;
- }
- // calculate time as current millis plus offset times 100 ns ticks
- long currentTime = (_currentMillis + GREG_OFFSET) * MILLI_MULT;
- // return the uuid time plus the artificial tick counter incremented
- return currentTime + _counter++;
- }
- /**
- * Increments the clock sequence for this uuid. Must be called from a
- * synchronized block.
- */
- private void incrementSequence() {
- // increment, but if it's greater than its 14-bits, reset it
- if (++_seq > MAX_14BIT) {
- _seq = (short) RANDOM.nextInt(MAX_14BIT); // semi-random
- }
- }
-
- //Add Dependant classes internally
+ byte[] ip = null;
+ try {
+ ip = InetAddress.getLocalHost().getAddress();
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ IP = new byte[6];
+ RANDOM.nextBytes(IP);
+ // OPENJPA-2055: account for the fact that 'getAddress'
+ // may return an IPv6 address which is 16 bytes wide.
+ for (int i = 0; i < ip.length; ++i) {
+ IP[2 + (i % 4)] ^= ip[i];
+ }
+ type1Initialized = true;
+ }
+ /**
+ * Return a unique UUID value.
+ */
+ public byte[] next(int type) {
+ if (type == TYPE4) {
+ return createType4();
+ }
+ return createType1();
+ }
+ /*
+ * Creates a type 1 UUID
+ */
+ public byte[] createType1() {
+ if (type1Initialized == false) {
+ initializeForType1();
+ }
+ // set ip addr
+ byte[] uuid = new byte[16];
+ System.arraycopy(IP, 0, uuid, 10, IP.length);
+ // Set time info. Have to do this processing within a synchronized
+ // block because of the statics...
+ long now = 0;
+ synchronized (UUIDGenerator.class) {
+ // Get the time to use for this uuid. This method has the side
+ // effect of modifying the clock sequence, as well.
+ now = getTime();
+ // Insert the resulting clock sequence into the uuid
+ uuid[IDX_TIME_SEQ] = (byte) ((_seq & 0x3F00) >>> 8);
+ uuid[IDX_VARIATION] |= 0x80;
+ uuid[IDX_TIME_SEQ + 1] = (byte) (_seq & 0xFF);
+ }
+ // have to break up time because bytes are spread through uuid
+ byte[] timeBytes = Bytes.toBytes(now);
+ // Copy time low
+ System.arraycopy(timeBytes, TS_TIME_LO_IDX, uuid, IDX_TIME_LO, TS_TIME_LO_LEN);
+ // Copy time mid
+ System.arraycopy(timeBytes, TS_TIME_MID_IDX, uuid, IDX_TIME_MID, TS_TIME_MID_LEN);
+ // Copy time hi
+ System.arraycopy(timeBytes, TS_TIME_HI_IDX, uuid, IDX_TIME_HI, TS_TIME_HI_LEN);
+ // Set version (time-based)
+ uuid[IDX_TYPE] |= TYPE_TIME_BASED; // 0001 0000
+ return uuid;
+ }
+ /*
+ * Creates a type 4 UUID
+ */
+ private byte[] createType4() {
+ UUID type4 = UUID.randomUUID();
+ byte[] uuid = new byte[16];
+ longToBytes(type4.getMostSignificantBits(), uuid, 0);
+ longToBytes(type4.getLeastSignificantBits(), uuid, 8);
+ return uuid;
+ }
+ /*
+ * Converts a long to byte values, setting them in a byte array
+ * at a given starting position.
+ */
+ private void longToBytes(long longVal, byte[] buf, int sPos) {
+ sPos += 7;
+ for (int i = 0; i < 8; i++) buf[sPos - i] = (byte) (longVal >>> (i * 8));
+ }
- /**
- * This class came from the Apache Commons Id sandbox project in support
- * of the UUIDGenerator implementation.
- *
- * <p>Static methods for managing byte arrays (all methods follow Big
- * Endian order where most significant bits are in front).</p>
- */
- public static final class Bytes {
- /**
- * <p>Hide constructor in utility class.</p>
- */
- private Bytes() {
- }
- /**
- * Appends two bytes array into one.
- *
- * @param a A byte[].
- * @param b A byte[].
- * @return A byte[].
- */
- public static byte[] append(byte[] a, byte[] b) {
- byte[] z = new byte[a.length + b.length];
- System.arraycopy(a, 0, z, 0, a.length);
- System.arraycopy(b, 0, z, a.length, b.length);
- return z;
- }
- /**
- * Returns a 8-byte array built from a long.
- *
- * @param n The number to convert.
- * @return A byte[].
- */
- public static byte[] toBytes(long n) {
- return toBytes(n, new byte[8]);
- }
- /**
- * Build a 8-byte array from a long. No check is performed on the
- * array length.
- *
- * @param n The number to convert.
- * @param b The array to fill.
- * @return A byte[].
- */
- public static byte[] toBytes(long n, byte[] b) {
- b[7] = (byte) (n);
- n >>>= 8;
- b[6] = (byte) (n);
- n >>>= 8;
- b[5] = (byte) (n);
- n >>>= 8;
- b[4] = (byte) (n);
- n >>>= 8;
- b[3] = (byte) (n);
- n >>>= 8;
- b[2] = (byte) (n);
- n >>>= 8;
- b[1] = (byte) (n);
- n >>>= 8;
- b[0] = (byte) (n);
-
- return b;
- }
- /**
- * Build a long from first 8 bytes of the array.
- *
- * @param b The byte[] to convert.
- * @return A long.
- */
- public static long toLong(byte[] b) {
- return ((((long) b[7]) & 0xFF)
- + ((((long) b[6]) & 0xFF) << 8)
- + ((((long) b[5]) & 0xFF) << 16)
- + ((((long) b[4]) & 0xFF) << 24)
- + ((((long) b[3]) & 0xFF) << 32)
- + ((((long) b[2]) & 0xFF) << 40)
- + ((((long) b[1]) & 0xFF) << 48)
- + ((((long) b[0]) & 0xFF) << 56));
- }
- /**
- * Compares two byte arrays for equality.
- *
- * @param a A byte[].
- * @param b A byte[].
- * @return True if the arrays have identical contents.
- */
- public static boolean areEqual(byte[] a, byte[] b) {
- int aLength = a.length;
- if (aLength != b.length) {
- return false;
- }
- for (int i = 0; i < aLength; i++) {
- if (a[i] != b[i]) {
- return false;
- }
- }
- return true;
- }
- /**
- * <p>Compares two byte arrays as specified by <code>Comparable</code>.
- *
- * @param lhs - left hand value in the comparison operation.
- * @param rhs - right hand value in the comparison operation.
- * @return a negative integer, zero, or a positive integer as
- * <code>lhs</code> is less than, equal to, or greater than
- * <code>rhs</code>.
- */
- public static int compareTo(byte[] lhs, byte[] rhs) {
- if (lhs == rhs) {
- return 0;
- }
- if (lhs == null) {
- return -1;
- }
- if (rhs == null) {
- return +1;
- }
- if (lhs.length != rhs.length) {
- return ((lhs.length < rhs.length) ? -1 : +1);
- }
- for (int i = 0; i < lhs.length; i++) {
- if (lhs[i] < rhs[i]) {
- return -1;
- } else if (lhs[i] > rhs[i]) {
- return 1;
- }
- }
- return 0;
- }
- /**
- * Build a short from first 2 bytes of the array.
- *
- * @param b The byte[] to convert.
- * @return A short.
- */
- public static short toShort(byte[] b) {
- return (short) ((b[1] & 0xFF) + ((b[0] & 0xFF) << 8));
- }
- }
- /**
- * Base 16 encoder.
- *
- * @author Marc Prud'hommeaux
- */
- public static final class Base16Encoder {
+ /**
+ * Return the next unique uuid value as a 16-character string.
+ */
+ public String nextString(int type) {
+ byte[] bytes = next(type);
+ try {
+ return new String(bytes, "ISO-8859-1");
+ } catch (Exception e) {
+ return new String(bytes);
+ }
+ }
+ /**
+ * Return the next unique uuid value as a 32-character hex string.
+ */
+ public String nextHex(int type) {
+ return Base16Encoder.encode(next(type));
+ }
+ /**
+ * Get the timestamp to be used for this uuid. Must be called from
+ * a synchronized block.
+ *
+ * @return long timestamp
+ */
+ // package-visibility for testing
+ private long getTime() {
+ if (RANDOM == null) initializeForType1();
+ long newTime = getUUIDTime();
+ if (newTime <= _lastMillis) {
+ incrementSequence();
+ newTime = getUUIDTime();
+ }
+ _lastMillis = newTime;
+ return newTime;
+ }
+ /**
+ * Gets the appropriately modified timestamep for the UUID. Must be called
+ * from a synchronized block.
+ *
+ * @return long timestamp in 100ns intervals since the Gregorian change
+ * offset
+ */
+ private long getUUIDTime() {
+ if (_currentMillis != System.currentTimeMillis()) {
+ _currentMillis = System.currentTimeMillis();
+ _counter = 0; // reset counter
+ }
+ // check to see if we have created too many uuid's for this timestamp
+ if (_counter + 1 >= MILLI_MULT) {
+ // Original algorithm threw exception. Seemed like overkill.
+ // Let's just increment the timestamp instead and start over...
+ _currentMillis++;
+ _counter = 0;
+ }
+ // calculate time as current millis plus offset times 100 ns ticks
+ long currentTime = (_currentMillis + GREG_OFFSET) * MILLI_MULT;
+ // return the uuid time plus the artificial tick counter incremented
+ return currentTime + _counter++;
+ }
+ /**
+ * Increments the clock sequence for this uuid. Must be called from a
+ * synchronized block.
+ */
+ private void incrementSequence() {
+ // increment, but if it's greater than its 14-bits, reset it
+ if (++_seq > MAX_14BIT) {
+ _seq = (short) RANDOM.nextInt(MAX_14BIT); // semi-random
+ }
+ }
- private final static char[] HEX = new char[]{
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- /**
- * Convert bytes to a base16 string.
- */
- public static String encode(byte[] byteArray) {
- StringBuilder hexBuffer = new StringBuilder(byteArray.length * 2);
- for (int i = 0; i < byteArray.length; i++)
- for (int j = 1; j >= 0; j--)
- hexBuffer.append(HEX[(byteArray[i] >> (j * 4)) & 0xF]);
- return hexBuffer.toString();
- }
- /**
- * Convert a base16 string into a byte array.
- */
- public static byte[] decode(String s) {
- int len = s.length();
- byte[] r = new byte[len / 2];
- for (int i = 0; i < r.length; i++) {
- int digit1 = s.charAt(i * 2), digit2 = s.charAt(i * 2 + 1);
- if (digit1 >= '0' && digit1 <= '9')
- digit1 -= '0';
- else if (digit1 >= 'A' && digit1 <= 'F')
- digit1 -= 'A' - 10;
- if (digit2 >= '0' && digit2 <= '9')
- digit2 -= '0';
- else if (digit2 >= 'A' && digit2 <= 'F')
- digit2 -= 'A' - 10;
+ // Add Dependant classes internally
- r[i] = (byte) ((digit1 << 4) + digit2);
- }
- return r;
- }
- }
+ /**
+ * This class came from the Apache Commons Id sandbox project in support
+ * of the UUIDGenerator implementation.
+ *
+ * <p>Static methods for managing byte arrays (all methods follow Big
+ * Endian order where most significant bits are in front).</p>
+ */
+ public static final class Bytes {
+ /**
+ * <p>Hide constructor in utility class.</p>
+ */
+ private Bytes() {}
+ /**
+ * Appends two bytes array into one.
+ *
+ * @param a A byte[].
+ * @param b A byte[].
+ * @return A byte[].
+ */
+ public static byte[] append(byte[] a, byte[] b) {
+ byte[] z = new byte[a.length + b.length];
+ System.arraycopy(a, 0, z, 0, a.length);
+ System.arraycopy(b, 0, z, a.length, b.length);
+ return z;
+ }
+ /**
+ * Returns a 8-byte array built from a long.
+ *
+ * @param n The number to convert.
+ * @return A byte[].
+ */
+ public static byte[] toBytes(long n) {
+ return toBytes(n, new byte[8]);
+ }
+ /**
+ * Build a 8-byte array from a long. No check is performed on the
+ * array length.
+ *
+ * @param n The number to convert.
+ * @param b The array to fill.
+ * @return A byte[].
+ */
+ public static byte[] toBytes(long n, byte[] b) {
+ b[7] = (byte) (n);
+ n >>>= 8;
+ b[6] = (byte) (n);
+ n >>>= 8;
+ b[5] = (byte) (n);
+ n >>>= 8;
+ b[4] = (byte) (n);
+ n >>>= 8;
+ b[3] = (byte) (n);
+ n >>>= 8;
+ b[2] = (byte) (n);
+ n >>>= 8;
+ b[1] = (byte) (n);
+ n >>>= 8;
+ b[0] = (byte) (n);
+ return b;
+ }
+ /**
+ * Build a long from first 8 bytes of the array.
+ *
+ * @param b The byte[] to convert.
+ * @return A long.
+ */
+ public static long toLong(byte[] b) {
+ return ((((long) b[7]) & 0xFF)
+ + ((((long) b[6]) & 0xFF) << 8)
+ + ((((long) b[5]) & 0xFF) << 16)
+ + ((((long) b[4]) & 0xFF) << 24)
+ + ((((long) b[3]) & 0xFF) << 32)
+ + ((((long) b[2]) & 0xFF) << 40)
+ + ((((long) b[1]) & 0xFF) << 48)
+ + ((((long) b[0]) & 0xFF) << 56));
+ }
+ /**
+ * Compares two byte arrays for equality.
+ *
+ * @param a A byte[].
+ * @param b A byte[].
+ * @return True if the arrays have identical contents.
+ */
+ public static boolean areEqual(byte[] a, byte[] b) {
+ int aLength = a.length;
+ if (aLength != b.length) {
+ return false;
+ }
+ for (int i = 0; i < aLength; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * <p>Compares two byte arrays as specified by <code>Comparable</code>.
+ *
+ * @param lhs - left hand value in the comparison operation.
+ * @param rhs - right hand value in the comparison operation.
+ * @return a negative integer, zero, or a positive integer as
+ * <code>lhs</code> is less than, equal to, or greater than
+ * <code>rhs</code>.
+ */
+ public static int compareTo(byte[] lhs, byte[] rhs) {
+ if (lhs == rhs) {
+ return 0;
+ }
+ if (lhs == null) {
+ return -1;
+ }
+ if (rhs == null) {
+ return +1;
+ }
+ if (lhs.length != rhs.length) {
+ return ((lhs.length < rhs.length) ? -1 : +1);
+ }
+ for (int i = 0; i < lhs.length; i++) {
+ if (lhs[i] < rhs[i]) {
+ return -1;
+ } else if (lhs[i] > rhs[i]) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+ /**
+ * Build a short from first 2 bytes of the array.
+ *
+ * @param b The byte[] to convert.
+ * @return A short.
+ */
+ public static short toShort(byte[] b) {
+ return (short) ((b[1] & 0xFF) + ((b[0] & 0xFF) << 8));
+ }
+ }
+ /**
+ * Base 16 encoder.
+ *
+ * @author Marc Prud'hommeaux
+ */
+ public static final class Base16Encoder {
+ private static final char[] HEX = new char[] {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+ /**
+ * Convert bytes to a base16 string.
+ */
+ public static String encode(byte[] byteArray) {
+ StringBuilder hexBuffer = new StringBuilder(byteArray.length * 2);
+ for (int i = 0; i < byteArray.length; i++)
+ for (int j = 1; j >= 0; j--) hexBuffer.append(HEX[(byteArray[i] >> (j * 4)) & 0xF]);
+ return hexBuffer.toString();
+ }
+ /**
+ * Convert a base16 string into a byte array.
+ */
+ public static byte[] decode(String s) {
+ int len = s.length();
+ byte[] r = new byte[len / 2];
+ for (int i = 0; i < r.length; i++) {
+ int digit1 = s.charAt(i * 2), digit2 = s.charAt(i * 2 + 1);
+ if (digit1 >= '0' && digit1 <= '9') digit1 -= '0';
+ else if (digit1 >= 'A' && digit1 <= 'F') digit1 -= 'A' - 10;
+ if (digit2 >= '0' && digit2 <= '9') digit2 -= '0';
+ else if (digit2 >= 'A' && digit2 <= 'F') digit2 -= 'A' - 10;
+ r[i] = (byte) ((digit1 << 4) + digit2);
+ }
+ return r;
+ }
+ }
}
-//========================================= APACHE BLOCK =========================================
-
+// ========================================= APACHE BLOCK =========================================
diff --git a/src/main/java/gtPlusPlus/api/objects/random/XSTR.java b/src/main/java/gtPlusPlus/api/objects/random/XSTR.java
index 6ce1cbeb6c..aaaa7a4d1d 100644
--- a/src/main/java/gtPlusPlus/api/objects/random/XSTR.java
+++ b/src/main/java/gtPlusPlus/api/objects/random/XSTR.java
@@ -23,7 +23,6 @@ package gtPlusPlus.api.objects.random;
* This code is released under the GNU Lesser General Public License Version 3
* http://www.gnu.org/licenses/lgpl-3.0.txt
*/
-
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
@@ -35,201 +34,202 @@ import java.util.concurrent.atomic.AtomicLong;
*/
public class XSTR extends Random implements Cloneable {
- private static final long serialVersionUID = 6208727693524452904L;
- private long seed;
- private long last;
- private static final long GAMMA = 0x9e3779b97f4a7c15L;
- private static final int PROBE_INCREMENT = 0x9e3779b9;
- private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
- private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
- private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
+ private static final long serialVersionUID = 6208727693524452904L;
+ private long seed;
+ private long last;
+ private static final long GAMMA = 0x9e3779b97f4a7c15L;
+ private static final int PROBE_INCREMENT = 0x9e3779b9;
+ private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
+ private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
+ private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
+
+ /*
+ MODIFIED BY: Robotia
+ Modification: Implemented Random class seed generator
+ */
+ /**
+ * Creates a new pseudo random number generator. The seed is initialized to
+ * the current time, as if by
+ * <code>setSeed(System.currentTimeMillis());</code>.
+ */
+ public XSTR() {
+ this(seedUniquifier() ^ System.nanoTime());
+ }
+
+ private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L);
+
+ private static long seedUniquifier() {
+ // L'Ecuyer, "Tables of Linear Congruential Generators of
+ // Different Sizes and Good Lattice Structure", 1999
+ for (; ; ) {
+ final long current = seedUniquifier.get();
+ final long next = current * 181783497276652981L;
+ if (seedUniquifier.compareAndSet(current, next)) {
+ return next;
+ }
+ }
+ }
+
+ /**
+ * Creates a new pseudo random number generator, starting with the specified
+ * seed, using <code>setSeed(seed);</code>.
+ *
+ * @param seed the initial seed
+ */
+ public XSTR(final long seed) {
+ this.seed = seed;
+ }
- /*
- MODIFIED BY: Robotia
- Modification: Implemented Random class seed generator
- */
- /**
- * Creates a new pseudo random number generator. The seed is initialized to
- * the current time, as if by
- * <code>setSeed(System.currentTimeMillis());</code>.
- */
- public XSTR() {
- this(seedUniquifier() ^ System.nanoTime());
- }
- private static final AtomicLong seedUniquifier
- = new AtomicLong(8682522807148012L);
+ @Override
+ public boolean nextBoolean() {
+ return this.next(1) != 0;
+ }
- private static long seedUniquifier() {
- // L'Ecuyer, "Tables of Linear Congruential Generators of
- // Different Sizes and Good Lattice Structure", 1999
- for (;;) {
- final long current = seedUniquifier.get();
- final long next = current * 181783497276652981L;
- if (seedUniquifier.compareAndSet(current, next)) {
- return next;
- }
- }
- }
+ @Override
+ public double nextDouble() {
+ return (((long) (this.next(26)) << 27) + this.next(27)) * DOUBLE_UNIT;
+ }
+ /**
+ * Returns the current state of the seed, can be used to clone the object
+ *
+ * @return the current seed
+ */
+ public synchronized long getSeed() {
+ return this.seed;
+ }
- /**
- * Creates a new pseudo random number generator, starting with the specified
- * seed, using <code>setSeed(seed);</code>.
- *
- * @param seed the initial seed
- */
- public XSTR(final long seed) {
- this.seed = seed;
- }
- @Override
- public boolean nextBoolean() {
- return this.next(1) != 0;
- }
+ /**
+ * Sets the seed for this pseudo random number generator. As described
+ * above, two instances of the same random class, starting with the same
+ * seed, produce the same results, if the same methods are called.
+ *
+ * @param seed the new seed
+ */
+ @Override
+ public synchronized void setSeed(final long seed) {
+ this.seed = seed;
+ }
- @Override
- public double nextDouble() {
- return (((long)(this.next(26)) << 27) + this.next(27)) * DOUBLE_UNIT;
- }
- /**
- * Returns the current state of the seed, can be used to clone the object
- *
- * @return the current seed
- */
- public synchronized long getSeed() {
- return this.seed;
- }
+ /**
+ * @return Returns an XSRandom object with the same state as the original
+ */
+ @Override
+ public XSTR clone() {
+ try {
+ super.clone();
+ } catch (CloneNotSupportedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return new XSTR(this.getSeed());
+ }
- /**
- * Sets the seed for this pseudo random number generator. As described
- * above, two instances of the same random class, starting with the same
- * seed, produce the same results, if the same methods are called.
- *
- * @param seed the new seed
- */
- @Override
- public synchronized void setSeed(final long seed) {
- this.seed = seed;
- }
+ /**
+ * Implementation of George Marsaglia's elegant Xorshift random generator
+ * 30% faster and better quality than the built-in java.util.random see also
+ * see http://www.javamex.com/tutorials/random_numbers/xorshift.shtml
+ *
+ * @param nbits
+ * @return
+ */
+ @Override
+ public int next(final int nbits) {
+ long x = this.seed;
+ x ^= (x << 21);
+ x ^= (x >>> 35);
+ x ^= (x << 4);
+ this.seed = x;
+ x &= ((1L << nbits) - 1);
+ return (int) x;
+ }
- /**
- * @return Returns an XSRandom object with the same state as the original
- */
- @Override
- public XSTR clone() {
- try {
- super.clone();
- }
- catch (CloneNotSupportedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return new XSTR(this.getSeed());
- }
+ boolean haveNextNextGaussian = false;
+ double nextNextGaussian = 0;
- /**
- * Implementation of George Marsaglia's elegant Xorshift random generator
- * 30% faster and better quality than the built-in java.util.random see also
- * see http://www.javamex.com/tutorials/random_numbers/xorshift.shtml
- *
- * @param nbits
- * @return
- */
- @Override
- public int next(final int nbits) {
- long x = this.seed;
- x ^= (x << 21);
- x ^= (x >>> 35);
- x ^= (x << 4);
- this.seed = x;
- x &= ((1L << nbits) - 1);
- return (int) x;
- }
- boolean haveNextNextGaussian = false;
- double nextNextGaussian = 0;
- @Override
- synchronized public double nextGaussian() {
- // See Knuth, ACP, Section 3.4.1 Algorithm C.
- if (this.haveNextNextGaussian) {
- this.haveNextNextGaussian = false;
- return this.nextNextGaussian;
- }
- double v1, v2, s;
- do {
- v1 = (2 * this.nextDouble()) - 1; // between -1 and 1
- v2 = (2 * this.nextDouble()) - 1; // between -1 and 1
- s = (v1 * v1) + (v2 * v2);
- } while ((s >= 1) || (s == 0));
- final double multiplier = StrictMath.sqrt((-2 * StrictMath.log(s))/s);
- this.nextNextGaussian = v2 * multiplier;
- this.haveNextNextGaussian = true;
- return v1 * multiplier;
- }
- /**
- * Returns a pseudorandom, uniformly distributed {@code int} value between 0
- * (inclusive) and the specified value (exclusive), drawn from this random
- * number generator's sequence. The general contract of {@code nextInt} is
- * that one {@code int} value in the specified range is pseudorandomly
- * generated and returned. All {@code bound} possible {@code int} values are
- * produced with (approximately) equal probability. The method
- * {@code nextInt(int bound)} is implemented by class {@code Random} as if
- * by:
- * <pre> {@code
- * public int nextInt(int bound) {
- * if (bound <= 0)
- * throw new IllegalArgumentException("bound must be positive");
- *
- * if ((bound & -bound) == bound) // i.e., bound is a power of 2
- * return (int)((bound * (long)next(31)) >> 31);
- *
- * int bits, val;
- * do {
- * bits = next(31);
- * val = bits % bound;
- * } while (bits - val + (bound-1) < 0);
- * return val;
- * }}</pre>
- *
- * <p>The hedge "approx
- * imately" is used in the foregoing description only because the next
- * method is only approximately an unbiased source of independently chosen
- * bits. If it were a perfect source of randomly chosen bits, then the
- * algorithm shown would choose {@code int} values from the stated range
- * with perfect uniformity.
- * <p>
- * The algorithm is slightly tricky. It rejects values that would result in
- * an uneven distribution (due to the fact that 2^31 is not divisible by n).
- * The probability of a value being rejected depends on n. The worst case is
- * n=2^30+1, for which the probability of a reject is 1/2, and the expected
- * number of iterations before the loop terminates is 2.
- * <p>
- * The algorithm treats the case where n is a power of two specially: it
- * returns the correct number of high-order bits from the underlying
- * pseudo-random number generator. In the absence of special treatment, the
- * correct number of <i>low-order</i> bits would be returned. Linear
- * congruential pseudo-random number generators such as the one implemented
- * by this class are known to have short periods in the sequence of values
- * of their low-order bits. Thus, this special case greatly increases the
- * length of the sequence of values returned by successive calls to this
- * method if n is a small power of two.
- *
- * @param bound the upper bound (exclusive). Must be positive.
- * @return the next pseudorandom, uniformly distributed {@code int} value
- * between zero (inclusive) and {@code bound} (exclusive) from this random
- * number generator's sequence
- * @throws IllegalArgumentException if bound is not positive
- * @since 1.2
- */
- @Override
- public int nextInt(final int bound) {
- final int newBound;
- if (bound <= 0) {
- newBound = 1;
- //throw new RuntimeException("BadBound");
- }
- else {
- newBound = bound;
- }
+ @Override
+ public synchronized double nextGaussian() {
+ // See Knuth, ACP, Section 3.4.1 Algorithm C.
+ if (this.haveNextNextGaussian) {
+ this.haveNextNextGaussian = false;
+ return this.nextNextGaussian;
+ }
+ double v1, v2, s;
+ do {
+ v1 = (2 * this.nextDouble()) - 1; // between -1 and 1
+ v2 = (2 * this.nextDouble()) - 1; // between -1 and 1
+ s = (v1 * v1) + (v2 * v2);
+ } while ((s >= 1) || (s == 0));
+ final double multiplier = StrictMath.sqrt((-2 * StrictMath.log(s)) / s);
+ this.nextNextGaussian = v2 * multiplier;
+ this.haveNextNextGaussian = true;
+ return v1 * multiplier;
+ }
+ /**
+ * Returns a pseudorandom, uniformly distributed {@code int} value between 0
+ * (inclusive) and the specified value (exclusive), drawn from this random
+ * number generator's sequence. The general contract of {@code nextInt} is
+ * that one {@code int} value in the specified range is pseudorandomly
+ * generated and returned. All {@code bound} possible {@code int} values are
+ * produced with (approximately) equal probability. The method
+ * {@code nextInt(int bound)} is implemented by class {@code Random} as if
+ * by:
+ * <pre> {@code
+ * public int nextInt(int bound) {
+ * if (bound <= 0)
+ * throw new IllegalArgumentException("bound must be positive");
+ *
+ * if ((bound & -bound) == bound) // i.e., bound is a power of 2
+ * return (int)((bound * (long)next(31)) >> 31);
+ *
+ * int bits, val;
+ * do {
+ * bits = next(31);
+ * val = bits % bound;
+ * } while (bits - val + (bound-1) < 0);
+ * return val;
+ * }}</pre>
+ *
+ * <p>The hedge "approx
+ * imately" is used in the foregoing description only because the next
+ * method is only approximately an unbiased source of independently chosen
+ * bits. If it were a perfect source of randomly chosen bits, then the
+ * algorithm shown would choose {@code int} values from the stated range
+ * with perfect uniformity.
+ * <p>
+ * The algorithm is slightly tricky. It rejects values that would result in
+ * an uneven distribution (due to the fact that 2^31 is not divisible by n).
+ * The probability of a value being rejected depends on n. The worst case is
+ * n=2^30+1, for which the probability of a reject is 1/2, and the expected
+ * number of iterations before the loop terminates is 2.
+ * <p>
+ * The algorithm treats the case where n is a power of two specially: it
+ * returns the correct number of high-order bits from the underlying
+ * pseudo-random number generator. In the absence of special treatment, the
+ * correct number of <i>low-order</i> bits would be returned. Linear
+ * congruential pseudo-random number generators such as the one implemented
+ * by this class are known to have short periods in the sequence of values
+ * of their low-order bits. Thus, this special case greatly increases the
+ * length of the sequence of values returned by successive calls to this
+ * method if n is a small power of two.
+ *
+ * @param bound the upper bound (exclusive). Must be positive.
+ * @return the next pseudorandom, uniformly distributed {@code int} value
+ * between zero (inclusive) and {@code bound} (exclusive) from this random
+ * number generator's sequence
+ * @throws IllegalArgumentException if bound is not positive
+ * @since 1.2
+ */
+ @Override
+ public int nextInt(final int bound) {
+ final int newBound;
+ if (bound <= 0) {
+ newBound = 1;
+ // throw new RuntimeException("BadBound");
+ } else {
+ newBound = bound;
+ }
- /*int r = next(31);
+ /*int r = next(31);
int m = bound - 1;
if ((bound & m) == 0) // i.e., bound is a power of 2
{
@@ -241,38 +241,39 @@ public class XSTR extends Random implements Cloneable {
;
}
return r;*/
- //speedup, new nextInt ~+40%
- this.last = this.seed ^ (this.seed << 21);
- this.last ^= (this.last >>> 35);
- this.last ^= (this.last << 4);
- this.seed = this.last;
- final int out = (int) this.last % newBound;
- return (out < 0) ? -out : out;
- }
- @Override
- public int nextInt() {
- return this.next(32);
- }
+ // speedup, new nextInt ~+40%
+ this.last = this.seed ^ (this.seed << 21);
+ this.last ^= (this.last >>> 35);
+ this.last ^= (this.last << 4);
+ this.seed = this.last;
+ final int out = (int) this.last % newBound;
+ return (out < 0) ? -out : out;
+ }
+
+ @Override
+ public int nextInt() {
+ return this.next(32);
+ }
- @Override
- public float nextFloat() {
- return this.next(24) * FLOAT_UNIT;
- }
+ @Override
+ public float nextFloat() {
+ return this.next(24) * FLOAT_UNIT;
+ }
- @Override
- public long nextLong() {
- // it's okay that the bottom word remains signed.
- return ((long)(this.next(32)) << 32) + this.next(32);
- }
+ @Override
+ public long nextLong() {
+ // it's okay that the bottom word remains signed.
+ return ((long) (this.next(32)) << 32) + this.next(32);
+ }
- @Override
- public void nextBytes(final byte[] bytes_arr) {
- for (int iba = 0, lenba = bytes_arr.length; iba < lenba; ) {
- for (int rndba = this.nextInt(),
- nba = Math.min(lenba - iba, Integer.SIZE/Byte.SIZE);
- nba-- > 0; rndba >>= Byte.SIZE) {
- bytes_arr[iba++] = (byte)rndba;
- }
- }
- }
-} \ No newline at end of file
+ @Override
+ public void nextBytes(final byte[] bytes_arr) {
+ for (int iba = 0, lenba = bytes_arr.length; iba < lenba; ) {
+ for (int rndba = this.nextInt(), nba = Math.min(lenba - iba, Integer.SIZE / Byte.SIZE);
+ nba-- > 0;
+ rndba >>= Byte.SIZE) {
+ bytes_arr[iba++] = (byte) rndba;
+ }
+ }
+ }
+}