Skip to content

Commit 172041b

Browse files
authored
Swap arguments to _mm*_{min,max}_ps (#1165)
Swap arguments to _mm_*{min,max}_ps `std::min` and `std::max` return their second argument if either argument is NAN, while the intrinsics return the first argument. This brings `xsimd::{min,max}` in line with `std::{min,max}`, at least on x86.
1 parent eb3bacb commit 172041b

File tree

4 files changed

+45
-12
lines changed

4 files changed

+45
-12
lines changed

include/xsimd/arch/xsimd_avx.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -925,12 +925,12 @@ namespace xsimd
925925
template <class A>
926926
XSIMD_INLINE batch<float, A> max(batch<float, A> const& self, batch<float, A> const& other, requires_arch<avx>) noexcept
927927
{
928-
return _mm256_max_ps(self, other);
928+
return _mm256_max_ps(other, self);
929929
}
930930
template <class A>
931931
XSIMD_INLINE batch<double, A> max(batch<double, A> const& self, batch<double, A> const& other, requires_arch<avx>) noexcept
932932
{
933-
return _mm256_max_pd(self, other);
933+
return _mm256_max_pd(other, self);
934934
}
935935
template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
936936
XSIMD_INLINE batch<T, A> max(batch<T, A> const& self, batch<T, A> const& other, requires_arch<avx>) noexcept
@@ -942,12 +942,12 @@ namespace xsimd
942942
template <class A>
943943
XSIMD_INLINE batch<float, A> min(batch<float, A> const& self, batch<float, A> const& other, requires_arch<avx>) noexcept
944944
{
945-
return _mm256_min_ps(self, other);
945+
return _mm256_min_ps(other, self);
946946
}
947947
template <class A>
948948
XSIMD_INLINE batch<double, A> min(batch<double, A> const& self, batch<double, A> const& other, requires_arch<avx>) noexcept
949949
{
950-
return _mm256_min_pd(self, other);
950+
return _mm256_min_pd(other, self);
951951
}
952952
template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
953953
XSIMD_INLINE batch<T, A> min(batch<T, A> const& self, batch<T, A> const& other, requires_arch<avx>) noexcept

include/xsimd/arch/xsimd_avx512f.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,12 +1326,12 @@ namespace xsimd
13261326
template <class A>
13271327
XSIMD_INLINE batch<float, A> max(batch<float, A> const& self, batch<float, A> const& other, requires_arch<avx512f>) noexcept
13281328
{
1329-
return _mm512_max_ps(self, other);
1329+
return _mm512_max_ps(other, self);
13301330
}
13311331
template <class A>
13321332
XSIMD_INLINE batch<double, A> max(batch<double, A> const& self, batch<double, A> const& other, requires_arch<avx512f>) noexcept
13331333
{
1334-
return _mm512_max_pd(self, other);
1334+
return _mm512_max_pd(other, self);
13351335
}
13361336
template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
13371337
XSIMD_INLINE batch<T, A> max(batch<T, A> const& self, batch<T, A> const& other, requires_arch<avx512f>) noexcept
@@ -1376,12 +1376,12 @@ namespace xsimd
13761376
template <class A>
13771377
XSIMD_INLINE batch<float, A> min(batch<float, A> const& self, batch<float, A> const& other, requires_arch<avx512f>) noexcept
13781378
{
1379-
return _mm512_min_ps(self, other);
1379+
return _mm512_min_ps(other, self);
13801380
}
13811381
template <class A>
13821382
XSIMD_INLINE batch<double, A> min(batch<double, A> const& self, batch<double, A> const& other, requires_arch<avx512f>) noexcept
13831383
{
1384-
return _mm512_min_pd(self, other);
1384+
return _mm512_min_pd(other, self);
13851385
}
13861386
template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
13871387
XSIMD_INLINE batch<T, A> min(batch<T, A> const& self, batch<T, A> const& other, requires_arch<avx512f>) noexcept

include/xsimd/arch/xsimd_sse2.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ namespace xsimd
11371137
template <class A>
11381138
XSIMD_INLINE batch<float, A> max(batch<float, A> const& self, batch<float, A> const& other, requires_arch<sse2>) noexcept
11391139
{
1140-
return _mm_max_ps(self, other);
1140+
return _mm_max_ps(other, self);
11411141
}
11421142
template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
11431143
XSIMD_INLINE batch<T, A> max(batch<T, A> const& self, batch<T, A> const& other, requires_arch<sse2>) noexcept
@@ -1147,14 +1147,14 @@ namespace xsimd
11471147
template <class A>
11481148
XSIMD_INLINE batch<double, A> max(batch<double, A> const& self, batch<double, A> const& other, requires_arch<sse2>) noexcept
11491149
{
1150-
return _mm_max_pd(self, other);
1150+
return _mm_max_pd(other, self);
11511151
}
11521152

11531153
// min
11541154
template <class A>
11551155
XSIMD_INLINE batch<float, A> min(batch<float, A> const& self, batch<float, A> const& other, requires_arch<sse2>) noexcept
11561156
{
1157-
return _mm_min_ps(self, other);
1157+
return _mm_min_ps(other, self);
11581158
}
11591159
template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
11601160
XSIMD_INLINE batch<T, A> min(batch<T, A> const& self, batch<T, A> const& other, requires_arch<sse2>) noexcept
@@ -1164,7 +1164,7 @@ namespace xsimd
11641164
template <class A>
11651165
XSIMD_INLINE batch<double, A> min(batch<double, A> const& self, batch<double, A> const& other, requires_arch<sse2>) noexcept
11661166
{
1167-
return _mm_min_pd(self, other);
1167+
return _mm_min_pd(other, self);
11681168
}
11691169

11701170
// mul

test/test_xsimd_api.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,29 @@ struct xsimd_api_float_types_functions
658658
value_type val(0);
659659
CHECK_EQ(extract(xsimd::log1p(T(val))), std::log1p(val));
660660
}
661+
662+
void test_max_nan()
663+
{
664+
value_type val0(2.7818);
665+
value_type valN(NAN);
666+
#if XSIMD_WITH_AVX || XSIMD_WITH_SSE2
667+
using isnan = doctest::IsNaN<value_type>;
668+
CHECK_EQ(isnan(extract(xsimd::max(T(val0), T(valN)))), isnan(std::max(val0, valN)));
669+
CHECK_EQ(isnan(extract(xsimd::max(T(valN), T(val0)))), isnan(std::max(valN, val0)));
670+
#endif
671+
}
672+
673+
void test_min_nan()
674+
{
675+
value_type val0(2.7818);
676+
value_type valN(NAN);
677+
#if XSIMD_WITH_AVX || XSIMD_WITH_SSE2
678+
using isnan = doctest::IsNaN<value_type>;
679+
CHECK_EQ(isnan(extract(xsimd::min(T(val0), T(valN)))), isnan(std::min(val0, valN)));
680+
CHECK_EQ(isnan(extract(xsimd::min(T(valN), T(val0)))), isnan(std::min(valN, val0)));
681+
#endif
682+
}
683+
661684
void test_nearbyint()
662685
{
663686
value_type val(3.1);
@@ -929,6 +952,16 @@ TEST_CASE_TEMPLATE("[xsimd api | float types functions]", B, FLOAT_TYPES)
929952
Test.test_log1p();
930953
}
931954

955+
SUBCASE("max_nan")
956+
{
957+
Test.test_max_nan();
958+
}
959+
960+
SUBCASE("min_nan")
961+
{
962+
Test.test_min_nan();
963+
}
964+
932965
SUBCASE("nearbyint")
933966
{
934967
Test.test_nearbyint();

0 commit comments

Comments
 (0)