LongProvider.java

  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.source64;

  18. import org.apache.commons.rng.core.util.NumberFactory;
  19. import org.apache.commons.rng.core.BaseProvider;

  20. /**
  21.  * Base class for all implementations that provide a {@code long}-based
  22.  * source randomness.
  23.  */
  24. public abstract class LongProvider
  25.     extends BaseProvider
  26.     implements RandomLongSource {

  27.     /** Empty boolean source. This is the location of the sign-bit after 63 right shifts on
  28.      * the boolean source. */
  29.     private static final long EMPTY_BOOL_SOURCE = 1;
  30.     /** Empty int source. This requires a negative value as the sign-bit is used to
  31.      * trigger a refill. */
  32.     private static final long EMPTY_INT_SOURCE = -1;

  33.     /**
  34.      * Provides a bit source for booleans.
  35.      *
  36.      * <p>A cached value from a call to {@link #next()}.
  37.      *
  38.      * <p>Only stores 63-bits when full as 1 bit has already been consumed.
  39.      * The sign bit is a flag that shifts down so the source eventually equals 1
  40.      * when all bits are consumed and will trigger a refill.
  41.      */
  42.     private long booleanSource = EMPTY_BOOL_SOURCE;

  43.     /**
  44.      * Provides a source for ints.
  45.      *
  46.      * <p>A cached half-value value from a call to {@link #next()}.
  47.      * The int is stored in the lower 32 bits with zeros in the upper bits.
  48.      * When empty this is set to negative to trigger a refill.
  49.      */
  50.     private long intSource = EMPTY_INT_SOURCE;

  51.     /**
  52.      * Creates a new instance.
  53.      */
  54.     public LongProvider() {
  55.         super();
  56.     }

  57.     /**
  58.      * Creates a new instance copying the state from the source.
  59.      *
  60.      * <p>This provides base functionality to allow a generator to create a copy, for example
  61.      * for use in the {@link org.apache.commons.rng.JumpableUniformRandomProvider
  62.      * JumpableUniformRandomProvider} interface.
  63.      *
  64.      * @param source Source to copy.
  65.      * @since 1.3
  66.      */
  67.     protected LongProvider(LongProvider source) {
  68.         booleanSource = source.booleanSource;
  69.         intSource = source.intSource;
  70.     }

  71.     /**
  72.      * Reset the cached state used in the default implementation of {@link #nextBoolean()}
  73.      * and {@link #nextInt()}.
  74.      *
  75.      * <p>This should be used when the state is no longer valid, for example after a jump
  76.      * performed for the {@link org.apache.commons.rng.JumpableUniformRandomProvider
  77.      * JumpableUniformRandomProvider} interface.</p>
  78.      *
  79.      * @since 1.3
  80.      */
  81.     protected void resetCachedState() {
  82.         booleanSource = EMPTY_BOOL_SOURCE;
  83.         intSource = EMPTY_INT_SOURCE;
  84.     }

  85.     /** {@inheritDoc} */
  86.     @Override
  87.     protected byte[] getStateInternal() {
  88.         final long[] state = {booleanSource, intSource};
  89.         return composeStateInternal(NumberFactory.makeByteArray(state),
  90.                                     super.getStateInternal());
  91.     }

  92.     /** {@inheritDoc} */
  93.     @Override
  94.     protected void setStateInternal(byte[] s) {
  95.         final byte[][] c = splitStateInternal(s, 2 * Long.BYTES);
  96.         final long[] state = NumberFactory.makeLongArray(c[0]);
  97.         booleanSource   = state[0];
  98.         intSource       = state[1];
  99.         super.setStateInternal(c[1]);
  100.     }

  101.     /** {@inheritDoc} */
  102.     @Override
  103.     public long nextLong() {
  104.         return next();
  105.     }

  106.     /** {@inheritDoc} */
  107.     @Override
  108.     public int nextInt() {
  109.         long bits = intSource;
  110.         if (bits < 0) {
  111.             // Refill
  112.             bits = next();
  113.             // Store high 32 bits, return low 32 bits
  114.             intSource = bits >>> 32;
  115.             return (int) bits;
  116.         }
  117.         // Reset and return previous low bits
  118.         intSource = -1;
  119.         return (int) bits;
  120.     }

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public boolean nextBoolean() {
  124.         long bits = booleanSource;
  125.         if (bits == 1) {
  126.             // Refill
  127.             bits = next();
  128.             // Store a refill flag in the sign bit and the unused 63 bits, return lowest bit
  129.             booleanSource = Long.MIN_VALUE | (bits >>> 1);
  130.             return (bits & 0x1) == 1;
  131.         }
  132.         // Shift down eventually triggering refill, return current lowest bit
  133.         booleanSource = bits >>> 1;
  134.         return (bits & 0x1) == 1;
  135.     }
  136. }