/*
* Copyright 2014 Jeff Hain
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.jafaran;
/**
* Abstract class for sequential (non-concurrent) RNGs,
* which implements bits storing in next(int).
*/
public abstract class AbstractSeqRNG extends AbstractRNG {
/*
* Not doing such a class for concurrent RNGs, since storing benefit might
* be neglectable compared to synchronization costs, and storing mechanics
* could have to be hacked into each RNG's concurrency logic.
*/
//--------------------------------------------------------------------------
// MEMBERS
//--------------------------------------------------------------------------
private static final long serialVersionUID = 1L;
/**
* Bits stored as LSBits.
*/
private int currentStoredBits;
/**
* In [0,32].
*/
private int currentNbrOfStoredBits;
//--------------------------------------------------------------------------
// PUBLIC METHODS
//--------------------------------------------------------------------------
/**
* Constructor using a random seed.
*/
public AbstractSeqRNG() {
}
/**
* Constructor using a specified seed.
*/
public AbstractSeqRNG(long seed) {
super(seed);
}
//--------------------------------------------------------------------------
// PROTECTED METHODS
//--------------------------------------------------------------------------
protected AbstractSeqRNG(Void dummy) {
super(dummy);
}
/**
* Must be called by overriding implementation, as well as any setSeed
* method, to clear stored bits.
* Not doing a specific method for stored bits clearing, else extending
* class creator would have greater chances of forgetting to call it.
*/
@Override
protected void setSeedImpl(long unused) {
this.currentStoredBits = 0;
this.currentNbrOfStoredBits = 0;
}
/**
* If nbrOfBits is too large, storing overhead by not be worth it,
* so it might be better to use nextInt() instead.
*/
@Override
protected int next(int nbrOfBits) {
final int result;
final int tmpBits;
final int nbrOfTmpBitsNotUsed;
final int nbrOfStoredBits = this.currentNbrOfStoredBits;
if (nbrOfBits <= nbrOfStoredBits) {
// Enough stored bits.
tmpBits = this.currentStoredBits;
nbrOfTmpBitsNotUsed = (nbrOfStoredBits-nbrOfBits);
// Using MSBits of current bits.
result = (tmpBits>>>nbrOfTmpBitsNotUsed);
} else {
// Not enough stored bits: getting more random bits.
tmpBits = this.nextInt();
// Number of new random bits to add to the value.
final int nbrOfNewBitsUsed = nbrOfBits - nbrOfStoredBits;
nbrOfTmpBitsNotUsed = (32-nbrOfNewBitsUsed);
// Using stored bits as MSBits, and MSBits of new bits as LSBits.
result = (this.currentStoredBits<<nbrOfNewBitsUsed) | (tmpBits>>>nbrOfTmpBitsNotUsed);
}
this.currentStoredBits = ((tmpBits & ((1<<nbrOfTmpBitsNotUsed)-1)));
this.currentNbrOfStoredBits = nbrOfTmpBitsNotUsed;
return result;
}
/*
* For state get/set.
*/
protected void setCurrentStoredBits(int currentStoredBits) {
this.currentStoredBits = currentStoredBits;
}
protected void setCurrentNbrOfStoredBits(int currentNbrOfStoredBits) {
this.currentNbrOfStoredBits = currentNbrOfStoredBits;
}
protected int getCurrentStoredBits() {
return this.currentStoredBits;
}
protected int getCurrentNbrOfStoredBits() {
return this.currentNbrOfStoredBits;
}
}