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 /** {@inheritDoc} */ 032 @Override 033 public long nextLong() { 034 return next(); 035 } 036 037 /** {@inheritDoc} */ 038 @Override 039 public int nextInt() { 040 return NumberFactory.makeInt(nextLong()); 041 } 042 043 /** {@inheritDoc} */ 044 @Override 045 public double nextDouble() { 046 return NumberFactory.makeDouble(nextLong()); 047 } 048 049 /** {@inheritDoc} */ 050 @Override 051 public boolean nextBoolean() { 052 return NumberFactory.makeBoolean(nextLong()); 053 } 054 055 /** {@inheritDoc} */ 056 @Override 057 public float nextFloat() { 058 return NumberFactory.makeFloat(nextInt()); 059 } 060 061 /** {@inheritDoc} */ 062 @Override 063 public void nextBytes(byte[] bytes) { 064 nextBytesFill(this, bytes, 0, bytes.length); 065 } 066 067 /** {@inheritDoc} */ 068 @Override 069 public void nextBytes(byte[] bytes, 070 int start, 071 int len) { 072 checkIndex(0, bytes.length - 1, start); 073 checkIndex(0, bytes.length - start, len); 074 075 nextBytesFill(this, bytes, start, len); 076 } 077 078 /** 079 * Generates random bytes and places them into a user-supplied array. 080 * 081 * <p> 082 * The array is filled with bytes extracted from random {@code long} values. 083 * This implies that the number of random bytes generated may be larger than 084 * the length of the byte array. 085 * </p> 086 * 087 * @param source Source of randomness. 088 * @param bytes Array in which to put the generated bytes. Cannot be null. 089 * @param start Index at which to start inserting the generated bytes. 090 * @param len Number of bytes to insert. 091 */ 092 static void nextBytesFill(RandomLongSource source, 093 byte[] bytes, 094 int start, 095 int len) { 096 int index = start; // Index of first insertion. 097 098 // Index of first insertion plus multiple of 8 part of length 099 // (i.e. length with 3 least significant bits unset). 100 final int indexLoopLimit = index + (len & 0x7ffffff8); 101 102 // Start filling in the byte array, 8 bytes at a time. 103 while (index < indexLoopLimit) { 104 final long random = source.next(); 105 bytes[index++] = (byte) random; 106 bytes[index++] = (byte) (random >>> 8); 107 bytes[index++] = (byte) (random >>> 16); 108 bytes[index++] = (byte) (random >>> 24); 109 bytes[index++] = (byte) (random >>> 32); 110 bytes[index++] = (byte) (random >>> 40); 111 bytes[index++] = (byte) (random >>> 48); 112 bytes[index++] = (byte) (random >>> 56); 113 } 114 115 final int indexLimit = start + len; // Index of last insertion + 1. 116 117 // Fill in the remaining bytes. 118 if (index < indexLimit) { 119 long random = source.next(); 120 while (true) { 121 bytes[index++] = (byte) random; 122 if (index < indexLimit) { 123 random >>>= 8; 124 } else { 125 break; 126 } 127 } 128 } 129 } 130}