View Javadoc
1   /*
2    * License : The MIT License
3    * Copyright(c) 2021 Olyutorskii
4    */
5   
6   package io.github.olyutorskii.aletojio.rng.xorsft;
7   
8   import io.github.olyutorskii.aletojio.rng.RndInt64;
9   
10  /**
11   * xoshiro256++ Pseudo Random Generator.
12   *
13   * <p>Warning: The default seed value will give a very biased result.
14   *
15   * @see <a href="https://en.wikipedia.org/wiki/Xorshift">Xorshift (Wikipedia)</a>
16   * @see <a href="https://prng.di.unimi.it/">xoshiro / xoroshiro generators and the PRNG shootout</a>
17   */
18  public class Xoshiro256pp implements RndInt64 {
19  
20      private static final int LSFT   = 17;
21      private static final int ROTL_0 = 23;
22      private static final int ROTL_1 = 45;
23  
24      private static final String MSG_ILLSEED = "At least one seed must be non-zero";
25  
26  
27      private long s0 = 1L;
28      private long s1 = 0L;
29      private long s2 = 0L;
30      private long s3 = 0L;
31  
32  
33      /**
34       * Constructor.
35       *
36       * <p>Warning: The default seed value will give a very biased result.
37       */
38      public Xoshiro256pp() {
39          super();
40          return;
41      }
42  
43  
44      /**
45       * {@inheritDoc}
46       *
47       * @return {@inheritDoc}
48       */
49      @Override
50      public long nextInt64() {
51          long tmp0 = this.s0;
52          long tmp1 = this.s1;
53          long tmp2 = this.s2;
54          long tmp3 = this.s3;
55  
56          final long sum03 = tmp0 + tmp3;
57          final long lsft1 = tmp1 << LSFT;
58  
59          final long result = Long.rotateLeft(sum03, ROTL_0) + tmp0;
60  
61          tmp2 ^= tmp0;
62          tmp3 ^= tmp1;
63          tmp1 ^= tmp2;
64          tmp0 ^= tmp3;
65  
66          tmp2 ^= lsft1;
67          tmp3  = Long.rotateLeft(tmp3, ROTL_1);
68  
69          this.s0 = tmp0;
70          this.s1 = tmp1;
71          this.s2 = tmp2;
72          this.s3 = tmp3;
73  
74          return result;
75      }
76  
77      /**
78       * Set seed.
79       *
80       * <p>At least one seed must be non-zero.
81       *
82       * @param s0Arg seed0
83       * @param s1Arg seed1
84       * @param s2Arg seed2
85       * @param s3Arg seed3
86       * @throws IllegalArgumentException At least one seed must be non-zero
87       */
88      public void setSeed(long s0Arg, long s1Arg, long s2Arg, long s3Arg)
89              throws IllegalArgumentException {
90          if ((s0Arg | s1Arg | s2Arg | s3Arg) == 0L) {
91              throw new IllegalArgumentException(MSG_ILLSEED);
92          }
93  
94          this.s0 = s0Arg;
95          this.s1 = s1Arg;
96          this.s2 = s2Arg;
97          this.s3 = s3Arg;
98  
99          return;
100     }
101 
102 }