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 Xoshiro256ss implements RndInt64 {
19  
20      private static final int LSFT   = 17;
21      private static final int ROTL_0 =  7;
22      private static final int ROTL_1 = 45;
23  
24      private static final long MUL_0 = 5L;
25      private static final long MUL_1 = 9L;
26  
27      private static final String MSG_ILLSEED = "At least one seed must be non-zero";
28  
29  
30      private long s0 = 1L;
31      private long s1 = 0L;
32      private long s2 = 0L;
33      private long s3 = 0L;
34  
35  
36      /**
37       * Constructor.
38       *
39       * <p>Warning: The default seed value will give a very biased result.
40       */
41      public Xoshiro256ss() {
42          super();
43          return;
44      }
45  
46  
47      /**
48       * {@inheritDoc}
49       *
50       * @return {@inheritDoc}
51       */
52      @Override
53      public long nextInt64() {
54          long tmp0 = this.s0;
55          long tmp1 = this.s1;
56          long tmp2 = this.s2;
57          long tmp3 = this.s3;
58  
59          final long lsft1 = tmp1 << LSFT;
60  
61          final long result = Long.rotateLeft(tmp1 * MUL_0, ROTL_0) * MUL_1;
62  
63          tmp2 ^= tmp0;
64          tmp3 ^= tmp1;
65          tmp1 ^= tmp2;
66          tmp0 ^= tmp3;
67  
68          tmp2 ^= lsft1;
69          tmp3 = Long.rotateLeft(tmp3, ROTL_1);
70  
71          this.s0 = tmp0;
72          this.s1 = tmp1;
73          this.s2 = tmp2;
74          this.s3 = tmp3;
75  
76          return result;
77      }
78  
79      /**
80       * Set seed.
81       *
82       * <p>At least one seed must be non-zero.
83       *
84       * @param s0Arg seed0
85       * @param s1Arg seed1
86       * @param s2Arg seed2
87       * @param s3Arg seed3
88       * @throws IllegalArgumentException At least one seed must be non-zero
89       */
90      public void setSeed(long s0Arg, long s1Arg, long s2Arg, long s3Arg)
91              throws IllegalArgumentException {
92          if ((s0Arg | s1Arg | s2Arg | s3Arg) == 0L) {
93              throw new IllegalArgumentException(MSG_ILLSEED);
94          }
95  
96          this.s0 = s0Arg;
97          this.s1 = s1Arg;
98          this.s2 = s2Arg;
99          this.s3 = s3Arg;
100 
101         return;
102     }
103 
104 }