33#ifndef GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
34#define GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
40#include <ginkgo/core/base/batch_dim.hpp>
41#include <ginkgo/core/base/dim.hpp>
42#include <ginkgo/core/base/exception.hpp>
43#include <ginkgo/core/base/name_demangling.hpp>
44#include <ginkgo/core/base/utils_helper.hpp>
57#define GKO_QUOTE(...) #__VA_ARGS__
66#define GKO_NOT_IMPLEMENTED \
68 throw ::gko::NotImplemented(__FILE__, __LINE__, __func__); \
71 "This assert is used to counter the false positive extra " \
72 "semi-colon warnings")
83#define GKO_NOT_COMPILED(_module) \
85 throw ::gko::NotCompiled(__FILE__, __LINE__, __func__, \
86 GKO_QUOTE(_module)); \
89 "This assert is used to counter the false positive extra " \
90 "semi-colon warnings")
96template <
typename T,
typename T2 =
void>
97struct dynamic_type_helper {
98 static const std::type_info& get(
const T& obj) {
return typeid(obj); }
102struct dynamic_type_helper<
T,
104 have_ownership<T>()>::type> {
105 static const std::type_info& get(
const T& obj)
107 return obj ?
typeid(*obj) :
typeid(
nullptr);
112const std::type_info& get_dynamic_type(
const T& obj)
114 return dynamic_type_helper<T>::get(obj);
128#define GKO_NOT_SUPPORTED(_obj) \
130 throw ::gko::NotSupported(__FILE__, __LINE__, __func__, \
131 ::gko::name_demangling::get_type_name( \
132 ::gko::detail::get_dynamic_type(_obj))); \
134 static_assert(true, \
135 "This assert is used to counter the false positive extra " \
136 "semi-colon warnings")
143inline dim<2> get_size(
const T&
op)
145 return op->get_size();
148inline dim<2> get_size(
const dim<2>& size) {
return size; }
152inline batch_dim<2> get_batch_size(
const T&
op)
154 return op->get_size();
157inline batch_dim<2> get_batch_size(
const batch_dim<2>& size) {
return size; }
161inline size_type get_num_batch_items(
const T& obj)
163 return obj.get_num_batch_items();
175#define GKO_ASSERT_EQ(_val1, _val2) \
176 if (_val1 != _val2) { \
177 throw ::gko::ValueMismatch(__FILE__, __LINE__, __func__, _val1, _val2, \
178 "expected equal values"); \
188#define GKO_ASSERT_IS_SQUARE_MATRIX(_op1) \
189 if (::gko::detail::get_size(_op1)[0] != \
190 ::gko::detail::get_size(_op1)[1]) { \
191 throw ::gko::DimensionMismatch( \
192 __FILE__, __LINE__, __func__, #_op1, \
193 ::gko::detail::get_size(_op1)[0], \
194 ::gko::detail::get_size(_op1)[1], #_op1, \
195 ::gko::detail::get_size(_op1)[0], \
196 ::gko::detail::get_size(_op1)[1], "expected square matrix"); \
205#define GKO_ASSERT_IS_NON_EMPTY_MATRIX(_op1) \
206 if (!(::gko::detail::get_size(_op1))) { \
207 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_op1, \
208 ::gko::detail::get_size(_op1)[0], \
209 ::gko::detail::get_size(_op1)[1], \
210 "expected non-empty matrix"); \
219#define GKO_ASSERT_IS_POWER_OF_TWO(_val) \
221 if (_val == 0 || (_val & (_val - 1)) != 0) { \
222 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_val, \
224 "expected power-of-two dimension"); \
234#define GKO_ASSERT_CONFORMANT(_op1, _op2) \
235 if (::gko::detail::get_size(_op1)[1] != \
236 ::gko::detail::get_size(_op2)[0]) { \
237 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
238 ::gko::detail::get_size(_op1)[0], \
239 ::gko::detail::get_size(_op1)[1], \
241 ::gko::detail::get_size(_op2)[0], \
242 ::gko::detail::get_size(_op2)[1], \
243 "expected matching inner dimensions"); \
252#define GKO_ASSERT_REVERSE_CONFORMANT(_op1, _op2) \
253 if (::gko::detail::get_size(_op1)[0] != \
254 ::gko::detail::get_size(_op2)[1]) { \
255 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
256 ::gko::detail::get_size(_op1)[0], \
257 ::gko::detail::get_size(_op1)[1], \
259 ::gko::detail::get_size(_op2)[0], \
260 ::gko::detail::get_size(_op2)[1], \
261 "expected matching inner dimensions"); \
270#define GKO_ASSERT_EQUAL_ROWS(_op1, _op2) \
271 if (::gko::detail::get_size(_op1)[0] != \
272 ::gko::detail::get_size(_op2)[0]) { \
273 throw ::gko::DimensionMismatch( \
274 __FILE__, __LINE__, __func__, #_op1, \
275 ::gko::detail::get_size(_op1)[0], \
276 ::gko::detail::get_size(_op1)[1], #_op2, \
277 ::gko::detail::get_size(_op2)[0], \
278 ::gko::detail::get_size(_op2)[1], "expected matching row length"); \
288#define GKO_ASSERT_EQUAL_COLS(_op1, _op2) \
289 if (::gko::detail::get_size(_op1)[1] != \
290 ::gko::detail::get_size(_op2)[1]) { \
291 throw ::gko::DimensionMismatch(__FILE__, __LINE__, __func__, #_op1, \
292 ::gko::detail::get_size(_op1)[0], \
293 ::gko::detail::get_size(_op1)[1], \
295 ::gko::detail::get_size(_op2)[0], \
296 ::gko::detail::get_size(_op2)[1], \
297 "expected matching column length"); \
307#define GKO_ASSERT_EQUAL_DIMENSIONS(_op1, _op2) \
308 if (::gko::detail::get_size(_op1) != ::gko::detail::get_size(_op2)) { \
309 throw ::gko::DimensionMismatch( \
310 __FILE__, __LINE__, __func__, #_op1, \
311 ::gko::detail::get_size(_op1)[0], \
312 ::gko::detail::get_size(_op1)[1], #_op2, \
313 ::gko::detail::get_size(_op2)[0], \
314 ::gko::detail::get_size(_op2)[1], "expected equal dimensions"); \
323#define GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2) \
325 auto equal_num_items = \
326 ::gko::detail::get_batch_size(_op1).get_num_batch_items() == \
327 ::gko::detail::get_batch_size(_op2).get_num_batch_items(); \
328 if (!equal_num_items) { \
329 throw ::gko::ValueMismatch( \
330 __FILE__, __LINE__, __func__, \
331 ::gko::detail::get_batch_size(_op1).get_num_batch_items(), \
332 ::gko::detail::get_batch_size(_op2).get_num_batch_items(), \
333 "expected equal number of batch items"); \
343#define GKO_ASSERT_BATCH_CONFORMANT(_op1, _op2) \
345 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
346 auto equal_inner_size = \
347 ::gko::detail::get_batch_size(_op1).get_common_size()[1] == \
348 ::gko::detail::get_batch_size(_op2).get_common_size()[0]; \
349 if (!equal_inner_size) { \
350 throw ::gko::DimensionMismatch( \
351 __FILE__, __LINE__, __func__, #_op1, \
352 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
353 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
355 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
356 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
357 "expected matching inner dimensions among all batch items"); \
367#define GKO_ASSERT_BATCH_REVERSE_CONFORMANT(_op1, _op2) \
369 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
370 auto equal_outer_size = \
371 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
372 ::gko::detail::get_batch_size(_op2).get_common_size()[1]; \
373 if (!equal_outer_size) { \
374 throw ::gko::DimensionMismatch( \
375 __FILE__, __LINE__, __func__, #_op1, \
376 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
377 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
379 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
380 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
381 "expected matching outer dimensions among all batch items"); \
391#define GKO_ASSERT_BATCH_EQUAL_ROWS(_op1, _op2) \
393 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
395 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
396 ::gko::detail::get_batch_size(_op2).get_common_size()[0]; \
398 throw ::gko::DimensionMismatch( \
399 __FILE__, __LINE__, __func__, #_op1, \
400 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
401 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
403 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
404 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
405 "expected matching number of rows among all batch items"); \
416#define GKO_ASSERT_BATCH_EQUAL_COLS(_op1, _op2) \
418 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
420 ::gko::detail::get_batch_size(_op1).get_common_size()[1] == \
421 ::gko::detail::get_batch_size(_op2).get_common_size()[1]; \
423 throw ::gko::DimensionMismatch( \
424 __FILE__, __LINE__, __func__, #_op1, \
425 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
426 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
428 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
429 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
430 "expected matching number of cols among all batch items"); \
441#define GKO_ASSERT_BATCH_EQUAL_DIMENSIONS(_op1, _op2) \
443 GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
445 ::gko::detail::get_batch_size(_op1).get_common_size() == \
446 ::gko::detail::get_batch_size(_op2).get_common_size(); \
448 throw ::gko::DimensionMismatch( \
449 __FILE__, __LINE__, __func__, #_op1, \
450 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
451 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
453 ::gko::detail::get_batch_size(_op2).get_common_size()[0], \
454 ::gko::detail::get_batch_size(_op2).get_common_size()[1], \
455 "expected matching size among all batch items"); \
466#define GKO_ASSERT_BATCH_HAS_SQUARE_DIMENSIONS(_op1) \
469 ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
470 ::gko::detail::get_batch_size(_op1).get_common_size()[1]; \
472 throw ::gko::BadDimension( \
473 __FILE__, __LINE__, __func__, #_op1, \
474 ::gko::detail::get_batch_size(_op1).get_common_size()[0], \
475 ::gko::detail::get_batch_size(_op1).get_common_size()[1], \
476 "expected common size of matrices to be square"); \
486#define GKO_MPI_ERROR(_errcode) \
487 ::gko::MpiError(__FILE__, __LINE__, __func__, _errcode)
495#define GKO_CUDA_ERROR(_errcode) \
496 ::gko::CudaError(__FILE__, __LINE__, __func__, _errcode)
504#define GKO_CUBLAS_ERROR(_errcode) \
505 ::gko::CublasError(__FILE__, __LINE__, __func__, _errcode)
513#define GKO_CURAND_ERROR(_errcode) \
514 ::gko::CurandError(__FILE__, __LINE__, __func__, _errcode)
522#define GKO_CUSPARSE_ERROR(_errcode) \
523 ::gko::CusparseError(__FILE__, __LINE__, __func__, _errcode)
531#define GKO_CUFFT_ERROR(_errcode) \
532 ::gko::CufftError(__FILE__, __LINE__, __func__, _errcode)
540#define GKO_ASSERT_NO_CUDA_ERRORS(_cuda_call) \
542 auto _errcode = _cuda_call; \
543 if (_errcode != cudaSuccess) { \
544 throw GKO_CUDA_ERROR(_errcode); \
554#define GKO_ASSERT_NO_CUBLAS_ERRORS(_cublas_call) \
556 auto _errcode = _cublas_call; \
557 if (_errcode != CUBLAS_STATUS_SUCCESS) { \
558 throw GKO_CUBLAS_ERROR(_errcode); \
568#define GKO_ASSERT_NO_CURAND_ERRORS(_curand_call) \
570 auto _errcode = _curand_call; \
571 if (_errcode != CURAND_STATUS_SUCCESS) { \
572 throw GKO_CURAND_ERROR(_errcode); \
582#define GKO_ASSERT_NO_CUSPARSE_ERRORS(_cusparse_call) \
584 auto _errcode = _cusparse_call; \
585 if (_errcode != CUSPARSE_STATUS_SUCCESS) { \
586 throw GKO_CUSPARSE_ERROR(_errcode); \
596#define GKO_ASSERT_NO_CUFFT_ERRORS(_cufft_call) \
598 auto _errcode = _cufft_call; \
599 if (_errcode != CUFFT_SUCCESS) { \
600 throw GKO_CUFFT_ERROR(_errcode); \
610#define GKO_HIP_ERROR(_errcode) \
611 ::gko::HipError(__FILE__, __LINE__, __func__, _errcode)
619#define GKO_HIPBLAS_ERROR(_errcode) \
620 ::gko::HipblasError(__FILE__, __LINE__, __func__, _errcode)
628#define GKO_HIPRAND_ERROR(_errcode) \
629 ::gko::HiprandError(__FILE__, __LINE__, __func__, _errcode)
637#define GKO_HIPSPARSE_ERROR(_errcode) \
638 ::gko::HipsparseError(__FILE__, __LINE__, __func__, _errcode)
646#define GKO_HIPFFT_ERROR(_errcode) \
647 ::gko::HipfftError(__FILE__, __LINE__, __func__, _errcode)
655#define GKO_ASSERT_NO_HIP_ERRORS(_hip_call) \
657 auto _errcode = _hip_call; \
658 if (_errcode != hipSuccess) { \
659 throw GKO_HIP_ERROR(_errcode); \
669#define GKO_ASSERT_NO_HIPBLAS_ERRORS(_hipblas_call) \
671 auto _errcode = _hipblas_call; \
672 if (_errcode != HIPBLAS_STATUS_SUCCESS) { \
673 throw GKO_HIPBLAS_ERROR(_errcode); \
683#define GKO_ASSERT_NO_HIPRAND_ERRORS(_hiprand_call) \
685 auto _errcode = _hiprand_call; \
686 if (_errcode != HIPRAND_STATUS_SUCCESS) { \
687 throw GKO_HIPRAND_ERROR(_errcode); \
697#define GKO_ASSERT_NO_HIPSPARSE_ERRORS(_hipsparse_call) \
699 auto _errcode = _hipsparse_call; \
700 if (_errcode != HIPSPARSE_STATUS_SUCCESS) { \
701 throw GKO_HIPSPARSE_ERROR(_errcode); \
711#define GKO_ASSERT_NO_HIPFFT_ERRORS(_hipfft_call) \
713 auto _errcode = _hipfft_call; \
714 if (_errcode != HIPFFT_SUCCESS) { \
715 throw GKO_HIPFFT_ERROR(_errcode); \
725#define GKO_ASSERT_NO_MPI_ERRORS(_mpi_call) \
727 auto _errcode = _mpi_call; \
728 if (_errcode != MPI_SUCCESS) { \
729 throw GKO_MPI_ERROR(_errcode); \
738inline T ensure_allocated_impl(
T ptr,
const std::string&
file,
int line,
741 if (ptr ==
nullptr) {
765#define GKO_ENSURE_ALLOCATED(_ptr, _dev, _size) \
766 ::gko::detail::ensure_allocated_impl(_ptr, __FILE__, __LINE__, _dev, _size)
777#define GKO_ENSURE_IN_BOUNDS(_index, _bound) \
778 if (_index >= _bound) { \
779 throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _index, _bound); \
781 static_assert(true, \
782 "This assert is used to counter the false positive extra " \
783 "semi-colon warnings")
796#define GKO_ENSURE_COMPATIBLE_BOUNDS(_source, _target) \
797 if (_source > _target) { \
798 throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _source, _target); \
800 static_assert(true, \
801 "This assert is used to counter the false positive extra " \
802 "semi-colon warnings")
815#define GKO_STREAM_ERROR(_message) \
816 ::gko::StreamError(__FILE__, __LINE__, __func__, _message)
825#define GKO_KERNEL_NOT_FOUND \
827 throw ::gko::KernelNotFound(__FILE__, __LINE__, __func__); \
829 static_assert(true, \
830 "This assert is used to counter the false positive extra " \
831 "semi-colon warnings")
840#define GKO_UNSUPPORTED_MATRIX_PROPERTY(_message) \
842 throw ::gko::UnsupportedMatrixProperty(__FILE__, __LINE__, _message); \
844 static_assert(true, \
845 "This assert is used to counter the false positive extra " \
846 "semi-colon warnings")
859#define GKO_ASSERT_BLOCK_SIZE_CONFORMANT(_size, _block_size) \
860 if (_size % _block_size != 0) { \
861 throw BlockSizeError<decltype(_size)>(__FILE__, __LINE__, _block_size, \
864 static_assert(true, \
865 "This assert is used to counter the false positive extra " \
866 "semi-colon warnings")
876#define GKO_ASSERT_IS_SCALAR(_op) \
878 auto sz = gko::detail::get_size(_op); \
879 if (sz[0] != 1 || sz[1] != 1) { \
880 throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_op, \
881 sz[0], sz[1], "expected scalar"); \
884 static_assert(true, \
885 "This assert is used to counter the false positive extra " \
886 "semi-colon warnings")
896#define GKO_INVALID_STATE(_message) \
898 throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
901 static_assert(true, \
902 "This assert is used to counter the false positive extra " \
903 "semi-colon warnings")
914#define GKO_THROW_IF_INVALID(_condition, _message) \
916 if (!(_condition)) { \
917 throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
921 static_assert(true, \
922 "This assert is used to counter the false positive extra " \
923 "semi-colon warnings")
The Ginkgo namespace.
Definition abstract_factory.hpp:48
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:803
std::size_t size_type
Integral type used for allocation quantities.
Definition types.hpp:120