001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.util;
019
020import javax.annotation.concurrent.ThreadSafe;
021
022/**
023 * A fast random class which generates low-quality pseudo-random values
024 *
025 * <p>Normally such a class should have been implemented upon using the time system with currentTimeMills(), however
026 * this was avoided for two reasons:
027 * <ul>
028 * <li>Security - If the timer did not update in time, a malicious user may use that same random. While this is not
029 * designed as a cryptographically secure random, malice is a strong enough reason to use nanoTime()</li>
030 * <li>Randomness - Using successive calls to this random may produce the same random number. The occurrance of this
031 * depends on the overhead of the method call, in which case a full millisecond has not passed yet, rather than the
032 * possibility that the timer has not updated (which again, is another plausible reason for this)</li>
033 * </ul></p>
034 *
035 * <p>Note that the methods which produce a random using the hash is not a seed. The next number is never ever
036 * consistent unless nanoTime returns the same value and the hashed object is the same. The methods which do not
037 * provide
038 * a hash do not create a new object, rather it does not hash the nanoTime at all.</p>
039 *
040 * @author The TridentSDK Team
041 * @since 0.3-alpha-DP
042 */
043@ThreadSafe
044public final class FastRandom {
045    private FastRandom() {
046    }
047
048    /**
049     * Finds a random number
050     *
051     * @return the random number
052     */
053    public static long random() {
054        long x = System.nanoTime();
055        x ^= (x << 21);
056        x ^= (x >>> 35);
057        x ^= (x << 4);
058        return (x > 0) ? x : -x;
059    }
060
061    /**
062     * Finds a random number with an upper limit
063     *
064     * @param upper the returned value is < upper
065     * @return the random number
066     */
067    public static long random(int upper) {
068        long x = System.nanoTime();
069        x ^= (x << 21);
070        x ^= (x >>> 35);
071        x ^= (x << 4);
072
073        long rand = x & (upper - 1);
074        return (rand > 0) ? rand : -rand;
075    }
076
077    /**
078     * Finds a random number with a hash
079     *
080     * @param hash the object to randomize the hash with hashCode
081     * @return the random number
082     */
083    public static long random(Object hash) {
084        long x = System.nanoTime() ^ hash.hashCode();
085        x ^= (x << 21);
086        x ^= (x >>> 35);
087        x ^= (x << 4);
088        return (x > 0) ? x : -x;
089    }
090
091    /**
092     * Finds a random number with a hash
093     *
094     * @param upper the returned value is < upper
095     * @param hash  the object to randomize the seed with hashCode
096     * @return the random number
097     */
098    public static long random(int upper, Object hash) {
099        long x = System.nanoTime() ^ hash.hashCode();
100        x ^= (x << 21);
101        x ^= (x >>> 35);
102        x ^= (x << 4);
103
104        long rand = x & (upper - 1);
105        return (rand > 0) ? rand : -rand;
106    }
107}