@@ -1437,13 +1437,21 @@ class CBasicTestFetchAddSpecialFloats
14371437 : CBasicTestMemOrderScope<HostAtomicType, HostDataType>(dataType,
14381438 useSVM)
14391439 {
1440- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1440+ // StartValue is used as an index divisor in the following test
1441+ // logic. It is set to the number of special values, which allows
1442+ // threads to be mapped deterministically onto the input data array.
1443+ // This enables repeated add operations arranged so that every
1444+ // special value is added to every other one (“all-to-all”).
1445+
1446+ if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
1447+ {
1448+ auto spec_vals = GetSpecialValues ();
1449+ StartValue (spec_vals.size ());
1450+ CBasicTestMemOrderScope<HostAtomicType,
1451+ HostDataType>::OldValueCheck (false );
1452+ }
1453+ else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
14411454 {
1442- // StartValue is used as an index divisor in the following test
1443- // logic. It is set to the number of special values, which allows
1444- // threads to be mapped deterministically onto the input data array.
1445- // This enables repeated add operations arranged so that every
1446- // special value is added to every other one (“all-to-all”).
14471455
14481456 auto spec_vals = GetSpecialValues ();
14491457 StartValue (cl_half_from_float (spec_vals.size (), gHalfRoundingMode ));
@@ -1454,10 +1462,42 @@ class CBasicTestFetchAddSpecialFloats
14541462
14551463 static std::vector<HostDataType> &GetSpecialValues ()
14561464 {
1465+ const float test_value_zero = 0 .0f ;
1466+ const float test_value_minus_zero = -0 .0f ;
1467+ const float test_value_without_fraction = 2 .0f ;
1468+ const float test_value_with_fraction = 2 .2f ;
1469+
14571470 static std::vector<HostDataType> special_values;
1458- if (special_values. empty () )
1471+ if constexpr (std::is_same_v<HostDataType, HOST_FLOAT> )
14591472 {
1460- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1473+ if (special_values.empty ())
1474+ {
1475+ special_values = {
1476+ static_cast <HostDataType>(test_value_minus_zero),
1477+ static_cast <HostDataType>(test_value_zero),
1478+ static_cast <HostDataType>(test_value_without_fraction),
1479+ static_cast <HostDataType>(test_value_with_fraction),
1480+ std::numeric_limits<HostDataType>::infinity (),
1481+ std::numeric_limits<HostDataType>::quiet_NaN (),
1482+ std::numeric_limits<HostDataType>::signaling_NaN (),
1483+ -std::numeric_limits<HostDataType>::infinity (),
1484+ -std::numeric_limits<HostDataType>::quiet_NaN (),
1485+ -std::numeric_limits<HostDataType>::signaling_NaN (),
1486+ std::numeric_limits<HostDataType>::lowest (),
1487+ std::numeric_limits<HostDataType>::min (),
1488+ std::numeric_limits<HostDataType>::max (),
1489+ };
1490+
1491+ if (0 != (CL_FP_DENORM & gFloatFPConfig ))
1492+ {
1493+ special_values.push_back (
1494+ std::numeric_limits<HostDataType>::denorm_min ());
1495+ }
1496+ }
1497+ }
1498+ else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1499+ {
1500+ if (special_values.empty ())
14611501 {
14621502 special_values = {
14631503 0xffff , 0x0000 , 0x7c00 , /* INFINITY*/
@@ -1491,7 +1531,10 @@ class CBasicTestFetchAddSpecialFloats
14911531 bool GenerateRefs (cl_uint threadCount, HostDataType *startRefValues,
14921532 MTdata d) override
14931533 {
1494- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1534+ if constexpr (
1535+ std::is_same_v<
1536+ HostDataType,
1537+ HOST_HALF> || std::is_same_v<HostDataType, HOST_FLOAT>)
14951538 {
14961539 if (threadCount > ref_vals.size ())
14971540 {
@@ -1522,7 +1565,10 @@ class CBasicTestFetchAddSpecialFloats
15221565 std::string memoryOrderScope = MemoryOrderScopeStr ();
15231566 std::string postfix (memoryOrderScope.empty () ? " " : " _explicit" );
15241567
1525- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1568+ if constexpr (
1569+ std::is_same_v<
1570+ HostDataType,
1571+ HOST_HALF> || std::is_same_v<HostDataType, HOST_FLOAT>)
15261572 {
15271573 // The start_value variable (set by StartValue) is used
15281574 // as a divisor of the thread index when selecting the operand for
@@ -1548,7 +1594,10 @@ class CBasicTestFetchAddSpecialFloats
15481594 volatile HostAtomicType *destMemory,
15491595 HostDataType *oldValues) override
15501596 {
1551- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1597+ if constexpr (
1598+ std::is_same_v<
1599+ HostDataType,
1600+ HOST_HALF> || std::is_same_v<HostDataType, HOST_FLOAT>)
15521601 {
15531602 auto spec_vals = GetSpecialValues ();
15541603 host_atomic_store (&destMemory[tid], (HostDataType)oldValues[tid],
@@ -1563,7 +1612,14 @@ class CBasicTestFetchAddSpecialFloats
15631612 cl_uint whichDestValue) override
15641613 {
15651614 expected = StartValue ();
1566- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1615+
1616+ if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
1617+ {
1618+ auto spec_vals = GetSpecialValues ();
1619+ expected = startRefValues[whichDestValue]
1620+ + startRefValues[whichDestValue / spec_vals.size ()];
1621+ }
1622+ else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
15671623 {
15681624 auto spec_vals = GetSpecialValues ();
15691625 expected = cl_half_from_float (
@@ -1575,13 +1631,18 @@ class CBasicTestFetchAddSpecialFloats
15751631
15761632 return true ;
15771633 }
1578-
15791634 bool IsTestNotAsExpected (const HostDataType &expected,
15801635 const std::vector<HostAtomicType> &testValues,
15811636 cl_uint whichDestValue) override
15821637 {
1583-
1584- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1638+ if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
1639+ {
1640+ if (std::isnan (testValues[whichDestValue]) && std::isnan (expected))
1641+ return false ;
1642+ else
1643+ return expected != testValues[whichDestValue];
1644+ }
1645+ else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
15851646 {
15861647 return static_cast <cl_half>(expected) != testValues[whichDestValue];
15871648 }
@@ -1591,11 +1652,28 @@ class CBasicTestFetchAddSpecialFloats
15911652 testValues,
15921653 whichDestValue);
15931654 }
1594-
15951655 int ExecuteSingleTest (cl_device_id deviceID, cl_context context,
15961656 cl_command_queue queue) override
15971657 {
1598- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1658+ if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
1659+ {
1660+ if (LocalMemory ()
1661+ && (gFloatAtomicCaps & CL_DEVICE_LOCAL_FP_ATOMIC_ADD_EXT) == 0 )
1662+ return 0 ; // skip test - not applicable
1663+
1664+ if (!LocalMemory ()
1665+ && (gFloatAtomicCaps & CL_DEVICE_GLOBAL_FP_ATOMIC_ADD_EXT) == 0 )
1666+ return 0 ;
1667+
1668+ if (!CBasicTestMemOrderScope<HostAtomicType,
1669+ HostDataType>::LocalMemory ()
1670+ && CBasicTestMemOrderScope<HostAtomicType,
1671+ HostDataType>::DeclaredInProgram ())
1672+ {
1673+ if ((gFloatFPConfig & CL_FP_INF_NAN) == 0 ) return 0 ;
1674+ }
1675+ }
1676+ else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
15991677 {
16001678 if (DeclaredInProgram ()) return 0 ; // skip test - not applicable
16011679
@@ -1621,7 +1699,10 @@ class CBasicTestFetchAddSpecialFloats
16211699 }
16221700 cl_uint NumResults (cl_uint threadCount, cl_device_id deviceID) override
16231701 {
1624- if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1702+ if constexpr (
1703+ std::is_same_v<
1704+ HostDataType,
1705+ HOST_HALF> || std::is_same_v<HostDataType, HOST_FLOAT>)
16251706 {
16261707 return threadCount;
16271708 }
@@ -1656,6 +1737,17 @@ static int test_atomic_fetch_add_generic(cl_device_id deviceID,
16561737
16571738 if (gFloatAtomicsSupported )
16581739 {
1740+ auto spec_vals_fp32 =
1741+ CBasicTestFetchAddSpecialFloats<HOST_ATOMIC_FLOAT,
1742+ HOST_FLOAT>::GetSpecialValues ();
1743+
1744+ CBasicTestFetchAddSpecialFloats<HOST_ATOMIC_FLOAT, HOST_FLOAT>
1745+ test_spec_float (TYPE_ATOMIC_FLOAT, useSVM);
1746+ EXECUTE_TEST (error,
1747+ test_spec_float.Execute (deviceID, context, queue,
1748+ spec_vals_fp32.size ()
1749+ * spec_vals_fp32.size ()));
1750+
16591751 auto spec_vals_halfs =
16601752 CBasicTestFetchAddSpecialFloats<HOST_ATOMIC_HALF,
16611753 HOST_HALF>::GetSpecialValues ();
0 commit comments