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 */ 017package org.apache.commons.rng.core.source64; 018 019import org.apache.commons.rng.core.util.NumberFactory; 020 021/** 022 * Implement the Small, Fast, Counting (SFC) 64-bit generator of Chris Doty-Humphrey. 023 * The original source is the PractRand test suite by the same author. 024 * 025 * <p>The state size is 256-bits; the period is a minimum of 2<sup>64</sup> and an 026 * average of approximately 2<sup>255</sup>.</p> 027 * 028 * @see <a href="http://pracrand.sourceforge.net/">PractRand</a> 029 * @since 1.3 030 */ 031public class DotyHumphreySmallFastCounting64 extends LongProvider { 032 /** Size of the seed. */ 033 private static final int SEED_SIZE = 3; 034 035 /** State a. */ 036 private long a; 037 /** State b. */ 038 private long b; 039 /** State c. */ 040 private long c; 041 /** Counter. */ 042 private long counter; 043 044 /** 045 * Creates an instance with the given seed. 046 * 047 * @param seed Initial seed. 048 * If the length is larger than 3, only the first 3 elements will 049 * be used; if smaller, the remaining elements will be automatically set. 050 */ 051 public DotyHumphreySmallFastCounting64(long[] seed) { 052 if (seed.length < SEED_SIZE) { 053 final long[] state = new long[SEED_SIZE]; 054 fillState(state, seed); 055 setSeedInternal(state); 056 } else { 057 setSeedInternal(seed); 058 } 059 } 060 061 /** 062 * Seeds the RNG. 063 * 064 * @param seed Seed. 065 */ 066 private void setSeedInternal(long[] seed) { 067 a = seed[0]; 068 b = seed[1]; 069 c = seed[2]; 070 counter = 1L; 071 for (int i = 0; i < 18; i++) { 072 next(); 073 } 074 } 075 076 /** {@inheritDoc} */ 077 @Override 078 public final long next() { 079 final long tmp = a + b + counter++; 080 a = b ^ (b >>> 11); 081 b = c + (c << 3); 082 c = Long.rotateLeft(c, 24) + tmp; 083 return tmp; 084 } 085 086 /** {@inheritDoc} */ 087 @Override 088 protected byte[] getStateInternal() { 089 return composeStateInternal(NumberFactory.makeByteArray(new long[] {a, b, c, counter}), 090 super.getStateInternal()); 091 } 092 093 /** {@inheritDoc} */ 094 @Override 095 protected void setStateInternal(byte[] s) { 096 final byte[][] parts = splitStateInternal(s, 4 * 8); 097 098 final long[] tmp = NumberFactory.makeLongArray(parts[0]); 099 a = tmp[0]; 100 b = tmp[1]; 101 c = tmp[2]; 102 counter = tmp[3]; 103 104 super.setStateInternal(parts[1]); 105 } 106}