001: /*
002: * (c) Copyright 2006 by Volker Bergmann. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, is permitted under the terms of the
006: * GNU General Public License.
007: *
008: * For redistributing this software or a derivative work under a license other
009: * than the GPL-compatible Free Software License as defined by the Free
010: * Software Foundation or approved by OSI, you must first obtain a commercial
011: * license to this software product from Volker Bergmann.
012: *
013: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
014: * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
015: * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
016: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
017: * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
018: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
019: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
020: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
021: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
022: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
023: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
024: * POSSIBILITY OF SUCH DAMAGE.
025: */
026:
027: package org.databene.benerator.primitive.number.distribution;
028:
029: import org.databene.benerator.*;
030: import org.databene.commons.NumberUtil;
031:
032: /**
033: * Long Generator that implements a 'bitreverse' Long Sequence.<br/>
034: * <br/>
035: * Created: 13.11.2007 14:39:29
036: */
037: public class BitReverseNaturalNumberGenerator extends
038: LightweightGenerator<Long> {
039:
040: private long max;
041: private long cursor;
042: private Long next;
043: private int bitsUsed;
044: private long maxCursor;
045: private boolean dirty;
046:
047: public BitReverseNaturalNumberGenerator() {
048: this (Long.MAX_VALUE);
049: }
050:
051: public BitReverseNaturalNumberGenerator(long max) {
052: this .max = max;
053: this .dirty = true;
054: }
055:
056: // config properties -----------------------------------------------------------------------------------------------
057:
058: public Class<Long> getGeneratedType() {
059: return Long.class;
060: }
061:
062: public Distribution getDistribution() {
063: return Sequence.BIT_REVERSE;
064: }
065:
066: public void setMax(Long max) {
067: if (max < 0)
068: throw new IllegalArgumentException(
069: "No negative min supported, was: " + max);
070: this .max = max;
071: this .dirty = true;
072: }
073:
074: // generator interface ---------------------------------------------------------------------------------------------
075:
076: public void validate() {
077: if (dirty) {
078: super .validate();
079: cursor = 0;
080: bitsUsed = NumberUtil.bitsUsed(max);
081: next = 0L;
082: this .maxCursor = 1 << bitsUsed;
083: this .dirty = false;
084: }
085: }
086:
087: public boolean available() {
088: if (dirty)
089: validate();
090: return next != null;
091: }
092:
093: public Long generate() throws IllegalGeneratorStateException {
094: if (dirty)
095: validate();
096: if (next == null)
097: throw new IllegalGeneratorStateException(
098: "No numbers available any more");
099: long result = next;
100: do {
101: cursor++;
102: next = cursorReversed();
103: } while (next > max && cursor < maxCursor);
104: if (cursor >= maxCursor)
105: next = null;
106: return result;
107: }
108:
109: public void reset() {
110: super .reset();
111: dirty = true;
112: validate();
113: }
114:
115: public void close() {
116: super .close();
117: next = null;
118: }
119:
120: // java.lang.Object overrides --------------------------------------------------------------------------------------
121:
122: public String toString() {
123: return getClass().getSimpleName() + '[' + renderState() + ']';
124: }
125:
126: // private helpers -------------------------------------------------------------------------------------------------
127:
128: private long cursorReversed() {
129: long result = 0;
130: for (int i = 0; i <= bitsUsed; i++)
131: result |= ((cursor >> i) & 1) << (bitsUsed - i - 1);
132: return result;
133: }
134:
135: private String renderState() {
136: return "max=" + max + ", cursor=" + cursor;
137: }
138: }
|