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 }