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  
18  package org.apache.commons.rng.core.source64;
19  
20  import org.apache.commons.rng.core.util.NumberFactory;
21  import org.apache.commons.rng.core.BaseProvider;
22  
23  /**
24   * Base class for all implementations that provide a {@code long}-based
25   * source randomness.
26   */
27  public abstract class LongProvider
28      extends BaseProvider
29      implements RandomLongSource {
30  
31      /** Empty boolean source. This is the location of the sign-bit after 63 right shifts on
32       * the boolean source. */
33      private static final long EMPTY_BOOL_SOURCE = 1;
34      /** Empty int source. This requires a negative value as the sign-bit is used to
35       * trigger a refill. */
36      private static final long EMPTY_INT_SOURCE = -1;
37  
38      /**
39       * Provides a bit source for booleans.
40       *
41       * <p>A cached value from a call to {@link #next()}.
42       *
43       * <p>Only stores 63-bits when full as 1 bit has already been consumed.
44       * The sign bit is a flag that shifts down so the source eventually equals 1
45       * when all bits are consumed and will trigger a refill.
46       */
47      private long booleanSource = EMPTY_BOOL_SOURCE;
48  
49      /**
50       * Provides a source for ints.
51       *
52       * <p>A cached half-value value from a call to {@link #next()}.
53       * The int is stored in the lower 32 bits with zeros in the upper bits.
54       * When empty this is set to negative to trigger a refill.
55       */
56      private long intSource = EMPTY_INT_SOURCE;
57  
58      /**
59       * Creates a new instance.
60       */
61      public LongProvider() {
62          super();
63      }
64  
65      /**
66       * Creates a new instance copying the state from the source.
67       *
68       * <p>This provides base functionality to allow a generator to create a copy, for example
69       * for use in the {@link org.apache.commons.rng.JumpableUniformRandomProvider
70       * JumpableUniformRandomProvider} interface.
71       *
72       * @param source Source to copy.
73       * @since 1.3
74       */
75      protected LongProvider(LongProvider source) {
76          booleanSource = source.booleanSource;
77          intSource = source.intSource;
78      }
79  
80      /**
81       * Reset the cached state used in the default implementation of {@link #nextBoolean()}
82       * and {@link #nextInt()}.
83       *
84       * <p>This should be used when the state is no longer valid, for example after a jump
85       * performed for the {@link org.apache.commons.rng.JumpableUniformRandomProvider
86       * JumpableUniformRandomProvider} interface.</p>
87       *
88       * @since 1.3
89       */
90      protected void resetCachedState() {
91          booleanSource = EMPTY_BOOL_SOURCE;
92          intSource = EMPTY_INT_SOURCE;
93      }
94  
95      /** {@inheritDoc} */
96      @Override
97      protected byte[] getStateInternal() {
98          final long[] state = {booleanSource, intSource};
99          return composeStateInternal(NumberFactory.makeByteArray(state),
100                                     super.getStateInternal());
101     }
102 
103     /** {@inheritDoc} */
104     @Override
105     protected void setStateInternal(byte[] s) {
106         final byte[][] c = splitStateInternal(s, 2 * Long.BYTES);
107         final long[] state = NumberFactory.makeLongArray(c[0]);
108         booleanSource   = state[0];
109         intSource       = state[1];
110         super.setStateInternal(c[1]);
111     }
112 
113     /** {@inheritDoc} */
114     @Override
115     public long nextLong() {
116         return next();
117     }
118 
119     /** {@inheritDoc} */
120     @Override
121     public int nextInt() {
122         long bits = intSource;
123         if (bits < 0) {
124             // Refill
125             bits = next();
126             // Store high 32 bits, return low 32 bits
127             intSource = bits >>> 32;
128             return (int) bits;
129         }
130         // Reset and return previous low bits
131         intSource = -1;
132         return (int) bits;
133     }
134 
135     /** {@inheritDoc} */
136     @Override
137     public boolean nextBoolean() {
138         long bits = booleanSource;
139         if (bits == 1) {
140             // Refill
141             bits = next();
142             // Store a refill flag in the sign bit and the unused 63 bits, return lowest bit
143             booleanSource = Long.MIN_VALUE | (bits >>> 1);
144             return (bits & 0x1) == 1;
145         }
146         // Shift down eventually triggering refill, return current lowest bit
147         booleanSource = bits >>> 1;
148         return (bits & 0x1) == 1;
149     }
150 }