001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.rng.core.source64;
019
020import org.apache.commons.rng.core.util.NumberFactory;
021import org.apache.commons.rng.core.BaseProvider;
022
023/**
024 * Base class for all implementations that provide a {@code long}-based
025 * source randomness.
026 */
027public abstract class LongProvider
028    extends BaseProvider
029    implements RandomLongSource {
030
031    /** Empty boolean source. This is the location of the sign-bit after 63 right shifts on
032     * the boolean source. */
033    private static final long EMPTY_BOOL_SOURCE = 1;
034    /** Empty int source. This requires a negative value as the sign-bit is used to
035     * trigger a refill. */
036    private static final long EMPTY_INT_SOURCE = -1;
037
038    /**
039     * Provides a bit source for booleans.
040     *
041     * <p>A cached value from a call to {@link #next()}.
042     *
043     * <p>Only stores 63-bits when full as 1 bit has already been consumed.
044     * The sign bit is a flag that shifts down so the source eventually equals 1
045     * when all bits are consumed and will trigger a refill.
046     */
047    private long booleanSource = EMPTY_BOOL_SOURCE;
048
049    /**
050     * Provides a source for ints.
051     *
052     * <p>A cached half-value value from a call to {@link #next()}.
053     * The int is stored in the lower 32 bits with zeros in the upper bits.
054     * When empty this is set to negative to trigger a refill.
055     */
056    private long intSource = EMPTY_INT_SOURCE;
057
058    /**
059     * Creates a new instance.
060     */
061    public LongProvider() {
062        super();
063    }
064
065    /**
066     * Creates a new instance copying the state from the source.
067     *
068     * <p>This provides base functionality to allow a generator to create a copy, for example
069     * for use in the {@link org.apache.commons.rng.JumpableUniformRandomProvider
070     * JumpableUniformRandomProvider} interface.
071     *
072     * @param source Source to copy.
073     * @since 1.3
074     */
075    protected LongProvider(LongProvider source) {
076        booleanSource = source.booleanSource;
077        intSource = source.intSource;
078    }
079
080    /**
081     * Reset the cached state used in the default implementation of {@link #nextBoolean()}
082     * and {@link #nextInt()}.
083     *
084     * <p>This should be used when the state is no longer valid, for example after a jump
085     * performed for the {@link org.apache.commons.rng.JumpableUniformRandomProvider
086     * JumpableUniformRandomProvider} interface.</p>
087     *
088     * @since 1.3
089     */
090    protected void resetCachedState() {
091        booleanSource = EMPTY_BOOL_SOURCE;
092        intSource = EMPTY_INT_SOURCE;
093    }
094
095    /** {@inheritDoc} */
096    @Override
097    protected byte[] getStateInternal() {
098        final long[] state = {booleanSource, intSource};
099        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}