View Javadoc

1   /*
2    * @(#) DX120Generator.java Mar 19, 2004
3    * 
4    * Copyright (c) 2004 Delft University of Technology Jaffalaan 5, 2628 BX Delft,
5    * the Netherlands All rights reserved.
6    * 
7    * This software is proprietary information of Delft University of Technology
8    * The code is published under the General Public License
9    */
10  package nl.tudelft.simulation.jstats.streams;
11  
12  /***
13   * The DX-120-4 pseudo random number generator. This generator is described in
14   * <a href="http://www.cs.memphis.edu/~dengl/dx-rng/dengxu2002.pdf"> A System of
15   * High-dimensional, Efficient, Long-cycle and Portable Uniform Random Number
16   * Generators </a>.
17   * <p>
18   * (c) copyright 2004 <a href="http://www.simulation.tudelft.nl">Delft
19   * University of Technology </a>, the Netherlands. <br>
20   * See for project information <a href="http://www.simulation.tudelft.nl">
21   * www.simulation.tudelft.nl </a> <br>
22   * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
23   * License (GPL) </a>, no warranty <br>
24   * 
25   * @author <a href="http://www.simulation.tudelft.nl/people/jacobs.html">Peter
26   *         Jacobs </a>
27   * @version 1.2 2004-03-18
28   * @since 1.0
29   */
30  public class DX120Generator extends RandomNumberGenerator
31  {
32  	/*** the k value of the DX-120 Generator */
33  	private static final int K = 120;
34  
35  	/*** the mask value 2^31-1 (or 1 < < 31)-1 */
36  	private static final int MASK = Integer.MAX_VALUE;
37  
38  	/*** the LCG multiplier */
39  	private static final int MULTIPLIER = 16807;
40  
41  	/*** the buffer for this generator */
42  	private int[] buffer = null;
43  
44  	/*** indexing attributes */
45  	private int index;
46  
47  	/*** indexing attributes */
48  	private int k13;
49  
50  	/*** indexing attributes */
51  	private int k23;
52  
53  	/***
54  	 * constructs a new LC48Generator. the seed value used equals
55  	 * System.currentTimeMillis()
56  	 */
57  	public DX120Generator()
58  	{
59  		this(System.currentTimeMillis());
60  	}
61  
62  	/***
63  	 * constructs a new LC48Generator
64  	 * 
65  	 * @param seed the seed
66  	 */
67  	public DX120Generator(final long seed)
68  	{
69  		super(seed);
70  		this.initialize();
71  	}
72  
73  	/***
74  	 * initializes the generator
75  	 */
76  	private void initialize()
77  	{
78  		this.buffer = new int[DX120Generator.K];
79  		this.buffer[0] = ((int) super.seed) & MASK;
80  		if (this.buffer[0] == 0)
81  		{
82  			//super.seed=Integer.MAXValue --> seed & UMASK==0
83  			//We set the seed again and enforce a different value.
84  			this.setSeed(System.currentTimeMillis());
85  		}
86  		if (this.buffer[0] < 0)
87  		{
88  			this.buffer[0] = Math.abs(this.buffer[0] - 1);
89  		}
90  		for (int i = 1; i < K; i++)
91  		{
92  			this.buffer[i] = (MULTIPLIER * this.buffer[i - 1]) & MASK;
93  		}
94  		this.index = K - 1; /* running index */
95  		this.k13 = K - K / 3 - 1; // (k13 = 79)
96  		this.k23 = K - 2 * K / 3 - 1; //(k23 = 39)
97  	}
98  
99  	/***
100 	 * @see nl.tudelft.simulation.jstats.streams.RandomNumberGenerator#next(int)
101 	 */
102 	protected synchronized long next(final int bits)
103 	{
104 		if (bits < 0 || bits > 64)
105 		{
106 			throw new IllegalArgumentException("bits (" + bits
107 					+ ") not in range [0,64]");
108 		}
109 		int tempIndex = this.index;
110 		if (++this.index >= K)
111 		{
112 			this.index = 0; /* wrap around running index */
113 		}
114 		if (++this.k13 >= K)
115 		{
116 			this.k13 = 0; /* wrap around k13 */
117 		}
118 		if (++this.k23 >= K)
119 		{
120 			this.k23 = 0; /* wrap around running k23 */
121 		}
122 		this.buffer[this.index] = (521673 * (this.buffer[this.index]
123 				+ this.buffer[this.k13] + this.buffer[this.k23] + this.buffer[tempIndex]))
124 				& MASK;
125 		if (bits <= 32)
126 		{
127 			return (this.buffer[this.index]) >>> (32 - bits);
128 		}
129 		return (this.buffer[this.index]) << 32 + this.next(bits - 32);
130 	}
131 
132 	/***
133 	 * @see nl.tudelft.simulation.jstats.streams.StreamInterface#setSeed(long)
134 	 */
135 	public synchronized void setSeed(final long seed)
136 	{
137 		this.seed = seed;
138 		this.initialize();
139 	}
140 }