View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.rng.core.source32;
18  
19  import org.apache.commons.rng.core.util.NumberFactory;
20  
21  /**
22   * Implement the Small, Fast, Counting (SFC) 32-bit generator of Chris Doty-Humphrey.
23   * The original source is the PractRand test suite by the same author.
24   *
25   * <p>The state size is 128-bits; the period is a minimum of 2<sup>32</sup> and an
26   * average of approximately 2<sup>127</sup>.</p>
27   *
28   * @see <a href="http://pracrand.sourceforge.net/">PractRand</a>
29   * @since 1.3
30   */
31  public class DotyHumphreySmallFastCounting32 extends IntProvider {
32      /** Size of the seed. */
33      private static final int SEED_SIZE = 3;
34  
35      /** State a. */
36      private int a;
37      /** State b. */
38      private int b;
39      /** State c. */
40      private int c;
41      /** Counter. */
42      private int counter;
43  
44      /**
45       * Creates an instance with the given seed.
46       *
47       * @param seed Initial seed.
48       * If the length is larger than 3, only the first 3 elements will
49       * be used; if smaller, the remaining elements will be automatically set.
50       */
51      public DotyHumphreySmallFastCounting32(int[] seed) {
52          if (seed.length < SEED_SIZE) {
53              final int[] state = new int[SEED_SIZE];
54              fillState(state, seed);
55              setSeedInternal(state);
56          } else {
57              setSeedInternal(seed);
58          }
59      }
60  
61      /**
62       * Seeds the RNG.
63       *
64       * @param seed Seed.
65       */
66      private void setSeedInternal(int[] seed) {
67          a = seed[0];
68          b = seed[1];
69          c = seed[2];
70          counter = 1;
71          for (int i = 0; i < 15; i++) {
72              next();
73          }
74      }
75  
76      /** {@inheritDoc} */
77      @Override
78      public final int next() {
79          final int tmp = a + b + counter++;
80          a = b ^ (b >>> 9);
81          b = c + (c << 3);
82          c = Integer.rotateLeft(c, 21) + tmp;
83          return tmp;
84      }
85  
86      /** {@inheritDoc} */
87      @Override
88      protected byte[] getStateInternal() {
89          return composeStateInternal(NumberFactory.makeByteArray(new int[] {a, b, c, counter}),
90                                      super.getStateInternal());
91      }
92  
93      /** {@inheritDoc} */
94      @Override
95      protected void setStateInternal(byte[] s) {
96          final byte[][] parts = splitStateInternal(s, 4 * 4);
97  
98          final int[] tmp = NumberFactory.makeIntArray(parts[0]);
99          a = tmp[0];
100         b = tmp[1];
101         c = tmp[2];
102         counter = tmp[3];
103 
104         super.setStateInternal(parts[1]);
105     }
106 }