View Javadoc
1   package io.jawk.jrt;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2026 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  	/**
38  	 * Creates a new generator with the specified seed.
39  	 *
40  	 * @param seed Initial pseudo-random seed
41  	 */
42  	public BSDRandom(int seed) {
43  		setSeed(seed);
44  	}
45  
46  	/**
47  	 * Seed the generator. A seed of {@code 0} is transformed to {@code 1}
48  	 * as in the original implementation.
49  	 *
50  	 * @param seed New pseudo-random seed
51  	 */
52  	public final void setSeed(int seed) {
53  		if (seed == 0) {
54  			seed = 1;
55  		}
56  		state[0] = seed;
57  		for (int i = 1; i < RAND_DEG; i++) {
58  			long val = 16807L * state[i - 1] % 2147483647L;
59  			state[i] = (int) val;
60  		}
61  		fptr = RAND_SEP;
62  		rptr = 0;
63  		for (int i = 0; i < 10 * RAND_DEG; i++) {
64  			nextInt();
65  		}
66  	}
67  
68  	private int nextInt() {
69  		int val = state[fptr] + state[rptr];
70  		state[fptr] = val;
71  		if (++fptr >= RAND_DEG) {
72  			fptr = 0;
73  		}
74  		if (++rptr >= RAND_DEG) {
75  			rptr = 0;
76  		}
77  		return (val >>> 1) & 0x7fffffff;
78  	}
79  
80  	/**
81  	 * Return the next pseudo-random number in the range {@code [0.0,1.0)}.
82  	 *
83  	 * @return Next pseudo-random floating-point value
84  	 */
85  	public double nextDouble() {
86  		return ((double) nextInt()) / 2147483647.0;
87  	}
88  }