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 }