Update compliance verify checks

Cope with large error bounds with small reference values.
Change how error bounds of NaN are avoided for ABS_ERRORs.
Update SIN/COS compliance to latest spec and use input value as
magnitude.

Signed-off-by: Jeremy Johnson <jeremy.johnson@arm.com>
Change-Id: I55aca59e0255e1cfd255b08edb845c3e33ca7eff
diff --git a/reference_model/src/ops/ewise_unary.cc b/reference_model/src/ops/ewise_unary.cc
index 310a174..6818f8c 100644
--- a/reference_model/src/ops/ewise_unary.cc
+++ b/reference_model/src/ops/ewise_unary.cc
@@ -181,8 +181,8 @@
         case TOSA_REF_TYPE_FP64:
             if (g_func_config.abs_mode)
             {
-                // ABS_ERROR bounds return 1.0
-                this->fcn = [](InEigenType a) -> OutEigenType { return 1.0; };
+                // ABS_ERROR bounds return
+                this->fcn = [](InEigenType a) -> OutEigenType { return a; };
             }
             else
             {
@@ -414,8 +414,8 @@
         case TOSA_REF_TYPE_FP64:
             if (g_func_config.abs_mode)
             {
-                // ABS_ERROR bounds return 1.0
-                this->fcn = [](InEigenType a) -> OutEigenType { return 1.0; };
+                // ABS_ERROR bounds return
+                this->fcn = [](InEigenType a) -> OutEigenType { return a; };
             }
             else
             {
diff --git a/reference_model/src/verify/verify_abs_error.cc b/reference_model/src/verify/verify_abs_error.cc
index 64f86a3..b49ce48 100644
--- a/reference_model/src/verify/verify_abs_error.cc
+++ b/reference_model/src/verify/verify_abs_error.cc
@@ -30,15 +30,29 @@
 {
     const auto cfg = reinterpret_cast<const AbsErrorVerifyInfo*>(cfgPtr);
 
-    double errorBound = 0.0;
-    if (std::isfinite(referenceValue) && std::abs(referenceValue) != 0.0)
+    double boundsMagnitude;
+    if (cfg->boundAsMagnitude)
     {
-        double valBound = std::abs(referenceValue) * boundsValue;
+        // Special case for SIN/COS
+        // use the input value (stored in the bounds tensor) as the magnitude and value
+        boundsMagnitude = boundsValue;
+        boundsValue     = std::abs(boundsValue);
+    }
+    else
+    {
+        // Use the referenceValue as the magnitude
+        boundsMagnitude = referenceValue;
+    }
+
+    double errorBound = 0.0;
+    if (std::isfinite(boundsValue) || std::abs(boundsMagnitude) != 0.0)
+    {
+        double valueBound = std::abs(boundsMagnitude) * (boundsValue + cfg->boundAddition);
         if (cfg->lowerBound > 0)
         {
-            valBound = std::max(cfg->lowerBound, valBound);
+            valueBound = std::max(cfg->lowerBound, valueBound);
         }
-        errorBound = exp2(-AccPrecision<OutType>::normal_frac / cfg->normalDivisor) * valBound;
+        errorBound = exp2(-AccPrecision<OutType>::normal_frac / cfg->normalDivisor) * valueBound;
     }
     return errorBound;
 }
diff --git a/reference_model/src/verify/verify_utils.cc b/reference_model/src/verify/verify_utils.cc
index d4657b3..594158c 100644
--- a/reference_model/src/verify/verify_utils.cc
+++ b/reference_model/src/verify/verify_utils.cc
@@ -84,6 +84,14 @@
     {
         j.at("normal_divisor").get_to(absErrorInfo.normalDivisor);
     }
+    if (j.contains("bound_as_magnitude"))
+    {
+        j.at("bound_as_magnitude").get_to(absErrorInfo.boundAsMagnitude);
+    }
+    if (j.contains("bound_addition"))
+    {
+        j.at("bound_addition").get_to(absErrorInfo.boundAddition);
+    }
 }
 
 void from_json(const nlohmann::json& j, RelativeVerifyInfo& rInfo)
@@ -112,8 +120,10 @@
     {
         j.at("reduce_product_info").get_to(cfg.reduceProductInfo);
     }
-    cfg.absErrorInfo.lowerBound    = 0;
-    cfg.absErrorInfo.normalDivisor = 1;
+    cfg.absErrorInfo.lowerBound       = 0;
+    cfg.absErrorInfo.normalDivisor    = 1;
+    cfg.absErrorInfo.boundAsMagnitude = false;
+    cfg.absErrorInfo.boundAddition    = 0;
     if (j.contains("abs_error_info"))
     {
         j.at("abs_error_info").get_to(cfg.absErrorInfo);
@@ -317,7 +327,8 @@
 
         if (referenceMin < AccPrecision<OutType>::normal_min)
         {
-            referenceMin = 0.0;
+            // Large error bounds could mean referenceMin is negative
+            referenceMin = std::min(0.0, referenceMin);
         }
     }
 
diff --git a/reference_model/src/verify/verify_utils.h b/reference_model/src/verify/verify_utils.h
index 9144317..33491e0 100644
--- a/reference_model/src/verify/verify_utils.h
+++ b/reference_model/src/verify/verify_utils.h
@@ -83,6 +83,8 @@
 
     double lowerBound;
     double normalDivisor;
+    bool boundAsMagnitude;
+    double boundAddition;
 };
 
 /// \brief relative verification meta-data
diff --git a/scripts/schemavalidation/compliance-config.schema.json b/scripts/schemavalidation/compliance-config.schema.json
index f4a310c..517dd99 100644
--- a/scripts/schemavalidation/compliance-config.schema.json
+++ b/scripts/schemavalidation/compliance-config.schema.json
@@ -74,6 +74,14 @@
                                 "normal_divisor": {
                                     "description": "normal_divisor for error bounds",
                                     "type": "number"
+                                },
+                                "bound_as_magnitude": {
+                                    "description": "when the bound magnitude is passed in the bound value",
+                                    "type": "boolean"
+                                },
+                                "bound_addition": {
+                                    "description": "addition to the bounds value",
+                                    "type": "number"
                                 }
                             },
                             "additionalProperties": false
diff --git a/verif/generator/tosa_test_gen.py b/verif/generator/tosa_test_gen.py
index 40788a2..b85dd03 100644
--- a/verif/generator/tosa_test_gen.py
+++ b/verif/generator/tosa_test_gen.py
@@ -290,10 +290,18 @@
                 }
         elif op["op"] in (Op.SIN, Op.COS):
             mode = gtu.ComplianceMode.ABS_ERROR
-            if "compliance" in op and "abs_error_normal_divisor" in op["compliance"]:
-                compliance_tens["abs_error_info"] = {
-                    "normal_divisor": op["compliance"]["abs_error_normal_divisor"]
-                }
+            if "compliance" in op:
+                normal_divisor = op["compliance"].get("abs_error_normal_divisor", 1)
+                bound_addition = op["compliance"].get("abs_error_bound_addition", 0)
+            else:
+                normal_divisor = 1
+                bound_addition = 0
+
+            compliance_tens["abs_error_info"] = {
+                "normal_divisor": normal_divisor,
+                "bound_as_magnitude": True,
+                "bound_addition": bound_addition,
+            }
         else:
             mode = gtu.ComplianceMode.EXACT
         compliance_tens["mode"] = gtu.ComplianceMode(mode).name
@@ -4139,7 +4147,10 @@
                 TosaErrorValidator.evWrongOutputList,
             ),
             "data_gen": PSEUDO_RANDOM_DATAGEN,
-            "compliance": {"abs_error_normal_divisor": 2},
+            "compliance": {
+                "abs_error_normal_divisor": 2,
+                "abs_error_bound_addition": 1,
+            },
         },
         "exp": {
             "op": Op.EXP,