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 setUp()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 tearDown()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. checkFloat16Output(int x, int y, short[][][] refValues, String operation)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 checkFloat16Add(int x, int y)129 private boolean checkFloat16Add(int x, int y) { 130 return checkFloat16Output(x, y, Float16TestData.ReferenceOutputForAdd, 131 "addition"); 132 } 133 testFloat16Add()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 checkFloat16Sub(int x, int y)147 private boolean checkFloat16Sub(int x, int y) { 148 return checkFloat16Output(x, y, Float16TestData.ReferenceOutputForSub, 149 "subtraction"); 150 } 151 testFloat16Sub()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 checkFloat16Mul(int x, int y)165 private boolean checkFloat16Mul(int x, int y) { 166 return checkFloat16Output(x, y, Float16TestData.ReferenceOutputForMul, 167 "multiplication"); 168 } 169 testFloat16Mul()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 checkFloat16Div(int x, int y)183 private boolean checkFloat16Div(int x, int y) { 184 return checkFloat16Output(x, y, Float16TestData.ReferenceOutputForDiv, 185 "division"); 186 } 187 testFloat16Div()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