Ginkgo  Generated from pipelines/1330831941 branch based on master. Ginkgo version 1.8.0
A numerical linear algebra library targeting many-core architectures
exception_helpers.hpp
1 // SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #ifndef GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
6 #define GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
7 
8 
9 #include <typeinfo>
10 
11 
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>
17 
18 
19 namespace gko {
20 
21 
29 #define GKO_QUOTE(...) #__VA_ARGS__
30 
31 
38 #define GKO_NOT_IMPLEMENTED \
39  { \
40  throw ::gko::NotImplemented(__FILE__, __LINE__, __func__); \
41  } \
42  static_assert(true, \
43  "This assert is used to counter the false positive extra " \
44  "semi-colon warnings")
45 
46 
55 #define GKO_NOT_COMPILED(_module) \
56  { \
57  throw ::gko::NotCompiled(__FILE__, __LINE__, __func__, \
58  GKO_QUOTE(_module)); \
59  } \
60  static_assert(true, \
61  "This assert is used to counter the false positive extra " \
62  "semi-colon warnings")
63 
64 
65 namespace detail {
66 
67 
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); }
71 };
72 
73 template <typename T>
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)
78  {
79  return obj ? typeid(*obj) : typeid(nullptr);
80  }
81 };
82 
83 template <typename T>
84 const std::type_info& get_dynamic_type(const T& obj)
85 {
86  return dynamic_type_helper<T>::get(obj);
87 }
88 
89 
90 } // namespace detail
91 
92 
100 #define GKO_NOT_SUPPORTED(_obj) \
101  { \
102  throw ::gko::NotSupported(__FILE__, __LINE__, __func__, \
103  ::gko::name_demangling::get_type_name( \
104  ::gko::detail::get_dynamic_type(_obj))); \
105  } \
106  static_assert(true, \
107  "This assert is used to counter the false positive extra " \
108  "semi-colon warnings")
109 
110 
111 namespace detail {
112 
113 
114 template <typename T>
115 inline dim<2> get_size(const T& op)
116 {
117  return op->get_size();
118 }
119 
120 inline dim<2> get_size(const dim<2>& size) { return size; }
121 
122 
123 template <typename T>
124 inline batch_dim<2> get_batch_size(const T& op)
125 {
126  return op->get_size();
127 }
128 
129 inline batch_dim<2> get_batch_size(const batch_dim<2>& size) { return size; }
130 
131 
132 template <typename T>
133 inline size_type get_num_batch_items(const T& obj)
134 {
135  return obj.get_num_batch_items();
136 }
137 
138 
139 } // namespace detail
140 
141 
147 #define GKO_ASSERT_EQ(_val1, _val2) \
148  if (_val1 != _val2) { \
149  throw ::gko::ValueMismatch(__FILE__, __LINE__, __func__, _val1, _val2, \
150  "expected equal values"); \
151  }
152 
153 
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"); \
169  }
170 
171 
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"); \
183  }
184 
185 
191 #define GKO_ASSERT_IS_POWER_OF_TWO(_val) \
192  do { \
193  if (_val == 0 || (_val & (_val - 1)) != 0) { \
194  throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_val, \
195  _val, _val, \
196  "expected power-of-two dimension"); \
197  } \
198  } while (false)
199 
200 
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], \
212  #_op2, \
213  ::gko::detail::get_size(_op2)[0], \
214  ::gko::detail::get_size(_op2)[1], \
215  "expected matching inner dimensions"); \
216  }
217 
218 
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], \
230  #_op2, \
231  ::gko::detail::get_size(_op2)[0], \
232  ::gko::detail::get_size(_op2)[1], \
233  "expected matching inner dimensions"); \
234  }
235 
236 
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"); \
251  }
252 
253 
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], \
266  #_op2, \
267  ::gko::detail::get_size(_op2)[0], \
268  ::gko::detail::get_size(_op2)[1], \
269  "expected matching column length"); \
270  }
271 
272 
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"); \
287  }
288 
289 
295 #define GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2) \
296  { \
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"); \
306  } \
307  }
308 
309 
315 #define GKO_ASSERT_BATCH_CONFORMANT(_op1, _op2) \
316  { \
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], \
326  #_op2, \
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"); \
330  } \
331  }
332 
333 
339 #define GKO_ASSERT_BATCH_REVERSE_CONFORMANT(_op1, _op2) \
340  { \
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], \
350  #_op2, \
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"); \
354  } \
355  }
356 
357 
363 #define GKO_ASSERT_BATCH_EQUAL_ROWS(_op1, _op2) \
364  { \
365  GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
366  auto equal_rows = \
367  ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
368  ::gko::detail::get_batch_size(_op2).get_common_size()[0]; \
369  if (!equal_rows) { \
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], \
374  #_op2, \
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"); \
378  } \
379  }
380 
381 
388 #define GKO_ASSERT_BATCH_EQUAL_COLS(_op1, _op2) \
389  { \
390  GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
391  auto equal_cols = \
392  ::gko::detail::get_batch_size(_op1).get_common_size()[1] == \
393  ::gko::detail::get_batch_size(_op2).get_common_size()[1]; \
394  if (!equal_cols) { \
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], \
399  #_op2, \
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"); \
403  } \
404  }
405 
406 
413 #define GKO_ASSERT_BATCH_EQUAL_DIMENSIONS(_op1, _op2) \
414  { \
415  GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
416  auto equal_size = \
417  ::gko::detail::get_batch_size(_op1).get_common_size() == \
418  ::gko::detail::get_batch_size(_op2).get_common_size(); \
419  if (!equal_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], \
424  #_op2, \
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"); \
428  } \
429  }
430 
431 
438 #define GKO_ASSERT_BATCH_HAS_SQUARE_DIMENSIONS(_op1) \
439  { \
440  auto is_square = \
441  ::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
442  ::gko::detail::get_batch_size(_op1).get_common_size()[1]; \
443  if (!is_square) { \
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"); \
449  } \
450  }
451 
452 
458 #define GKO_MPI_ERROR(_errcode) \
459  ::gko::MpiError(__FILE__, __LINE__, __func__, _errcode)
460 
461 
467 #define GKO_CUDA_ERROR(_errcode) \
468  ::gko::CudaError(__FILE__, __LINE__, __func__, _errcode)
469 
470 
476 #define GKO_CUBLAS_ERROR(_errcode) \
477  ::gko::CublasError(__FILE__, __LINE__, __func__, _errcode)
478 
479 
485 #define GKO_CURAND_ERROR(_errcode) \
486  ::gko::CurandError(__FILE__, __LINE__, __func__, _errcode)
487 
488 
494 #define GKO_CUSPARSE_ERROR(_errcode) \
495  ::gko::CusparseError(__FILE__, __LINE__, __func__, _errcode)
496 
497 
503 #define GKO_CUFFT_ERROR(_errcode) \
504  ::gko::CufftError(__FILE__, __LINE__, __func__, _errcode)
505 
506 
512 #define GKO_ASSERT_NO_CUDA_ERRORS(_cuda_call) \
513  do { \
514  auto _errcode = _cuda_call; \
515  if (_errcode != cudaSuccess) { \
516  throw GKO_CUDA_ERROR(_errcode); \
517  } \
518  } while (false)
519 
520 
526 #define GKO_ASSERT_NO_CUBLAS_ERRORS(_cublas_call) \
527  do { \
528  auto _errcode = _cublas_call; \
529  if (_errcode != CUBLAS_STATUS_SUCCESS) { \
530  throw GKO_CUBLAS_ERROR(_errcode); \
531  } \
532  } while (false)
533 
534 
540 #define GKO_ASSERT_NO_CURAND_ERRORS(_curand_call) \
541  do { \
542  auto _errcode = _curand_call; \
543  if (_errcode != CURAND_STATUS_SUCCESS) { \
544  throw GKO_CURAND_ERROR(_errcode); \
545  } \
546  } while (false)
547 
548 
554 #define GKO_ASSERT_NO_CUSPARSE_ERRORS(_cusparse_call) \
555  do { \
556  auto _errcode = _cusparse_call; \
557  if (_errcode != CUSPARSE_STATUS_SUCCESS) { \
558  throw GKO_CUSPARSE_ERROR(_errcode); \
559  } \
560  } while (false)
561 
562 
568 #define GKO_ASSERT_NO_CUFFT_ERRORS(_cufft_call) \
569  do { \
570  auto _errcode = _cufft_call; \
571  if (_errcode != CUFFT_SUCCESS) { \
572  throw GKO_CUFFT_ERROR(_errcode); \
573  } \
574  } while (false)
575 
576 
582 #define GKO_HIP_ERROR(_errcode) \
583  ::gko::HipError(__FILE__, __LINE__, __func__, _errcode)
584 
585 
591 #define GKO_HIPBLAS_ERROR(_errcode) \
592  ::gko::HipblasError(__FILE__, __LINE__, __func__, _errcode)
593 
594 
600 #define GKO_HIPRAND_ERROR(_errcode) \
601  ::gko::HiprandError(__FILE__, __LINE__, __func__, _errcode)
602 
603 
609 #define GKO_HIPSPARSE_ERROR(_errcode) \
610  ::gko::HipsparseError(__FILE__, __LINE__, __func__, _errcode)
611 
612 
618 #define GKO_HIPFFT_ERROR(_errcode) \
619  ::gko::HipfftError(__FILE__, __LINE__, __func__, _errcode)
620 
621 
627 #define GKO_ASSERT_NO_HIP_ERRORS(_hip_call) \
628  do { \
629  auto _errcode = _hip_call; \
630  if (_errcode != hipSuccess) { \
631  throw GKO_HIP_ERROR(_errcode); \
632  } \
633  } while (false)
634 
635 
641 #define GKO_ASSERT_NO_HIPBLAS_ERRORS(_hipblas_call) \
642  do { \
643  auto _errcode = _hipblas_call; \
644  if (_errcode != HIPBLAS_STATUS_SUCCESS) { \
645  throw GKO_HIPBLAS_ERROR(_errcode); \
646  } \
647  } while (false)
648 
649 
655 #define GKO_ASSERT_NO_HIPRAND_ERRORS(_hiprand_call) \
656  do { \
657  auto _errcode = _hiprand_call; \
658  if (_errcode != HIPRAND_STATUS_SUCCESS) { \
659  throw GKO_HIPRAND_ERROR(_errcode); \
660  } \
661  } while (false)
662 
663 
669 #define GKO_ASSERT_NO_HIPSPARSE_ERRORS(_hipsparse_call) \
670  do { \
671  auto _errcode = _hipsparse_call; \
672  if (_errcode != HIPSPARSE_STATUS_SUCCESS) { \
673  throw GKO_HIPSPARSE_ERROR(_errcode); \
674  } \
675  } while (false)
676 
677 
683 #define GKO_ASSERT_NO_HIPFFT_ERRORS(_hipfft_call) \
684  do { \
685  auto _errcode = _hipfft_call; \
686  if (_errcode != HIPFFT_SUCCESS) { \
687  throw GKO_HIPFFT_ERROR(_errcode); \
688  } \
689  } while (false)
690 
691 
697 #define GKO_ASSERT_NO_MPI_ERRORS(_mpi_call) \
698  do { \
699  auto _errcode = _mpi_call; \
700  if (_errcode != MPI_SUCCESS) { \
701  throw GKO_MPI_ERROR(_errcode); \
702  } \
703  } while (false)
704 
705 
706 namespace detail {
707 
708 
709 template <typename T>
710 inline T ensure_allocated_impl(T ptr, const std::string& file, int line,
711  const std::string& dev, size_type size)
712 {
713  if (ptr == nullptr) {
714  throw AllocationError(file, line, dev, size);
715  }
716  return ptr;
717 }
718 
719 
720 } // namespace detail
721 
722 
737 #define GKO_ENSURE_ALLOCATED(_ptr, _dev, _size) \
738  ::gko::detail::ensure_allocated_impl(_ptr, __FILE__, __LINE__, _dev, _size)
739 
740 
749 #define GKO_ENSURE_IN_BOUNDS(_index, _bound) \
750  if (_index >= _bound) { \
751  throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _index, _bound); \
752  } \
753  static_assert(true, \
754  "This assert is used to counter the false positive extra " \
755  "semi-colon warnings")
756 
757 
768 #define GKO_ENSURE_COMPATIBLE_BOUNDS(_source, _target) \
769  if (_source > _target) { \
770  throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _source, _target); \
771  } \
772  static_assert(true, \
773  "This assert is used to counter the false positive extra " \
774  "semi-colon warnings")
775 
776 
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])
789 
790 
801 #define GKO_STREAM_ERROR(_message) \
802  ::gko::StreamError(__FILE__, __LINE__, __func__, _message)
803 
804 
811 #define GKO_KERNEL_NOT_FOUND \
812  { \
813  throw ::gko::KernelNotFound(__FILE__, __LINE__, __func__); \
814  } \
815  static_assert(true, \
816  "This assert is used to counter the false positive extra " \
817  "semi-colon warnings")
818 
819 
826 #define GKO_UNSUPPORTED_MATRIX_PROPERTY(_message) \
827  { \
828  throw ::gko::UnsupportedMatrixProperty(__FILE__, __LINE__, _message); \
829  } \
830  static_assert(true, \
831  "This assert is used to counter the false positive extra " \
832  "semi-colon warnings")
833 
834 
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, \
848  _size); \
849  } \
850  static_assert(true, \
851  "This assert is used to counter the false positive extra " \
852  "semi-colon warnings")
853 
854 
862 #define GKO_ASSERT_IS_SCALAR(_op) \
863  { \
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"); \
868  } \
869  } \
870  static_assert(true, \
871  "This assert is used to counter the false positive extra " \
872  "semi-colon warnings")
873 
874 
882 #define GKO_INVALID_STATE(_message) \
883  { \
884  throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
885  _message); \
886  } \
887  static_assert(true, \
888  "This assert is used to counter the false positive extra " \
889  "semi-colon warnings")
890 
891 
900 #define GKO_THROW_IF_INVALID(_condition, _message) \
901  { \
902  if (!(_condition)) { \
903  throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
904  _message); \
905  } \
906  } \
907  static_assert(true, \
908  "This assert is used to counter the false positive extra " \
909  "semi-colon warnings")
910 
911 
912 } // namespace gko
913 
914 
915 #endif // GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
gko::size_type
std::size_t size_type
Integral type used for allocation quantities.
Definition: types.hpp:108
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:20