@@ -28,6 +28,42 @@ namespace amrex::simd
2828# if __cplusplus >= 202002L
2929 using vir::cvt;
3030# endif
31+
32+ /* * Vectorized ternary operator: select(mask, true_val, false_val)
33+ *
34+ * Selects elements from true_val where mask is true and from false_val
35+ * where mask is false. Analogous to (mask ? true_val : false_val) for
36+ * scalars.
37+ *
38+ * Note: both true_val and false_val are eagerly evaluated (function
39+ * arguments). To guard against operations like division by zero,
40+ * sanitize inputs before the operation rather than relying on
41+ * conditional selection.
42+ *
43+ * Example:
44+ * ```cpp
45+ * template <typename T>
46+ * T compute (T const& a, T const& b)
47+ * {
48+ * auto safe_b = amrex::simd::stdx::select(b != T(0), b, T(1));
49+ * return amrex::simd::stdx::select(b != T(0), a / safe_b, T(0));
50+ * }
51+ * ```
52+ *
53+ * @see C++26 std::simd select
54+ */
55+ // TODO: remove when SIMD provider (vir-simd / C++26) provides select
56+ template <typename T, typename Abi>
57+ AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
58+ simd<T, Abi> select (
59+ typename simd<T, Abi>::mask_type const & mask,
60+ simd<T, Abi> const & true_val,
61+ simd<T, Abi> const & false_val)
62+ {
63+ simd<T, Abi> result = false_val;
64+ where (mask, result) = true_val;
65+ return result;
66+ }
3167#else
3268 // fallback implementations for functions that are commonly used in portable code paths
3369
@@ -82,6 +118,19 @@ namespace amrex::simd
82118 {
83119 return {mask, value};
84120 }
121+
122+ /* * Vectorized ternary operator (scalar fallback for simd select)
123+ *
124+ * @see select in the AMREX_USE_SIMD path above
125+ * @see C++26 std::simd select
126+ */
127+ // TODO: remove when SIMD provider (vir-simd / C++26) provides select
128+ template <typename T>
129+ AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
130+ T select (bool const mask, T const & true_val, T const & false_val)
131+ {
132+ return mask ? true_val : false_val;
133+ }
85134#endif
86135 }
87136
@@ -214,48 +263,6 @@ namespace amrex::simd
214263 return val_arr[n];
215264 }
216265
217- /* * Vectorized ternary operator: select(mask, true_val, false_val)
218- *
219- * Selects elements from true_val where mask is true and from false_val where
220- * mask is false. Analogous to (mask ? true_val : false_val) for scalars.
221- *
222- * Note: both true_val and false_val are eagerly evaluated (function arguments).
223- * To guard against operations like division by zero, sanitize inputs before
224- * the operation rather than relying on conditional selection.
225- *
226- * Example:
227- * ```cpp
228- * template <typename T>
229- * T compute (T const& a, T const& b)
230- * {
231- * auto safe_b = amrex::simd::select(b != T(0), b, T(1));
232- * return amrex::simd::select(b != T(0), a / safe_b, T(0));
233- * }
234- * ```
235- *
236- * @see C++26 std::datapar::select
237- */
238- #ifdef AMREX_USE_SIMD
239- template <typename T, typename Abi>
240- AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
241- stdx::simd<T, Abi> select (
242- typename stdx::simd<T, Abi>::mask_type const & mask,
243- stdx::simd<T, Abi> const & true_val,
244- stdx::simd<T, Abi> const & false_val)
245- {
246- stdx::simd<T, Abi> result = false_val;
247- stdx::where (mask, result) = true_val;
248- return result;
249- }
250- #else
251- template <typename T>
252- AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
253- T select (bool const mask, T const & true_val, T const & false_val)
254- {
255- return mask ? true_val : false_val;
256- }
257- #endif
258-
259266 /* * Load 1D contiguous data from array pointers
260267 *
261268 * On GPU and CPU w/o SIMD, this dereferences a 1D array element at the
0 commit comments