@@ -1116,7 +1116,7 @@ template <typename T> struct ExpectedBuilder<OpType::Dot, T> {
11161116 static std::vector<T> buildExpected (Op<OpType::Dot, T, 2 > &Op,
11171117 const InputSets<T> &Inputs) {
11181118
1119- std::vector<double > Products ;
1119+ std::vector<double > PositiveProducts ;
11201120 std::vector<double > NegativeProducts;
11211121
11221122 const size_t VectorSize = Inputs[0 ].size ();
@@ -1136,31 +1136,34 @@ template <typename T> struct ExpectedBuilder<OpType::Dot, T> {
11361136 DotProduct += Product;
11371137
11381138 if (Product >= 0.0 )
1139- Products .push_back (Product);
1139+ PositiveProducts .push_back (Product);
11401140 else
11411141 NegativeProducts.push_back (Product);
11421142 }
11431143
11441144 // Sort each by magnitude so that we can accumulate them in worst case
11451145 // order.
1146- std::sort (Products .begin (), Products .end (), std::greater<double >());
1146+ std::sort (PositiveProducts .begin (), PositiveProducts .end (), std::greater<double >());
11471147 std::sort (NegativeProducts.begin (), NegativeProducts.end ());
11481148
1149- // Put them together for final accumulation.
1150- Products.reserve (Products.size () + NegativeProducts.size ());
1151- Products.insert (Products.end (), NegativeProducts.begin (),
1152- NegativeProducts.end ());
1149+ // Helper to sum the products and compute/add to the running absolute
1150+ // epsilon total.
1151+ auto SumProducts = [&](const std::vector<double > &Values){
1152+ double Sum = 0 ;
1153+ for (size_t I = 1 ; I < Values.size (); ++I) {
1154+ Sum += Values[I];
1155+ AbsoluteEpsilon += computeAbsoluteEpsilon<T>(Sum, ULPTolerance);
1156+ }
1157+ return Sum;
1158+ };
11531159
11541160 // Accumulate products in the worst case order while computing the absolute
11551161 // epsilon error for each intermediate step. And accumulate that error.
1156- double Sum = Products.empty () ? 0.0 : Products.front ();
1157- for (size_t I = 1 ; I < Products.size (); ++I) {
1158- Sum += Products[I];
1159- AbsoluteEpsilon += computeAbsoluteEpsilon<T>(Sum, ULPTolerance);
1160- }
1162+ const double SumPos = SumProducts (PositiveProducts);
1163+ const double SumNeg = SumProducts (NegativeProducts);
11611164
1162- // Finally, compute and add in the ULP on our final sum of epsilons.
1163- AbsoluteEpsilon += computeAbsoluteEpsilon<T>(AbsoluteEpsilon , ULPTolerance);
1165+ if (!PositiveProducts. empty () && !NegativeProducts. empty ())
1166+ AbsoluteEpsilon += computeAbsoluteEpsilon<T>((SumPos + SumNeg) , ULPTolerance);
11641167
11651168 Op.ValidationConfig .Tolerance = static_cast <float >(AbsoluteEpsilon);
11661169
@@ -1172,9 +1175,7 @@ template <typename T> struct ExpectedBuilder<OpType::Dot, T> {
11721175
11731176template <typename T>
11741177static double computeAbsoluteEpsilon (double A, float ULPTolerance) {
1175- if (isinf (A) || isnan (A))
1176- // None of the existing input values should produce inf or nan results.
1177- DXASSERT_NOMSG (false );
1178+ DXASSERT ((!isinf (A) && !isnan (A)), " Input values should not produce inf or nan results" );
11781179
11791180 // ULP is a positive value by definition. So, working with abs(A) simplifies
11801181 // our logic for computing ULP in the first place.
0 commit comments