VCTR
Loading...
Searching...
No Matches
SIMDHelpers.h
1/*
2 ==============================================================================
3 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
5 Copyright 2022- by sonible GmbH.
6
7 This file is part of VCTR - Versatile Container Templates Reconceptualized.
8
9 VCTR is free software: you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License version 3
11 only, as published by the Free Software Foundation.
12
13 VCTR is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Lesser General Public License version 3 for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 version 3 along with VCTR. If not, see <https://www.gnu.org/licenses/>.
20 ==============================================================================
21*/
22
23namespace vctr::detail
24{
25template <size_t value>
26requires (is::powerOfTwoInt<value>)
27constexpr size_t previousMultipleOf (size_t numElements)
28{
29 constexpr auto numMaskBits = std::bit_width (value) - 1;
30 constexpr auto allBitsOne = size_t (-1);
31 constexpr auto mask = allBitsOne << numMaskBits;
32
33 return numElements & mask;
34}
35
36template <size_t value>
37requires (is::powerOfTwoInt<value>)
38constexpr size_t nextMultipleOf (size_t numElements)
39{
40 return size_t ((int64_t (numElements) + int64_t (value) - 1) & -int64_t (value));
41}
42
43} // namespace vctr::detail
44
45namespace vctr
46{
47
56template <uintptr_t requiredAlignment = Config::maxSIMDRegisterSize>
57inline constexpr bool isPtrAligned (const void* ptr)
58{
59 // SIMD alignment is not meaningful in case of constant evaluation
60 if (std::is_constant_evaluated())
61 return false;
62
63 return reinterpret_cast<std::uintptr_t> (ptr) % requiredAlignment == 0;
64}
65
81template <class StorageType>
83{
84 // The default implementation is empty and should never be used
85};
86
87template <has::sizeAndData StorageType>
88struct StorageInfo<StorageType>
89{
90 constexpr StorageInfo()
91 : dataIsSIMDAligned (false),
92 hasSIMDExtendedStorage (false)
93 {}
94
95 template <is::storageInfo OtherStorageInfoType>
96 constexpr StorageInfo (const OtherStorageInfoType& other)
97 : dataIsSIMDAligned (other.dataIsSIMDAligned),
98 hasSIMDExtendedStorage (other.hasSIMDExtendedStorage)
99 {}
100
101 template <class T>
102 constexpr StorageInfo init (const T* ptr, size_t s)
103 {
104 dataIsSIMDAligned = isPtrAligned (ptr);
105 hasSIMDExtendedStorage = (s * sizeof (T)) % Config::maxSIMDRegisterSize == 0;
106 return *this;
107 }
108
109 static constexpr size_t memberAlignment = alignof (StorageType);
110
111 bool dataIsSIMDAligned;
112
113 bool hasSIMDExtendedStorage;
114};
115
116template <class ElementType, size_t alignmentInBytes>
117struct StorageInfo<std::vector<ElementType, AlignedAllocator<ElementType, alignmentInBytes>>>
118{
119 constexpr StorageInfo init (const void*, size_t) { return *this; }
120
121 static constexpr size_t memberAlignment = alignof (std::vector<ElementType, AlignedAllocator<ElementType, alignmentInBytes>>);
122
123 static constexpr bool dataIsSIMDAligned = alignmentInBytes == Config::maxSIMDRegisterSize;
124
126 static constexpr bool hasSIMDExtendedStorage = true;
127};
128
129template <class ElementType, size_t size>
130struct StorageInfo<std::array<ElementType, size>>
131{
132 constexpr StorageInfo init (const void*, size_t) { return *this; }
133
134 static constexpr size_t memberAlignment = Config::alignedArray ? Config::maxSIMDRegisterSize : alignof (std::array<ElementType, size>);
135
137 static constexpr bool dataIsSIMDAligned = Config::alignedArray;
138
139 static constexpr bool hasSIMDExtendedStorage = (size * sizeof (ElementType)) % Config::maxSIMDRegisterSize == 0;
140};
141
142template <class Allocator>
143struct StorageInfo<detail::VectorBoolWorkaround<Allocator>>
144{
145 constexpr StorageInfo init (const void*, size_t) { return *this; }
146
147 static constexpr size_t memberAlignment = alignof (detail::VectorBoolWorkaround<Allocator>);
148
149 static constexpr bool dataIsSIMDAligned = false;
150
151 static constexpr bool hasSIMDExtendedStorage = false;
152};
153
157template <bool isDataSIMDAligned, bool isStorageSIMDExtended, size_t customMemberAlignment>
159{
160 static constexpr bool dataIsSIMDAligned = isDataSIMDAligned;
161 static constexpr bool hasSIMDExtendedStorage = isStorageSIMDExtended;
162 static constexpr size_t memberAlignment = customMemberAlignment;
163};
164
171template <size_t alignment, class WrappedInfo>
173{
174 constexpr StorageInfoWithMemberAlignment() = default;
175
176 constexpr StorageInfoWithMemberAlignment (const WrappedInfo& i) : WrappedInfo (i) {}
177
178 static constexpr size_t memberAlignment = alignment;
179};
180
181namespace detail
182{
183
184template <bool, bool>
185struct ConstexprStorageInfoChecker
186{
187};
188} // namespace detail
189
190namespace is
191{
192template <class T>
193concept constexprStorageInfo = requires (const T&) { detail::ConstexprStorageInfoChecker<T::dataIsSIMDAligned, T::hasSIMDExtendedStorage>(); };
194}
195
196template <class First, class... Others>
198{
199 CombinedStorageInfo (const First& first, const Others&... others)
200 : dataIsSIMDAligned (first.dataIsSIMDAligned && (others.dataIsSIMDAligned && ...)),
201 hasSIMDExtendedStorage (first.hasSIMDExtendedStorage && (others.hasSIMDExtendedStorage && ...))
202 {}
203
204 bool dataIsSIMDAligned;
205
206 bool hasSIMDExtendedStorage;
207};
208
209template <is::constexprStorageInfo First, is::constexprStorageInfo... Others>
210struct CombinedStorageInfo<First, Others...>
211{
212 constexpr CombinedStorageInfo (const First&, const Others&...) {}
213
214 static constexpr bool dataIsSIMDAligned = First::dataIsSIMDAligned && (Others::dataIsSIMDAligned && ...);
215
216 static constexpr bool hasSIMDExtendedStorage = First::hasSIMDExtendedStorage && (Others::hasSIMDExtendedStorage && ...);
217};
218
219} // namespace vctr
Definition: SIMDHelpers.h:193
The main namespace of the VCTR project.
Definition: Array.h:24
constexpr bool isPtrAligned(const void *ptr)
Helper function to check if a pointer is aligned to the required alignment value.
Definition: SIMDHelpers.h:57
Definition: SIMDHelpers.h:198
A storage info type especially used to pass compile time constant traits when viewing externally owne...
Definition: SIMDHelpers.h:159
A storage info type especially used for vctr::Span.
Definition: SIMDHelpers.h:173
A helper class to describe some properties regarding the storage class wrapped in a VctrBase instance...
Definition: SIMDHelpers.h:83