5 #ifndef GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
6 #define GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
12 #include <ginkgo/core/base/batch_dim.hpp>
13 #include <ginkgo/core/base/dim.hpp>
14 #include <ginkgo/core/base/exception.hpp>
15 #include <ginkgo/core/base/name_demangling.hpp>
16 #include <ginkgo/core/base/utils_helper.hpp>
29 #define GKO_QUOTE(...) #__VA_ARGS__
38 #define GKO_NOT_IMPLEMENTED \
40 throw ::gko::NotImplemented(__FILE__, __LINE__, __func__); \
43 "This assert is used to counter the false positive extra " \
44 "semi-colon warnings")
55 #define GKO_NOT_COMPILED(_module) \
57 throw ::gko::NotCompiled(__FILE__, __LINE__, __func__, \
58 GKO_QUOTE(_module)); \
61 "This assert is used to counter the false positive extra " \
62 "semi-colon warnings")
68 template <
typename T,
typename T2 =
void>
69 struct dynamic_type_helper {
70 static const std::type_info& get(
const T& obj) {
return typeid(obj); }
74 struct dynamic_type_helper<T,
75 typename std::enable_if<std::is_pointer<T>::value ||
76 have_ownership<T>()>::type> {
77 static const std::type_info& get(
const T& obj)
79 return obj ?
typeid(*obj) :
typeid(
nullptr);
84 const std::type_info& get_dynamic_type(
const T& obj)
86 return dynamic_type_helper<T>::get(obj);
100 #define GKO_NOT_SUPPORTED(_obj) \
102 throw ::gko::NotSupported(__FILE__, __LINE__, __func__, \
103 ::gko::name_demangling::get_type_name( \
104 ::gko::detail::get_dynamic_type(_obj))); \
106 static_assert(true, \
107 "This assert is used to counter the false positive extra " \
108 "semi-colon warnings")
114 template <
typename T>
115 inline dim<2> get_size(
const T& op)
117 return op->get_size();
120 inline dim<2> get_size(
const dim<2>& size) {
return size; }
123 template <
typename T>
124 inline batch_dim<2> get_batch_size(
const T& op)
126 return op->get_size();
129 inline batch_dim<2> get_batch_size(
const batch_dim<2>& size) {
return size; }
132 template <
typename T>
133 inline size_type get_num_batch_items(
const T& obj)
135 return obj.get_num_batch_items();
147 #define GKO_ASSERT_EQ(_val1, _val2) \
148 if (_val1 != _val2) { \
149 throw ::gko::ValueMismatch(__FILE__, __LINE__, __func__, _val1, _val2, \
150 "expected equal values"); \
160 #define GKO_ASSERT_IS_SQUARE_MATRIX(_op1) \
161 if (::gko::detail::get_size(_op1)[0] != \
162 ::gko::detail::get_size(_op1)[1]) { \
163 throw ::gko::DimensionMismatch( \
164 __FILE__, __LINE__, __func__, #_op1, \
165 ::gko::detail::get_size(_op1)[0], \
166 ::gko::detail::get_size(_op1)[1], #_op1, \
167 ::gko::detail::get_size(_op1)[0], \
168 ::gko::detail::get_size(_op1)[1], "expected square matrix"); \
177 #define GKO_ASSERT_IS_NON_EMPTY_MATRIX(_op1) \
178 if (!(::gko::detail::get_size(_op1))) { \
179 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_op1, \
180 ::gko::detail::get_size(_op1)[0], \
181 ::gko::detail::get_size(_op1)[1], \
182 "expected non-empty matrix"); \
191 #define GKO_ASSERT_IS_POWER_OF_TWO(_val) \
193 if (_val == 0 || (_val & (_val - 1)) != 0) { \
194 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_val, \
196 "expected power-of-two dimension"); \
206 #define GKO_ASSERT_CONFORMANT(_op1, _op2) \
207 if (::gko::detail::get_size(_op1)[1] != \
208 ::gko::detail::get_size(_op2)[0]) { \
209 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
210 ::gko::detail::get_size(_op1)[0], \
211 ::gko::detail::get_size(_op1)[1], \
213 ::gko::detail::get_size(_op2)[0], \
214 ::gko::detail::get_size(_op2)[1], \
215 "expected matching inner dimensions"); \
224 #define GKO_ASSERT_REVERSE_CONFORMANT(_op1, _op2) \
225 if (::gko::detail::get_size(_op1)[0] != \
226 ::gko::detail::get_size(_op2)[1]) { \
227 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
228 ::gko::detail::get_size(_op1)[0], \
229 ::gko::detail::get_size(_op1)[1], \
231 ::gko::detail::get_size(_op2)[0], \
232 ::gko::detail::get_size(_op2)[1], \
233 "expected matching inner dimensions"); \
242 #define GKO_ASSERT_EQUAL_ROWS(_op1, _op2) \
243 if (::gko::detail::get_size(_op1)[0] != \
244 ::gko::detail::get_size(_op2)[0]) { \
245 throw ::gko::DimensionMismatch( \
246 __FILE__, __LINE__, __func__, #_op1, \
247 ::gko::detail::get_size(_op1)[0], \
248 ::gko::detail::get_size(_op1)[1], #_op2, \
249 ::gko::detail::get_size(_op2)[0], \
250 ::gko::detail::get_size(_op2)[1], "expected matching row length"); \
260 #define GKO_ASSERT_EQUAL_COLS(_op1, _op2) \
261 if (::gko::detail::get_size(_op1)[1] != \
262 ::gko::detail::get_size(_op2)[1]) { \
263 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
264 ::gko::detail::get_size(_op1)[0], \
265 ::gko::detail::get_size(_op1)[1], \
267 ::gko::detail::get_size(_op2)[0], \
268 ::gko::detail::get_size(_op2)[1], \
269 "expected matching column length"); \
279 #define GKO_ASSERT_EQUAL_DIMENSIONS(_op1, _op2) \
280 if (::gko::detail::get_size(_op1) != ::gko::detail::get_size(_op2)) { \
281 throw ::gko::DimensionMismatch( \
282 __FILE__, __LINE__, __func__, #_op1, \
283 ::gko::detail::get_size(_op1)[0], \
284 ::gko::detail::get_size(_op1)[1], #_op2, \
285 ::gko::detail::get_size(_op2)[0], \
286 ::gko::detail::get_size(_op2)[1], "expected equal dimensions"); \
295 #define GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2) \
297 auto equal_num_items = \
298 ::gko::detail::get_batch_size(_op1).get_num_batch_items() == \
299 ::gko::detail::get_batch_size(_op2).get_num_batch_items(); \
300 if (!equal_num_items) { \
301 throw ::gko::ValueMismatch( \
302 __FILE__, __LINE__, __func__, \
303 ::gko::detail::get_batch_size(_op1).get_num_batch_items(), \
304 ::gko::detail::get_batch_size(_op2).get_num_batch_items(), \
305 "expected equal number of batch items"); \
315 #define GKO_ASSERT_BATCH_CONFORMANT(_op1, _op2) \
317 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
318 auto equal_inner_size = \
319 ::gko::detail::get_batch_size(_op1).get_common_size()[1] == \
320 ::gko::detail::get_batch_size(_op2).get_common_size()[0]; \
321 if (!equal_inner_size) { \
322 throw ::gko::DimensionMismatch( \
323 __FILE__, __LINE__, __func__, #_op1, \
324 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
325 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
327 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
328 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
329 "expected matching inner dimensions among all batch items"); \
339 #define GKO_ASSERT_BATCH_REVERSE_CONFORMANT(_op1, _op2) \
341 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
342 auto equal_outer_size = \
343 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
344 ::gko::detail::get_batch_size(_op2).get_common_size()[1]; \
345 if (!equal_outer_size) { \
346 throw ::gko::DimensionMismatch( \
347 __FILE__, __LINE__, __func__, #_op1, \
348 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
349 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
351 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
352 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
353 "expected matching outer dimensions among all batch items"); \
363 #define GKO_ASSERT_BATCH_EQUAL_ROWS(_op1, _op2) \
365 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
367 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
368 ::gko::detail::get_batch_size(_op2).get_common_size()[0]; \
370 throw ::gko::DimensionMismatch( \
371 __FILE__, __LINE__, __func__, #_op1, \
372 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
373 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
375 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
376 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
377 "expected matching number of rows among all batch items"); \
388 #define GKO_ASSERT_BATCH_EQUAL_COLS(_op1, _op2) \
390 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
392 ::gko::detail::get_batch_size(_op1).get_common_size()[1] == \
393 ::gko::detail::get_batch_size(_op2).get_common_size()[1]; \
395 throw ::gko::DimensionMismatch( \
396 __FILE__, __LINE__, __func__, #_op1, \
397 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
398 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
400 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
401 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
402 "expected matching number of cols among all batch items"); \
413 #define GKO_ASSERT_BATCH_EQUAL_DIMENSIONS(_op1, _op2) \
415 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
417 ::gko::detail::get_batch_size(_op1).get_common_size() == \
418 ::gko::detail::get_batch_size(_op2).get_common_size(); \
420 throw ::gko::DimensionMismatch( \
421 __FILE__, __LINE__, __func__, #_op1, \
422 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
423 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
425 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
426 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
427 "expected matching size among all batch items"); \
438 #define GKO_ASSERT_BATCH_HAS_SQUARE_DIMENSIONS(_op1) \
441 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
442 ::gko::detail::get_batch_size(_op1).get_common_size()[1]; \
444 throw ::gko::BadDimension( \
445 __FILE__, __LINE__, __func__, #_op1, \
446 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
447 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
448 "expected common size of matrices to be square"); \
458 #define GKO_MPI_ERROR(_errcode) \
459 ::gko::MpiError(__FILE__, __LINE__, __func__, _errcode)
467 #define GKO_CUDA_ERROR(_errcode) \
468 ::gko::CudaError(__FILE__, __LINE__, __func__, _errcode)
476 #define GKO_CUBLAS_ERROR(_errcode) \
477 ::gko::CublasError(__FILE__, __LINE__, __func__, _errcode)
485 #define GKO_CURAND_ERROR(_errcode) \
486 ::gko::CurandError(__FILE__, __LINE__, __func__, _errcode)
494 #define GKO_CUSPARSE_ERROR(_errcode) \
495 ::gko::CusparseError(__FILE__, __LINE__, __func__, _errcode)
503 #define GKO_CUFFT_ERROR(_errcode) \
504 ::gko::CufftError(__FILE__, __LINE__, __func__, _errcode)
512 #define GKO_ASSERT_NO_CUDA_ERRORS(_cuda_call) \
514 auto _errcode = _cuda_call; \
515 if (_errcode != cudaSuccess) { \
516 throw GKO_CUDA_ERROR(_errcode); \
526 #define GKO_ASSERT_NO_CUBLAS_ERRORS(_cublas_call) \
528 auto _errcode = _cublas_call; \
529 if (_errcode != CUBLAS_STATUS_SUCCESS) { \
530 throw GKO_CUBLAS_ERROR(_errcode); \
540 #define GKO_ASSERT_NO_CURAND_ERRORS(_curand_call) \
542 auto _errcode = _curand_call; \
543 if (_errcode != CURAND_STATUS_SUCCESS) { \
544 throw GKO_CURAND_ERROR(_errcode); \
554 #define GKO_ASSERT_NO_CUSPARSE_ERRORS(_cusparse_call) \
556 auto _errcode = _cusparse_call; \
557 if (_errcode != CUSPARSE_STATUS_SUCCESS) { \
558 throw GKO_CUSPARSE_ERROR(_errcode); \
568 #define GKO_ASSERT_NO_CUFFT_ERRORS(_cufft_call) \
570 auto _errcode = _cufft_call; \
571 if (_errcode != CUFFT_SUCCESS) { \
572 throw GKO_CUFFT_ERROR(_errcode); \
582 #define GKO_HIP_ERROR(_errcode) \
583 ::gko::HipError(__FILE__, __LINE__, __func__, _errcode)
591 #define GKO_HIPBLAS_ERROR(_errcode) \
592 ::gko::HipblasError(__FILE__, __LINE__, __func__, _errcode)
600 #define GKO_HIPRAND_ERROR(_errcode) \
601 ::gko::HiprandError(__FILE__, __LINE__, __func__, _errcode)
609 #define GKO_HIPSPARSE_ERROR(_errcode) \
610 ::gko::HipsparseError(__FILE__, __LINE__, __func__, _errcode)
618 #define GKO_HIPFFT_ERROR(_errcode) \
619 ::gko::HipfftError(__FILE__, __LINE__, __func__, _errcode)
627 #define GKO_ASSERT_NO_HIP_ERRORS(_hip_call) \
629 auto _errcode = _hip_call; \
630 if (_errcode != hipSuccess) { \
631 throw GKO_HIP_ERROR(_errcode); \
641 #define GKO_ASSERT_NO_HIPBLAS_ERRORS(_hipblas_call) \
643 auto _errcode = _hipblas_call; \
644 if (_errcode != HIPBLAS_STATUS_SUCCESS) { \
645 throw GKO_HIPBLAS_ERROR(_errcode); \
655 #define GKO_ASSERT_NO_HIPRAND_ERRORS(_hiprand_call) \
657 auto _errcode = _hiprand_call; \
658 if (_errcode != HIPRAND_STATUS_SUCCESS) { \
659 throw GKO_HIPRAND_ERROR(_errcode); \
669 #define GKO_ASSERT_NO_HIPSPARSE_ERRORS(_hipsparse_call) \
671 auto _errcode = _hipsparse_call; \
672 if (_errcode != HIPSPARSE_STATUS_SUCCESS) { \
673 throw GKO_HIPSPARSE_ERROR(_errcode); \
683 #define GKO_ASSERT_NO_HIPFFT_ERRORS(_hipfft_call) \
685 auto _errcode = _hipfft_call; \
686 if (_errcode != HIPFFT_SUCCESS) { \
687 throw GKO_HIPFFT_ERROR(_errcode); \
697 #define GKO_ASSERT_NO_MPI_ERRORS(_mpi_call) \
699 auto _errcode = _mpi_call; \
700 if (_errcode != MPI_SUCCESS) { \
701 throw GKO_MPI_ERROR(_errcode); \
709 template <
typename T>
710 inline T ensure_allocated_impl(T ptr,
const std::string& file,
int line,
713 if (ptr ==
nullptr) {
714 throw AllocationError(file, line, dev, size);
737 #define GKO_ENSURE_ALLOCATED(_ptr, _dev, _size) \
738 ::gko::detail::ensure_allocated_impl(_ptr, __FILE__, __LINE__, _dev, _size)
749 #define GKO_ENSURE_IN_BOUNDS(_index, _bound) \
750 if (_index >= _bound) { \
751 throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _index, _bound); \
753 static_assert(true, \
754 "This assert is used to counter the false positive extra " \
755 "semi-colon warnings")
768 #define GKO_ENSURE_COMPATIBLE_BOUNDS(_source, _target) \
769 if (_source > _target) { \
770 throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _source, _target); \
772 static_assert(true, \
773 "This assert is used to counter the false positive extra " \
774 "semi-colon warnings")
786 #define GKO_ENSURE_IN_DIMENSION_BOUNDS(_row, _col, _bound) \
787 GKO_ENSURE_IN_BOUNDS(_row, ::gko::detail::get_size(_bound)[0]); \
788 GKO_ENSURE_IN_BOUNDS(_col, ::gko::detail::get_size(_bound)[1])
801 #define GKO_STREAM_ERROR(_message) \
802 ::gko::StreamError(__FILE__, __LINE__, __func__, _message)
811 #define GKO_KERNEL_NOT_FOUND \
813 throw ::gko::KernelNotFound(__FILE__, __LINE__, __func__); \
815 static_assert(true, \
816 "This assert is used to counter the false positive extra " \
817 "semi-colon warnings")
826 #define GKO_UNSUPPORTED_MATRIX_PROPERTY(_message) \
828 throw ::gko::UnsupportedMatrixProperty(__FILE__, __LINE__, _message); \
830 static_assert(true, \
831 "This assert is used to counter the false positive extra " \
832 "semi-colon warnings")
845 #define GKO_ASSERT_BLOCK_SIZE_CONFORMANT(_size, _block_size) \
846 if (_size % _block_size != 0) { \
847 throw BlockSizeError<decltype(_size)>(__FILE__, __LINE__, _block_size, \
850 static_assert(true, \
851 "This assert is used to counter the false positive extra " \
852 "semi-colon warnings")
862 #define GKO_ASSERT_IS_SCALAR(_op) \
864 auto sz = gko::detail::get_size(_op); \
865 if (sz[0] != 1 || sz[1] != 1) { \
866 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_op, \
867 sz[0], sz[1], "expected scalar"); \
870 static_assert(true, \
871 "This assert is used to counter the false positive extra " \
872 "semi-colon warnings")
882 #define GKO_INVALID_STATE(_message) \
884 throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
887 static_assert(true, \
888 "This assert is used to counter the false positive extra " \
889 "semi-colon warnings")
900 #define GKO_THROW_IF_INVALID(_condition, _message) \
902 if (!(_condition)) { \
903 throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
907 static_assert(true, \
908 "This assert is used to counter the false positive extra " \
909 "semi-colon warnings")
915 #endif // GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_