View Javadoc
1   package org.metricshub.jawk.jrt;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2025 MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  /**
26   * Simple pseudo-random number generator compatible with the C library
27   * {@code random()} function.
28   */
29  public class BSDRandom {
30  
31  	private static final int RAND_DEG = 31;
32  	private static final int RAND_SEP = 3;
33  	private final int[] state = new int[RAND_DEG];
34  	private int fptr;
35  	private int rptr;
36  
37  	/** Create a new generator with the specified seed. */
38  	public BSDRandom(int seed) {
39  		setSeed(seed);
40  	}
41  
42  	/**
43  	 * Seed the generator. A seed of {@code 0} is transformed to {@code 1}
44  	 * as in the original implementation.
45  	 */
46  	public final void setSeed(int seed) {
47  		if (seed == 0) {
48  			seed = 1;
49  		}
50  		state[0] = seed;
51  		for (int i = 1; i < RAND_DEG; i++) {
52  			long val = 16807L * state[i - 1] % 2147483647L;
53  			state[i] = (int) val;
54  		}
55  		fptr = RAND_SEP;
56  		rptr = 0;
57  		for (int i = 0; i < 10 * RAND_DEG; i++) {
58  			nextInt();
59  		}
60  	}
61  
62  	private int nextInt() {
63  		int val = state[fptr] + state[rptr];
64  		state[fptr] = val;
65  		if (++fptr >= RAND_DEG) {
66  			fptr = 0;
67  		}
68  		if (++rptr >= RAND_DEG) {
69  			rptr = 0;
70  		}
71  		return (val >>> 1) & 0x7fffffff;
72  	}
73  
74  	/**
75  	 * Return the next pseudo-random number in the range {@code [0.0,1.0)}.
76  	 */
77  	public double nextDouble() {
78  		return ((double) nextInt()) / 2147483647.0;
79  	}
80  }