@@ -353,6 +353,43 @@ namespace xsimd
353353 return kernel::bitwise_cast<A>(x, batch<T_out, A> {}, A {});
354354 }
355355
356+ namespace detail
357+ {
358+ // Detection for kernel overloads accepting ``batch_constant`` in ``bitwise_lshift``
359+ // directly (or in a parent register function).
360+ // The ``batch_constant`` overload is a rare but useful optimization.
361+ // Running the detection here is less error prone than to add a fallback to all
362+ // architectures.
363+
364+ template <class Arch , class Batch , class BatchConstant , class = void >
365+ struct has_bitwise_lshift_batch_const : std::false_type
366+ {
367+ };
368+
369+ template <class Arch , class Batch , class BatchConstant >
370+ struct has_bitwise_lshift_batch_const <
371+ Arch, Batch, BatchConstant,
372+ void_t <decltype (kernel::bitwise_lshift<Arch>(
373+ std::declval<Batch>(), std::declval<BatchConstant>(), Arch {}))>>
374+ : std::true_type
375+ {
376+ };
377+
378+ template <class Arch , class T , T... Values>
379+ XSIMD_INLINE batch<T, Arch> bitwise_lshift_batch_const (batch<T, Arch> const & x, batch_constant<T, Arch, Values...> shift, std::true_type) noexcept
380+ {
381+ // Optimized ``batch_constant`` implementation
382+ return kernel::bitwise_lshift<Arch>(x, shift, Arch {});
383+ }
384+
385+ template <class Arch , class T , T... Values>
386+ XSIMD_INLINE batch<T, Arch> bitwise_lshift_batch_const (batch<T, Arch> const & x, batch_constant<T, Arch, Values...> shift, std::false_type) noexcept
387+ {
388+ // Fallback to regular run-time implementation
389+ return kernel::bitwise_lshift<Arch>(x, shift.as_batch (), Arch {});
390+ }
391+ }
392+
356393 /* *
357394 * @ingroup batch_bitwise
358395 *
@@ -367,17 +404,24 @@ namespace xsimd
367404 detail::static_check_supported_config<T, A>();
368405 return kernel::bitwise_lshift<A>(x, shift, A {});
369406 }
407+ template <size_t shift, class T , class A >
408+ XSIMD_INLINE batch<T, A> bitwise_lshift (batch<T, A> const & x) noexcept
409+ {
410+ detail::static_check_supported_config<T, A>();
411+ return kernel::bitwise_lshift<shift, A>(x, A {});
412+ }
370413 template <class T , class A >
371414 XSIMD_INLINE batch<T, A> bitwise_lshift (batch<T, A> const & x, batch<T, A> const & shift) noexcept
372415 {
373416 detail::static_check_supported_config<T, A>();
374417 return kernel::bitwise_lshift<A>(x, shift, A {});
375418 }
376- template <size_t shift, class T , class A >
377- XSIMD_INLINE batch<T, A> bitwise_lshift (batch<T, A> const & x) noexcept
419+ template <class T , class A , T... Values >
420+ XSIMD_INLINE batch<T, A> bitwise_lshift (batch<T, A> const & x, batch_constant<T, A, Values...> shift ) noexcept
378421 {
379422 detail::static_check_supported_config<T, A>();
380- return kernel::bitwise_lshift<shift, A>(x, A {});
423+ using has_batch_const_impl = detail::has_bitwise_lshift_batch_const<A, decltype (x), decltype (shift)>;
424+ return detail::bitwise_lshift_batch_const<A>(x, shift, has_batch_const_impl {});
381425 }
382426
383427 /* *
0 commit comments