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.core.util; 18 19 import java.util.Arrays; 20 21 /** 22 * Utility for creating number types from one or two {@code int} values 23 * or one {@code long} value, or a sequence of bytes. 24 */ 25 public final class NumberFactory { 26 /** See {@link #makeDouble(long)}. */ 27 private static final long DOUBLE_HIGH_BITS = 0x3ffL << 52; 28 /** See {@link #makeFloat(int)}. */ 29 private static final float FLOAT_MULTIPLIER = 0x1.0p-23f; 30 /** See {@link #makeDouble(int, int)}. */ 31 private static final double DOUBLE_MULTIPLIER = 0x1.0p-52d; 32 /** Lowest byte mask. */ 33 private static final long LONG_LOWEST_BYTE_MASK = 0xffL; 34 /** Number of bytes in a {@code long}. */ 35 private static final int LONG_SIZE = 8; 36 /** Lowest byte mask. */ 37 private static final int INT_LOWEST_BYTE_MASK = 0xff; 38 /** Number of bytes in a {@code int}. */ 39 private static final int INT_SIZE = 4; 40 41 /** 42 * Class contains only static methods. 43 */ 44 private NumberFactory() {} 45 46 /** 47 * @param v Number. 48 * @return a boolean. 49 */ 50 public static boolean makeBoolean(int v) { 51 return (v >>> 31) != 0; 52 } 53 54 /** 55 * @param v Number. 56 * @return a boolean. 57 */ 58 public static boolean makeBoolean(long v) { 59 return (v >>> 63) != 0; 60 } 61 62 /** 63 * @param v Number. 64 * @return a {@code double} value in the interval {@code [0, 1]}. 65 */ 66 public static double makeDouble(long v) { 67 // http://xorshift.di.unimi.it 68 return Double.longBitsToDouble(DOUBLE_HIGH_BITS | v >>> 12) - 1d; 69 } 70 71 /** 72 * @param v Number (high order bits). 73 * @param w Number (low order bits). 74 * @return a {@code double} value in the interval {@code [0, 1]}. 75 */ 76 public static double makeDouble(int v, 77 int w) { 78 final long high = ((long) (v >>> 6)) << 26; 79 final int low = w >>> 6; 80 return (high | low) * DOUBLE_MULTIPLIER; 81 } 82 83 /** 84 * @param v Number. 85 * @return a {@code float} value in the interval {@code [0, 1]}. 86 */ 87 public static float makeFloat(int v) { 88 return (v >>> 9) * FLOAT_MULTIPLIER; 89 } 90 91 /** 92 * @param v Number (high order bits). 93 * @param w Number (low order bits). 94 * @return a {@code long} value. 95 */ 96 public static long makeLong(int v, 97 int w) { 98 return (((long) v) << 32) | (w & 0xffffffffL); 99 } 100 101 /** 102 * Creates an {@code int} from a {@code long}. 103 * 104 * @param v Number. 105 * @return an {@code int} value made from the "xor" of the 106 * {@link #extractHi(long) high order bits} and 107 * {@link #extractLo(long) low order bits} of {@code v}. 108 */ 109 public static int makeInt(long v) { 110 return extractHi(v) ^ extractLo(v); 111 } 112 113 /** 114 * Creates an {@code int} from a {@code long}, using the high order bits. 115 * 116 * <p>The returned value is such that if</p> 117 * <pre><code> 118 * vL = extractLo(v); 119 * vH = extractHi(v); 120 * </code></pre> 121 * 122 * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p> 123 * 124 * @param v Number. 125 * @return an {@code int} value made from the most significant bits 126 * of {@code v}. 127 */ 128 public static int extractHi(long v) { 129 return (int) (v >>> 32); 130 } 131 132 /** 133 * Creates an {@code int} from a {@code long}, using the low order bits. 134 * 135 * <p>The returned value is such that if</p> 136 * 137 * <pre><code> 138 * vL = extractLo(v); 139 * vH = extractHi(v); 140 * </code></pre> 141 * 142 * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p> 143 * 144 * @param v Number. 145 * @return an {@code int} value made from the least significant bits 146 * of {@code v}. 147 */ 148 public static int extractLo(long v) { 149 return (int) v; 150 } 151 152 /** 153 * Splits a {@code long} into 8 bytes. 154 * 155 * @param v Value. 156 * @return the bytes that compose the given value (least-significant 157 * byte first). 158 */ 159 public static byte[] makeByteArray(long v) { 160 final byte[] b = new byte[LONG_SIZE]; 161 162 for (int i = 0; i < LONG_SIZE; i++) { 163 final int shift = i * 8; 164 b[i] = (byte) ((v >>> shift) & LONG_LOWEST_BYTE_MASK); 165 } 166 167 return b; 168 } 169 170 /** 171 * Creates a {@code long} from 8 bytes. 172 * 173 * @param input Input. 174 * @return the value that correspond to the given bytes assuming 175 * that the is ordered in increasing byte significance (i.e. the 176 * first byte in the array is the least-siginficant). 177 * @throws IllegalArgumentException if {@code input.length != 8}. 178 */ 179 public static long makeLong(byte[] input) { 180 checkSize(LONG_SIZE, input.length); 181 182 long v = 0; 183 for (int i = 0; i < LONG_SIZE; i++) { 184 final int shift = i * 8; 185 v |= (((long) input[i]) & LONG_LOWEST_BYTE_MASK) << shift; 186 } 187 188 return v; 189 } 190 191 /** 192 * Splits an array of {@code long} values into a sequence of bytes. 193 * This method calls {@link #makeByteArray(long)} for each element of 194 * the {@code input}. 195 * 196 * @param input Input. 197 * @return an array of bytes. 198 */ 199 public static byte[] makeByteArray(long[] input) { 200 final int size = input.length * LONG_SIZE; 201 final byte[] b = new byte[size]; 202 203 for (int i = 0; i < input.length; i++) { 204 final byte[] current = makeByteArray(input[i]); 205 System.arraycopy(current, 0, b, i * LONG_SIZE, LONG_SIZE); 206 } 207 208 return b; 209 } 210 211 /** 212 * Creates an array of {@code long} values from a sequence of bytes. 213 * This method calls {@link #makeLong(byte[])} for each subsequence 214 * of 8 bytes. 215 * 216 * @param input Input. 217 * @return an array of {@code long}. 218 * @throws IllegalArgumentException if {@code input.length} is not 219 * a multiple of 8. 220 */ 221 public static long[] makeLongArray(byte[] input) { 222 final int size = input.length; 223 final int num = size / LONG_SIZE; 224 checkSize(num * LONG_SIZE, size); 225 226 final long[] output = new long[num]; 227 for (int i = 0; i < num; i++) { 228 final int from = i * LONG_SIZE; 229 final byte[] current = Arrays.copyOfRange(input, from, from + LONG_SIZE); 230 output[i] = makeLong(current); 231 } 232 233 return output; 234 } 235 236 /** 237 * Splits an {@code int} into 4 bytes. 238 * 239 * @param v Value. 240 * @return the bytes that compose the given value (least-significant 241 * byte first). 242 */ 243 public static byte[] makeByteArray(int v) { 244 final byte[] b = new byte[INT_SIZE]; 245 246 for (int i = 0; i < INT_SIZE; i++) { 247 final int shift = i * 8; 248 b[i] = (byte) ((v >>> shift) & INT_LOWEST_BYTE_MASK); 249 } 250 251 return b; 252 } 253 254 /** 255 * Creates an {@code int} from 4 bytes. 256 * 257 * @param input Input. 258 * @return the value that correspond to the given bytes assuming 259 * that the is ordered in increasing byte significance (i.e. the 260 * first byte in the array is the least-siginficant). 261 * @throws IllegalArgumentException if {@code input.length != 4}. 262 */ 263 public static int makeInt(byte[] input) { 264 checkSize(INT_SIZE, input.length); 265 266 int v = 0; 267 for (int i = 0; i < INT_SIZE; i++) { 268 final int shift = i * 8; 269 v |= (((int) input[i]) & INT_LOWEST_BYTE_MASK) << shift; 270 } 271 272 return v; 273 } 274 275 /** 276 * Splits an array of {@code int} values into a sequence of bytes. 277 * This method calls {@link #makeByteArray(int)} for each element of 278 * the {@code input}. 279 * 280 * @param input Input. 281 * @return an array of bytes. 282 */ 283 public static byte[] makeByteArray(int[] input) { 284 final int size = input.length * INT_SIZE; 285 final byte[] b = new byte[size]; 286 287 for (int i = 0; i < input.length; i++) { 288 final byte[] current = makeByteArray(input[i]); 289 System.arraycopy(current, 0, b, i * INT_SIZE, INT_SIZE); 290 } 291 292 return b; 293 } 294 295 /** 296 * Creates an array of {@code int} values from a sequence of bytes. 297 * This method calls {@link #makeInt(byte[])} for each subsequence 298 * of 4 bytes. 299 * 300 * @param input Input. Length must be a multiple of 4. 301 * @return an array of {@code int}. 302 * @throws IllegalArgumentException if {@code input.length} is not 303 * a multiple of 4. 304 */ 305 public static int[] makeIntArray(byte[] input) { 306 final int size = input.length; 307 final int num = size / INT_SIZE; 308 checkSize(num * INT_SIZE, size); 309 310 final int[] output = new int[num]; 311 for (int i = 0; i < num; i++) { 312 final int from = i * INT_SIZE; 313 final byte[] current = Arrays.copyOfRange(input, from, from + INT_SIZE); 314 output[i] = makeInt(current); 315 } 316 317 return output; 318 } 319 320 /** 321 * @param expected Expected value. 322 * @param actual Actual value. 323 * @throw IllegalArgumentException if {@code expected != actual}. 324 */ 325 private static void checkSize(int expected, 326 int actual) { 327 if (expected != actual) { 328 throw new IllegalArgumentException("Array size: Expected " + expected + 329 " but was " + actual); 330 } 331 } 332 }