1
+ #ifndef JSF_HPP_INCLUDED
2
+ #define JSF_HPP_INCLUDED 1
3
+
4
+ /*
5
+ * A C++ implementation of a Bob Jenkins Small Fast (Noncryptographic) PRNGs
6
+ *
7
+ * The MIT License (MIT)
8
+ *
9
+ * Copyright (c) 2018 Melissa E. O'Neill
10
+ *
11
+ * Permission is hereby granted, free of charge, to any person obtaining a
12
+ * copy of this software and associated documentation files (the "Software"),
13
+ * to deal in the Software without restriction, including without limitation
14
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
+ * and/or sell copies of the Software, and to permit persons to whom the
16
+ * Software is furnished to do so, subject to the following conditions:
17
+ *
18
+ * The above copyright notice and this permission notice shall be included in
19
+ * all copies or substantial portions of the Software.
20
+ *
21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
+ * DEALINGS IN THE SOFTWARE.
28
+ */
29
+
30
+ /* Based on code published by Bob Jenkins in 2007, adapted for C++ */
31
+
32
+ #include < cstdint>
33
+
34
+ namespace jsf_detail {
35
+
36
+ template <typename itype, typename rtype,
37
+ unsigned int p, unsigned int q, unsigned int r>
38
+ class jsf {
39
+ protected:
40
+ itype a_, b_, c_, d_;
41
+
42
+ static constexpr unsigned int ITYPE_BITS = 8 *sizeof (itype);
43
+ static constexpr unsigned int RTYPE_BITS = 8 *sizeof (rtype);
44
+
45
+ static itype rotate (itype x, unsigned int k)
46
+ {
47
+ return (x << k) | (x >> (ITYPE_BITS - k));
48
+ }
49
+
50
+ public:
51
+ using result_type = rtype;
52
+ using state_type = itype;
53
+
54
+ static constexpr result_type min () { return 0 ; }
55
+ static constexpr result_type max () { return ~ result_type (0 ); }
56
+
57
+ jsf (itype seed = itype(0xcafe5eed00000001ULL ))
58
+ : a_(0xf1ea5eed ), b_(seed), c_(seed), d_(seed)
59
+ {
60
+ for (unsigned int i=0 ; i<20 ; ++i)
61
+ advance ();
62
+ }
63
+
64
+ void advance ()
65
+ {
66
+ itype e = a_ - rotate (b_, p);
67
+ a_ = b_ ^ rotate (c_, q);
68
+ b_ = c_ + (r ? rotate (d_, r) : d_);
69
+ c_ = d_ + e;
70
+ d_ = e + a_;
71
+ }
72
+
73
+
74
+ rtype operator ()()
75
+ {
76
+ advance ();
77
+ return rtype (d_);
78
+ }
79
+
80
+ bool operator ==(const jsf& rhs)
81
+ {
82
+ return (a_ == rhs.a_ ) && (b_ == rhs.b_ )
83
+ && (c_ == rhs.c_ ) && (d_ == rhs.d_ );
84
+ }
85
+
86
+ bool operator !=(const jsf& rhs)
87
+ {
88
+ return !operator ==(rhs);
89
+ }
90
+
91
+ // Not (yet) implemented:
92
+ // - arbitrary jumpahead (doable, but annoying to write).
93
+ // - I/O
94
+ // - Seeding from a seed_seq.
95
+ };
96
+
97
+ } // end namespace
98
+
99
+ // /// ---- Specific JSF Generators ---- ////
100
+ //
101
+ // Each size has variations corresponding to different parameter sets.
102
+ // Each variant will create a distinct (and hopefully statistically
103
+ // independent) sequence.
104
+ //
105
+
106
+ // - 128 state bits, 32-bit output
107
+ //
108
+ // The constants are all those suggested by Bob Jenkins. The n variants
109
+ // perform only two rotations, the r variants perform three.
110
+
111
+ using jsf32na = jsf_detail::jsf<uint32_t , uint32_t , 27 , 17 , 0 >;
112
+ using jsf32nb = jsf_detail::jsf<uint32_t , uint32_t , 9 , 16 , 0 >;
113
+ using jsf32nc = jsf_detail::jsf<uint32_t , uint32_t , 9 , 24 , 0 >;
114
+ using jsf32nd = jsf_detail::jsf<uint32_t , uint32_t , 10 , 16 , 0 >;
115
+ using jsf32ne = jsf_detail::jsf<uint32_t , uint32_t , 10 , 24 , 0 >;
116
+ using jsf32nf = jsf_detail::jsf<uint32_t , uint32_t , 11 , 16 , 0 >;
117
+ using jsf32ng = jsf_detail::jsf<uint32_t , uint32_t , 11 , 24 , 0 >;
118
+ using jsf32nh = jsf_detail::jsf<uint32_t , uint32_t , 25 , 8 , 0 >;
119
+ using jsf32ni = jsf_detail::jsf<uint32_t , uint32_t , 25 , 16 , 0 >;
120
+ using jsf32nj = jsf_detail::jsf<uint32_t , uint32_t , 26 , 8 , 0 >;
121
+ using jsf32nk = jsf_detail::jsf<uint32_t , uint32_t , 26 , 16 , 0 >;
122
+ using jsf32nl = jsf_detail::jsf<uint32_t , uint32_t , 26 , 17 , 0 >;
123
+ using jsf32nm = jsf_detail::jsf<uint32_t , uint32_t , 27 , 16 , 0 >;
124
+
125
+ using jsf32ra = jsf_detail::jsf<uint32_t , uint32_t , 3 , 14 , 24 >;
126
+ using jsf32rb = jsf_detail::jsf<uint32_t , uint32_t , 3 , 25 , 15 >;
127
+ using jsf32rc = jsf_detail::jsf<uint32_t , uint32_t , 4 , 15 , 24 >;
128
+ using jsf32rd = jsf_detail::jsf<uint32_t , uint32_t , 6 , 16 , 28 >;
129
+ using jsf32re = jsf_detail::jsf<uint32_t , uint32_t , 7 , 16 , 27 >;
130
+ using jsf32rf = jsf_detail::jsf<uint32_t , uint32_t , 8 , 14 , 3 >;
131
+ using jsf32rg = jsf_detail::jsf<uint32_t , uint32_t , 11 , 16 , 23 >;
132
+ using jsf32rh = jsf_detail::jsf<uint32_t , uint32_t , 12 , 16 , 22 >;
133
+ using jsf32ri = jsf_detail::jsf<uint32_t , uint32_t , 12 , 17 , 23 >;
134
+ using jsf32rj = jsf_detail::jsf<uint32_t , uint32_t , 13 , 16 , 22 >;
135
+ using jsf32rk = jsf_detail::jsf<uint32_t , uint32_t , 15 , 25 , 3 >;
136
+ using jsf32rl = jsf_detail::jsf<uint32_t , uint32_t , 16 , 9 , 3 >;
137
+ using jsf32rm = jsf_detail::jsf<uint32_t , uint32_t , 17 , 9 , 3 >;
138
+ using jsf32rn = jsf_detail::jsf<uint32_t , uint32_t , 17 , 27 , 7 >;
139
+ using jsf32ro = jsf_detail::jsf<uint32_t , uint32_t , 19 , 7 , 3 >;
140
+ using jsf32rp = jsf_detail::jsf<uint32_t , uint32_t , 23 , 15 , 11 >;
141
+ using jsf32rq = jsf_detail::jsf<uint32_t , uint32_t , 23 , 16 , 11 >;
142
+ using jsf32rr = jsf_detail::jsf<uint32_t , uint32_t , 23 , 17 , 11 >;
143
+ using jsf32rs = jsf_detail::jsf<uint32_t , uint32_t , 24 , 3 , 16 >;
144
+ using jsf32rt = jsf_detail::jsf<uint32_t , uint32_t , 24 , 4 , 16 >;
145
+ using jsf32ru = jsf_detail::jsf<uint32_t , uint32_t , 25 , 14 , 3 >;
146
+ using jsf32rv = jsf_detail::jsf<uint32_t , uint32_t , 27 , 16 , 6 >;
147
+ using jsf32rw = jsf_detail::jsf<uint32_t , uint32_t , 27 , 16 , 7 >;
148
+
149
+ using jsf32n = jsf32na;
150
+ using jsf32r = jsf32rq;
151
+ using jsf32 = jsf32n;
152
+
153
+ // - 256 state bits, uint64_t output
154
+
155
+ using jsf64na = jsf_detail::jsf<uint64_t , uint64_t , 39 , 11 , 0 >;
156
+ using jsf64ra = jsf_detail::jsf<uint64_t , uint64_t , 7 , 13 , 37 >;
157
+
158
+ using jsf64n = jsf64na;
159
+ using jsf64r = jsf64ra;
160
+ using jsf64 = jsf64r;
161
+
162
+ // TINY VERSIONS FOR TESTING AND SPECIALIZED USES ONLY
163
+ //
164
+ // Parameters derived using a variant of rngav.c, originally written by
165
+ // Bob Jenkins.
166
+
167
+ // - 64 state bits, uint16_t output
168
+
169
+ using jsf16na = jsf_detail::jsf<uint16_t , uint16_t , 13 , 8 , 0 >;
170
+
171
+ using jsf16 = jsf16na;
172
+
173
+ // - 32 state bits, uint8_t output
174
+
175
+ using jsf8na = jsf_detail::jsf<uint8_t , uint8_t , 1 , 4 , 0 >;
176
+
177
+ using jsf8 = jsf8na;
178
+
179
+ #endif // JSF_HPP_INCLUDED
0 commit comments