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