Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2015 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 java.util.Random;
     20 import java.lang.Math;
     21 import java.lang.Float;
     22 import java.lang.Integer;
     23 import java.lang.Short;
     24 
     25 import android.content.Context;
     26 import android.content.res.Resources;
     27 import android.renderscript.Allocation;
     28 import android.renderscript.cts.Float16Utils;
     29 import android.renderscript.Element;
     30 import android.renderscript.RenderScript;
     31 import android.renderscript.RSRuntimeException;
     32 import android.renderscript.Script;
     33 import android.renderscript.Type;
     34 import android.util.Log;
     35 
     36 public class Float16ArithmeticTest extends RSBaseCompute {
     37     private int numInputs = Float16TestData.input.length;
     38 
     39     private ScriptC_float16_arithmetic script;
     40 
     41     // Allocations to hold float16 input and output
     42     private Allocation mInput;
     43     private Allocation mF16Matrix;
     44     private Allocation mU16Matrix;
     45 
     46     // A numInputs * numInputs length 1-D array with data copied from
     47     // mU16Matrix
     48     private short[] output = new short[numInputs * numInputs];
     49 
     50     // Create input, intermediate, and output allocations.  Copy input data to
     51     // the input allocation
     52     @Override
     53     protected void setUp() throws Exception {
     54         super.setUp();
     55 
     56         Element f16 = Element.F16(mRS);
     57         Element u16 = Element.U16(mRS);
     58         Type f16Matrix = Type.createXY(mRS, f16, numInputs, numInputs);
     59         Type u16Matrix = Type.createXY(mRS, u16, numInputs, numInputs);
     60 
     61         mInput = Allocation.createSized(mRS, f16, numInputs);
     62         mF16Matrix = Allocation.createTyped(mRS, f16Matrix);
     63         mU16Matrix = Allocation.createTyped(mRS, u16Matrix);
     64 
     65         mInput.copyFromUnchecked(Float16TestData.input);
     66 
     67         script = new ScriptC_float16_arithmetic(mRS);
     68     }
     69 
     70     @Override
     71     protected void tearDown() throws Exception {
     72         mInput.destroy();
     73         mF16Matrix.destroy();
     74         mU16Matrix.destroy();
     75         script.destroy();
     76         super.tearDown();
     77     }
     78 
     79     // Check the output of performing 'operation' on inputs x and y against the
     80     // reference output in refValues.  For special cases like Infinity, NaN and
     81     // zero, use exact comparison.  Otherwise, check if the output is within
     82     // the bounds in 'refValues' by converting all values to float.
     83     private boolean checkFloat16Output(int x, int y, short[][][] refValues,
     84                                        String operation)
     85     {
     86         // Find the input, output and reference values based on the indices
     87         short in1 = Float16TestData.input[x];
     88         short in2 = Float16TestData.input[y];
     89         short out = output[x + y * numInputs];
     90         short lb = refValues[x][y][0];
     91         short ub = refValues[x][y][1];
     92 
     93         // Do exact match if the reference value is a special case (Nan, zero
     94         // infinity or their negative equivalents).
     95         if (Float16Utils.isFloat16Infinite(lb))
     96             return lb == out;
     97         // NaN can have any non-zero mantissa.  Do not use equality check
     98         if (Float16Utils.isFloat16NaN(lb))
     99             return Float16Utils.isFloat16NaN(out);
    100         // If reference output is zero, test for exact equivalence if at least
    101         // one of the input values is a special-case FP16 value.
    102         if (Float16Utils.isFloat16Zero(lb)) {
    103             if (!Float16Utils.isFloat16FiniteNonZero(in1) ||
    104                 !Float16Utils.isFloat16FiniteNonZero(in2)) {
    105                 return lb == out;
    106             }
    107         }
    108 
    109         float floatLB = Float16Utils.convertFloat16ToFloat(lb);
    110         float floatUB = Float16Utils.convertFloat16ToFloat(ub);
    111         float floatOut = Float16Utils.convertFloat16ToFloat(out);
    112 
    113         if (floatOut < floatLB || floatOut > floatUB) {
    114             StringBuilder message = new StringBuilder();
    115             message.append("Incorrect output for float16 " + operation + ":");
    116             message.append("\nInput 1: " + Short.toString(in1));
    117             message.append("\nInput 2: " + Short.toString(in2));
    118             message.append("\nExpected output between: " + Short.toString(lb) +
    119                            " and " + Short.toString(ub));
    120             message.append("\nActual   output: " + Short.toString(out));
    121             message.append("\nExpected output (in float) between: " +
    122                            Float.toString(floatLB) + " and " + Float.toString(floatUB));
    123             message.append("\nActual   output: " + Float.toString(floatOut));
    124             assertTrue(message.toString(), false);
    125         }
    126         return true;
    127     }
    128 
    129     private boolean checkFloat16Add(int x, int y) {
    130         return checkFloat16Output(x, y, Float16TestData.ReferenceOutputForAdd,
    131                                   "addition");
    132     }
    133 
    134     public void testFloat16Add() {
    135         script.set_gInput(mInput);
    136         script.forEach_add(mF16Matrix);
    137         script.forEach_bitcast(mF16Matrix, mU16Matrix);
    138         mU16Matrix.copyTo(output);
    139 
    140         for (int x = 0; x < numInputs; x ++) {
    141             for (int y = 0; y < numInputs; y ++) {
    142                 checkFloat16Add(x, y);
    143             }
    144         }
    145     }
    146 
    147     private boolean checkFloat16Sub(int x, int y) {
    148         return checkFloat16Output(x, y, Float16TestData.ReferenceOutputForSub,
    149                                   "subtraction");
    150     }
    151 
    152     public void testFloat16Sub() {
    153         script.set_gInput(mInput);
    154         script.forEach_sub(mF16Matrix);
    155         script.forEach_bitcast(mF16Matrix, mU16Matrix);
    156         mU16Matrix.copyTo(output);
    157 
    158         for (int x = 0; x < numInputs; x ++) {
    159             for (int y = 0; y < numInputs; y ++) {
    160                 checkFloat16Sub(x, y);
    161             }
    162         }
    163     }
    164 
    165     private boolean checkFloat16Mul(int x, int y) {
    166         return checkFloat16Output(x, y, Float16TestData.ReferenceOutputForMul,
    167                                   "multiplication");
    168     }
    169 
    170     public void testFloat16Mul() {
    171         script.set_gInput(mInput);
    172         script.forEach_mul(mF16Matrix);
    173         script.forEach_bitcast(mF16Matrix, mU16Matrix);
    174         mU16Matrix.copyTo(output);
    175 
    176         for (int x = 0; x < numInputs; x ++) {
    177             for (int y = 0; y < numInputs; y ++) {
    178                 checkFloat16Mul(x, y);
    179             }
    180         }
    181     }
    182 
    183     private boolean checkFloat16Div(int x, int y) {
    184         return checkFloat16Output(x, y, Float16TestData.ReferenceOutputForDiv,
    185                                   "division");
    186     }
    187 
    188     public void testFloat16Div() {
    189         script.set_gInput(mInput);
    190         script.forEach_div(mF16Matrix);
    191         script.forEach_bitcast(mF16Matrix, mU16Matrix);
    192         mU16Matrix.copyTo(output);
    193 
    194         for (int x = 0; x < numInputs; x ++) {
    195             for (int y = 0; y < numInputs; y ++) {
    196                 checkFloat16Div(x, y);
    197             }
    198         }
    199     }
    200 }
    201