diff options
author | Jakub <53441451+kuba6000@users.noreply.github.com> | 2022-08-29 16:04:28 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-29 16:04:28 +0200 |
commit | 7d1f51a8937e0a86486267437d444696e81e8aa0 (patch) | |
tree | a5b145e7271998f7b4b968a2212ed487e54a92b5 /src/main/java/gtPlusPlus/api/objects/random | |
parent | 5267969156d30b4bb5f4cb2279ebb49db6bd40e2 (diff) | |
download | GT5-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')
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; + } + } + } +} |