@@ -353,6 +353,41 @@ 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 A , class B , class C , class = void >
365+ struct has_bitwise_lshift_batch_const : std::false_type
366+ {
367+ };
368+
369+ template <class A , class B , class C >
370+ struct has_bitwise_lshift_batch_const <A, B, C,
371+ void_t <decltype (kernel::bitwise_lshift<A>(std::declval<B>(), std::declval<C>(), A {}))>>
372+ : std::true_type
373+ {
374+ };
375+
376+ template <class A , class T , T... Values>
377+ XSIMD_INLINE batch<T, A> bitwise_lshift_batch_const (batch<T, A> const & x, batch_constant<T, A, Values...> shift, std::true_type) noexcept
378+ {
379+ // Optimized ``batch_constant`` implementation
380+ return kernel::bitwise_lshift<A>(x, shift, A {});
381+ }
382+
383+ template <class A , class T , T... Values>
384+ XSIMD_INLINE batch<T, A> bitwise_lshift_batch_const (batch<T, A> const & x, batch_constant<T, A, Values...> shift, std::false_type) noexcept
385+ {
386+ // Fallback to regular run-time implementation
387+ return kernel::bitwise_lshift<A>(x, shift.as_batch (), A {});
388+ }
389+ }
390+
356391 /* *
357392 * @ingroup batch_bitwise
358393 *
@@ -367,17 +402,24 @@ namespace xsimd
367402 detail::static_check_supported_config<T, A>();
368403 return kernel::bitwise_lshift<A>(x, shift, A {});
369404 }
405+ template <size_t shift, class T , class A >
406+ XSIMD_INLINE batch<T, A> bitwise_lshift (batch<T, A> const & x) noexcept
407+ {
408+ detail::static_check_supported_config<T, A>();
409+ return kernel::bitwise_lshift<shift, A>(x, A {});
410+ }
370411 template <class T , class A >
371412 XSIMD_INLINE batch<T, A> bitwise_lshift (batch<T, A> const & x, batch<T, A> const & shift) noexcept
372413 {
373414 detail::static_check_supported_config<T, A>();
374415 return kernel::bitwise_lshift<A>(x, shift, A {});
375416 }
376- template <size_t shift, class T , class A >
377- XSIMD_INLINE batch<T, A> bitwise_lshift (batch<T, A> const & x) noexcept
417+ template <class T , class A , T... Values >
418+ XSIMD_INLINE batch<T, A> bitwise_lshift (batch<T, A> const & x, batch_constant<T, A, Values...> shift ) noexcept
378419 {
379420 detail::static_check_supported_config<T, A>();
380- return kernel::bitwise_lshift<shift, A>(x, A {});
421+ using has_batch_const_impl = detail::has_bitwise_lshift_batch_const<A, decltype (x), decltype (shift)>;
422+ return detail::bitwise_lshift_batch_const<A>(x, shift, has_batch_const_impl {});
381423 }
382424
383425 /* *
0 commit comments