Java: simplest integer hash - java

I need a quick hash function for integers:
int hash(int n) { return ...; }
Is there something that exists already in Java?
The minimal properties that I need are:
hash(n) & 1 does not appear periodic when used with a bunch of consecutive values of n.
hash(n) & 1 is approximately equally likely to be 0 or 1.

HashMap, as well as Guava's hash-based utilities, use the following method on hashCode() results to improve bit distributions and defend against weaker hash functions:
/*
* This method was written by Doug Lea with assistance from members of JCP
* JSR-166 Expert Group and released to the public domain, as explained at
* http://creativecommons.org/licenses/publicdomain
*
* As of 2010/06/11, this method is identical to the (package private) hash
* method in OpenJDK 7's java.util.HashMap class.
*/
static int smear(int hashCode) {
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
}

So, I read this question, thought hmm this is a pretty math-y question, it's probably out of my league. Then, I ended up spending so much time thinking about it that I actually believe I've got the answer: No function can satisfy the criteria that f(n) & 1 is non-periodic for consecutive values of n.
Hopefully someone will tell me how ridiculous my reasoning is, but until then I believe it's correct.
Here goes: Any binary integer n can be represented as either 1...0 or 1...1, and only the least significant bit of that bitmap will affect the result of n & 1. Further, the next consecutive integer n + 1 will always contain the opposite least significant bit. So, clearly any series of consecutive integers will exhibit a period of 2 when passed to the function n & 1. So then, is there any function f(n) that will sufficiently distribute the series of consecutive integers such that periodicity is eliminated?
Any function f(n) = n + c fails, as c must end in either 0 or 1, so the LSB will either flip or stay the same depending on the constant chosen.
The above also eliminates subtraction for all trivial cases, but I have not taken the time to analyze the carry behavior yet, so there may be a crack here.
Any function f(n) = c*n fails, as the LSB will always be 0 if c ends in 0 and always be equal to the LSB of n if c ends in 1.
Any function f(n) = n^c fails, by similar reasoning. A power function would always have the same LSB as n.
Any function f(n) = c^n fails, for the same reason.
Division and modulus were a bit less intuitive to me, but basically, the LSB of either option ends up being determined by a subtraction (already ruled out). The modulus will also obviously have a period equal to the divisor.
Unfortunately, I don't have the rigor necessary to prove this, but I believe any combination of the above operations will ultimately fail as well. This leads me to believe that we can rule out any transcendental function, because these are implemented with polynomials (Taylor series? not a terminology guy).
Finally, I held out hope on the train ride home that counting the bits would work; however, this is actually a periodic function as well. The way I thought about it was, imagine taking the sum of the digits of any decimal number. That sum obviously would run from 0 through 9, then drop to 1, run from 1 to 10, then drop to 2... It has a period, the range just keeps shifting higher the higher we count. We can actually do the same thing for the sum of the binary digits, in which case we get something like: 0,1,1,2,2,....5,5,6,6,7,7,8,8....
Did I leave anything out?
TL;DR I don't think your question has an answer.

[SO decided to convert my "trivial answer" to comment. Trying to add little text to it to see if it can be fooled]
Unless you need the ranger of hashing function to be wider..
The NumberOfSetBits function seems to vary quite a lot more then the hashCode, and as such seems more appropriate for your needs. Turns out there is already a fairly efficient algorithm on SO.
See Best algorithm to count the number of set bits in a 32-bit integer.

I did some experimentation (see test program below); computation of 2^n in Galois fields, and floor(A*sin(n)) both did very well to produce a sequence of "random" bits. I tried multiplicative congruential random number generators and some algebra and CRC (which is analogous of k*n in Galois fields), none of which did well.
The floor(A*sin(n)) approach is the simplest and quickest; the 2^n calculation in GF32 takes approx 64 multiplies and 1024 XORs worstcase, but the periodicity of output bits is extremely well-understood in the context of linear-feedback shift registers.
package com.example.math;
public class QuickHash {
interface Hasher
{
public int hash(int n);
}
static class MultiplicativeHasher1 implements Hasher
{
/* multiplicative random number generator
* from L'Ecuyer is x[n+1] = 1223106847 x[n] mod (2^32-5)
* http://dimsboiv.uqac.ca/Cours/C2012/8INF802_Hiv12/ref/paper/RNG/TableLecuyer.pdf
*/
final static long a = 1223106847L;
final static long m = (1L << 32)-5;
/*
* iterative step towards computing mod m
* (j*(2^32)+k) mod (2^32-5)
* = (j*(2^32-5)+j*5+k) mod (2^32-5)
* = (j*5+k) mod (2^32-5)
* repeat twice to get a number between 0 and 2^31+24
*/
private long quickmod(long x)
{
long j = x >>> 32;
long k = x & 0xffffffffL;
return j*5+k;
}
// treat n as unsigned before computation
#Override public int hash(int n) {
long h = a*(n&0xffffffffL);
long h2 = quickmod(quickmod(h));
return (int) (h2 >= m ? (h2-m) : h2);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
/**
* computes (2^n) mod P where P is the polynomial in GF2
* with coefficients 2^(k+1) represented by the bits k=31:0 in "poly";
* coefficient 2^0 is always 1
*/
static class GF32Hasher implements Hasher
{
static final public GF32Hasher CRC32 = new GF32Hasher(0x82608EDB, 32);
final private int poly;
final private int ofs;
public GF32Hasher(int poly, int ofs) {
this.ofs = ofs;
this.poly = poly;
}
static private long uint(int x) { return x&0xffffffffL; }
// modulo GF2 via repeated subtraction
int mod(long n) {
long rem = n;
long q = uint(this.poly);
q = (q << 32) | (1L << 31);
long bitmask = 1L << 63;
for (int i = 0; i < 32; ++i, bitmask >>>= 1, q >>>= 1)
{
if ((rem & bitmask) != 0)
rem ^= q;
}
return (int) rem;
}
int mul(int x, int y)
{
return mod(uint(x)*uint(y));
}
int pow2(int n) {
// compute 2^n mod P using repeated squaring
int y = 1;
int x = 2;
while (n > 0)
{
if ((n&1) != 0)
y = mul(y,x);
x = mul(x,x);
n = n >>> 1;
}
return y;
}
#Override public int hash(int n) {
return pow2(n+this.ofs);
}
#Override public String toString() {
return String.format("GF32[%08x, ofs=%d]", this.poly, this.ofs);
}
}
static class QuickHasher implements Hasher
{
#Override public int hash(int n) {
return (int) ((131111L*n)^n^(1973*n)%7919);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
// adapted from http://www.w3.org/TR/PNG-CRCAppendix.html
static class CRC32TableHasher implements Hasher
{
final private int table[];
static final private int polyval = 0xedb88320;
public CRC32TableHasher()
{
this.table = make_table();
}
/* Make the table for a fast CRC. */
static public int[] make_table()
{
int[] table = new int[256];
int c;
int n, k;
for (n = 0; n < 256; n++) {
c = n;
for (k = 0; k < 8; k++) {
if ((c & 1) != 0)
c = polyval ^ (c >>> 1);
else
c = c >>> 1;
}
table[n] = (int) c;
}
return table;
}
public int iterate(int state, int i)
{
return this.table[(state ^ i) & 0xff] ^ (state >>> 8);
}
#Override public int hash(int n) {
int h = -1;
h = iterate(h, n >>> 24);
h = iterate(h, n >>> 16);
h = iterate(h, n >>> 8);
h = iterate(h, n);
return h ^ -1;
}
#Override public String toString() { return getClass().getSimpleName(); }
}
static class TrigHasher implements Hasher
{
#Override public String toString() { return getClass().getSimpleName(); }
#Override public int hash(int n) {
double s = Math.sin(n);
return (int) Math.floor((1<<31)*s);
}
}
private static void test(Hasher hasher) {
System.out.println(hasher+":");
for (int i = 0; i < 64; ++i)
{
int h = hasher.hash(i);
System.out.println(String.format("%08x -> %08x %%2 = %d",
i,h,(h&1)));
}
for (int i = 0; i < 256; ++i)
{
System.out.print(hasher.hash(i) & 1);
}
System.out.println();
analyzeBits(hasher);
}
private static void analyzeBits(Hasher hasher) {
final int N = 65536;
final int maxrunlength=32;
int[][] runs = {new int[maxrunlength], new int[maxrunlength]};
int[] count = new int[2];
int prev = -1;
System.out.println("Run length test of "+N+" bits");
for (int i = 0; i < maxrunlength; ++i)
{
runs[0][i] = 0;
runs[1][i] = 0;
}
int runlength_minus1 = 0;
for (int i = 0; i < N; ++i)
{
int b = hasher.hash(i) & 0x1;
count[b]++;
if (b == prev)
++runlength_minus1;
else if (i > 0)
{
++runs[prev][runlength_minus1];
runlength_minus1 = 0;
}
prev = b;
}
++runs[prev][runlength_minus1];
System.out.println(String.format("%d zeros, %d ones", count[0], count[1]));
for (int i = 0; i < maxrunlength; ++i)
{
System.out.println(String.format("%d runs of %d zeros, %d runs of %d ones", runs[0][i], i+1, runs[1][i], i+1));
}
}
public static void main(String[] args) {
Hasher[] hashers = {
new MultiplicativeHasher1(),
GF32Hasher.CRC32,
new QuickHasher(),
new CRC32TableHasher(),
new TrigHasher()
};
for (Hasher hasher : hashers)
{
test(hasher);
}
}
}

The simplest hash for int value is the int value.
See Java Integer class
public int hashCode()
public static int hashCode(int value)
Returns:
a hash code value for this object, equal to the primitive int value represented by this Integer object.

Related

Bit mask generation to minimize number of 1

In order to explore some solutions, I need to generate all possibilities. I'm doing it by using bit masking, like this:
for (long i = 0; i < 1L << NB; i++) {
System.out.println(Long.toBinaryString(i));
if(checkSolution(i)) {
this.add(i); // add i to solutions
}
}
this.getBest(); // get the solution with lowest number of 1
this allow me to explore (if NB=3):
000
001
010
011
100
101
110
111
My problem is that the best solution is the one with the lowest number of 1.
So, in order to stop the search as soon as I found a solution, I would like to have a different order and produce something like this:
000
001
010
100
011
101
110
111
That would make the search a lot faster since I could stop as soon as I get the first solution. But I don't know how can I change my loop to get this output...
PS: NB is undefined...
The idea is to turn your loop into two nested loops; the outer loop sets the number of 1's, and the inner loop iterates through every combination of binary numbers with N 1's. Thus, your loop becomes:
for (long i = 1; i < (1L << NB); i = (i << 1) | 1) {
long j = i;
do {
System.out.println(Long.toBinaryString(j));
if(checkSolution(j)) {
this.add(j); // add j to solutions
}
j = next_of_n(j);
} while (j < (1L << NB));
}
next_of_n() is defined as:
long next_of_n(long j) {
long smallest, ripple, new_smallest, ones;
if (j == 0)
return j;
smallest = (j & -j);
ripple = j + smallest;
new_smallest = (ripple & -ripple);
ones = ((new_smallest / smallest) >> 1) - 1;
return (ripple | ones);
}
The algorithm behind next_of_n() is described in C: A Reference Manual, 5th edition, section 7.6, while showing an example of a SET implementation using bitwise operations. It may be a little hard to understand the code at first, but here's what the book says about it:
This code exploits many unusual properties of unsigned arithmetic. As
an illustration:
if x == 001011001111000, then
smallest == 000000000001000
ripple == 001011010000000
new_smallest == 000000010000000
ones == 000000000000111
the returned value == 001011010000111
The overall idea is that you find the rightmost contiguous group of
1-bits. Of that group, you slide the leftmost 1-bit to the left one
place, and slide all the others back to the extreme right. (This code
was adapted from HAKMEM.)
I can provide a deeper explanation if you still don't get it. Note that the algorithm assumes 2 complement, and that all arithmetic should ideally take place on unsigned integers, mainly because of the right shift operation. I'm not a huge Java guy, I tested this in C with unsigned long and it worked pretty well. I hope the same applies to Java, although there's no such thing as unsigned long in Java. As long as you use reasonable values for NB, there should be no problem.
This is an iterator that iterates bit patterns of the same cardinality.
/**
* Iterates all bit patterns containing the specified number of bits.
*
* See "Compute the lexicographically next bit permutation"
* http://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
*
* #author OldCurmudgeon
*/
public class BitPattern implements Iterable<BigInteger> {
// Useful stuff.
private static final BigInteger ONE = BigInteger.ONE;
private static final BigInteger TWO = ONE.add(ONE);
// How many bits to work with.
private final int bits;
// Value to stop at. 2^max_bits.
private final BigInteger stop;
// Should we invert the output.
private final boolean not;
// All patterns of that many bits up to the specified number of bits - invberting if required.
public BitPattern(int bits, int max, boolean not) {
this.bits = bits;
this.stop = TWO.pow(max);
this.not = not;
}
// All patterns of that many bits up to the specified number of bits.
public BitPattern(int bits, int max) {
this(bits, max, false);
}
#Override
public Iterator<BigInteger> iterator() {
return new BitPatternIterator();
}
/*
* From the link:
*
* Suppose we have a pattern of N bits set to 1 in an integer and
* we want the next permutation of N 1 bits in a lexicographical sense.
*
* For example, if N is 3 and the bit pattern is 00010011, the next patterns would be
* 00010101, 00010110, 00011001,
* 00011010, 00011100, 00100011,
* and so forth.
*
* The following is a fast way to compute the next permutation.
*/
private class BitPatternIterator implements Iterator<BigInteger> {
// Next to deliver - initially 2^n - 1
BigInteger next = TWO.pow(bits).subtract(ONE);
// The last one we delivered.
BigInteger last;
#Override
public boolean hasNext() {
if (next == null) {
// Next one!
// t gets v's least significant 0 bits set to 1
// unsigned int t = v | (v - 1);
BigInteger t = last.or(last.subtract(BigInteger.ONE));
// Silly optimisation.
BigInteger notT = t.not();
// Next set to 1 the most significant bit to change,
// set to 0 the least significant ones, and add the necessary 1 bits.
// w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
// The __builtin_ctz(v) GNU C compiler intrinsic for x86 CPUs returns the number of trailing zeros.
next = t.add(ONE).or(notT.and(notT.negate()).subtract(ONE).shiftRight(last.getLowestSetBit() + 1));
if (next.compareTo(stop) >= 0) {
// Dont go there.
next = null;
}
}
return next != null;
}
#Override
public BigInteger next() {
last = hasNext() ? next : null;
next = null;
return not ? last.not(): last;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
#Override
public String toString () {
return next != null ? next.toString(2) : last != null ? last.toString(2): "";
}
}
public static void main(String[] args) {
System.out.println("BitPattern(3, 10)");
for (BigInteger i : new BitPattern(3, 10)) {
System.out.println(i.toString(2));
}
}
}
First you loop over your number of ones, say n. First you start with 2^n-1, which is the first integer to contain exactly n ones and test it. To get the next one, you use the algorithm from Hamming weight based indexing (it's C code, but should not be to hard to translate it to java).
Here's some code I put together some time ago to do this. Use the combinadic method giving it the number of digits you want, the number of bits you want and which number in the sequence.
// n = digits, k = weight, m = position.
public static BigInteger combinadic(int n, int k, BigInteger m) {
BigInteger out = BigInteger.ZERO;
for (; n > 0; n--) {
BigInteger y = nChooseK(n - 1, k);
if (m.compareTo(y) >= 0) {
m = m.subtract(y);
out = out.setBit(n - 1);
k -= 1;
}
}
return out;
}
// Algorithm borrowed (and tweaked) from: http://stackoverflow.com/a/15302448/823393
public static BigInteger nChooseK(int n, int k) {
if (k > n) {
return BigInteger.ZERO;
}
if (k <= 0 || k == n) {
return BigInteger.ONE;
}
// ( n * ( nChooseK(n-1,k-1) ) ) / k;
return BigInteger.valueOf(n).multiply(nChooseK(n - 1, k - 1)).divide(BigInteger.valueOf(k));
}
public void test() {
System.out.println("Hello");
BigInteger m = BigInteger.ZERO;
for ( int i = 1; i < 10; i++ ) {
BigInteger c = combinadic(5, 2, m);
System.out.println("c["+m+"] = "+c.toString(2));
m = m.add(BigInteger.ONE);
}
}
Not sure how it matches up in efficiency with the other posts.

Java XpowYmodN function, DiffieHellman

I need for the Diffie Hellman protocol to create a function XpowYmodN. I have found online the following function:
public long XpowYmodN(long x, long y, long N) {
long result = 1;
final long oneShift63 = ((long) 1) << 63;
for (int i = 0; i < 64; y <<= 1, i++) {
result = result * result % N;
if ((y & oneShift63) != 0)
result = result * x % N;
}
return result;
}
For this example: XpowYmodN(29,83,53) the result is 43. According to the manufacturer of the device calculations the result should be 50. Could anyone point me where i am doing it wrong?
I have tried with Math.pow(X,Y) % N, for this example and i get result 28. Im condused and would like some tips on how to fix it. Thank you.
Why don't you use the class java.math.BigInteger? This class has a method called modPow() which is designed for cryptography usage.
The usage would be
BigInteger result = BigInteger.valueOf(x).modPow(BigInteger.valueof(y), BigInteger.valueOf(n));
By the way variables a named with lower case letters (n in my case).
Your answer is correct. But the value the calculator provides is not the calculation but the exchanged key. And your answer refers to the public value as seen by the sender or receiver
I tested various numbers into that function and it worked great. I then created a duplicate function that used the following code based on Uwe Plonus' answer:
public long XpowYmodN(long x, long y, long N) {
return BigInteger.valueOf(x).modPow(BigInteger.valueOf(y), BigInteger.valueOf(N)).longValue();
}
I tested your numbers into it and got 43, just like that function; so that function seems to be working perfectly. The person that posted 29,83,53 numbers as resulting in 50 appears to be wrong. The correct answer for 29,83,53 is 43.
Here's the complete code I used:
public class Main {
public static long XpowYmodN_(long x, long y, long N) {
long result = 1;
final long oneShift63 = ((long) 1) << 63;
for (int i = 0; i < 64; y <<= 1, i++) {
result = result * result % N;
if ((y & oneShift63) != 0)
result = result * x % N;
}
return result;
}
public static long XpowYmodN(long x, long y, long N) {
return BigInteger.valueOf(x).modPow(BigInteger.valueOf(y), BigInteger.valueOf(N)).longValue();
}
public static void main(String[] args)
{
System.out.println("BEGIN main");
System.out.println(Main.XpowYmodN_(29,83,53));
System.out.println(Main.XpowYmodN(29,83,53));
}
}
which gave the output of:
BEGIN main
43
43

java - how to create and manipulate a bit array with length of 10 million bits

I just came across a problem; it was easy to solve in pseudo code, but when I started coding it in java; I started to realize I didn't know where to start...
Here is what I need to do:
I need a bit array of size 10 million (bits) (let's call it A).
I need to be able to set the elements in this array to 1 or 0 (A[99000]=1).
I need to iterate through the 10 million elements.
The "proper" way in Java is to use the already-existing BitSet class pointed out by Hunter McMillen. If you're figuring out how a large bit-array is managed purely for the purpose of thinking through an interesting problem, then calculating the position of a bit in an array of bytes is just basic modular arithmetic.
public class BitArray {
private static final int ALL_ONES = 0xFFFFFFFF;
private static final int WORD_SIZE = 32;
private int bits[] = null;
public BitArray(int size) {
bits = new int[size / WORD_SIZE + (size % WORD_SIZE == 0 ? 0 : 1)];
}
public boolean getBit(int pos) {
return (bits[pos / WORD_SIZE] & (1 << (pos % WORD_SIZE))) != 0;
}
public void setBit(int pos, boolean b) {
int word = bits[pos / WORD_SIZE];
int posBit = 1 << (pos % WORD_SIZE);
if (b) {
word |= posBit;
} else {
word &= (ALL_ONES - posBit);
}
bits[pos / WORD_SIZE] = word;
}
}
Use BitSet (as Hunter McMillen already pointed out in a comment). You can easily get and set bits. To iterate just use a normal for loop.
Here is a more optimized implementation of phatfingers 'BitArray'
class BitArray {
private static final int MASK = 63;
private final long len;
private long bits[] = null;
public BitArray(long size) {
if ((((size-1)>>6) + 1) > 2147483647) {
throw new IllegalArgumentException(
"Field size to large, max size = 137438953408");
}else if (size < 1) {
throw new IllegalArgumentException(
"Field size to small, min size = 1");
}
len = size;
bits = new long[(int) (((size-1)>>6) + 1)];
}
public boolean getBit(long pos) {
return (bits[(int)(pos>>6)] & (1L << (pos&MASK))) != 0;
}
public void setBit(long pos, boolean b) {
if (getBit(pos) != b) { bits[(int)(pos>>6)] ^= (1L << (pos&MASK)); }
}
public long getLength() {
return len;
}
}
Since we use fields of 64 we extend the maximum size to 137438953408-bits which is roughly what fits in 16GB of ram. Additionally we use masks and bit shifts instead of division and modulo operations the reducing the computation time. The improvement is quite substantial.
byte[] A = new byte[10000000];
A[99000] = 1;
for(int i = 0; i < A.length; i++) {
//do something
}
If you really want bits, you can use boolean and let true = 1, and false = 0.
boolean[] A = new boolean[10000000];
//etc

Getting a random number without the Random library [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I would like to get random numbers between a range I give, but the problem I don't want to use the Random library of Java or anything I have to initializate.
Does anyone know an alternative way to get random numbers without using the java library?
Thanks
EDIT: What do you think about this solution?
int random = i + (int)(System.currentTimeMillis()%((j - i) + 1));
Where i and j are the range
You have to implement your own pseudo-random number generation algorithm, which is literally reinventing the wheel and will not be secure!
Another solution is to use a service that generates true random numbers like Random.org
I learned that the best method for generating the most random numbers is using the Mersenne Twister random number generator. This generator will provide you with enough random numbers to not need to reseed, it has a period of (2^19937) − 1
Here is source code for MerseeneTwister
https://java2s.com/Open-Source/Java/Natural-Language-Processing/MorphAdorner/edu/northwestern/at/utils/math/randomnumbers/MersenneTwister.java.htm
Here is a class to generate your random numbers.
class RandomVariable {
/** Initialize Mersenne Twister generator. */
private static MersenneTwister rnd = new MersenneTwister();
public static double rand() {
return rnd.nextDouble();
}
/** Generate a random number from a uniform random variable.
*
* #param min Mininum value for the random variable.
* #param max Maximum value for the random variable.
*
* #return A random double between min and max.
*/
public static double uniform(double min, double max) {
return min + (max - min) * rand();
}
}
Here is a sample to generate a random number. Please note that I removed the comments from the source. This may voliate the open source nature of the code, but I couldnt copy it all and have it formated as code.
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class sample{
public static void main(String args[]){
RandomVariable gen = new RandomVariable();
double num = gen.uniform(-1,1);
int n = 10000;
Set<Double> nums = new HashSet<Double>();
while (numbers.size() < n)
nums.add(gen.uniform(-1,1));
}
}
class RandomVariable {
/** Initialize Mersenne Twister generator. */
private static MersenneTwister rnd = new MersenneTwister();
public static double rand() {
return rnd.nextDouble();
}
/** Generate a random number from a uniform random variable.
*
* #param min Mininum value for the random variable.
* #param max Maximum value for the random variable.
*
* #return A random double between min and max.
*/
public static double uniform(double min, double max) {
return min + (max - min) * rand();
}
}
class MersenneTwister extends java.util.Random implements Serializable {
// Period parameters
private static final int N = 624;
private static final int M = 397;
private static final int MATRIX_A = 0x9908b0df; // private static final
//* constant vector a
private static final int UPPER_MASK = 0x80000000; // most significant
// w-r bits
private static final int LOWER_MASK = 0x7fffffff; // least significant
// r bits
// Tempering parameters
private static final int TEMPERING_MASK_B = 0x9d2c5680;
private static final int TEMPERING_MASK_C = 0xefc60000;
private int mt[]; // the array for the state vector
private int mti; // mti==N+1 means mt[N] is not initialized
private int mag01[];
// a good initial seed (of int size, though stored in a long)
// private static final long GOOD_SEED = 4357;
/* implemented here because there's a bug in Random's implementation
of the Gaussian code (divide by zero, and log(0), ugh!), yet its
gaussian variables are private so we can't access them here. :-( */
private double __nextNextGaussian;
private boolean __haveNextNextGaussian;
/**
* Constructor using the default seed.
*/
public MersenneTwister() {
this(System.currentTimeMillis());
}
/**
* Constructor using a given seed. Though you pass this seed in
* as a long, it's best to make sure it's actually an integer.
*/
public MersenneTwister(final long seed) {
super(seed); /* just in case */
setSeed(seed);
}
/**
* Constructor using an array.
*/
public MersenneTwister(final int[] array) {
super(System.currentTimeMillis());
/* pick something at random just in case */
setSeed(array);
}
/**
* Initalize the pseudo random number generator. Don't
* pass in a long that's bigger than an int (Mersenne Twister
* only uses the first 32 bits for its seed).
*/
synchronized public void setSeed(final long seed) {
// it's always good style to call super
super.setSeed(seed);
// Due to a bug in java.util.Random clear up to 1.2, we're
// doing our own Gaussian variable.
__haveNextNextGaussian = false;
mt = new int[N];
mag01 = new int[2];
mag01[0] = 0x0;
mag01[1] = MATRIX_A;
mt[0] = (int) (seed & 0xfffffff);
for (mti = 1; mti < N; mti++) {
mt[mti] =
(1812433253 * (mt[mti - 1] ^ (mt[mti - 1] >>> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffff;
/* for >32 bit machines */
}
}
/**
* An alternative, more complete, method of seeding the
* pseudo random number generator. array must be an
* array of 624 ints, and they can be any value as long as
* they're not *all* zero.
*/
synchronized public void setSeed(final int[] array) {
int i, j, k;
setSeed(19650218);
i = 1;
j = 0;
k = (N > array.length ? N : array.length);
for (; k != 0; k--) {
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * 1664525))
+ array[j] + j; /* non linear */
mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
i++;
j++;
if (i >= N) {
mt[0] = mt[N - 1];
i = 1;
}
if (j >= array.length) {
j = 0;
}
}
for (k = N - 1; k != 0; k--) {
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * 1566083941))
- i; /* non linear */
mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
i++;
if (i >= N) {
mt[0] = mt[N - 1];
i = 1;
}
}
mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */
}
/**
* Returns an integer with <em>bits</em> bits filled with a random number.
*/
synchronized protected int next(final int bits) {
int y;
if (mti >= N) // generate N words at one time
{
int kk;
final int[] mt = this.mt; // locals are slightly faster
final int[] mag01 = this.mag01; // locals are slightly faster
for (kk = 0; kk < N - M; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + M] ^ (y >>> 1) ^ mag01[y & 0x1];
}
for (; kk < N - 1; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + (M - N)] ^ (y >>> 1) ^ mag01[y & 0x1];
}
y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];
mti = 0;
}
y = mt[mti++];
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y)
y ^= (y >>> 18); // TEMPERING_SHIFT_L(y)
return y >>> (32 - bits); // hope that's right!
}
/* If you've got a truly old version of Java, you can omit these
two next methods. */
private synchronized void writeObject(final ObjectOutputStream out)
throws IOException {
// just so we're synchronized.
out.defaultWriteObject();
}
private synchronized void readObject(final ObjectInputStream in)
throws IOException, ClassNotFoundException {
// just so we're synchronized.
in.defaultReadObject();
}
/** This method is missing from jdk 1.0.x and below. JDK 1.1
includes this for us, but what the heck.*/
public boolean nextBoolean() {
return next(1) != 0;
}
/** This generates a coin flip with a probability <tt>probability</tt>
of returning true, else returning false. <tt>probability</tt> must
be between 0.0 and 1.0, inclusive. Not as precise a random real
event as nextBoolean(double), but twice as fast. To explicitly
use this, remember you may need to cast to float first. */
public boolean nextBoolean(final float probability) {
if (probability < 0.0f || probability > 1.0f) {
throw new IllegalArgumentException("probability must be between 0.0"
+ " and 1.0 inclusive.");
}
if (probability == 0.0f) {
return false; // fix half-open issues
} else if (probability == 1.0f) {
return true; // fix half-open issues
}
return nextFloat() < probability;
}
/** This generates a coin flip with a probability <tt>probability</tt>
of returning true, else returning false. <tt>probability</tt> must
be between 0.0 and 1.0, inclusive. */
public boolean nextBoolean(final double probability) {
if (probability < 0.0 || probability > 1.0) {
throw new IllegalArgumentException("probability must be between 0.0"
+ " and 1.0 inclusive.");
}
if (probability == 0.0) {
return false; // fix half-open issues
} else if (probability == 1.0) {
return true; // fix half-open issues
}
return nextDouble() < probability;
}
/** This method is missing from JDK 1.1 and below. JDK 1.2
includes this for us, but what the heck. */
public int nextInt(final int n) {
if (n <= 0) {
throw new IllegalArgumentException("n must be >= 0");
}
if ((n & -n) == n) {
return (int) ((n * (long) next(31)) >> 31);
}
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n - 1) < 0);
return val;
}
/** This method is for completness' sake.
Returns a long drawn uniformly from 0 to n-1. Suffice it to say,
n must be > 0, or an IllegalArgumentException is raised. */
public long nextLong(final long n) {
if (n <= 0) {
throw new IllegalArgumentException("n must be >= 0");
}
long bits, val;
do {
bits = (nextLong() >>> 1);
val = bits % n;
} while (bits - val + (n - 1) < 0);
return val;
}
/** A bug fix for versions of JDK 1.1 and below. JDK 1.2 fixes
this for us, but what the heck. */
public double nextDouble() {
return (((long) next(26) << 27) + next(27))
/ (double) (1L << 53);
}
/** A bug fix for versions of JDK 1.1 and below. JDK 1.2 fixes
this for us, but what the heck. */
public float nextFloat() {
return next(24) / ((float) (1 << 24));
}
/** A bug fix for all versions of the JDK. The JDK appears to
use all four bytes in an integer as independent byte values!
Totally wrong. I've submitted a bug report. */
public void nextBytes(final byte[] bytes) {
for (int x = 0; x < bytes.length; x++) {
bytes[x] = (byte) next(8);
}
}
/** For completeness' sake, though it's not in java.util.Random. */
public char nextChar() {
// chars are 16-bit UniCode values
return (char) (next(16));
}
/** For completeness' sake, though it's not in java.util.Random. */
public short nextShort() {
return (short) (next(16));
}
/** For completeness' sake, though it's not in java.util.Random. */
public byte nextByte() {
return (byte) (next(8));
}
/** A bug fix for all JDK code including 1.2. nextGaussian can theoretical
* ly
ask for the log of 0 and divide it by 0! See Java bug
<a href="http://developer.java.sun.com/developer/bugParade/bugs/4254501.h
* tml">
http://developer.java.sun.com/developer/bugParade/bugs/4254501.html</a>
*/
synchronized public double nextGaussian() {
if (__haveNextNextGaussian) {
__haveNextNextGaussian = false;
return __nextNextGaussian;
} else {
double v1, v2, s;
do {
v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
double multiplier = /* Strict*/ Math.sqrt(-2
* /* Strict*/ Math.log(s) / s);
__nextNextGaussian = v2 * multiplier;
__haveNextNextGaussian = true;
return v1 * multiplier;
}
}
}
There is a default random method in java.lang.math.
It returns a double between 0.0 and 1.0 (0.0 <= n < 1.0).
You can do some simple tricks to convert this to various random values:
boolean coinFlip = (Math.random() >= 0.5);
int card = (int)(Math.random() * 52);
However, this makes a new java.util.Random() behind the scenes, which I think you are trying to avoid.
If you don't want to use any library, then you have to make your own implementation, which will probably end up being much more complicated.
You mentioned using time, this could certainly work for generating numbers, but for any practical purpose it is not really random. Something like:
long betweenOneAndTen = 1 + (System.currentTimeMillis() % 10);
If you use the Math.random() function, you are neiter making a dependence on the Random class nor initializing anything (at least it's not your responsibility). There is no fundamental difference between calling System.currentTimeMillis(), System.nanoTime() and Math.random()---except that the latter is more performant and better at returning a random value.

AtomicBitSet implementation for java

The standard api does not include an AtomicBitSet implementation. I could roll my own on top of AtomicIntegerArray, but would prefer not too.
Is anyone aware of an existing implementation released under a licence compatible with Apache 2? I require only basic operations to set and check bits.
Edit:
The code is both performance and memory critical so I'd like to avoid synchronization or an integer per flag if possible.
I would use an AtomicIntegerArray and I would use 32 flags per integer which would give you the same density as BitSet but without needing locks for thread safety.
public class AtomicBitSet {
private final AtomicIntegerArray array;
public AtomicBitSet(int length) {
int intLength = (length + 31) >>> 5; // unsigned / 32
array = new AtomicIntegerArray(intLength);
}
public void set(long n) {
int bit = 1 << n;
int idx = (int) (n >>> 5);
while (true) {
int num = array.get(idx);
int num2 = num | bit;
if (num == num2 || array.compareAndSet(idx, num, num2))
return;
}
}
public boolean get(long n) {
int bit = 1 << n;
int idx = (int) (n >>> 5);
int num = array.get(idx);
return (num & bit) != 0;
}
}
Look at http://www.javamex.com/tutorials/synchronization_concurrency_7_atomic_integer_long.shtml
Not exactly using BitSet, but AtomicInteger.

Categories

Resources