View Javadoc
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 }