Home | History | Annotate | Download | only in cts
      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      */
     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      */
    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 
    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      */
    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      */
    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 
    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 
    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 
    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.
    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