Developer documentation
Version 3.0.3-105-gd3941f44
types.h
Go to the documentation of this file.
1/* Copyright (c) 2008-2022 the MRtrix3 contributors.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 *
7 * Covered Software is provided under this License on an "as is"
8 * basis, without warranty of any kind, either expressed, implied, or
9 * statutory, including, without limitation, warranties that the
10 * Covered Software is free of defects, merchantable, fit for a
11 * particular purpose or non-infringing.
12 * See the Mozilla Public License v. 2.0 for more details.
13 *
14 * For more details, see http://www.mrtrix.org/.
15 */
16
17#ifndef __mrtrix_types_h__
18#define __mrtrix_types_h__
19
20#include <cinttypes>
21#include <complex>
22#include <cstddef>
23#include <deque>
24#include <map>
25#include <memory>
26#include <iostream>
27#include <vector>
28
29
30#define NOMEMALIGN
31
32#ifdef _WIN32
33# ifdef _WIN64
34# define PRI_SIZET PRIu64
35# else
36# define PRI_SIZET PRIu32
37# endif
38#else
39# define PRI_SIZET "zu"
40#endif
41
42
43namespace MR {
44
45#ifdef MRTRIX_MAX_ALIGN_T_NOT_DEFINED
46# ifdef MRTRIX_STD_MAX_ALIGN_T_NOT_DEFINED
47 // needed for clang 3.4:
48 using __max_align_t = struct { NOMEMALIGN
49 long long __clang_max_align_nonce1
50 __attribute__((__aligned__(__alignof__(long long))));
51 long double __clang_max_align_nonce2
52 __attribute__((__aligned__(__alignof__(long double))));
53 };
54 constexpr size_t malloc_align = alignof (__max_align_t);
55# else
56 constexpr size_t malloc_align = alignof (std::max_align_t);
57# endif
58#else
59 constexpr size_t malloc_align = alignof (::max_align_t);
60#endif
61
62 namespace Helper {
63 template <class ImageType> class ConstRow;
64 template <class ImageType> class Row;
65 }
66}
67
68#ifdef EIGEN_HAS_OPENMP
69# undef EIGEN_HAS_OPENMP
70#endif
71
72#define EIGEN_DENSEBASE_PLUGIN "eigen_plugins/dense_base.h"
73#define EIGEN_MATRIXBASE_PLUGIN "eigen_plugins/dense_base.h"
74#define EIGEN_ARRAYBASE_PLUGIN "eigen_plugins/dense_base.h"
75#define EIGEN_MATRIX_PLUGIN "eigen_plugins/matrix.h"
76#define EIGEN_ARRAY_PLUGIN "eigen_plugins/array.h"
77
78#include <Eigen/Geometry>
79
93
112#ifdef MRTRIX_NO_VLA
113# define VLA(name, type, num) \
114 vector<type> __vla__ ## name(num); \
115 type* name = &__vla__ ## name[0]
116# define VLA_MAX(name, type, num, max) type name[max]
117#else
118# define VLA(name, type, num) type name[num]
119# define VLA_MAX(name, type, num, max) type name[num]
120#endif
121
122
141#ifdef MRTRIX_NO_NON_POD_VLA
142# define NON_POD_VLA(name, type, num) \
143 vector<type> __vla__ ## name(num); \
144 type* name = &__vla__ ## name[0]
145# define NON_POD_VLA_MAX(name, type, num, max) type name[max]
146#else
147# define NON_POD_VLA(name, type, num) type name[num]
148# define NON_POD_VLA_MAX(name, type, num, max) type name[num]
149#endif
150
152
153#ifdef NDEBUG
154# define FORCE_INLINE inline __attribute__((always_inline))
155#else // don't force inlining in debug mode, so we can get more informative backtraces
156# define FORCE_INLINE inline
157#endif
158
159
160#ifndef EIGEN_DEFAULT_ALIGN_BYTES
161// Assume 16 byte alignment as hard-coded in Eigen 3.2:
162# define EIGEN_DEFAULT_ALIGN_BYTES 16
163#endif
164
165
166template <class T> class __has_custom_new_operator { NOMEMALIGN
167 template <typename C> static inline char test (decltype(C::operator new (sizeof(C)))) ;
168 template <typename C> static inline long test (...);
169 public:
170 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) };
171};
172
173
174inline void* __aligned_malloc (std::size_t size) {
175 auto* original = std::malloc (size + EIGEN_DEFAULT_ALIGN_BYTES);
176 if (!original) throw std::bad_alloc();
177 void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::size_t(EIGEN_DEFAULT_ALIGN_BYTES-1))) + EIGEN_DEFAULT_ALIGN_BYTES);
178 *(reinterpret_cast<void**>(aligned) - 1) = original;
179 return aligned;
180}
181
182inline void __aligned_free (void* ptr) { if (ptr) std::free (*(reinterpret_cast<void**>(ptr) - 1)); }
183
184
185#define MEMALIGN(...) public: \
186 FORCE_INLINE void* operator new (std::size_t size) { return (alignof(__VA_ARGS__)>::MR::malloc_align) ? __aligned_malloc (size) : ::operator new (size); } \
187 FORCE_INLINE void* operator new[] (std::size_t size) { return (alignof(__VA_ARGS__)>::MR::malloc_align) ? __aligned_malloc (size) : ::operator new[] (size); } \
188 FORCE_INLINE void operator delete (void* ptr) { if (alignof(__VA_ARGS__)>::MR::malloc_align) __aligned_free (ptr); else ::operator delete (ptr); } \
189 FORCE_INLINE void operator delete[] (void* ptr) { if (alignof(__VA_ARGS__)>::MR::malloc_align) __aligned_free (ptr); else ::operator delete[] (ptr); }
190
191
206#define CHECK_MEM_ALIGN(...) \
207 static_assert ( (alignof(__VA_ARGS__) <= ::MR::malloc_align) || __has_custom_new_operator<__VA_ARGS__>::value, \
208 "class requires over-alignment, but no operator new defined! Please insert MEMALIGN() into class definition.")
209
210
211
212namespace MR
213{
214
215 using float32 = float;
216 using float64 = double;
217 using cdouble = std::complex<double>;
218 using cfloat = std::complex<float>;
219
220 template <typename T>
221 struct container_cast : public T { MEMALIGN(container_cast<T>)
222 template <typename U>
223 container_cast (const U& x) :
224 T (x.begin(), x.end()) { }
225 };
226
228 using default_type = double;
229
230 constexpr default_type NaN = std::numeric_limits<default_type>::quiet_NaN();
231 constexpr default_type Inf = std::numeric_limits<default_type>::infinity();
232
234 using transform_type = Eigen::Transform<default_type, 3, Eigen::AffineCompact>;
235
236
238 using KeyValues = std::map<std::string, std::string>;
239
240
242 template <class ValueType> struct is_complex : std::false_type { NOMEMALIGN };
243 template <class ValueType> struct is_complex<std::complex<ValueType>> : std::true_type { NOMEMALIGN };
244
245
247 template <class ValueType>
248 struct is_data_type :
249 std::integral_constant<bool, std::is_arithmetic<ValueType>::value || is_complex<ValueType>::value> { NOMEMALIGN };
250
251
252 template <typename X, int N=(alignof(X)>::MR::malloc_align)>
253 class vector : public ::std::vector<X, Eigen::aligned_allocator<X>> { NOMEMALIGN
254 public:
255 using ::std::vector<X,Eigen::aligned_allocator<X>>::vector;
256 vector() { }
257 };
258
259 template <typename X>
260 class vector<X,0> : public ::std::vector<X> { NOMEMALIGN
261 public:
262 using ::std::vector<X>::vector;
263 vector() { }
264 };
265
266
267 template <typename X, int N=(alignof(X)>::MR::malloc_align)>
268 class deque : public ::std::deque<X, Eigen::aligned_allocator<X>> { NOMEMALIGN
269 public:
270 using ::std::deque<X,Eigen::aligned_allocator<X>>::deque;
271 deque() { }
272 };
273
274 template <typename X>
275 class deque<X,0> : public ::std::deque<X> { NOMEMALIGN
276 public:
277 using ::std::deque<X>::deque;
278 deque() { }
279 };
280
281
282 template <typename X, typename... Args>
283 inline std::shared_ptr<X> make_shared (Args&&... args) {
284 return std::shared_ptr<X> (new X (std::forward<Args> (args)...));
285 }
286
287 template <typename X, typename... Args>
288 inline std::unique_ptr<X> make_unique (Args&&... args) {
289 return std::unique_ptr<X> (new X (std::forward<Args> (args)...));
290 }
291
292
293 // required to allow use of abs() call on unsigned integers in template
294 // functions, etc, since the standard labels such calls ill-formed:
295 // http://en.cppreference.com/w/cpp/numeric/math/abs
296 template <typename X>
297 inline constexpr typename std::enable_if<std::is_arithmetic<X>::value && std::is_unsigned<X>::value,X>::type abs (X x) { return x; }
298 template <typename X>
299 inline constexpr typename std::enable_if<std::is_arithmetic<X>::value && !std::is_unsigned<X>::value,X>::type abs (X x) { return std::abs(x); }
300}
301
302namespace std
303{
304
305 template <class T> inline ostream& operator<< (ostream& stream, const vector<T>& V)
306 {
307 stream << "[ ";
308 for (size_t n = 0; n < V.size(); n++)
309 stream << V[n] << " ";
310 stream << "]";
311 return stream;
312 }
313
314 template <class T, std::size_t N> inline ostream& operator<< (ostream& stream, const array<T,N>& V)
315 {
316 stream << "[ ";
317 for (size_t n = 0; n < N; n++)
318 stream << V[n] << " ";
319 stream << "]";
320 return stream;
321 }
322
323}
324
325#endif
326
327
328
329
330
deque()
Definition: types.h:271
vector()
Definition: types.h:256
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
Definition: SH.h:233
Definition: base.h:24
std::map< std::string, std::string > KeyValues
used in various places for storing key-value pairs
Definition: types.h:238
std::complex< float > cfloat
Definition: types.h:218
std::complex< double > cdouble
Definition: types.h:217
double default_type
the default type used throughout MRtrix
Definition: types.h:228
constexpr size_t malloc_align
Definition: types.h:59
double float64
Definition: types.h:216
std::unique_ptr< X > make_unique(Args &&... args)
Definition: types.h:288
constexpr std::enable_if< std::is_arithmetic< X >::value &&std::is_unsigned< X >::value, X >::type abs(X x)
Definition: types.h:297
Eigen::Transform< default_type, 3, Eigen::AffineCompact > transform_type
the type for the affine transform of an image:
Definition: types.h:234
constexpr default_type Inf
Definition: types.h:231
std::shared_ptr< X > make_shared(Args &&... args)
Definition: types.h:283
constexpr default_type NaN
Definition: types.h:230
constexpr std::enable_if< std::is_arithmetic< X >::value &&!std::is_unsigned< X >::value, X >::type abs(X x)
Definition: types.h:299
float float32
Definition: types.h:215
Definition: types.h:303
ostream & operator<<(ostream &stream, const vector< T > &V)
Definition: types.h:305
#define MEMALIGN(...)
Definition: types.h:185
void __aligned_free(void *ptr)
Definition: types.h:182
#define NOMEMALIGN
void * __aligned_malloc(std::size_t size)
Definition: types.h:174
#define EIGEN_DEFAULT_ALIGN_BYTES
Definition: types.h:162
container_cast(const U &x)
Definition: types.h:223