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.util; 018 019/** 020 * Utility for creating number types from one or two {@code int} values 021 * or one {@code long} value, or a sequence of bytes. 022 */ 023public final class NumberFactory { 024 /** 025 * The multiplier to convert the least significant 24-bits of an {@code int} to a {@code float}. 026 * See {@link #makeFloat(int)}. 027 * 028 * <p>This is equivalent to 1.0f / (1 << 24). 029 */ 030 private static final float FLOAT_MULTIPLIER = 0x1.0p-24f; 031 /** 032 * The multiplier to convert the least significant 53-bits of a {@code long} to a {@code double}. 033 * See {@link #makeDouble(long)} and {@link #makeDouble(int, int)}. 034 * 035 * <p>This is equivalent to 1.0 / (1L << 53). 036 */ 037 private static final double DOUBLE_MULTIPLIER = 0x1.0p-53d; 038 /** Lowest byte mask. */ 039 private static final long LONG_LOWEST_BYTE_MASK = 0xffL; 040 /** Number of bytes in a {@code long}. */ 041 private static final int LONG_SIZE = 8; 042 /** Lowest byte mask. */ 043 private static final int INT_LOWEST_BYTE_MASK = 0xff; 044 /** Number of bytes in a {@code int}. */ 045 private static final int INT_SIZE = 4; 046 047 /** 048 * Class contains only static methods. 049 */ 050 private NumberFactory() {} 051 052 /** 053 * Creates a {@code boolean} from an {@code int} value. 054 * 055 * @param v Number. 056 * @return a boolean. 057 * 058 * @deprecated Since version 1.2. Method has become obsolete following 059 * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>. 060 */ 061 @Deprecated 062 public static boolean makeBoolean(int v) { 063 return v < 0; 064 } 065 066 /** 067 * Creates a {@code boolean} from a {@code long} value. 068 * 069 * @param v Number. 070 * @return a boolean. 071 * 072 * @deprecated Since version 1.2. Method has become obsolete following 073 * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>. 074 */ 075 @Deprecated 076 public static boolean makeBoolean(long v) { 077 return v < 0; 078 } 079 080 /** 081 * Creates a {@code double} from a {@code long} value. 082 * 083 * @param v Number. 084 * @return a {@code double} value in the interval {@code [0, 1]}. 085 */ 086 public static double makeDouble(long v) { 087 // Require the least significant 53-bits so shift the higher bits across 088 return (v >>> 11) * DOUBLE_MULTIPLIER; 089 } 090 091 /** 092 * Creates a {@code double} from two {@code int} values. 093 * 094 * @param v Number (high order bits). 095 * @param w Number (low order bits). 096 * @return a {@code double} value in the interval {@code [0, 1]}. 097 */ 098 public static double makeDouble(int v, 099 int w) { 100 // Require the least significant 53-bits from a long. 101 // Join the most significant 26 from v with 27 from w. 102 final long high = ((long) (v >>> 6)) << 27; // 26-bits remain 103 final int low = w >>> 5; // 27-bits remain 104 return (high | low) * DOUBLE_MULTIPLIER; 105 } 106 107 /** 108 * Creates a {@code float} from an {@code int} value. 109 * 110 * @param v Number. 111 * @return a {@code float} value in the interval {@code [0, 1]}. 112 */ 113 public static float makeFloat(int v) { 114 // Require the least significant 24-bits so shift the higher bits across 115 return (v >>> 8) * FLOAT_MULTIPLIER; 116 } 117 118 /** 119 * Creates a {@code long} from two {@code int} values. 120 * 121 * @param v Number (high order bits). 122 * @param w Number (low order bits). 123 * @return a {@code long} value. 124 */ 125 public static long makeLong(int v, 126 int w) { 127 return (((long) v) << 32) | (w & 0xffffffffL); 128 } 129 130 /** 131 * Creates an {@code int} from a {@code long}. 132 * 133 * @param v Number. 134 * @return an {@code int} value made from the "xor" of the 135 * {@link #extractHi(long) high order bits} and 136 * {@link #extractLo(long) low order bits} of {@code v}. 137 * 138 * @deprecated Since version 1.2. Method has become obsolete following 139 * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>. 140 */ 141 @Deprecated 142 public static int makeInt(long v) { 143 return extractHi(v) ^ extractLo(v); 144 } 145 146 /** 147 * Creates an {@code int} from a {@code long}, using the high order bits. 148 * 149 * <p>The returned value is such that if</p> 150 * <pre><code> 151 * vL = extractLo(v); 152 * vH = extractHi(v); 153 * </code></pre> 154 * 155 * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p> 156 * 157 * @param v Number. 158 * @return an {@code int} value made from the most significant bits 159 * of {@code v}. 160 */ 161 public static int extractHi(long v) { 162 return (int) (v >>> 32); 163 } 164 165 /** 166 * Creates an {@code int} from a {@code long}, using the low order bits. 167 * 168 * <p>The returned value is such that if</p> 169 * 170 * <pre><code> 171 * vL = extractLo(v); 172 * vH = extractHi(v); 173 * </code></pre> 174 * 175 * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p> 176 * 177 * @param v Number. 178 * @return an {@code int} value made from the least significant bits 179 * of {@code v}. 180 */ 181 public static int extractLo(long v) { 182 return (int) v; 183 } 184 185 /** 186 * Splits a {@code long} into 8 bytes. 187 * 188 * @param v Value. 189 * @return the bytes that compose the given value (least-significant 190 * byte first). 191 */ 192 public static byte[] makeByteArray(long v) { 193 final byte[] b = new byte[LONG_SIZE]; 194 putLong(v, b, 0); 195 return b; 196 } 197 198 /** 199 * Puts the {@code long} into the buffer starting at the given position. 200 * Adds 8 bytes (least-significant first). 201 * 202 * @param v Value. 203 * @param buffer the buffer. 204 * @param index the index. 205 */ 206 private static void putLong(long v, 207 byte[] buffer, 208 int index) { 209 buffer[index ] = (byte) (v & LONG_LOWEST_BYTE_MASK); 210 buffer[index + 1] = (byte)((v >>> 8) & LONG_LOWEST_BYTE_MASK); 211 buffer[index + 2] = (byte)((v >>> 16) & LONG_LOWEST_BYTE_MASK); 212 buffer[index + 3] = (byte)((v >>> 24) & LONG_LOWEST_BYTE_MASK); 213 buffer[index + 4] = (byte)((v >>> 32) & LONG_LOWEST_BYTE_MASK); 214 buffer[index + 5] = (byte)((v >>> 40) & LONG_LOWEST_BYTE_MASK); 215 buffer[index + 6] = (byte)((v >>> 48) & LONG_LOWEST_BYTE_MASK); 216 buffer[index + 7] = (byte) (v >>> 56); 217 } 218 219 /** 220 * Creates a {@code long} from 8 bytes. 221 * 222 * @param input Input. 223 * @return the value that correspond to the given bytes assuming 224 * that the order is in increasing byte significance (i.e. the 225 * first byte in the array is the least-significant). 226 * @throws IllegalArgumentException if {@code input.length != 8}. 227 */ 228 public static long makeLong(byte[] input) { 229 checkSize(LONG_SIZE, input.length); 230 return getLong(input, 0); 231 } 232 233 /** 234 * Gets the {@code long} from the buffer starting at the given position. 235 * Uses 8 bytes (least-significant first). 236 * 237 * @param input the input bytes. 238 * @param index the index. 239 * @return the value that correspond to the given bytes assuming 240 * that the order is in increasing byte significance (i.e. the 241 * first byte in the array is the least-significant). 242 */ 243 private static long getLong(byte[] input, 244 int index) { 245 return (input[index ] & LONG_LOWEST_BYTE_MASK) | 246 (input[index + 1] & LONG_LOWEST_BYTE_MASK) << 8 | 247 (input[index + 2] & LONG_LOWEST_BYTE_MASK) << 16 | 248 (input[index + 3] & LONG_LOWEST_BYTE_MASK) << 24 | 249 (input[index + 4] & LONG_LOWEST_BYTE_MASK) << 32 | 250 (input[index + 5] & LONG_LOWEST_BYTE_MASK) << 40 | 251 (input[index + 6] & LONG_LOWEST_BYTE_MASK) << 48 | 252 (input[index + 7] & LONG_LOWEST_BYTE_MASK) << 56; 253 } 254 255 /** 256 * Splits an array of {@code long} values into a sequence of bytes. 257 * This method calls {@link #makeByteArray(long)} for each element of 258 * the {@code input}. 259 * 260 * @param input Input. 261 * @return an array of bytes. 262 */ 263 public static byte[] makeByteArray(long[] input) { 264 final int size = input.length * LONG_SIZE; 265 final byte[] b = new byte[size]; 266 267 for (int i = 0; i < input.length; i++) { 268 putLong(input[i], b, i * LONG_SIZE); 269 } 270 271 return b; 272 } 273 274 /** 275 * Creates an array of {@code long} values from a sequence of bytes. 276 * This method calls {@link #makeLong(byte[])} for each subsequence 277 * of 8 bytes. 278 * 279 * @param input Input. 280 * @return an array of {@code long}. 281 * @throws IllegalArgumentException if {@code input.length} is not 282 * a multiple of 8. 283 */ 284 public static long[] makeLongArray(byte[] input) { 285 final int size = input.length; 286 final int num = size / LONG_SIZE; 287 checkSize(num * LONG_SIZE, size); 288 289 final long[] output = new long[num]; 290 for (int i = 0; i < num; i++) { 291 output[i] = getLong(input, i * LONG_SIZE); 292 } 293 294 return output; 295 } 296 297 /** 298 * Splits an {@code int} into 4 bytes. 299 * 300 * @param v Value. 301 * @return the bytes that compose the given value (least-significant 302 * byte first). 303 */ 304 public static byte[] makeByteArray(int v) { 305 final byte[] b = new byte[INT_SIZE]; 306 putInt(v, b, 0); 307 return b; 308 } 309 310 /** 311 * Puts the {@code int} into the buffer starting at the given position. 312 * Adds 4 bytes (least-significant first). 313 * 314 * @param v the value. 315 * @param buffer the buffer. 316 * @param index the index. 317 */ 318 private static void putInt(int v, 319 byte[] buffer, 320 int index) { 321 buffer[index ] = (byte) (v & INT_LOWEST_BYTE_MASK); 322 buffer[index + 1] = (byte)((v >>> 8) & INT_LOWEST_BYTE_MASK); 323 buffer[index + 2] = (byte)((v >>> 16) & INT_LOWEST_BYTE_MASK); 324 buffer[index + 3] = (byte) (v >>> 24); 325 } 326 /** 327 * Creates an {@code int} from 4 bytes. 328 * 329 * @param input Input. 330 * @return the value that correspond to the given bytes assuming 331 * that the order is in increasing byte significance (i.e. the 332 * first byte in the array is the least-significant). 333 * @throws IllegalArgumentException if {@code input.length != 4}. 334 */ 335 public static int makeInt(byte[] input) { 336 checkSize(INT_SIZE, input.length); 337 return getInt(input, 0); 338 } 339 340 /** 341 * Gets the {@code int} from the buffer starting at the given position. 342 * Uses 4 bytes (least-significant first). 343 * 344 * @param input the input bytes. 345 * @param index the index. 346 * @return the value that correspond to the given bytes assuming 347 * that the order is in increasing byte significance (i.e. the 348 * first byte in the array is the least-significant). 349 */ 350 private static int getInt(byte[] input, 351 int index) { 352 return (input[index ] & INT_LOWEST_BYTE_MASK) | 353 (input[index + 1] & INT_LOWEST_BYTE_MASK) << 8 | 354 (input[index + 2] & INT_LOWEST_BYTE_MASK) << 16 | 355 (input[index + 3] & INT_LOWEST_BYTE_MASK) << 24; 356 } 357 358 /** 359 * Splits an array of {@code int} values into a sequence of bytes. 360 * This method calls {@link #makeByteArray(int)} for each element of 361 * the {@code input}. 362 * 363 * @param input Input. 364 * @return an array of bytes. 365 */ 366 public static byte[] makeByteArray(int[] input) { 367 final int size = input.length * INT_SIZE; 368 final byte[] b = new byte[size]; 369 370 for (int i = 0; i < input.length; i++) { 371 putInt(input[i], b, i * INT_SIZE); 372 } 373 374 return b; 375 } 376 377 /** 378 * Creates an array of {@code int} values from a sequence of bytes. 379 * This method calls {@link #makeInt(byte[])} for each subsequence 380 * of 4 bytes. 381 * 382 * @param input Input. Length must be a multiple of 4. 383 * @return an array of {@code int}. 384 * @throws IllegalArgumentException if {@code input.length} is not 385 * a multiple of 4. 386 */ 387 public static int[] makeIntArray(byte[] input) { 388 final int size = input.length; 389 final int num = size / INT_SIZE; 390 checkSize(num * INT_SIZE, size); 391 392 final int[] output = new int[num]; 393 for (int i = 0; i < num; i++) { 394 output[i] = getInt(input, i * INT_SIZE); 395 } 396 397 return output; 398 } 399 400 /** 401 * @param expected Expected value. 402 * @param actual Actual value. 403 * @throws IllegalArgumentException if {@code expected != actual}. 404 */ 405 private static void checkSize(int expected, 406 int actual) { 407 if (expected != actual) { 408 throw new IllegalArgumentException("Array size: Expected " + expected + 409 " but was " + actual); 410 } 411 } 412}