| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.commons.rng.core.source64; |
| |
| import org.apache.commons.rng.core.util.NumberFactory; |
| import org.apache.commons.rng.core.BaseProvider; |
| |
| /** |
| * Base class for all implementations that provide a {@code long}-based |
| * source randomness. |
| */ |
| public abstract class LongProvider |
| extends BaseProvider |
| implements RandomLongSource { |
| |
| /** Empty boolean source. This is the location of the sign-bit after 63 right shifts on |
| * the boolean source. */ |
| private static final long EMPTY_BOOL_SOURCE = 1; |
| /** Empty int source. This requires a negative value as the sign-bit is used to |
| * trigger a refill. */ |
| private static final long EMPTY_INT_SOURCE = -1; |
| |
| /** |
| * Provides a bit source for booleans. |
| * |
| * <p>A cached value from a call to {@link #next()}. |
| * |
| * <p>Only stores 63-bits when full as 1 bit has already been consumed. |
| * The sign bit is a flag that shifts down so the source eventually equals 1 |
| * when all bits are consumed and will trigger a refill. |
| */ |
| private long booleanSource = EMPTY_BOOL_SOURCE; |
| |
| /** |
| * Provides a source for ints. |
| * |
| * <p>A cached half-value value from a call to {@link #next()}. |
| * The int is stored in the lower 32 bits with zeros in the upper bits. |
| * When empty this is set to negative to trigger a refill. |
| */ |
| private long intSource = EMPTY_INT_SOURCE; |
| |
| /** |
| * Creates a new instance. |
| */ |
| public LongProvider() { |
| super(); |
| } |
| |
| /** |
| * Creates a new instance copying the state from the source. |
| * |
| * <p>This provides base functionality to allow a generator to create a copy, for example |
| * for use in the {@link org.apache.commons.rng.JumpableUniformRandomProvider |
| * JumpableUniformRandomProvider} interface. |
| * |
| * @param source Source to copy. |
| * @since 1.3 |
| */ |
| protected LongProvider(LongProvider source) { |
| booleanSource = source.booleanSource; |
| intSource = source.intSource; |
| } |
| |
| /** |
| * Reset the cached state used in the default implementation of {@link #nextBoolean()} |
| * and {@link #nextInt()}. |
| * |
| * <p>This should be used when the state is no longer valid, for example after a jump |
| * performed for the {@link org.apache.commons.rng.JumpableUniformRandomProvider |
| * JumpableUniformRandomProvider} interface.</p> |
| * |
| * @since 1.3 |
| */ |
| protected void resetCachedState() { |
| booleanSource = EMPTY_BOOL_SOURCE; |
| intSource = EMPTY_INT_SOURCE; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| protected byte[] getStateInternal() { |
| final long[] state = {booleanSource, intSource}; |
| return composeStateInternal(NumberFactory.makeByteArray(state), |
| super.getStateInternal()); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| protected void setStateInternal(byte[] s) { |
| final byte[][] c = splitStateInternal(s, 2 * Long.BYTES); |
| final long[] state = NumberFactory.makeLongArray(c[0]); |
| booleanSource = state[0]; |
| intSource = state[1]; |
| super.setStateInternal(c[1]); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public long nextLong() { |
| return next(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public int nextInt() { |
| long bits = intSource; |
| if (bits < 0) { |
| // Refill |
| bits = next(); |
| // Store high 32 bits, return low 32 bits |
| intSource = bits >>> 32; |
| return (int) bits; |
| } |
| // Reset and return previous low bits |
| intSource = -1; |
| return (int) bits; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public boolean nextBoolean() { |
| long bits = booleanSource; |
| if (bits == 1) { |
| // Refill |
| bits = next(); |
| // Store a refill flag in the sign bit and the unused 63 bits, return lowest bit |
| booleanSource = Long.MIN_VALUE | (bits >>> 1); |
| return (bits & 0x1) == 1; |
| } |
| // Shift down eventually triggering refill, return current lowest bit |
| booleanSource = bits >>> 1; |
| return (bits & 0x1) == 1; |
| } |
| } |