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.JumpableUniformRandomProvider; 21 import org.apache.commons.rng.UniformRandomProvider; 22 import org.apache.commons.rng.core.util.NumberFactory; 23 24 /** 25 * This abstract class is a base for algorithms from the LXM family of 26 * generators with a 64-bit LCG and 128-bit XBG sub-generator. The class implements 27 * the state save/restore functions. 28 * 29 * @since 1.5 30 */ 31 abstract class AbstractL64X128 extends AbstractL64 { 32 /** LCG multiplier. */ 33 protected static final long M = LXMSupport.M64; 34 /** Size of the seed vector. */ 35 private static final int SEED_SIZE = 4; 36 /** Size of the XBG state vector. */ 37 private static final int XBG_STATE_SIZE = 2; 38 39 /** State 0 of the XBG. */ 40 protected long x0; 41 /** State 1 of the XBG. */ 42 protected long x1; 43 44 /** 45 * Creates a new instance. 46 * 47 * @param seed Initial seed. 48 * If the length is larger than 4, only the first 4 elements will 49 * be used; if smaller, the remaining elements will be automatically 50 * set. A seed containing all zeros in the last two elements 51 * will create a non-functional XBG sub-generator and a low 52 * quality output with a period of 2<sup>64</sup>. 53 * 54 * <p>The 1st element is used to set the LCG increment; the least significant bit 55 * is set to odd to ensure a full period LCG. The 2nd element is used 56 * to set the LCG state.</p> 57 */ 58 AbstractL64X128(long[] seed) { 59 super(seed = extendSeed(seed, SEED_SIZE)); 60 x0 = seed[2]; 61 x1 = seed[3]; 62 } 63 64 /** 65 * Creates a new instance using a 4 element seed. 66 * A seed containing all zeros in the last two elements 67 * will create a non-functional XBG sub-generator and a low 68 * quality output with a period of 2<sup>64</sup>. 69 * 70 * <p>The 1st element is used to set the LCG increment; the least significant bit 71 * is set to odd to ensure a full period LCG. The 2nd element is used 72 * to set the LCG state.</p> 73 * 74 * @param seed0 Initial seed element 0. 75 * @param seed1 Initial seed element 1. 76 * @param seed2 Initial seed element 2. 77 * @param seed3 Initial seed element 3. 78 */ 79 AbstractL64X128(long seed0, long seed1, long seed2, long seed3) { 80 super(seed0, seed1); 81 x0 = seed2; 82 x1 = seed3; 83 } 84 85 /** 86 * Creates a copy instance. 87 * 88 * @param source Source to copy. 89 */ 90 AbstractL64X128(AbstractL64X128 source) { 91 super(source); 92 x0 = source.x0; 93 x1 = source.x1; 94 } 95 96 /** {@inheritDoc} */ 97 @Override 98 protected byte[] getStateInternal() { 99 return composeStateInternal(NumberFactory.makeByteArray( 100 new long[] {x0, x1}), 101 super.getStateInternal()); 102 } 103 104 /** {@inheritDoc} */ 105 @Override 106 protected void setStateInternal(byte[] s) { 107 final byte[][] c = splitStateInternal(s, XBG_STATE_SIZE * Long.BYTES); 108 final long[] tmp = NumberFactory.makeLongArray(c[0]); 109 x0 = tmp[0]; 110 x1 = tmp[1]; 111 super.setStateInternal(c[1]); 112 } 113 114 /** 115 * {@inheritDoc} 116 * 117 * <p>The jump size is the equivalent of moving the state <em>backwards</em> by 118 * (2<sup>128</sup> - 1) positions. It can provide up to 2<sup>64</sup> 119 * non-overlapping subsequences. 120 */ 121 @Override 122 public UniformRandomProvider jump() { 123 return super.jump(); 124 } 125 126 /** 127 * {@inheritDoc} 128 * 129 * <p>The jump size is the equivalent of moving the state <em>backwards</em> by 130 * 2<sup>32</sup> (2<sup>128</sup> - 1) positions. It can provide up to 131 * 2<sup>32</sup> non-overlapping subsequences of length 2<sup>32</sup> 132 * (2<sup>128</sup> - 1); each subsequence can provide up to 2<sup>32</sup> 133 * non-overlapping subsequences of length (2<sup>128</sup> - 1) using the 134 * {@link #jump()} method. 135 */ 136 @Override 137 public JumpableUniformRandomProvider longJump() { 138 return super.longJump(); 139 } 140 }