5 #ifndef GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
6 #define GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
11 #include <ginkgo/core/base/batch_dim.hpp>
12 #include <ginkgo/core/base/dim.hpp>
13 #include <ginkgo/core/base/exception.hpp>
14 #include <ginkgo/core/base/name_demangling.hpp>
15 #include <ginkgo/core/base/utils_helper.hpp>
28 #define GKO_QUOTE(...) #__VA_ARGS__
37 #define GKO_NOT_IMPLEMENTED \
39 throw ::gko::NotImplemented(__FILE__, __LINE__, __func__); \
42 "This assert is used to counter the false positive extra " \
43 "semi-colon warnings")
54 #define GKO_NOT_COMPILED(_module) \
56 throw ::gko::NotCompiled(__FILE__, __LINE__, __func__, \
57 GKO_QUOTE(_module)); \
60 "This assert is used to counter the false positive extra " \
61 "semi-colon warnings")
67 template <
typename T,
typename T2 =
void>
68 struct dynamic_type_helper {
69 static const std::type_info& get(
const T& obj) {
return typeid(obj); }
73 struct dynamic_type_helper<T,
74 typename std::enable_if<std::is_pointer<T>::value ||
75 have_ownership<T>()>::type> {
76 static const std::type_info& get(
const T& obj)
78 return obj ?
typeid(*obj) :
typeid(
nullptr);
83 const std::type_info& get_dynamic_type(
const T& obj)
85 return dynamic_type_helper<T>::get(obj);
99 #define GKO_NOT_SUPPORTED(_obj) \
101 throw ::gko::NotSupported(__FILE__, __LINE__, __func__, \
102 ::gko::name_demangling::get_type_name( \
103 ::gko::detail::get_dynamic_type(_obj))); \
105 static_assert(true, \
106 "This assert is used to counter the false positive extra " \
107 "semi-colon warnings")
113 template <
typename T>
114 inline dim<2> get_size(
const T& op)
116 return op->get_size();
119 inline dim<2> get_size(
const dim<2>& size) {
return size; }
122 template <
typename T>
123 inline batch_dim<2> get_batch_size(
const T& op)
125 return op->get_size();
128 inline batch_dim<2> get_batch_size(
const batch_dim<2>& size) {
return size; }
131 template <
typename T>
132 inline size_type get_num_batch_items(
const T& obj)
134 return obj.get_num_batch_items();
146 #define GKO_ASSERT_EQ(_val1, _val2) \
147 if (_val1 != _val2) { \
148 throw ::gko::ValueMismatch(__FILE__, __LINE__, __func__, _val1, _val2, \
149 "expected equal values"); \
159 #define GKO_ASSERT_IS_SQUARE_MATRIX(_op1) \
160 if (::gko::detail::get_size(_op1)[0] != \
161 ::gko::detail::get_size(_op1)[1]) { \
162 throw ::gko::DimensionMismatch( \
163 __FILE__, __LINE__, __func__, #_op1, \
164 ::gko::detail::get_size(_op1)[0], \
165 ::gko::detail::get_size(_op1)[1], #_op1, \
166 ::gko::detail::get_size(_op1)[0], \
167 ::gko::detail::get_size(_op1)[1], "expected square matrix"); \
176 #define GKO_ASSERT_IS_NON_EMPTY_MATRIX(_op1) \
177 if (!(::gko::detail::get_size(_op1))) { \
178 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_op1, \
179 ::gko::detail::get_size(_op1)[0], \
180 ::gko::detail::get_size(_op1)[1], \
181 "expected non-empty matrix"); \
190 #define GKO_ASSERT_IS_POWER_OF_TWO(_val) \
192 if (_val == 0 || (_val & (_val - 1)) != 0) { \
193 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_val, \
195 "expected power-of-two dimension"); \
205 #define GKO_ASSERT_CONFORMANT(_op1, _op2) \
206 if (::gko::detail::get_size(_op1)[1] != \
207 ::gko::detail::get_size(_op2)[0]) { \
208 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
209 ::gko::detail::get_size(_op1)[0], \
210 ::gko::detail::get_size(_op1)[1], \
212 ::gko::detail::get_size(_op2)[0], \
213 ::gko::detail::get_size(_op2)[1], \
214 "expected matching inner dimensions"); \
223 #define GKO_ASSERT_REVERSE_CONFORMANT(_op1, _op2) \
224 if (::gko::detail::get_size(_op1)[0] != \
225 ::gko::detail::get_size(_op2)[1]) { \
226 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
227 ::gko::detail::get_size(_op1)[0], \
228 ::gko::detail::get_size(_op1)[1], \
230 ::gko::detail::get_size(_op2)[0], \
231 ::gko::detail::get_size(_op2)[1], \
232 "expected matching inner dimensions"); \
241 #define GKO_ASSERT_EQUAL_ROWS(_op1, _op2) \
242 if (::gko::detail::get_size(_op1)[0] != \
243 ::gko::detail::get_size(_op2)[0]) { \
244 throw ::gko::DimensionMismatch( \
245 __FILE__, __LINE__, __func__, #_op1, \
246 ::gko::detail::get_size(_op1)[0], \
247 ::gko::detail::get_size(_op1)[1], #_op2, \
248 ::gko::detail::get_size(_op2)[0], \
249 ::gko::detail::get_size(_op2)[1], "expected matching row length"); \
259 #define GKO_ASSERT_EQUAL_COLS(_op1, _op2) \
260 if (::gko::detail::get_size(_op1)[1] != \
261 ::gko::detail::get_size(_op2)[1]) { \
262 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
263 ::gko::detail::get_size(_op1)[0], \
264 ::gko::detail::get_size(_op1)[1], \
266 ::gko::detail::get_size(_op2)[0], \
267 ::gko::detail::get_size(_op2)[1], \
268 "expected matching column length"); \
278 #define GKO_ASSERT_EQUAL_DIMENSIONS(_op1, _op2) \
279 if (::gko::detail::get_size(_op1) != ::gko::detail::get_size(_op2)) { \
280 throw ::gko::DimensionMismatch( \
281 __FILE__, __LINE__, __func__, #_op1, \
282 ::gko::detail::get_size(_op1)[0], \
283 ::gko::detail::get_size(_op1)[1], #_op2, \
284 ::gko::detail::get_size(_op2)[0], \
285 ::gko::detail::get_size(_op2)[1], "expected equal dimensions"); \
294 #define GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2) \
296 auto equal_num_items = \
297 ::gko::detail::get_batch_size(_op1).get_num_batch_items() == \
298 ::gko::detail::get_batch_size(_op2).get_num_batch_items(); \
299 if (!equal_num_items) { \
300 throw ::gko::ValueMismatch( \
301 __FILE__, __LINE__, __func__, \
302 ::gko::detail::get_batch_size(_op1).get_num_batch_items(), \
303 ::gko::detail::get_batch_size(_op2).get_num_batch_items(), \
304 "expected equal number of batch items"); \
314 #define GKO_ASSERT_BATCH_CONFORMANT(_op1, _op2) \
316 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
317 auto equal_inner_size = \
318 ::gko::detail::get_batch_size(_op1).get_common_size()[1] == \
319 ::gko::detail::get_batch_size(_op2).get_common_size()[0]; \
320 if (!equal_inner_size) { \
321 throw ::gko::DimensionMismatch( \
322 __FILE__, __LINE__, __func__, #_op1, \
323 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
324 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
326 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
327 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
328 "expected matching inner dimensions among all batch items"); \
338 #define GKO_ASSERT_BATCH_REVERSE_CONFORMANT(_op1, _op2) \
340 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
341 auto equal_outer_size = \
342 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
343 ::gko::detail::get_batch_size(_op2).get_common_size()[1]; \
344 if (!equal_outer_size) { \
345 throw ::gko::DimensionMismatch( \
346 __FILE__, __LINE__, __func__, #_op1, \
347 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
348 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
350 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
351 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
352 "expected matching outer dimensions among all batch items"); \
362 #define GKO_ASSERT_BATCH_EQUAL_ROWS(_op1, _op2) \
364 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
366 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
367 ::gko::detail::get_batch_size(_op2).get_common_size()[0]; \
369 throw ::gko::DimensionMismatch( \
370 __FILE__, __LINE__, __func__, #_op1, \
371 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
372 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
374 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
375 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
376 "expected matching number of rows among all batch items"); \
387 #define GKO_ASSERT_BATCH_EQUAL_COLS(_op1, _op2) \
389 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
391 ::gko::detail::get_batch_size(_op1).get_common_size()[1] == \
392 ::gko::detail::get_batch_size(_op2).get_common_size()[1]; \
394 throw ::gko::DimensionMismatch( \
395 __FILE__, __LINE__, __func__, #_op1, \
396 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
397 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
399 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
400 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
401 "expected matching number of cols among all batch items"); \
412 #define GKO_ASSERT_BATCH_EQUAL_DIMENSIONS(_op1, _op2) \
414 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
416 ::gko::detail::get_batch_size(_op1).get_common_size() == \
417 ::gko::detail::get_batch_size(_op2).get_common_size(); \
419 throw ::gko::DimensionMismatch( \
420 __FILE__, __LINE__, __func__, #_op1, \
421 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
422 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
424 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
425 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
426 "expected matching size among all batch items"); \
437 #define GKO_ASSERT_BATCH_HAS_SQUARE_DIMENSIONS(_op1) \
440 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
441 ::gko::detail::get_batch_size(_op1).get_common_size()[1]; \
443 throw ::gko::BadDimension( \
444 __FILE__, __LINE__, __func__, #_op1, \
445 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
446 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
447 "expected common size of matrices to be square"); \
457 #define GKO_MPI_ERROR(_errcode) \
458 ::gko::MpiError(__FILE__, __LINE__, __func__, _errcode)
466 #define GKO_CUDA_ERROR(_errcode) \
467 ::gko::CudaError(__FILE__, __LINE__, __func__, _errcode)
475 #define GKO_CUBLAS_ERROR(_errcode) \
476 ::gko::CublasError(__FILE__, __LINE__, __func__, _errcode)
484 #define GKO_CURAND_ERROR(_errcode) \
485 ::gko::CurandError(__FILE__, __LINE__, __func__, _errcode)
493 #define GKO_CUSPARSE_ERROR(_errcode) \
494 ::gko::CusparseError(__FILE__, __LINE__, __func__, _errcode)
502 #define GKO_CUFFT_ERROR(_errcode) \
503 ::gko::CufftError(__FILE__, __LINE__, __func__, _errcode)
511 #define GKO_ASSERT_NO_CUDA_ERRORS(_cuda_call) \
513 auto _errcode = _cuda_call; \
514 if (_errcode != cudaSuccess) { \
515 throw GKO_CUDA_ERROR(_errcode); \
525 #define GKO_ASSERT_NO_CUBLAS_ERRORS(_cublas_call) \
527 auto _errcode = _cublas_call; \
528 if (_errcode != CUBLAS_STATUS_SUCCESS) { \
529 throw GKO_CUBLAS_ERROR(_errcode); \
539 #define GKO_ASSERT_NO_CURAND_ERRORS(_curand_call) \
541 auto _errcode = _curand_call; \
542 if (_errcode != CURAND_STATUS_SUCCESS) { \
543 throw GKO_CURAND_ERROR(_errcode); \
553 #define GKO_ASSERT_NO_CUSPARSE_ERRORS(_cusparse_call) \
555 auto _errcode = _cusparse_call; \
556 if (_errcode != CUSPARSE_STATUS_SUCCESS) { \
557 throw GKO_CUSPARSE_ERROR(_errcode); \
567 #define GKO_ASSERT_NO_CUFFT_ERRORS(_cufft_call) \
569 auto _errcode = _cufft_call; \
570 if (_errcode != CUFFT_SUCCESS) { \
571 throw GKO_CUFFT_ERROR(_errcode); \
581 #define GKO_HIP_ERROR(_errcode) \
582 ::gko::HipError(__FILE__, __LINE__, __func__, _errcode)
590 #define GKO_HIPBLAS_ERROR(_errcode) \
591 ::gko::HipblasError(__FILE__, __LINE__, __func__, _errcode)
599 #define GKO_HIPRAND_ERROR(_errcode) \
600 ::gko::HiprandError(__FILE__, __LINE__, __func__, _errcode)
608 #define GKO_HIPSPARSE_ERROR(_errcode) \
609 ::gko::HipsparseError(__FILE__, __LINE__, __func__, _errcode)
617 #define GKO_HIPFFT_ERROR(_errcode) \
618 ::gko::HipfftError(__FILE__, __LINE__, __func__, _errcode)
626 #define GKO_ASSERT_NO_HIP_ERRORS(_hip_call) \
628 auto _errcode = _hip_call; \
629 if (_errcode != hipSuccess) { \
630 throw GKO_HIP_ERROR(_errcode); \
640 #define GKO_ASSERT_NO_HIPBLAS_ERRORS(_hipblas_call) \
642 auto _errcode = _hipblas_call; \
643 if (_errcode != HIPBLAS_STATUS_SUCCESS) { \
644 throw GKO_HIPBLAS_ERROR(_errcode); \
654 #define GKO_ASSERT_NO_HIPRAND_ERRORS(_hiprand_call) \
656 auto _errcode = _hiprand_call; \
657 if (_errcode != HIPRAND_STATUS_SUCCESS) { \
658 throw GKO_HIPRAND_ERROR(_errcode); \
668 #define GKO_ASSERT_NO_HIPSPARSE_ERRORS(_hipsparse_call) \
670 auto _errcode = _hipsparse_call; \
671 if (_errcode != HIPSPARSE_STATUS_SUCCESS) { \
672 throw GKO_HIPSPARSE_ERROR(_errcode); \
682 #define GKO_ASSERT_NO_HIPFFT_ERRORS(_hipfft_call) \
684 auto _errcode = _hipfft_call; \
685 if (_errcode != HIPFFT_SUCCESS) { \
686 throw GKO_HIPFFT_ERROR(_errcode); \
696 #define GKO_ASSERT_NO_MPI_ERRORS(_mpi_call) \
698 auto _errcode = _mpi_call; \
699 if (_errcode != MPI_SUCCESS) { \
700 throw GKO_MPI_ERROR(_errcode); \
708 template <
typename T>
709 inline T ensure_allocated_impl(T ptr,
const std::string& file,
int line,
712 if (ptr ==
nullptr) {
713 throw AllocationError(file, line, dev, size);
736 #define GKO_ENSURE_ALLOCATED(_ptr, _dev, _size) \
737 ::gko::detail::ensure_allocated_impl(_ptr, __FILE__, __LINE__, _dev, _size)
748 #define GKO_ENSURE_IN_BOUNDS(_index, _bound) \
749 if (_index >= _bound) { \
750 throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _index, _bound); \
752 static_assert(true, \
753 "This assert is used to counter the false positive extra " \
754 "semi-colon warnings")
767 #define GKO_ENSURE_COMPATIBLE_BOUNDS(_source, _target) \
768 if (_source > _target) { \
769 throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _source, _target); \
771 static_assert(true, \
772 "This assert is used to counter the false positive extra " \
773 "semi-colon warnings")
785 #define GKO_ENSURE_IN_DIMENSION_BOUNDS(_row, _col, _bound) \
786 GKO_ENSURE_IN_BOUNDS(_row, ::gko::detail::get_size(_bound)[0]); \
787 GKO_ENSURE_IN_BOUNDS(_col, ::gko::detail::get_size(_bound)[1])
800 #define GKO_STREAM_ERROR(_message) \
801 ::gko::StreamError(__FILE__, __LINE__, __func__, _message)
810 #define GKO_KERNEL_NOT_FOUND \
812 throw ::gko::KernelNotFound(__FILE__, __LINE__, __func__); \
814 static_assert(true, \
815 "This assert is used to counter the false positive extra " \
816 "semi-colon warnings")
825 #define GKO_UNSUPPORTED_MATRIX_PROPERTY(_message) \
827 throw ::gko::UnsupportedMatrixProperty(__FILE__, __LINE__, _message); \
829 static_assert(true, \
830 "This assert is used to counter the false positive extra " \
831 "semi-colon warnings")
844 #define GKO_ASSERT_BLOCK_SIZE_CONFORMANT(_size, _block_size) \
845 if (_size % _block_size != 0) { \
846 throw BlockSizeError<decltype(_size)>(__FILE__, __LINE__, _block_size, \
849 static_assert(true, \
850 "This assert is used to counter the false positive extra " \
851 "semi-colon warnings")
861 #define GKO_ASSERT_IS_SCALAR(_op) \
863 auto sz = gko::detail::get_size(_op); \
864 if (sz[0] != 1 || sz[1] != 1) { \
865 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_op, \
866 sz[0], sz[1], "expected scalar"); \
869 static_assert(true, \
870 "This assert is used to counter the false positive extra " \
871 "semi-colon warnings")
881 #define GKO_INVALID_STATE(_message) \
883 throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
886 static_assert(true, \
887 "This assert is used to counter the false positive extra " \
888 "semi-colon warnings")
899 #define GKO_THROW_IF_INVALID(_condition, _message) \
901 if (!(_condition)) { \
902 throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
906 static_assert(true, \
907 "This assert is used to counter the false positive extra " \
908 "semi-colon warnings")
914 #endif // GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_