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 }