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.math4.random; 018 019import java.io.Serializable; 020import java.io.IOException; 021import java.io.ObjectOutputStream; 022import java.io.ObjectInputStream; 023import org.apache.commons.math4.util.FastMath; 024import org.apache.commons.rng.RestorableUniformRandomProvider; 025import org.apache.commons.rng.simple.RandomSource; 026import org.apache.commons.rng.core.RandomProviderDefaultState; 027 028/** 029 * Adaptor that delegates to a 030 * {@link org.apache.commons.rng.UniformRandomProvider} instance. 031 * <p> 032 * It is provided for users who wish to test the new RNG implementations 033 * the <i>current</i> generators (up to version 3.6 of Commons Math) in 034 * codes that require the {@code RandomGenerator} interface. 035 * </p> 036 * <p> 037 * Applications should upgrade to use the new generators ASAP. 038 * If problems are found that jeopardize the upgrade, please report them 039 * on the project's 040 * <a href="https://issues.apache.org/jira/browse/MATH"> 041 * issue tracking system</a>. 042 * </p> 043 * 044 * <p> 045 * <b>Notes:</b> 046 * <ul> 047 * <li> 048 * The 049 * {@link RandomGenerator#setSeed(int) setSeed(int)}, 050 * {@link RandomGenerator#setSeed(int[]) setSeed(int[])} and 051 * {@link RandomGenerator#setSeed(long) setSeed(long)} 052 * methods of the {@link RandomGenerator} are not part of the 053 * {@link org.apache.commons.rng.UniformRandomProvider new API}. 054 * </li> 055 * <li> 056 * The new RNG implementations are not {@code Serializable}. 057 * Use {@link RestorableUniformRandomProvider#saveState()} 058 * instead. 059 * </li> 060 * <li> 061 * {@link RandomGenerator#nextGaussian() nextGaussian()} is not 062 * part of the {@link org.apache.commons.rng.UniformRandomProvider 063 * new API} as it defines a "post-processing" of the output of a 064 * <i>uniform</i> RNG in order to follow a different distribution. 065 * </li> 066 * </ul> 067 * 068 * @since 4.0 069 * 070 * @deprecated As of 4.0. This class is made available for testing 071 * the {@link RandomSource new RNG implementations} in existing 072 * applications. 073 * It will be removed in the next major release. 074 */ 075@Deprecated 076public final class RngAdaptor 077 implements RandomGenerator, 078 Serializable { 079 /** Serializable version identifier. */ 080 private static final long serialVersionUID = 12345L; 081 /** Source. */ 082 private final RandomSource source; 083 /** Delegate. */ 084 private transient RestorableUniformRandomProvider delegate; 085 /** Next gaussian. */ 086 private double nextGaussian = Double.NaN; 087 088 /** 089 * Creates a new instance. 090 * 091 * @param source Source of randomness. 092 */ 093 public RngAdaptor(RandomSource source) { 094 this(source, null); 095 } 096 097 /** 098 * Creates a new instance. 099 * 100 * @param source Source of randomness. 101 * @param seed Seed. Can be {@code null}. 102 */ 103 public RngAdaptor(RandomSource source, 104 Object seed) { 105 this.source = source; 106 delegate = RandomSource.create(source, seed); 107 } 108 109 /** {@inheritDoc} */ 110 @Override 111 public void setSeed(int seed) { 112 delegate = RandomSource.create(source, seed); 113 clear(); 114 } 115 116 /** {@inheritDoc} */ 117 @Override 118 public void setSeed(int[] seed) { 119 delegate = RandomSource.create(source, seed); 120 clear(); 121 } 122 123 /** {@inheritDoc} */ 124 @Override 125 public void setSeed(long seed) { 126 delegate = RandomSource.create(source, seed); 127 clear(); 128 } 129 130 /** {@inheritDoc} */ 131 @Override 132 public boolean nextBoolean() { 133 return delegate.nextBoolean(); 134 } 135 136 /** {@inheritDoc} */ 137 @Override 138 public void nextBytes(byte[] bytes) { 139 delegate.nextBytes(bytes); 140 } 141 142 /** {@inheritDoc} */ 143 @Override 144 public double nextDouble() { 145 return delegate.nextDouble(); 146 } 147 148 /** {@inheritDoc} */ 149 @Override 150 public float nextFloat() { 151 return delegate.nextFloat(); 152 } 153 154 /** {@inheritDoc} */ 155 @Override 156 public double nextGaussian() { 157 final double random; 158 if (Double.isNaN(nextGaussian)) { 159 // generate a new pair of gaussian numbers 160 final double x = nextDouble(); 161 final double y = nextDouble(); 162 final double alpha = 2 * FastMath.PI * x; 163 final double r = FastMath.sqrt(-2 * FastMath.log(y)); 164 random = r * FastMath.cos(alpha); 165 nextGaussian = r * FastMath.sin(alpha); 166 } else { 167 // use the second element of the pair already generated 168 random = nextGaussian; 169 nextGaussian = Double.NaN; 170 } 171 172 return random; 173 } 174 175 /** {@inheritDoc} */ 176 @Override 177 public int nextInt() { 178 return delegate.nextInt(); 179 } 180 181 /** {@inheritDoc} */ 182 @Override 183 public int nextInt(int n) { 184 return delegate.nextInt(n); 185 } 186 187 /** {@inheritDoc} */ 188 @Override 189 public long nextLong() { 190 return delegate.nextLong(); 191 } 192 193 /** 194 * Clears the cache used by the default implementation of 195 * {@link #nextGaussian}. 196 */ 197 private void clear() { 198 nextGaussian = Double.NaN; 199 } 200 201 /** 202 * @param out Output stream. 203 * @throws IOException if an error occurs. 204 */ 205 private void writeObject(ObjectOutputStream out) 206 throws IOException { 207 // Write non-transient fields. 208 out.defaultWriteObject(); 209 210 // Save current state. 211 out.writeObject(((RandomProviderDefaultState) delegate.saveState()).getState()); 212 } 213 214 /** 215 * @param in Input stream. 216 * @throws IOException if an error occurs. 217 * @throws ClassNotFoundException if an error occurs. 218 */ 219 private void readObject(ObjectInputStream in) 220 throws IOException, 221 ClassNotFoundException { 222 // Read non-transient fields. 223 in.defaultReadObject(); 224 225 // Recreate the "delegate" from serialized info. 226 delegate = RandomSource.create(source); 227 // And restore its state. 228 final RandomProviderDefaultState state = new RandomProviderDefaultState((byte[]) in.readObject()); 229 delegate.restoreState(state); 230 } 231}