1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.renderscript.cts; 18 19 import android.content.res.Resources; 20 import android.renderscript.Allocation; 21 import android.renderscript.RSRuntimeException; 22 23 import java.util.Random; 24 25 /** 26 * This class supplies some utils for renderscript tests 27 */ 28 public class RSUtils { 29 public static final short FLOAT16_POSITIVE_INFINITY = (short) 0x7c00; 30 public static final short FLOAT16_NEGATIVE_INFINITY = (short) 0xfc00; 31 public static final short FLOAT16_MIN_NORMAL = (short) 0x0400; // 0.00006103516 32 public static final short FLOAT16_MAX_VALUE = (short) 0x7bff; // 65504 33 34 private static final double[] sInterestingDoubles = { 35 0.0, 36 1.0, 37 Math.E, 38 Math.PI, 39 Math.PI / 2.0, 40 Math.PI * 2.0, 41 -0.0, 42 -1.0, 43 -Math.E, 44 -Math.PI, 45 -Math.PI / 2.0, 46 -Math.PI * 2.0, 47 }; 48 49 // Constants E, PI etc. are set to their nearest representations in Float16. 50 private static final short[] sInterestingFloat16s = { 51 (short) 0x0, // zero 52 (short) 0x3c00, // one 53 (short) 0x4170, // E, 2.71875000000 54 (short) 0x4248, // PI, 3.14062500000 55 (short) 0x3e48, // PI / 2, 1.57031250000 56 (short) 0x4648, // PI * 2, 6.28125000000 57 58 (short) 0x8000, // negative zero 59 (short) 0xbc00, // negative one 60 (short) 0xc170, // -E, -2.71875000000 61 (short) 0xc248, // -PI, -3.14062500000 62 (short) 0xbe48, // -PI / 2, -1.57031250000 63 (short) 0xc648, // -PI * 2, -6.28125000000 64 }; 65 66 /** 67 * Fills the array with random doubles. Values will be between min (inclusive) and 68 * max (inclusive). 69 */ genRandomDoubles(long seed, double min, double max, double array[], boolean includeExtremes)70 public static void genRandomDoubles(long seed, double min, double max, double array[], 71 boolean includeExtremes) { 72 Random r = new Random(seed); 73 int minExponent = Math.min(Math.getExponent(min), 0); 74 int maxExponent = Math.max(Math.getExponent(max), 0); 75 if (minExponent < -6 || maxExponent > 6) { 76 // Use an exponential distribution 77 int exponentDiff = maxExponent - minExponent; 78 for (int i = 0; i < array.length; i++) { 79 double mantissa = r.nextDouble(); 80 int exponent = minExponent + r.nextInt(maxExponent - minExponent); 81 int sign = (min >= 0) ? 1 : 1 - r.nextInt(2) * 2; // -1 or 1 82 double rand = sign * mantissa * Math.pow(2.0, exponent); 83 if (rand < min || rand > max) { 84 continue; 85 } 86 array[i] = rand; 87 } 88 } else { 89 // Use a linear distribution 90 for (int i = 0; i < array.length; i++) { 91 double rand = r.nextDouble(); 92 array[i] = min + rand * (max - min); 93 } 94 } 95 // Seed a few special numbers we want to be sure to test. 96 for (int i = 0; i < sInterestingDoubles.length; i++) { 97 double d = sInterestingDoubles[i]; 98 if (min <= d && d <= max) { 99 array[r.nextInt(array.length)] = d; 100 } 101 } 102 array[r.nextInt(array.length)] = min; 103 array[r.nextInt(array.length)] = max; 104 if (includeExtremes) { 105 array[r.nextInt(array.length)] = Double.NaN; 106 array[r.nextInt(array.length)] = Double.POSITIVE_INFINITY; 107 array[r.nextInt(array.length)] = Double.NEGATIVE_INFINITY; 108 array[r.nextInt(array.length)] = Double.MIN_VALUE; 109 array[r.nextInt(array.length)] = Double.MIN_NORMAL; 110 array[r.nextInt(array.length)] = Double.MAX_VALUE; 111 array[r.nextInt(array.length)] = -Double.MIN_VALUE; 112 array[r.nextInt(array.length)] = -Double.MIN_NORMAL; 113 array[r.nextInt(array.length)] = -Double.MAX_VALUE; 114 } 115 } 116 117 /** 118 * Fills the array with random floats. Values will be between min (inclusive) and 119 * max (inclusive). 120 */ genRandomFloats(long seed, float min, float max, float array[], boolean includeExtremes)121 public static void genRandomFloats(long seed, float min, float max, float array[], 122 boolean includeExtremes) { 123 Random r = new Random(seed); 124 int minExponent = Math.min(Math.getExponent(min), 0); 125 int maxExponent = Math.max(Math.getExponent(max), 0); 126 if (minExponent < -6 || maxExponent > 6) { 127 // Use an exponential distribution 128 int exponentDiff = maxExponent - minExponent; 129 for (int i = 0; i < array.length; i++) { 130 float mantissa = r.nextFloat(); 131 int exponent = minExponent + r.nextInt(maxExponent - minExponent); 132 int sign = (min >= 0) ? 1 : 1 - r.nextInt(2) * 2; // -1 or 1 133 float rand = sign * mantissa * (float) Math.pow(2.0, exponent); 134 if (rand < min || rand > max) { 135 continue; 136 } 137 array[i] = rand; 138 } 139 } else { 140 // Use a linear distribution 141 for (int i = 0; i < array.length; i++) { 142 float rand = r.nextFloat(); 143 array[i] = min + rand * (max - min); 144 } 145 } 146 // Seed a few special numbers we want to be sure to test. 147 for (int i = 0; i < sInterestingDoubles.length; i++) { 148 float f = (float) sInterestingDoubles[i]; 149 if (min <= f && f <= max) { 150 array[r.nextInt(array.length)] = f; 151 } 152 } 153 array[r.nextInt(array.length)] = min; 154 array[r.nextInt(array.length)] = max; 155 if (includeExtremes) { 156 array[r.nextInt(array.length)] = Float.NaN; 157 array[r.nextInt(array.length)] = Float.POSITIVE_INFINITY; 158 array[r.nextInt(array.length)] = Float.NEGATIVE_INFINITY; 159 array[r.nextInt(array.length)] = Float.MIN_VALUE; 160 array[r.nextInt(array.length)] = Float.MIN_NORMAL; 161 array[r.nextInt(array.length)] = Float.MAX_VALUE; 162 array[r.nextInt(array.length)] = -Float.MIN_VALUE; 163 array[r.nextInt(array.length)] = -Float.MIN_NORMAL; 164 array[r.nextInt(array.length)] = -Float.MAX_VALUE; 165 } 166 } 167 genRandomFloat16s(long seed, double minDoubleValue, double maxDoubleValue, short array[], boolean includeExtremes)168 public static void genRandomFloat16s(long seed, double minDoubleValue, double maxDoubleValue, 169 short array[], boolean includeExtremes) { 170 171 // Ensure that requests for random Float16s span a reasnoable range. 172 if (maxDoubleValue - minDoubleValue <= 1.) { 173 throw new RSRuntimeException("Unexpected: Range is too small"); 174 } 175 176 boolean includeNegatives = false; 177 178 // Identify a range of 'short' values from the input range of 'double' If either 179 // minValueInHalf or maxValueInHalf is +/- infinity, use MAX_VALUE with appropriate sign 180 // instead. The extreme values will get included if includeExtremes flag is set. 181 double minValueInHalf = Float16Utils.roundToFloat16(minDoubleValue)[1]; 182 double maxValueInHalf = Float16Utils.roundToFloat16(maxDoubleValue)[0]; 183 184 if (Double.isInfinite(minValueInHalf)) { 185 minValueInHalf = Math.copySign(Float16Utils.MAX_VALUE, minValueInHalf); 186 } 187 if (Double.isInfinite(maxValueInHalf)) { 188 maxValueInHalf = Math.copySign(Float16Utils.MAX_VALUE, maxValueInHalf); 189 } 190 191 short min = Float16Utils.convertDoubleToFloat16(minValueInHalf); 192 short max = Float16Utils.convertDoubleToFloat16(maxValueInHalf); 193 194 // If range spans across zero, set the range to be entirely positive and set 195 // includeNegatives to true. In this scenario, the upper bound is set to the larger of 196 // maxValue and abs(minValue). The lower bound is FLOAT16_MIN_NORMAL. 197 if (minDoubleValue < 0. && maxDoubleValue > 0.) { 198 includeNegatives = true; 199 min = FLOAT16_MIN_NORMAL; 200 201 // If abs(minDoubleValue) is greater than maxDoubleValue, pick abs(minValue) as the 202 // upper bound. 203 // TODO Update this function to generate random float16s exactly between minDoubleValue 204 // and maxDoubleValue. 205 if (Math.abs(minDoubleValue) > maxDoubleValue) { 206 max = (short) (0x7fff & min); 207 } 208 } else if (maxDoubleValue < 0.) { 209 throw new RSRuntimeException("Unexpected: Range is entirely negative: " + 210 Double.toString(minDoubleValue) + " to " + Double.toString(maxDoubleValue)); 211 } 212 213 // If min is 0 or subnormal, set it to FLOAT16_MIN_NORMAL 214 if (Float16Utils.isFloat16Zero(min) || Float16Utils.isFloat16SubNormal(min)) { 215 min = FLOAT16_MIN_NORMAL; 216 } 217 218 Random r = new Random(seed); 219 short range = (short) (max - min + 1); 220 for (int i = 0; i < array.length; i ++) { 221 array[i] = (short) (min + r.nextInt(range)); 222 } 223 array[r.nextInt(array.length)] = min; 224 array[r.nextInt(array.length)] = max; 225 226 // Negate approximately half of the elements. 227 if (includeNegatives) { 228 for (int i = 0; i < array.length; i ++) { 229 if (r.nextBoolean()) { 230 array[i] = (short) (0x8000 | array[i]); 231 } 232 } 233 } 234 235 for (short s : sInterestingFloat16s) { 236 if (!includeNegatives && s < 0) 237 continue; 238 array[r.nextInt(array.length)] = s; 239 } 240 if (includeExtremes) { 241 array[r.nextInt(array.length)] = (short) 0x7c01; // NaN 242 array[r.nextInt(array.length)] = FLOAT16_POSITIVE_INFINITY; 243 array[r.nextInt(array.length)] = FLOAT16_NEGATIVE_INFINITY; 244 array[r.nextInt(array.length)] = FLOAT16_MIN_NORMAL; 245 array[r.nextInt(array.length)] = FLOAT16_MAX_VALUE; 246 array[r.nextInt(array.length)] = (short) 0x8400; // -MIN_NORMAL, -0.00006103516 247 array[r.nextInt(array.length)] = (short) 0xfbff; // -MAX_VALUE, -65504 248 } 249 } 250 251 /** 252 * Fills the array with random ints. Values will be between min (inclusive) and 253 * max (inclusive). 254 */ genRandomInts(long seed, int min, int max, int array[])255 public static void genRandomInts(long seed, int min, int max, int array[]) { 256 Random r = new Random(seed); 257 for (int i = 0; i < array.length; i++) { 258 long range = max - min + 1; 259 array[i] = (int) (min + r.nextLong() % range); 260 } 261 array[r.nextInt(array.length)] = min; 262 array[r.nextInt(array.length)] = max; 263 } 264 265 /** 266 * Fills the array with random longs. If signed is true, negative values can be generated. 267 * The values will fit within 'numberOfBits'. This is useful for conversion tests. 268 */ genRandomLongs(long seed, long array[], boolean signed, int numberOfBits)269 public static void genRandomLongs(long seed, long array[], boolean signed, int numberOfBits) { 270 long positiveMask = numberOfBits == 64 ? -1 : ((1l << numberOfBits) - 1); 271 long negativeMask = ~positiveMask; 272 Random r = new Random(seed); 273 for (int i = 0; i < array.length; i++) { 274 long l = r.nextLong(); 275 if (signed && l < 0) { 276 l = l | negativeMask; 277 } else { 278 l = l & positiveMask; 279 } 280 array[i] = l; 281 } 282 // Seed a few special numbers we want to be sure to test. 283 array[r.nextInt(array.length)] = 0l; 284 array[r.nextInt(array.length)] = 1l; 285 array[r.nextInt(array.length)] = positiveMask; 286 if (signed) { 287 array[r.nextInt(array.length)] = negativeMask; 288 array[r.nextInt(array.length)] = -1; 289 } 290 } 291 genRandomInts(long seed, int array[], boolean signed, int numberOfBits)292 public static void genRandomInts(long seed, int array[], boolean signed, int numberOfBits) { 293 long[] longs = new long[array.length]; 294 genRandomLongs(seed, longs, signed, numberOfBits); 295 for (int i = 0; i < array.length; i++) { 296 array[i] = (int) longs[i]; 297 } 298 } 299 genRandomShorts(long seed, short array[], boolean signed, int numberOfBits)300 public static void genRandomShorts(long seed, short array[], boolean signed, int numberOfBits) { 301 long[] longs = new long[array.length]; 302 genRandomLongs(seed, longs, signed, numberOfBits); 303 for (int i = 0; i < array.length; i++) { 304 array[i] = (short) longs[i]; 305 } 306 } 307 genRandomBytes(long seed, byte array[], boolean signed, int numberOfBits)308 public static void genRandomBytes(long seed, byte array[], boolean signed, int numberOfBits) { 309 long[] longs = new long[array.length]; 310 genRandomLongs(seed, longs, signed, numberOfBits); 311 for (int i = 0; i < array.length; i++) { 312 array[i] = (byte) longs[i]; 313 } 314 } 315 316 // Compares two unsigned long. Returns < 0 if a < b, 0 if a == b, > 0 if a > b. compareUnsignedLong(long a, long b)317 public static long compareUnsignedLong(long a, long b) { 318 long aFirstFourBits = a >>> 60; 319 long bFirstFourBits = b >>> 60; 320 long firstFourBitsDiff = aFirstFourBits - bFirstFourBits; 321 if (firstFourBitsDiff != 0) { 322 return firstFourBitsDiff; 323 } 324 long aRest = a & 0x0fffffffffffffffl; 325 long bRest = b & 0x0fffffffffffffffl; 326 return aRest - bRest; 327 } 328 } 329