diff options
-rw-r--r-- | src/core/SkNx.h | 4 | ||||
-rw-r--r-- | src/opts/SkNx_neon.h | 18 | ||||
-rw-r--r-- | src/opts/SkNx_sse.h | 12 | ||||
-rw-r--r-- | tests/SkNxTest.cpp | 12 |
4 files changed, 46 insertions, 0 deletions
diff --git a/src/core/SkNx.h b/src/core/SkNx.h index 0b41365e82..11c8f7c665 100644 --- a/src/core/SkNx.h +++ b/src/core/SkNx.h @@ -103,6 +103,8 @@ struct SkNx { Half::Store2(ptr + 2*N/2*sizeof(T), a.fHi, b.fHi); } + AI T min() const { return std::min(fLo.min(), fHi.min()); } + AI T max() const { return std::max(fLo.max(), fHi.max()); } AI bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } AI bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } @@ -211,6 +213,8 @@ struct SkNx<1,T> { b.store(ptr + 1*sizeof(T)); } + AI T min() const { return fVal; } + AI T max() const { return fVal; } AI bool anyTrue() const { return fVal != 0; } AI bool allTrue() const { return fVal != 0; } diff --git a/src/opts/SkNx_neon.h b/src/opts/SkNx_neon.h index 232903ab67..9020036076 100644 --- a/src/opts/SkNx_neon.h +++ b/src/opts/SkNx_neon.h @@ -244,6 +244,24 @@ public: return pun.fs[k&3]; } + AI float min() const { + #if defined(__aarch64__) + return vminvq_f32(fVec); + #else + SkNx min = Min(*this, vrev64q_f32(fVec)); + return std::min(min[0], min[2]); + #endif + } + + AI float max() const { + #if defined(__aarch64__) + return vmaxvq_f32(fVec); + #else + SkNx max = Max(*this, vrev64q_f32(fVec)); + return std::max(max[0], max[2]); + #endif + } + AI bool allTrue() const { #if defined(__aarch64__) return 0 != vminvq_u32(vreinterpretq_u32_f32(fVec)); diff --git a/src/opts/SkNx_sse.h b/src/opts/SkNx_sse.h index bd5c58e261..00edc3a51f 100644 --- a/src/opts/SkNx_sse.h +++ b/src/opts/SkNx_sse.h @@ -176,6 +176,18 @@ public: return pun.fs[k&3]; } + AI float min() const { + SkNx min = Min(*this, _mm_shuffle_ps(fVec, fVec, _MM_SHUFFLE(2,3,0,1))); + min = Min(min, _mm_shuffle_ps(min.fVec, min.fVec, _MM_SHUFFLE(0,1,2,3))); + return min[0]; + } + + AI float max() const { + SkNx max = Max(*this, _mm_shuffle_ps(fVec, fVec, _MM_SHUFFLE(2,3,0,1))); + max = Max(max, _mm_shuffle_ps(max.fVec, max.fVec, _MM_SHUFFLE(0,1,2,3))); + return max[0]; + } + AI bool allTrue() const { return 0xffff == _mm_movemask_epi8(_mm_castps_si128(fVec)); } AI bool anyTrue() const { return 0x0000 != _mm_movemask_epi8(_mm_castps_si128(fVec)); } diff --git a/tests/SkNxTest.cpp b/tests/SkNxTest.cpp index c27b88c12b..c82f39d516 100644 --- a/tests/SkNxTest.cpp +++ b/tests/SkNxTest.cpp @@ -466,6 +466,18 @@ DEF_TEST(Sk2f_Store4, r) { REPORTER_ASSERT(r, dst[7] == 7); } +DEF_TEST(Sk4f_minmax, r) { + REPORTER_ASSERT(r, 3 == Sk4f(0,1,2,3).max()); + REPORTER_ASSERT(r, 2 == Sk4f(1,-5,2,-1).max()); + REPORTER_ASSERT(r, -1 == Sk4f(-2,-1,-6,-3).max()); + REPORTER_ASSERT(r, 3 == Sk4f(3,2,1,0).max()); + + REPORTER_ASSERT(r, 0 == Sk4f(0,1,2,3).min()); + REPORTER_ASSERT(r, -5 == Sk4f(1,-5,2,-1).min()); + REPORTER_ASSERT(r, -6 == Sk4f(-2,-1,-6,-3).min()); + REPORTER_ASSERT(r, 0 == Sk4f(3,2,1,0).min()); +} + DEF_TEST(SkNf_anyTrue_allTrue, r) { REPORTER_ASSERT(r, (Sk2f{1,2} < Sk2f{3,4}).anyTrue()); REPORTER_ASSERT(r, (Sk2f{1,2} < Sk2f{3,4}).allTrue()); |