Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package Vc for openSUSE:Factory checked in at 2023-10-24 20:08:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/Vc (Old) and /work/SRC/openSUSE:Factory/.Vc.new.24901 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "Vc" Tue Oct 24 20:08:06 2023 rev:18 rq:1119735 version:1.4.4 Changes: -------- --- /work/SRC/openSUSE:Factory/Vc/Vc.changes 2022-07-06 15:42:15.686540379 +0200 +++ /work/SRC/openSUSE:Factory/.Vc.new.24901/Vc.changes 2023-10-24 20:08:14.220262353 +0200 @@ -1,0 +2,10 @@ +Mon Oct 23 20:12:57 UTC 2023 - Christoph G <f...@grueninger.de> + +- Update to version 1.4.4 + * Add missing vectorcall to isImplementationSupported + * Adapt to cpp17: std::iterator is deprecated + * Rename None to NoTransformation in enum class Category to avoid + a clash with X11 library + * Fix horizontal min/max for uchar + +------------------------------------------------------------------- Old: ---- Vc-1.4.3.tar.gz New: ---- Vc-1.4.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ Vc.spec ++++++ --- /var/tmp/diff_new_pack.pv8M5J/_old 2023-10-24 20:08:15.032291875 +0200 +++ /var/tmp/diff_new_pack.pv8M5J/_new 2023-10-24 20:08:15.036292021 +0200 @@ -1,7 +1,7 @@ # # spec file for package Vc # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: Vc -Version: 1.4.3 +Version: 1.4.4 Release: 0 Summary: Collection of SIMD Vector Classes License: BSD-3-Clause ++++++ Vc-1.4.3.tar.gz -> Vc-1.4.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/README.md new/Vc-1.4.4/README.md --- old/Vc-1.4.3/README.md 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/README.md 2023-10-06 09:47:32.000000000 +0200 @@ -164,6 +164,7 @@ Alternatively, you can find nightly builds of the documentation at: * [1.4 branch](https://vcdevel.github.io/Vc-1.4/) +* [1.4.4 release](https://vcdevel.github.io/Vc-1.4.4/) * [1.4.3 release](https://vcdevel.github.io/Vc-1.4.3/) * [1.4.2 release](https://vcdevel.github.io/Vc-1.4.2/) * [1.4.1 release](https://vcdevel.github.io/Vc-1.4.1/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/Vc/common/simdize.h new/Vc-1.4.4/Vc/common/simdize.h --- old/Vc-1.4.3/Vc/common/simdize.h 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/Vc/common/simdize.h 2023-10-06 09:47:32.000000000 +0200 @@ -152,7 +152,7 @@ */ enum class Category { ///\internal No transformation - None, + NoTransformation, ///\internal simple Vector<T> transformation ArithmeticVectorizable, ///\internal transform an input iterator to return vectorized entries @@ -186,7 +186,7 @@ ? Category::OutputIterator : is_base_of<std::input_iterator_tag, ItCat>::value ? Category::InputIterator - : Category::None; + : Category::NoTransformation; } /**\internal * This overload is selected for pointer types => RandomAccessIterator. @@ -201,7 +201,7 @@ */ template <typename T> constexpr Category iteratorCategories(...) { - return Category::None; + return Category::NoTransformation; } /**\internal @@ -225,10 +225,10 @@ is_same<T, unsigned int>::value || is_same<T, float>::value || is_same<T, double>::value) ? Category::ArithmeticVectorizable - : iteratorCategories<T>(int()) != Category::None + : iteratorCategories<T>(int()) != Category::NoTransformation ? iteratorCategories<T>(int()) : is_class_template<T>::value ? Category::ClassTemplate - : Category::None; + : Category::NoTransformation; } /**\internal @@ -279,7 +279,7 @@ * Specialization of ReplaceTypes that is used for types that should not be transformed by * simdize. */ -template <typename T, size_t N, typename MT> struct ReplaceTypes<T, N, MT, Category::None> +template <typename T, size_t N, typename MT> struct ReplaceTypes<T, N, MT, Category::NoTransformation> { typedef T type; }; @@ -1553,12 +1553,11 @@ template <typename T, size_t N, IteratorDetails::Mutable M, typename V, size_t Size_> class Iterator<T, N, M, V, Size_, std::forward_iterator_tag> - : public std::iterator<typename std::iterator_traits<T>::iterator_category, V, - typename std::iterator_traits<T>::difference_type, - IteratorDetails::Pointer<T, V, M>, - IteratorDetails::Reference<T, V, M>> { public: + using iterator_category = typename std::iterator_traits<T>::iterator_category; + using difference_type = typename std::iterator_traits<T>::difference_type; + using value_type = V; using pointer = IteratorDetails::Pointer<T, V, M>; using reference = IteratorDetails::Reference<T, V, M>; using const_pointer = IteratorDetails::Pointer<T, V, IteratorDetails::Mutable::No>; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/Vc/sse/detail.h new/Vc-1.4.4/Vc/sse/detail.h --- old/Vc-1.4.3/Vc/sse/detail.h 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/Vc/sse/detail.h 2023-10-06 09:47:32.000000000 +0200 @@ -719,9 +719,9 @@ return std::min(schar(_mm_cvtsi128_si32(a) >> 8), schar(_mm_cvtsi128_si32(a))); } Vc_INTRINSIC uchar min(__m128i a, uchar) { - a = min(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2)), schar()); - a = min(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 0, 3, 2)), schar()); - a = min(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 1, 1, 1)), schar()); + a = min(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2)), uchar()); + a = min(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 0, 3, 2)), uchar()); + a = min(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 1, 1, 1)), uchar()); return std::min((_mm_cvtsi128_si32(a) >> 8) & 0xff, _mm_cvtsi128_si32(a) & 0xff); } @@ -764,9 +764,9 @@ return std::max(schar(_mm_cvtsi128_si32(a) >> 8), schar(_mm_cvtsi128_si32(a))); } Vc_INTRINSIC uchar max(__m128i a, uchar) { - a = max(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2)), schar()); - a = max(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 0, 3, 2)), schar()); - a = max(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 1, 1, 1)), schar()); + a = max(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2)), uchar()); + a = max(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 0, 3, 2)), uchar()); + a = max(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 1, 1, 1)), uchar()); return std::max((_mm_cvtsi128_si32(a) >> 8) & 0xff, _mm_cvtsi128_si32(a) & 0xff); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/Vc/version.h new/Vc-1.4.4/Vc/version.h --- old/Vc-1.4.3/Vc/version.h 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/Vc/version.h 2023-10-06 09:47:32.000000000 +0200 @@ -37,13 +37,13 @@ * \ingroup Utilities * Contains the version string of the %Vc headers. Same as Vc::versionString(). */ -#define Vc_VERSION_STRING "1.4.3" +#define Vc_VERSION_STRING "1.4.4" /** * \ingroup Utilities * Contains the encoded version number of the %Vc headers. Same as Vc::versionNumber(). */ -#define Vc_VERSION_NUMBER 0x010406 +#define Vc_VERSION_NUMBER 0x010408 /** * \ingroup Utilities diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/doc/Doxyfile new/Vc-1.4.4/doc/Doxyfile --- old/Vc-1.4.3/doc/Doxyfile 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/doc/Doxyfile 2023-10-06 09:47:32.000000000 +0200 @@ -38,7 +38,7 @@ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.4.3 +PROJECT_NUMBER = 1.4.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/godbolt/Vc new/Vc-1.4.4/godbolt/Vc --- old/Vc-1.4.3/godbolt/Vc 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/godbolt/Vc 2023-10-06 09:47:32.000000000 +0200 @@ -476,8 +476,8 @@ } #ifndef VC_VERSION_H_ #define VC_VERSION_H_ -#define Vc_VERSION_STRING "1.4.2-dev" -#define Vc_VERSION_NUMBER 0x010405 +#define Vc_VERSION_STRING "1.4.3-dev" +#define Vc_VERSION_NUMBER 0x010407 #define Vc_VERSION_CHECK(major,minor,patch) ((major << 16) | (minor << 8) | (patch << 1)) #define Vc_LIBRARY_ABI_VERSION 5 #define Vc_IS_VERSION_2 (Vc_VERSION_NUMBER >= Vc_VERSION_CHECK(1, 70, 0)) @@ -913,9 +913,6 @@ #if defined Vc_GCC && Vc_GCC >= 0x60000 #define Vc_TEMPLATES_DROP_ATTRIBUTES 1 #endif -#if Vc_IS_VERSION_2 || (defined Vc_GCC && Vc_GCC >= 0x60000) -#define Vc_RECURSIVE_MEMORY 1 -#endif #if defined Vc_CLANG || defined Vc_APPLECLANG #define Vc_UNREACHABLE __builtin_unreachable #define Vc_NEVER_INLINE [[gnu::noinline]] @@ -1134,11 +1131,6 @@ #define Vc_EXACT_TYPE(_test,_reference,_type) \ typename std::enable_if<std::is_same<_test, _reference>::value, _type>::type #define Vc_make_unique(name) Vc_CAT(Vc_,name,_,__LINE__) -#if defined(Vc_ICC) || defined(Vc_CLANG) || defined Vc_APPLECLANG -#define Vc_OFFSETOF(Type,member) (reinterpret_cast<const char *>(&reinterpret_cast<const Type *>(0)->member) - reinterpret_cast<const char *>(0)) -#else -#define Vc_OFFSETOF(Type,member) offsetof(Type, member) -#endif #if defined(Vc_NO_NOEXCEPT) #define Vc_NOEXCEPT throw() #else @@ -1187,6 +1179,9 @@ namespace Detail { template<typename T> struct MayAliasImpl { +#ifdef Vc_ICC +#pragma warning(disable:2621) +#endif #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wattributes" @@ -1195,13 +1190,12 @@ #ifdef __GNUC__ #pragma GCC diagnostic pop #endif +#ifdef Vc_ICC +#pragma warning(enable:2621) +#endif }; } -#ifdef Vc_ICC -template <typename T> using MayAlias [[gnu::may_alias]] = T; -#else template <typename T> using MayAlias = typename Detail::MayAliasImpl<T>::type; -#endif template <class To, class From> MayAlias<To> &aliasing_cast(From &x) { return *reinterpret_cast<MayAlias<To> *>(&x); @@ -2300,6 +2294,137 @@ gatherImplementation( Common::make_gather<1>(mem, Common::convertIndexVector(indexes)), mask); } +template <typename S1, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array, +const EntryType S1::*member1, +IT indexes) +{ +gather(Common::SubscriptOperation<const S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1] +.gatherArguments()); +} +template <typename S1, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array, +const EntryType S1::*member1, +IT indexes, MaskArgument mask) +{ +gather(Common::SubscriptOperation<const S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1] +.gatherArguments(), +mask); +} +template <typename S1, typename S2, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array, +const S2 S1::*member1, +const EntryType S2::*member2, +IT indexes) +{ +gather(Common::SubscriptOperation<const S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1][member2] +.gatherArguments()); +} +template <typename S1, typename S2, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array, +const S2 S1::*member1, +const EntryType S2::*member2, +IT indexes, MaskArgument mask) +{ +gather(Common::SubscriptOperation<const S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1][member2] +.gatherArguments(), +mask); +} +template <typename S1, typename IT1, typename IT2> +Vc_DEPRECATED( +"use the subscript operator to Vc::array or Vc::vector " +"instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array, +const EntryType *const S1::*ptrMember1, +IT1 outerIndexes, IT2 innerIndexes) +{ +gather(Common::SubscriptOperation<const S1, IT1, std::ratio<1, 1>, true>( +array, outerIndexes)[ptrMember1][innerIndexes] +.gatherArguments()); +} +template <typename S1, typename IT1, typename IT2> +Vc_DEPRECATED( +"use the subscript operator to Vc::array or Vc::vector " +"instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array, +const EntryType *const S1::*ptrMember1, +IT1 outerIndexes, IT2 innerIndexes, +MaskArgument mask) +{ +gather(Common::SubscriptOperation<const S1, IT1, std::ratio<1, 1>, true>( +array, outerIndexes)[ptrMember1][innerIndexes] +.gatherArguments(), +mask); +} +template <typename S1, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void gather(const S1 *array, +const EntryType S1::*member1, IT indexes) +{ +gather(Common::SubscriptOperation<const S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1] +.gatherArguments()); +} +template <typename S1, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void gather(const S1 *array, +const EntryType S1::*member1, +IT indexes, +MaskArgument mask) +{ +gather(Common::SubscriptOperation<const S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1] +.gatherArguments(), +mask); +} +template <typename S1, typename S2, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void gather(const S1 *array, const S2 S1::*member1, +const EntryType S2::*member2, IT indexes) +{ +gather(Common::SubscriptOperation<const S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1][member2] +.gatherArguments()); +} +template <typename S1, typename S2, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void gather(const S1 *array, const S2 S1::*member1, +const EntryType S2::*member2, IT indexes, +MaskArgument mask) +{ +gather(Common::SubscriptOperation<const S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1][member2] +.gatherArguments(), +mask); +} +template <typename S1, typename IT1, typename IT2> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void gather(const S1 *array, +const EntryType *const S1::*ptrMember1, +IT1 outerIndexes, IT2 innerIndexes) +{ +gather(Common::SubscriptOperation<const S1, IT1, std::ratio<1, 1>, true>( +array, outerIndexes)[ptrMember1][innerIndexes] +.gatherArguments()); +} +template <typename S1, typename IT1, typename IT2> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void gather(const S1 *array, +const EntryType *const S1::*ptrMember1, +IT1 outerIndexes, IT2 innerIndexes, +MaskArgument mask) +{ +gather(Common::SubscriptOperation<const S1, IT1, std::ratio<1, 1>, true>( +array, outerIndexes)[ptrMember1][innerIndexes] +.gatherArguments(), +mask); +} template <class MT, class IT, int Scale> Vc_INTRINSIC void gather(const Common::GatherArguments<MT, IT, Scale> &args) { @@ -2355,6 +2480,67 @@ Vc_ASSERT_SCATTER_PARAMETER_TYPES_; scatterImplementation(mem, std::forward<IT>(indexes), mask); } +template <typename S1, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void scatter(S1 *array, EntryType S1::*member1, +IT indexes) const +{ +scatter(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1] +.scatterArguments()); +} +template <typename S1, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void scatter(S1 *array, EntryType S1::*member1, +IT indexes, MaskArgument mask) const +{ +scatter(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1] +.scatterArguments(), +mask); +} +template <typename S1, typename S2, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void scatter(S1 *array, S2 S1::*member1, +EntryType S2::*member2, +IT indexes) const +{ +scatter(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1][member2] +.scatterArguments()); +} +template <typename S1, typename S2, typename IT> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void scatter(S1 *array, S2 S1::*member1, +EntryType S2::*member2, IT indexes, +MaskArgument mask) const +{ +scatter(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>( +array, indexes)[member1][member2] +.scatterArguments(), +mask); +} +template <typename S1, typename IT1, typename IT2> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void scatter(S1 *array, EntryType *S1::*ptrMember1, +IT1 outerIndexes, +IT2 innerIndexes) const +{ +scatter(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>( +array, outerIndexes)[ptrMember1][innerIndexes] +.scatterArguments()); +} +template <typename S1, typename IT1, typename IT2> +Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector " +"instead.") inline void scatter(S1 *array, EntryType *S1::*ptrMember1, +IT1 outerIndexes, IT2 innerIndexes, +MaskArgument mask) const +{ +scatter(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>( +array, outerIndexes)[ptrMember1][innerIndexes] +.scatterArguments(), +mask); +} template <typename MT, typename IT> Vc_INTRINSIC void scatter(const Common::ScatterArguments<MT, IT> &args) const { @@ -4978,6 +5164,74 @@ } #endif #include <cstdlib> +#ifndef VC_SSE_DEBUG_H_ +#define VC_SSE_DEBUG_H_ +#ifndef NDEBUG +#include <iostream> +#include <iomanip> +#endif +namespace Vc_VERSIONED_NAMESPACE +{ +namespace SSE +{ +#ifdef NDEBUG +class DebugStream +{ +public: +DebugStream(const char *, const char *, int) {} +template<typename T> inline DebugStream &operator<<(const T &) { return *this; } +}; +#else +class DebugStream +{ +private: +static char hexChar(char x) { return x + (x > 9 ? 87 : 48); } +template<typename T, typename V> static void printVector(V _x) +{ +std::cerr << "0x"; +const auto bytes = reinterpret_cast<const std::uint8_t *>(&_x); +for (std::size_t i = 0; i < sizeof(V); ++i) { +std::cerr << hexChar(bytes[i] >> 4) << hexChar(bytes[i] & 0xf); +if (i % 4 == 3) { +std::cerr << '\''; +} +} +enum { Size = sizeof(V) / sizeof(T) }; +union { V v; T m[Size]; } x = { _x }; +std::cerr << " = [" << std::setprecision(24) << x.m[0]; +for (int i = 1; i < Size; ++i) { +std::cerr << ", " << std::setprecision(24) << x.m[i]; +} +std::cerr << ']'; +} +public: +DebugStream(const char *func, const char *file, int line) +{ +std::cerr << "\033[1;40;33mDEBUG: " << file << ':' << line << ' ' << func << ' '; +} +template<typename T> DebugStream &operator<<(const T &x) { std::cerr << x; return *this; } +DebugStream &operator<<(__m128 x) { +printVector<float, __m128>(x); +return *this; +} +DebugStream &operator<<(__m128d x) { +printVector<double, __m128d>(x); +return *this; +} +DebugStream &operator<<(__m128i x) { +printVector<int, __m128i>(x); +return *this; +} +~DebugStream() +{ +std::cerr << "\033[0m" << std::endl; +} +}; +#endif +#define Vc_DEBUG Vc::SSE::DebugStream(__PRETTY_FUNCTION__, __FILE__, __LINE__) +} +} +#endif #if defined(Vc_GCC) && !defined(__OPTIMIZE__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" @@ -6898,9 +7152,9 @@ return std::min(schar(_mm_cvtsi128_si32(a) >> 8), schar(_mm_cvtsi128_si32(a))); } Vc_INTRINSIC uchar min(__m128i a, uchar) { -a = min(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2)), schar()); -a = min(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 0, 3, 2)), schar()); -a = min(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 1, 1, 1)), schar()); +a = min(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2)), uchar()); +a = min(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 0, 3, 2)), uchar()); +a = min(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 1, 1, 1)), uchar()); return std::min((_mm_cvtsi128_si32(a) >> 8) & 0xff, _mm_cvtsi128_si32(a) & 0xff); } Vc_INTRINSIC float max(__m128 a, float) { @@ -6941,9 +7195,9 @@ return std::max(schar(_mm_cvtsi128_si32(a) >> 8), schar(_mm_cvtsi128_si32(a))); } Vc_INTRINSIC uchar max(__m128i a, uchar) { -a = max(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2)), schar()); -a = max(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 0, 3, 2)), schar()); -a = max(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 1, 1, 1)), schar()); +a = max(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2)), uchar()); +a = max(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 0, 3, 2)), uchar()); +a = max(a, _mm_shufflelo_epi16(a, _MM_SHUFFLE(1, 1, 1, 1)), uchar()); return std::max((_mm_cvtsi128_si32(a) >> 8) & 0xff, _mm_cvtsi128_si32(a) & 0xff); } template <Vc::Implementation, typename T> @@ -20036,7 +20290,7 @@ #define Vc_FIXED_OP(op) \ template <class T, int N, \ class = typename std::enable_if<fixed_size_simd<T, N>::is_atomic>::type> \ -fixed_size_simd<T, N> operator op(const fixed_size_simd<T, N> &a, \ +Vc_INTRINSIC fixed_size_simd<T, N> operator op(const fixed_size_simd<T, N> &a, \ const fixed_size_simd<T, N> &b) \ { \ return {private_init, internal_data(a) op internal_data(b)}; \ @@ -20044,7 +20298,7 @@ template <class T, int N, \ class = typename std::enable_if<!fixed_size_simd<T, N>::is_atomic>::type, \ class = T> \ -fixed_size_simd<T, N> operator op(const fixed_size_simd<T, N> &a, \ +Vc_INTRINSIC fixed_size_simd<T, N> operator op(const fixed_size_simd<T, N> &a, \ const fixed_size_simd<T, N> &b) \ { \ return {internal_data0(a) op internal_data0(b), \ @@ -20057,7 +20311,7 @@ #define Vc_FIXED_OP(op) \ template <class T, int N, \ class = typename std::enable_if<fixed_size_simd<T, N>::is_atomic>::type> \ -fixed_size_simd_mask<T, N> operator op(const fixed_size_simd<T, N> &a, \ +Vc_INTRINSIC fixed_size_simd_mask<T, N> operator op(const fixed_size_simd<T, N> &a, \ const fixed_size_simd<T, N> &b) \ { \ return {private_init, internal_data(a) op internal_data(b)}; \ @@ -20065,7 +20319,7 @@ template <class T, int N, \ class = typename std::enable_if<!fixed_size_simd<T, N>::is_atomic>::type, \ class = T> \ -fixed_size_simd_mask<T, N> operator op(const fixed_size_simd<T, N> &a, \ +Vc_INTRINSIC fixed_size_simd_mask<T, N> operator op(const fixed_size_simd<T, N> &a, \ const fixed_size_simd<T, N> &b) \ { \ return {internal_data0(a) op internal_data0(b), \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/godbolt/algorithm new/Vc-1.4.4/godbolt/algorithm --- old/Vc-1.4.3/godbolt/algorithm 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/godbolt/algorithm 2023-10-06 09:47:32.000000000 +0200 @@ -335,7 +335,7 @@ using std::size_t; template <typename... Ts> struct Typelist; enum class Category { -None, +NoTransformation, ArithmeticVectorizable, InputIterator, OutputIterator, @@ -357,7 +357,7 @@ ? Category::OutputIterator : is_base_of<std::input_iterator_tag, ItCat>::value ? Category::InputIterator -: Category::None; +: Category::NoTransformation; } template <typename T> constexpr enable_if<std::is_pointer<T>::value, Category> iteratorCategories(float) @@ -366,7 +366,7 @@ } template <typename T> constexpr Category iteratorCategories(...) { -return Category::None; +return Category::NoTransformation; } template <typename T> struct is_class_template : public false_type { @@ -382,10 +382,10 @@ is_same<T, unsigned int>::value || is_same<T, float>::value || is_same<T, double>::value) ? Category::ArithmeticVectorizable -: iteratorCategories<T>(int()) != Category::None +: iteratorCategories<T>(int()) != Category::NoTransformation ? iteratorCategories<T>(int()) : is_class_template<T>::value ? Category::ClassTemplate -: Category::None; +: Category::NoTransformation; } template <typename T, size_t TupleSize = std::tuple_size<T>::value> constexpr size_t determine_tuple_size() @@ -408,7 +408,7 @@ struct ReplaceTypes : public The_simdization_for_the_requested_type_is_not_implemented<T> { }; -template <typename T, size_t N, typename MT> struct ReplaceTypes<T, N, MT, Category::None> +template <typename T, size_t N, typename MT> struct ReplaceTypes<T, N, MT, Category::NoTransformation> { typedef T type; }; @@ -1188,7 +1188,9 @@ Traits::is_simd_vector<V>::value && Traits::has_contiguous_storage<It>::value, It> it) { +#ifndef _MSC_VER Vc_ASSERT(&*it + 1 == &*(it + 1)); +#endif return V(&*it, Vc::Unaligned); } template <typename It, typename V> @@ -1299,12 +1301,11 @@ class Iterator; template <typename T, size_t N, IteratorDetails::Mutable M, typename V, size_t Size_> class Iterator<T, N, M, V, Size_, std::forward_iterator_tag> -: public std::iterator<typename std::iterator_traits<T>::iterator_category, V, -typename std::iterator_traits<T>::difference_type, -IteratorDetails::Pointer<T, V, M>, -IteratorDetails::Reference<T, V, M>> { public: +using iterator_category = typename std::iterator_traits<T>::iterator_category; +using difference_type = typename std::iterator_traits<T>::difference_type; +using value_type = V; using pointer = IteratorDetails::Pointer<T, V, M>; using reference = IteratorDetails::Reference<T, V, M>; using const_pointer = IteratorDetails::Pointer<T, V, IteratorDetails::Mutable::No>; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/godbolt/containers new/Vc-1.4.4/godbolt/containers --- old/Vc-1.4.3/godbolt/containers 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/godbolt/containers 2023-10-06 09:47:32.000000000 +0200 @@ -151,9 +151,481 @@ #endif #ifndef VC_MEMORY_ #define VC_MEMORY_ -#ifndef VC_COMMON_MAKE_UNIQUE_H_ -#define VC_COMMON_MAKE_UNIQUE_H_ -#include <memory> +#ifndef VC_COMMON_MEMORY_H_ +#define VC_COMMON_MEMORY_H_ +#ifndef VC_COMMON_MEMORYBASE_H_ +#define VC_COMMON_MEMORYBASE_H_ +#include <assert.h> +#include <type_traits> +#include <iterator> +namespace Vc_VERSIONED_NAMESPACE +{ +namespace Common +{ +#define Vc_MEM_OPERATOR_EQ(op) \ +template<typename T> \ +Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator op##=(const T &x) { \ +const V v = value() op x; \ +v.store(&m_data[0], Flags()); \ +return *this; \ +} +template<typename _V, typename Flags> class MemoryVector +{ +typedef typename std::remove_cv<_V>::type V; +template<typename T, typename R> using enable_if_mutable = +typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type; +using EntryType = +typename std::conditional<std::is_const<_V>::value, const typename V::EntryType, +typename V::EntryType>::type; +typedef typename V::Mask Mask; +EntryType m_data[V::Size]; +public: +Vc_INTRINSIC MemoryVector() = default; +MemoryVector(const MemoryVector &) = delete; +MemoryVector(MemoryVector &&) = delete; +Vc_ALWAYS_INLINE Vc_PURE V value() const { return V(&m_data[0], Flags()); } +Vc_ALWAYS_INLINE Vc_PURE operator V() const { return value(); } +template<typename T> +Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator=(const T &x) { +V v; +v = x; +v.store(&m_data[0], Flags()); +return *this; +} +Vc_ALL_BINARY(Vc_MEM_OPERATOR_EQ); +Vc_ALL_ARITHMETICS(Vc_MEM_OPERATOR_EQ); +Vc_ALWAYS_INLINE EntryType &operator[](size_t i) { return m_data[i]; } +Vc_ALWAYS_INLINE const EntryType &operator[](size_t i) const { return m_data[i]; } +}; +template<typename _V, typename Flags> class MemoryVectorIterator +{ +typedef typename std::remove_cv<_V>::type V; +template<typename T, typename R> using enable_if_mutable = +typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type; +using iterator_traits = std::iterator_traits<MemoryVector<_V, Flags> *>; +MemoryVector<_V, Flags> *d; +public: +typedef typename iterator_traits::difference_type difference_type; +typedef typename iterator_traits::value_type value_type; +typedef typename iterator_traits::pointer pointer; +typedef typename iterator_traits::reference reference; +typedef typename iterator_traits::iterator_category iterator_category; +constexpr MemoryVectorIterator(MemoryVector<_V, Flags> *dd) : d(dd) {} +constexpr MemoryVectorIterator(const MemoryVectorIterator &) = default; +constexpr MemoryVectorIterator(MemoryVectorIterator &&) = default; +Vc_ALWAYS_INLINE MemoryVectorIterator &operator=(const MemoryVectorIterator &) = default; +Vc_ALWAYS_INLINE void *orderBy() const { return d; } +Vc_ALWAYS_INLINE difference_type operator-(const MemoryVectorIterator &rhs) const { return d - rhs.d; } +Vc_ALWAYS_INLINE reference operator[](size_t i) const { return d[i]; } +Vc_ALWAYS_INLINE reference operator*() const { return *d; } +Vc_ALWAYS_INLINE pointer operator->() const { return d; } +Vc_ALWAYS_INLINE MemoryVectorIterator &operator++() { ++d; return *this; } +Vc_ALWAYS_INLINE MemoryVectorIterator operator++(int) { MemoryVectorIterator r(*this); ++d; return r; } +Vc_ALWAYS_INLINE MemoryVectorIterator &operator--() { --d; return *this; } +Vc_ALWAYS_INLINE MemoryVectorIterator operator--(int) { MemoryVectorIterator r(*this); --d; return r; } +Vc_ALWAYS_INLINE MemoryVectorIterator &operator+=(size_t n) { d += n; return *this; } +Vc_ALWAYS_INLINE MemoryVectorIterator &operator-=(size_t n) { d -= n; return *this; } +Vc_ALWAYS_INLINE MemoryVectorIterator operator+(size_t n) const { return MemoryVectorIterator(d + n); } +Vc_ALWAYS_INLINE MemoryVectorIterator operator-(size_t n) const { return MemoryVectorIterator(d - n); } +}; +template<typename V, typename FlagsL, typename FlagsR> +Vc_ALWAYS_INLINE bool operator==(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r) +{ +return l.orderBy() == r.orderBy(); +} +template<typename V, typename FlagsL, typename FlagsR> +Vc_ALWAYS_INLINE bool operator!=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r) +{ +return l.orderBy() != r.orderBy(); +} +template<typename V, typename FlagsL, typename FlagsR> +Vc_ALWAYS_INLINE bool operator>=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r) +{ +return l.orderBy() >= r.orderBy(); +} +template<typename V, typename FlagsL, typename FlagsR> +Vc_ALWAYS_INLINE bool operator<=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r) +{ +return l.orderBy() <= r.orderBy(); +} +template<typename V, typename FlagsL, typename FlagsR> +Vc_ALWAYS_INLINE bool operator> (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r) +{ +return l.orderBy() > r.orderBy(); +} +template<typename V, typename FlagsL, typename FlagsR> +Vc_ALWAYS_INLINE bool operator< (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r) +{ +return l.orderBy() < r.orderBy(); +} +#undef Vc_MEM_OPERATOR_EQ +#define Vc_VPH_OPERATOR(op) \ +template <typename V1, typename Flags1, typename V2, typename Flags2> \ +decltype(std::declval<V1>() op std::declval<V2>()) operator op( \ +const MemoryVector<V1, Flags1> &x, const MemoryVector<V2, Flags2> &y) \ +{ \ +return x.value() op y.value(); \ +} +Vc_ALL_ARITHMETICS(Vc_VPH_OPERATOR); +Vc_ALL_BINARY (Vc_VPH_OPERATOR); +Vc_ALL_COMPARES (Vc_VPH_OPERATOR); +#undef Vc_VPH_OPERATOR +template<typename V, typename Parent, typename Flags = Prefetch<>> class MemoryRange +{ +Parent *m_parent; +size_t m_first; +size_t m_last; +public: +MemoryRange(Parent *p, size_t firstIndex, size_t lastIndex) +: m_parent(p), m_first(firstIndex), m_last(lastIndex) +{} +MemoryVectorIterator<V, Flags> begin() const { return &m_parent->vector(m_first , Flags()); } +MemoryVectorIterator<V, Flags> end() const { return &m_parent->vector(m_last + 1, Flags()); } +}; +template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryDimensionBase; +template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 1, RowMemory> +{ +private: +Parent *p() { return static_cast<Parent *>(this); } +const Parent *p() const { return static_cast<const Parent *>(this); } +public: +typedef typename V::EntryType EntryType; +Vc_ALWAYS_INLINE Vc_PURE EntryType *entries() { return &p()->m_mem[0]; } +Vc_ALWAYS_INLINE Vc_PURE const EntryType *entries() const { return &p()->m_mem[0]; } +Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(size_t i) { return entries()[i]; } +Vc_ALWAYS_INLINE Vc_PURE const EntryType scalar(size_t i) const { return entries()[i]; } +#ifdef DOXYGEN +Vc_ALWAYS_INLINE Vc_PURE operator EntryType*() { return entries(); } +Vc_ALWAYS_INLINE Vc_PURE operator const EntryType*() const { return entries(); } +#else +template <typename T, +typename std::enable_if< +std::is_same<typename std::remove_const<T>::type, EntryType *>::value || +std::is_same<typename std::remove_const<T>::type, void *>::value, +int>::type = 0> +Vc_ALWAYS_INLINE Vc_PURE operator T() +{ +return entries(); +} +template <typename T, +typename std::enable_if<std::is_same<T, const EntryType *>::value || +std::is_same<T, const void *>::value, +int>::type = 0> +Vc_ALWAYS_INLINE Vc_PURE operator T() const +{ +return entries(); +} +#endif +template<typename Flags> +Vc_ALWAYS_INLINE MemoryRange<V, Parent, Flags> range(size_t firstIndex, size_t lastIndex, Flags) { +return MemoryRange<V, Parent, Flags>(p(), firstIndex, lastIndex); +} +Vc_ALWAYS_INLINE MemoryRange<V, Parent> range(size_t firstIndex, size_t lastIndex) { +return MemoryRange<V, Parent>(p(), firstIndex, lastIndex); +} +template<typename Flags> +Vc_ALWAYS_INLINE MemoryRange<const V, Parent, Flags> range(size_t firstIndex, size_t lastIndex, Flags) const { +return MemoryRange<const V, Parent, Flags>(p(), firstIndex, lastIndex); +} +Vc_ALWAYS_INLINE MemoryRange<const V, Parent> range(size_t firstIndex, size_t lastIndex) const { +return MemoryRange<const V, Parent>(p(), firstIndex, lastIndex); +} +Vc_ALWAYS_INLINE EntryType &operator[](size_t i) { return entries()[i]; } +Vc_ALWAYS_INLINE const EntryType &operator[](size_t i) const { return entries()[i]; } +template<typename IndexT> Vc_ALWAYS_INLINE Vc_PURE V operator[](Vector<IndexT> i) const +{ +return V(entries(), i); +} +}; +template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 2, RowMemory> +{ +private: +Parent *p() { return static_cast<Parent *>(this); } +const Parent *p() const { return static_cast<const Parent *>(this); } +public: +typedef typename V::EntryType EntryType; +static constexpr size_t rowCount() { return Parent::RowCount; } +Vc_ALWAYS_INLINE Vc_PURE EntryType *entries(size_t x = 0) { return &p()->m_mem[x][0]; } +Vc_ALWAYS_INLINE Vc_PURE const EntryType *entries(size_t x = 0) const { return &p()->m_mem[x][0]; } +Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(size_t i, size_t j) { return entries(i)[j]; } +Vc_ALWAYS_INLINE Vc_PURE const EntryType scalar(size_t i, size_t j) const { return entries(i)[j]; } +Vc_ALWAYS_INLINE Vc_PURE RowMemory &operator[](size_t i) { +return p()->m_mem[i]; +} +Vc_ALWAYS_INLINE Vc_PURE const RowMemory &operator[](size_t i) const { +return p()->m_mem[i]; +} +Vc_ALWAYS_INLINE Vc_PURE size_t rowsCount() const { return p()->rowsCount(); } +}; +template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryBase : public MemoryDimensionBase<V, Parent, Dimension, RowMemory> +{ +static_assert((V::size() * sizeof(typename V::EntryType)) % V::MemoryAlignment == 0, +"Vc::Memory can only be used for data-parallel types storing a number " +"of values that's a multiple of the memory alignment."); +private: +Parent *p() { return static_cast<Parent *>(this); } +const Parent *p() const { return static_cast<const Parent *>(this); } +template <class Flags> +using vector_reference = MayAlias<MemoryVector<V, Flags>> &; +template <class Flags> +using const_vector_reference = const MayAlias<MemoryVector<const V, Flags>> &; +public: +typedef typename V::EntryType EntryType; +Vc_ALWAYS_INLINE Vc_PURE size_t entriesCount() const { return p()->entriesCount(); } +Vc_ALWAYS_INLINE Vc_PURE size_t vectorsCount() const { return p()->vectorsCount(); } +using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::entries; +using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::scalar; +template<typename Flags = AlignedTag> +Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> begin(Flags flags = Flags()) { return &firstVector(flags); } +template<typename Flags = AlignedTag> +Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> begin(Flags flags = Flags()) const { return &firstVector(flags); } +template<typename Flags = AlignedTag> +Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> end(Flags flags = Flags()) { return &lastVector(flags) + 1; } +template<typename Flags = AlignedTag> +Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> end(Flags flags = Flags()) const { return &lastVector(flags) + 1; } +template <typename Flags = AlignedTag> +Vc_ALWAYS_INLINE Vc_PURE +typename std::enable_if<!std::is_convertible<Flags, int>::value, +vector_reference<Flags>>::type +vector(size_t i, Flags = Flags()) +{ +return *aliasing_cast<MemoryVector<V, Flags>>(&entries()[i * V::Size]); +} +template <typename Flags = AlignedTag> +Vc_ALWAYS_INLINE Vc_PURE +typename std::enable_if<!std::is_convertible<Flags, int>::value, +const_vector_reference<Flags>>::type +vector(size_t i, Flags = Flags()) const +{ +return *aliasing_cast<MemoryVector<const V, Flags>>(&entries()[i * V::Size]); +} +template <typename Flags = UnalignedTag> +Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> vectorAt(size_t i, +Flags flags = Flags()) +{ +return *aliasing_cast<MemoryVector<V, Flags>>(&entries()[i]); +} +template <typename Flags = UnalignedTag> +Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> vectorAt( +size_t i, Flags flags = Flags()) const +{ +return *aliasing_cast<MemoryVector<const V, Flags>>(&entries()[i]); +} +template <typename ShiftT, typename Flags = decltype(Unaligned)> +Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if< +std::is_convertible<ShiftT, int>::value, +vector_reference<decltype(std::declval<Flags>() | Unaligned)>>::type +vector(size_t i, ShiftT shift, Flags = Flags()) +{ +return *aliasing_cast< +MemoryVector<V, decltype(std::declval<Flags>() | Unaligned)>>( +&entries()[i * V::Size + shift]); +} +template <typename ShiftT, typename Flags = decltype(Unaligned)> +Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if< +std::is_convertible<ShiftT, int>::value, +const_vector_reference<decltype(std::declval<Flags>() | Unaligned)>>::type +vector(size_t i, ShiftT shift, Flags = Flags()) const +{ +return *aliasing_cast< +MemoryVector<const V, decltype(std::declval<Flags>() | Unaligned)>>( +&entries()[i * V::Size + shift]); +} +template <typename Flags = AlignedTag> +Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> firstVector(Flags f = Flags()) +{ +return vector(0, f); +} +template <typename Flags = AlignedTag> +Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> firstVector( +Flags f = Flags()) const +{ +return vector(0, f); +} +template <typename Flags = AlignedTag> +Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> lastVector(Flags f = Flags()) +{ +return vector(vectorsCount() - 1, f); +} +template <typename Flags = AlignedTag> +Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> lastVector( +Flags f = Flags()) const +{ +return vector(vectorsCount() - 1, f); +} +Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned char *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); } +Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned short *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); } +Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned int *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); } +Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned long *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); } +Vc_ALWAYS_INLINE void setZero() { +V zero(Vc::Zero); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) = zero; +} +} +template<typename U> +Vc_ALWAYS_INLINE Parent &operator=(U &&x) { +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) = std::forward<U>(x); +} +} +template<typename P2, typename RM> +inline Parent &operator+=(const MemoryBase<V, P2, Dimension, RM> &rhs) { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) += rhs.vector(i); +} +return static_cast<Parent &>(*this); +} +template<typename P2, typename RM> +inline Parent &operator-=(const MemoryBase<V, P2, Dimension, RM> &rhs) { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) -= rhs.vector(i); +} +return static_cast<Parent &>(*this); +} +template<typename P2, typename RM> +inline Parent &operator*=(const MemoryBase<V, P2, Dimension, RM> &rhs) { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) *= rhs.vector(i); +} +return static_cast<Parent &>(*this); +} +template<typename P2, typename RM> +inline Parent &operator/=(const MemoryBase<V, P2, Dimension, RM> &rhs) { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) /= rhs.vector(i); +} +return static_cast<Parent &>(*this); +} +inline Parent &operator+=(EntryType rhs) { +V v(rhs); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) += v; +} +return static_cast<Parent &>(*this); +} +inline Parent &operator-=(EntryType rhs) { +V v(rhs); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) -= v; +} +return static_cast<Parent &>(*this); +} +inline Parent &operator*=(EntryType rhs) { +V v(rhs); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) *= v; +} +return static_cast<Parent &>(*this); +} +inline Parent &operator/=(EntryType rhs) { +V v(rhs); +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) /= v; +} +return static_cast<Parent &>(*this); +} +template<typename P2, typename RM> +inline bool operator==(const MemoryBase<V, P2, Dimension, RM> &rhs) const { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +if (!(V(vector(i)) == V(rhs.vector(i))).isFull()) { +return false; +} +} +return true; +} +template<typename P2, typename RM> +inline bool operator!=(const MemoryBase<V, P2, Dimension, RM> &rhs) const { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +if (!(V(vector(i)) == V(rhs.vector(i))).isEmpty()) { +return false; +} +} +return true; +} +template<typename P2, typename RM> +inline bool operator<(const MemoryBase<V, P2, Dimension, RM> &rhs) const { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +if (!(V(vector(i)) < V(rhs.vector(i))).isFull()) { +return false; +} +} +return true; +} +template<typename P2, typename RM> +inline bool operator<=(const MemoryBase<V, P2, Dimension, RM> &rhs) const { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +if (!(V(vector(i)) <= V(rhs.vector(i))).isFull()) { +return false; +} +} +return true; +} +template<typename P2, typename RM> +inline bool operator>(const MemoryBase<V, P2, Dimension, RM> &rhs) const { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +if (!(V(vector(i)) > V(rhs.vector(i))).isFull()) { +return false; +} +} +return true; +} +template<typename P2, typename RM> +inline bool operator>=(const MemoryBase<V, P2, Dimension, RM> &rhs) const { +assert(vectorsCount() == rhs.vectorsCount()); +for (size_t i = 0; i < vectorsCount(); ++i) { +if (!(V(vector(i)) >= V(rhs.vector(i))).isFull()) { +return false; +} +} +return true; +} +}; +namespace Detail +{ +template <typename V, +typename ParentL, +typename ParentR, +int Dimension, +typename RowMemoryL, +typename RowMemoryR> +inline void copyVectors(MemoryBase<V, ParentL, Dimension, RowMemoryL> &dst, +const MemoryBase<V, ParentR, Dimension, RowMemoryR> &src) +{ +const size_t vectorsCount = dst.vectorsCount(); +size_t i = 3; +for (; i < vectorsCount; i += 4) { +const V tmp3 = src.vector(i - 3); +const V tmp2 = src.vector(i - 2); +const V tmp1 = src.vector(i - 1); +const V tmp0 = src.vector(i - 0); +dst.vector(i - 3) = tmp3; +dst.vector(i - 2) = tmp2; +dst.vector(i - 1) = tmp1; +dst.vector(i - 0) = tmp0; +} +for (i -= 3; i < vectorsCount; ++i) { +dst.vector(i) = src.vector(i); +} +} +} +} +} +#endif +#include <assert.h> +#include <algorithm> +#include <cstring> +#include <cstddef> +#include <initializer_list> #ifndef VC_COMMON_MALLOC_H_ #define VC_COMMON_MALLOC_H_ #ifndef Vc_VECTOR_DECLARED_ @@ -233,6 +705,249 @@ namespace Vc_VERSIONED_NAMESPACE { namespace Common +{ +template<typename V, size_t Size> struct _MemorySizeCalculation +{ +enum AlignmentCalculations { +Alignment = V::Size, +AlignmentMask = Alignment - 1, +MaskedSize = Size & AlignmentMask, +Padding = Alignment - MaskedSize, +PaddedSize = MaskedSize == 0 ? Size : Size + Padding +}; +}; +template <typename V, size_t Size1, size_t Size2, bool InitPadding> +class Memory : public MemoryBase<V, Memory<V, Size1, Size2, InitPadding>, 2, +Memory<V, Size2, 0, InitPadding>> +{ +public: +typedef typename V::EntryType EntryType; +private: +using RowMemory = Memory<V, Size2, 0, InitPadding>; +typedef MemoryBase<V, Memory<V, Size1, Size2, InitPadding>, 2, RowMemory> Base; +friend class MemoryBase<V, Memory<V, Size1, Size2, InitPadding>, 2, RowMemory>; +friend class MemoryDimensionBase<V, Memory<V, Size1, Size2, InitPadding>, 2, +RowMemory>; +enum : size_t { +Alignment = V::MemoryAlignment, +PaddedSize2 = _MemorySizeCalculation<V, Size2>::PaddedSize +}; +alignas(static_cast<size_t>(Alignment)) +RowMemory m_mem[Size1]; +public: +using Base::vector; +enum Constants { +RowCount = Size1, +VectorsCount = PaddedSize2 / V::Size +}; +Memory() = default; +static constexpr size_t rowsCount() { return RowCount; } +static constexpr size_t entriesCount() { return Size1 * Size2; } +static constexpr size_t vectorsCount() { return VectorsCount * Size1; } +template<typename Parent, typename RM> +Vc_ALWAYS_INLINE Memory &operator=(const MemoryBase<V, Parent, 2, RM> &rhs) { +assert(vectorsCount() == rhs.vectorsCount()); +Detail::copyVectors(*this, rhs); +return *this; +} +Vc_ALWAYS_INLINE Memory &operator=(const Memory &rhs) { +Detail::copyVectors(*this, rhs); +return *this; +} +inline Memory &operator=(const V &v) { +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) = v; +} +return *this; +} +}; +template <typename V, size_t Size, bool InitPadding> +class Memory<V, Size, 0u, InitPadding> : +public MemoryBase<V, Memory<V, Size, 0u, InitPadding>, 1, void> +{ +public: +typedef typename V::EntryType EntryType; +private: +typedef MemoryBase<V, Memory<V, Size, 0u, InitPadding>, 1, void> Base; +friend class MemoryBase<V, Memory<V, Size, 0u, InitPadding>, 1, void>; +friend class MemoryDimensionBase<V, Memory<V, Size, 0u, InitPadding>, 1, void>; +enum : size_t { +Alignment = V::MemoryAlignment, +MaskedSize = Size & (V::Size - 1), +Padding = V::Size - MaskedSize, +PaddedSize = MaskedSize == 0 ? Size : Size + Padding +}; +alignas(static_cast<size_t>(Alignment)) +EntryType m_mem[PaddedSize]; +public: +using Base::vector; +enum Constants { +EntriesCount = Size, +VectorsCount = PaddedSize / V::Size +}; +Memory() +{ +if (InitPadding) { +Base::lastVector() = V::Zero(); +} +} +Memory(std::initializer_list<EntryType> init) +{ +Vc_ASSERT(init.size() <= Size); +Base::lastVector() = V::Zero(); +std::copy(init.begin(), init.end(), &m_mem[0]); +} +static Vc_ALWAYS_INLINE Vc_CONST Memory<V, Size, 0u, false> &fromRawData(EntryType *ptr) +{ +char *addr = reinterpret_cast<char *>(ptr); +typedef Memory<V, Size, 0u, false> MM; +addr -= offsetof(MM, m_mem); +return *new(addr) MM; +} +static constexpr size_t entriesCount() { return EntriesCount; } +static constexpr size_t vectorsCount() { return VectorsCount; } +inline Memory(const Memory &rhs) +{ +Detail::copyVectors(*this, rhs); +} +template <size_t S> inline Memory(const Memory<V, S> &rhs) +{ +assert(vectorsCount() == rhs.vectorsCount()); +Detail::copyVectors(*this, rhs); +} +inline Memory &operator=(const Memory &rhs) +{ +Detail::copyVectors(*this, rhs); +return *this; +} +template <size_t S> inline Memory &operator=(const Memory<V, S> &rhs) +{ +assert(vectorsCount() == rhs.vectorsCount()); +Detail::copyVectors(*this, rhs); +return *this; +} +Vc_ALWAYS_INLINE Memory &operator=(const EntryType *rhs) { +std::memcpy(m_mem, rhs, entriesCount() * sizeof(EntryType)); +return *this; +} +inline Memory &operator=(const V &v) { +for (size_t i = 0; i < vectorsCount(); ++i) { +vector(i) = v; +} +return *this; +} +}; +template<typename V> class Memory<V, 0u, 0u, true> : public MemoryBase<V, Memory<V, 0u, 0u, true>, 1, void> +{ +public: +typedef typename V::EntryType EntryType; +private: +typedef MemoryBase<V, Memory<V>, 1, void> Base; +friend class MemoryBase<V, Memory<V>, 1, void>; +friend class MemoryDimensionBase<V, Memory<V>, 1, void>; +enum InternalConstants { +Alignment = V::Size, +AlignmentMask = Alignment - 1 +}; +size_t m_entriesCount; +size_t m_vectorsCount; +EntryType *m_mem; +size_t calcPaddedEntriesCount(size_t x) +{ +size_t masked = x & AlignmentMask; +return (masked == 0 ? x : x + (Alignment - masked)); +} +public: +using Base::vector; +Vc_ALWAYS_INLINE Memory(size_t size) +: m_entriesCount(size), +m_vectorsCount(calcPaddedEntriesCount(m_entriesCount)), +m_mem(Vc::malloc<EntryType, Vc::AlignOnVector>(m_vectorsCount)) +{ +m_vectorsCount /= V::Size; +Base::lastVector() = V::Zero(); +} +template<typename Parent, typename RM> +Vc_ALWAYS_INLINE Memory(const MemoryBase<V, Parent, 1, RM> &rhs) +: m_entriesCount(rhs.entriesCount()), +m_vectorsCount(rhs.vectorsCount()), +m_mem(Vc::malloc<EntryType, Vc::AlignOnVector>(m_vectorsCount * V::Size)) +{ +Detail::copyVectors(*this, rhs); +} +Vc_ALWAYS_INLINE Memory(const Memory &rhs) +: m_entriesCount(rhs.entriesCount()), +m_vectorsCount(rhs.vectorsCount()), +m_mem(Vc::malloc<EntryType, Vc::AlignOnVector>(m_vectorsCount * V::Size)) +{ +Detail::copyVectors(*this, rhs); +} +Vc_ALWAYS_INLINE ~Memory() +{ +Vc::free(m_mem); +} +inline void swap(Memory &rhs) { +std::swap(m_mem, rhs.m_mem); +std::swap(m_entriesCount, rhs.m_entriesCount); +std::swap(m_vectorsCount, rhs.m_vectorsCount); +} +Vc_ALWAYS_INLINE Vc_PURE size_t entriesCount() const { return m_entriesCount; } +Vc_ALWAYS_INLINE Vc_PURE size_t vectorsCount() const { return m_vectorsCount; } +template<typename Parent, typename RM> +Vc_ALWAYS_INLINE Memory &operator=(const MemoryBase<V, Parent, 1, RM> &rhs) { +assert(vectorsCount() == rhs.vectorsCount()); +Detail::copyVectors(*this, rhs); +return *this; +} +Vc_ALWAYS_INLINE Memory &operator=(const Memory &rhs) { +assert(vectorsCount() == rhs.vectorsCount()); +Detail::copyVectors(*this, rhs); +return *this; +} +Vc_ALWAYS_INLINE Memory &operator=(const EntryType *rhs) { +std::memcpy(m_mem, rhs, entriesCount() * sizeof(EntryType)); +return *this; +} +}; +Vc_ALWAYS_INLINE void prefetchForOneRead(const void *addr) +{ +Vc::Detail::prefetchForOneRead(addr, VectorAbi::Best<float>()); +} +Vc_ALWAYS_INLINE void prefetchForModify(const void *addr) +{ +Vc::Detail::prefetchForModify(addr, VectorAbi::Best<float>()); +} +Vc_ALWAYS_INLINE void prefetchClose(const void *addr) +{ +Vc::Detail::prefetchClose(addr, VectorAbi::Best<float>()); +} +Vc_ALWAYS_INLINE void prefetchMid(const void *addr) +{ +Vc::Detail::prefetchMid(addr, VectorAbi::Best<float>()); +} +Vc_ALWAYS_INLINE void prefetchFar(const void *addr) +{ +Vc::Detail::prefetchFar(addr, VectorAbi::Best<float>()); +} +} +using Common::Memory; +using Common::prefetchForOneRead; +using Common::prefetchForModify; +using Common::prefetchClose; +using Common::prefetchMid; +using Common::prefetchFar; +} +namespace std +{ +template<typename V> Vc_ALWAYS_INLINE void swap(Vc::Memory<V> &a, Vc::Memory<V> &b) { a.swap(b); } +} +#endif +#ifndef VC_COMMON_MAKE_UNIQUE_H_ +#define VC_COMMON_MAKE_UNIQUE_H_ +#include <memory> +namespace Vc_VERSIONED_NAMESPACE +{ +namespace Common { template<typename T> struct Deleter { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/src/support_x86.cpp new/Vc-1.4.4/src/support_x86.cpp --- old/Vc-1.4.3/src/support_x86.cpp 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/src/support_x86.cpp 2023-10-06 09:47:32.000000000 +0200 @@ -59,7 +59,7 @@ } Vc_TARGET_NO_SIMD -bool isImplementationSupported(Implementation impl) +bool Vc_VDECL isImplementationSupported(Implementation impl) { CpuId::init(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vc-1.4.3/tests/arithmetics.cpp new/Vc-1.4.4/tests/arithmetics.cpp --- old/Vc-1.4.3/tests/arithmetics.cpp 2022-05-20 15:36:24.000000000 +0200 +++ new/Vc-1.4.4/tests/arithmetics.cpp 2023-10-06 09:47:32.000000000 +0200 @@ -472,6 +472,23 @@ } } +#if defined(Vc_IMPL_AVX2) && !defined(Vc_MSVC) +TEST(minChar) +{ + uint8_t a[64]{0, 10, 250}; + COMPARE(Vc::schar_v(reinterpret_cast<Vc::schar*>(a)).min(), Vc::schar{-6}); + COMPARE(Vc::uchar_v(a).min(), Vc::uchar{0}); +} + +// Tests issue: https://github.com/VcDevel/Vc/issues/349 +TEST(maxChar) +{ + uint8_t a[64]{0, 10, 250}; + COMPARE(Vc::schar_v(reinterpret_cast<Vc::schar*>(a)).max(), Vc::schar{10}); + COMPARE(Vc::uchar_v(a).max(), Vc::uchar{250}); +} +#endif + // testProduct{{{1 TEST_TYPES(Vec, testProduct, AllVectors) {