Extend test generator to generate tests for Float16

http://b/27512382

Extend the test generator to add a short and double field to the
Arguments class for Float16 parameters.  Input short values get
converted to double while initializating the Arguments class and output
short values get converted to double before invoking
Target.Floaty.couldBe().

Change-Id: I9848cb4b2ba7b79c5b77d849a4c48e827d24f64c
diff --git a/api/GenerateTestFiles.cpp b/api/GenerateTestFiles.cpp
index c5a5b54..92633d2 100644
--- a/api/GenerateTestFiles.cpp
+++ b/api/GenerateTestFiles.cpp
@@ -251,16 +251,29 @@
         mJava->startBlock();
 
         for (auto p : mAllInputsAndOutputs) {
+            bool isFieldArray = !scalar && p->mVectorSize != "1";
+            bool isFloatyField = p->isOutParameter && p->isFloatType && mPermutation.getTest() != "custom";
+
             mJava->indent() << "public ";
-            if (p->isOutParameter && p->isFloatType && mPermutation.getTest() != "custom") {
+            if (isFloatyField) {
                 *mJava << "Target.Floaty";
             } else {
                 *mJava << p->javaBaseType;
             }
-            if (!scalar && p->mVectorSize != "1") {
+            if (isFieldArray) {
                 *mJava << "[]";
             }
             *mJava << " " << p->variableName << ";\n";
+
+            // For Float16 parameters, add an extra 'double' field in the class
+            // to hold the Double value converted from the input.
+            if (p->isFloat16Parameter() && !isFloatyField) {
+                mJava->indent() << "public double";
+                if (isFieldArray) {
+                    *mJava << "[]";
+                }
+                *mJava << " " + p->variableName << "Double;\n";
+            }
         }
         mJava->endBlock();
         *mJava << "\n";
@@ -420,6 +433,14 @@
                 *mJava << " * " << p->vectorWidth << " + j";
             }
             *mJava << "];\n";
+
+            // Convert the Float16 parameter to double and store it in the appropriate field in the
+            // Arguments class.
+            if (p->isFloat16Parameter()) {
+                mJava->indent() << "args." << p->doubleVariableName
+                                << " = Float16Utils.convertFloat16ToDouble(args."
+                                << p->variableName << ");\n";
+            }
         }
     }
     const bool hasFloat = mPermutation.hasFloatAnswers();
@@ -523,6 +544,10 @@
             }
             mJava->indent() << "args." << p->variableName << " = new " << type << "["
                             << p->mVectorSize << "];\n";
+            if (p->isFloat16Parameter() && !p->isOutParameter) {
+                mJava->indent() << "args." << p->variableName << "Double = new double["
+                                << p->mVectorSize << "];\n";
+            }
         }
     }
 
@@ -538,6 +563,14 @@
                 mJava->indent() << "args." << p->variableName << "[j] = "
                                 << p->javaArrayName << "[i * " << p->vectorWidth << " + j]"
                                 << ";\n";
+
+                // Convert the Float16 parameter to double and store it in the appropriate field in
+                // the Arguments class.
+                if (p->isFloat16Parameter()) {
+                    mJava->indent() << "args." << p->doubleVariableName << "[j] = "
+                                    << "Float16Utils.convertFloat16ToDouble(args."
+                                    << p->variableName << "[j]);\n";
+                }
                 mJava->endBlock();
             }
         }
@@ -653,10 +686,17 @@
 
 void PermutationWriter::writeJavaTestOneValue(const ParameterDefinition& p, const string& argsIndex,
                                               const string& actualIndex) const {
+    string actualOut;
+    if (p.isFloat16Parameter()) {
+        // For Float16 values, the output needs to be converted to Double.
+        actualOut = "Float16Utils.convertFloat16ToDouble(" + p.javaArrayName + actualIndex + ")";
+    } else {
+        actualOut = p.javaArrayName + actualIndex;
+    }
+
     mJava->indent() << "if (";
     if (p.isFloatType) {
-        *mJava << "!args." << p.variableName << argsIndex << ".couldBe(" << p.javaArrayName
-               << actualIndex;
+        *mJava << "!args." << p.variableName << argsIndex << ".couldBe(" << actualOut;
         const string s = mPermutation.getPrecisionLimit();
         if (!s.empty()) {
             *mJava << ", " << s;
@@ -703,6 +743,14 @@
         mJava->indent() << "appendVariableToMessage(message, " << p.javaArrayName << actualIndex
                         << ");\n";
 
+        if (p.isFloat16Parameter()) {
+            writeJavaAppendNewLineToMessage();
+            mJava->indent() << "message.append(\"Actual   output " << p.variableName
+                            << " (in double): \");\n";
+            mJava->indent() << "appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble("
+                            << p.javaArrayName << actualIndex << "));\n";
+        }
+
         writeJavaTestOneValue(p, argsIndex, actualIndex);
         mJava->startBlock();
         mJava->indent() << "message.append(\" FAIL\");\n";
diff --git a/api/Specification.cpp b/api/Specification.cpp
index 7afeea4..3b794ad 100644
--- a/api/Specification.cpp
+++ b/api/Specification.cpp
@@ -35,7 +35,7 @@
 const unsigned int MIN_API_LEVEL = 9;
 
 const NumericalType TYPES[] = {
-            {"f16", "FLOAT_16", "half", "float", FLOATING_POINT, 11, 5},
+            {"f16", "FLOAT_16", "half", "short", FLOATING_POINT, 11, 5},
             {"f32", "FLOAT_32", "float", "float", FLOATING_POINT, 24, 8},
             {"f64", "FLOAT_64", "double", "double", FLOATING_POINT, 53, 11},
             {"i8", "SIGNED_8", "char", "byte", SIGNED_INTEGER, 7, 0},
@@ -170,6 +170,7 @@
             scanner->error(lineNumber) << "Should have a name.\n";
         }
         variableName += capitalize(specName);
+        doubleVariableName = variableName + "Double";
     }
     rsAllocName = "gAlloc" + capitalize(variableName);
     javaAllocName = variableName;
diff --git a/api/Specification.h b/api/Specification.h
index c467c5c..bcd5737 100644
--- a/api/Specification.h
+++ b/api/Specification.h
@@ -96,6 +96,8 @@
     std::string rsAllocName;    // e.g. gAllocInX
     std::string javaAllocName;  // e.g. inX
     std::string javaArrayName;  // e.g. arrayInX
+    std::string doubleVariableName; // e.g. inXDouble, used in .java for storing Float16 parameters
+                                    // in double.
 
     // If non empty, the mininum and maximum values to be used when generating the test data.
     std::string minValue;
@@ -117,6 +119,8 @@
     void parseParameterDefinition(const std::string& type, const std::string& name,
                                   const std::string& testOption, int lineNumber, bool isReturn,
                                   Scanner* scanner);
+
+    bool isFloat16Parameter() const { return specType.compare("f16") == 0; }
 };
 
 struct VersionInfo {