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 package org.apache.commons.rng.simple.internal;
18
19 import org.apache.commons.rng.core.util.NumberFactory;
20
21 /**
22 * The native seed type. Contains values for all native seed types and methods
23 * to convert supported seed types to the native seed type.
24 *
25 * <p>Valid native seed types are:</p>
26 * <ul>
27 * <li>{@code Integer}</li>
28 * <li>{@code Long}</li>
29 * <li>{@code int[]}</li>
30 * <li>{@code long[]}</li>
31 * </ul>
32 *
33 * <p>Valid types for seed conversion are:</p>
34 * <ul>
35 * <li>{@code Integer} (or {@code int})</li>
36 * <li>{@code Long} (or {@code long})</li>
37 * <li>{@code int[]}</li>
38 * <li>{@code long[]}</li>
39 * <li>{@code byte[]}</li>
40 * </ul>
41 *
42 * @since 1.3
43 */
44 public enum NativeSeedType {
45 /** The seed type is {@code Integer}. */
46 INT(Integer.class, 4) {
47 @Override
48 public Integer createSeed(int size) {
49 return SeedFactory.createInt();
50 }
51 @Override
52 protected Integer convert(Integer seed, int size) {
53 return seed;
54 }
55 @Override
56 protected Integer convert(Long seed, int size) {
57 return LONG_TO_INT.convert(seed);
58 }
59 @Override
60 protected Integer convert(int[] seed, int size) {
61 return INT_ARRAY_TO_INT.convert(seed);
62 }
63 @Override
64 protected Integer convert(long[] seed, int size) {
65 return LONG_TO_INT.convert(LONG_ARRAY_TO_LONG.convert(seed));
66 }
67 @Override
68 protected Integer convert(byte[] seed, int size) {
69 return INT_ARRAY_TO_INT.convert(BYTE_ARRAY_TO_INT_ARRAY.convert(seed));
70 }
71 },
72 /** The seed type is {@code Long}. */
73 LONG(Long.class, 8) {
74 @Override
75 public Long createSeed(int size) {
76 return SeedFactory.createLong();
77 }
78 @Override
79 protected Long convert(Integer seed, int size) {
80 return INT_TO_LONG.convert(seed);
81 }
82 @Override
83 protected Long convert(Long seed, int size) {
84 return seed;
85 }
86 @Override
87 protected Long convert(int[] seed, int size) {
88 return INT_TO_LONG.convert(INT_ARRAY_TO_INT.convert(seed));
89 }
90 @Override
91 protected Long convert(long[] seed, int size) {
92 return LONG_ARRAY_TO_LONG.convert(seed);
93 }
94 @Override
95 protected Long convert(byte[] seed, int size) {
96 return LONG_ARRAY_TO_LONG.convert(BYTE_ARRAY_TO_LONG_ARRAY.convert(seed));
97 }
98 },
99 /** The seed type is {@code int[]}. */
100 INT_ARRAY(int[].class, 4) {
101 @Override
102 public int[] createSeed(int size) {
103 // Limit the number of calls to the synchronized method. The generator
104 // will support self-seeding.
105 return SeedFactory.createIntArray(Math.min(size, RANDOM_SEED_ARRAY_SIZE));
106 }
107 @Override
108 protected int[] convert(Integer seed, int size) {
109 return LONG_TO_INT_ARRAY.convert(INT_TO_LONG.convert(seed), size);
110 }
111 @Override
112 protected int[] convert(Long seed, int size) {
113 return LONG_TO_INT_ARRAY.convert(seed, size);
114 }
115 @Override
116 protected int[] convert(int[] seed, int size) {
117 return seed;
118 }
119 @Override
120 protected int[] convert(long[] seed, int size) {
121 return LONG_ARRAY_TO_INT_ARRAY.convert(seed);
122 }
123 @Override
124 protected int[] convert(byte[] seed, int size) {
125 return BYTE_ARRAY_TO_INT_ARRAY.convert(seed);
126 }
127 },
128 /** The seed type is {@code long[]}. */
129 LONG_ARRAY(long[].class, 8) {
130 @Override
131 public long[] createSeed(int size) {
132 // Limit the number of calls to the synchronized method. The generator
133 // will support self-seeding.
134 return SeedFactory.createLongArray(Math.min(size, RANDOM_SEED_ARRAY_SIZE));
135 }
136 @Override
137 protected long[] convert(Integer seed, int size) {
138 return LONG_TO_LONG_ARRAY.convert(INT_TO_LONG.convert(seed), size);
139 }
140 @Override
141 protected long[] convert(Long seed, int size) {
142 return LONG_TO_LONG_ARRAY.convert(seed, size);
143 }
144 @Override
145 protected long[] convert(int[] seed, int size) {
146 return INT_ARRAY_TO_LONG_ARRAY.convert(seed);
147 }
148 @Override
149 protected long[] convert(long[] seed, int size) {
150 return seed;
151 }
152 @Override
153 protected long[] convert(byte[] seed, int size) {
154 return BYTE_ARRAY_TO_LONG_ARRAY.convert(seed);
155 }
156 };
157
158 /** Error message for unrecognised seed types. */
159 private static final String UNRECOGNISED_SEED = "Unrecognized seed type: ";
160 /** Maximum length of the seed array (for creating array seeds). */
161 private static final int RANDOM_SEED_ARRAY_SIZE = 128;
162 /** Convert {@code Long} to {@code Integer}. */
163 private static final Long2Int LONG_TO_INT = new Long2Int();
164 /** Convert {@code Integer} to {@code Long}. */
165 private static final Int2Long INT_TO_LONG = new Int2Long();
166 /** Convert {@code Long} to {@code int[]}. */
167 private static final Long2IntArray LONG_TO_INT_ARRAY = new Long2IntArray(0);
168 /** Convert {@code Long} to {@code long[]}. */
169 private static final Long2LongArray LONG_TO_LONG_ARRAY = new Long2LongArray(0);
170 /** Convert {@code long[]} to {@code Long}. */
171 private static final LongArray2Long LONG_ARRAY_TO_LONG = new LongArray2Long();
172 /** Convert {@code int[]} to {@code Integer}. */
173 private static final IntArray2Int INT_ARRAY_TO_INT = new IntArray2Int();
174 /** Convert {@code long[]} to {@code int[]}. */
175 private static final LongArray2IntArray LONG_ARRAY_TO_INT_ARRAY = new LongArray2IntArray();
176 /** Convert {@code Long} to {@code long[]}. */
177 private static final IntArray2LongArray INT_ARRAY_TO_LONG_ARRAY = new IntArray2LongArray();
178 /** Convert {@code byte[]} to {@code int[]}. */
179 private static final ByteArray2IntArray BYTE_ARRAY_TO_INT_ARRAY = new ByteArray2IntArray();
180 /** Convert {@code byte[]} to {@code long[]}. */
181 private static final ByteArray2LongArray BYTE_ARRAY_TO_LONG_ARRAY = new ByteArray2LongArray();
182
183 /** Define the class type of the native seed. */
184 private final Class<?> type;
185
186 /**
187 * Define the number of bytes required to represent the native seed. If the type is
188 * an array then this represents the size of a single value of the type.
189 */
190 private final int bytes;
191
192 /**
193 * Instantiates a new native seed type.
194 *
195 * @param type Define the class type of the native seed.
196 * @param bytes Define the number of bytes required to represent the native seed.
197 */
198 NativeSeedType(Class<?> type, int bytes) {
199 this.type = type;
200 this.bytes = bytes;
201 }
202
203 /**
204 * Gets the class type of the native seed.
205 *
206 * @return the type
207 */
208 public Class<?> getType() {
209 return type;
210 }
211
212 /**
213 * Gets the number of bytes required to represent the native seed type. If the type is
214 * an array then this represents the size of a single value of the type.
215 *
216 * @return the number of bytes
217 */
218 public int getBytes() {
219 return bytes;
220 }
221
222 /**
223 * Creates the seed. The output seed type is determined by the native seed type. If the
224 * output is an array the required size of the array can be specified.
225 *
226 * @param size The size of the seed (array types only).
227 * @return the seed
228 */
229 public abstract Object createSeed(int size);
230
231 /**
232 * Converts the input seed from any of the supported seed types to the native seed type.
233 * If the output is an array the required size of the array can be specified.
234 *
235 * @param seed Input seed.
236 * @param size The size of the output seed (array types only).
237 * @return the native seed.
238 * @throws UnsupportedOperationException if the {@code seed} type is invalid.
239 */
240 public Object convertSeed(Object seed,
241 int size) {
242 // Convert to native type.
243 // Each method must be overridden by specific implementations.
244
245 if (seed instanceof Integer) {
246 return convert((Integer) seed, size);
247 } else if (seed instanceof Long) {
248 return convert((Long) seed, size);
249 } else if (seed instanceof int[]) {
250 return convert((int[]) seed, size);
251 } else if (seed instanceof long[]) {
252 return convert((long[]) seed, size);
253 } else if (seed instanceof byte[]) {
254 return convert((byte[]) seed, size);
255 }
256
257 throw new UnsupportedOperationException(UNRECOGNISED_SEED + seed);
258 }
259
260 /**
261 * Convert the input {@code Integer} seed to the native seed type.
262 *
263 * @param seed Input seed.
264 * @param size The size of the output seed (array types only).
265 * @return the native seed.
266 */
267 protected abstract Object convert(Integer seed, int size);
268
269 /**
270 * Convert the input {@code Long} seed to the native seed type.
271 *
272 * @param seed Input seed.
273 * @param size The size of the output seed (array types only).
274 * @return the native seed.
275 */
276 protected abstract Object convert(Long seed, int size);
277
278 /**
279 * Convert the input {@code int[]} seed to the native seed type.
280 *
281 * @param seed Input seed.
282 * @param size The size of the output seed (array types only).
283 * @return the native seed.
284 */
285 protected abstract Object convert(int[] seed, int size);
286
287 /**
288 * Convert the input {@code long[]} seed to the native seed type.
289 *
290 * @param seed Input seed.
291 * @param size The size of the output seed (array types only).
292 * @return the native seed.
293 */
294 protected abstract Object convert(long[] seed, int size);
295
296 /**
297 * Convert the input {@code byte[]} seed to the native seed type.
298 *
299 * @param seed Input seed.
300 * @param size The size of the output seed (array types only).
301 * @return the native seed.
302 */
303 protected abstract Object convert(byte[] seed, int size);
304
305 /**
306 * Converts the input seed from any of the supported seed types to bytes.
307 *
308 * @param seed Input seed.
309 * @return the seed bytes.
310 * @throws UnsupportedOperationException if the {@code seed} type is invalid.
311 */
312 public static byte[] convertSeedToBytes(Object seed) {
313 if (seed instanceof Integer) {
314 return NumberFactory.makeByteArray((Integer) seed);
315 } else if (seed instanceof Long) {
316 return NumberFactory.makeByteArray((Long) seed);
317 } else if (seed instanceof int[]) {
318 return NumberFactory.makeByteArray((int[]) seed);
319 } else if (seed instanceof long[]) {
320 return NumberFactory.makeByteArray((long[]) seed);
321 } else if (seed instanceof byte[]) {
322 return (byte[]) seed;
323 }
324
325 throw new UnsupportedOperationException(UNRECOGNISED_SEED + seed);
326 }
327 }