Ginkgo
Generated from branch based on main. Ginkgo version 1.11.0
A numerical linear algebra library targeting many-core architectures
Toggle main menu visibility
Loading...
Searching...
No Matches
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
#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>
16
17
18
namespace
gko
{
19
20
28
#define GKO_QUOTE(...) #__VA_ARGS__
29
30
37
#define GKO_NOT_IMPLEMENTED \
38
{ \
39
throw ::gko::NotImplemented(__FILE__, __LINE__, __func__); \
40
} \
41
static_assert(true, \
42
"This assert is used to counter the false positive extra " \
43
"semi-colon warnings")
44
45
54
#define GKO_NOT_COMPILED(_module) \
55
{ \
56
throw ::gko::NotCompiled(__FILE__, __LINE__, __func__, \
57
GKO_QUOTE(_module)); \
58
} \
59
static_assert(true, \
60
"This assert is used to counter the false positive extra " \
61
"semi-colon warnings")
62
63
64
namespace
detail {
65
66
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); }
70
};
71
72
template
<
typename
T>
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)
77
{
78
return
obj ?
typeid
(*obj) :
typeid
(
nullptr
);
79
}
80
};
81
82
template
<
typename
T>
83
const
std::type_info& get_dynamic_type(
const
T& obj)
84
{
85
return
dynamic_type_helper<T>::get(obj);
86
}
87
88
89
}
// namespace detail
90
91
99
#define GKO_NOT_SUPPORTED(_obj) \
100
{ \
101
throw ::gko::NotSupported(__FILE__, __LINE__, __func__, \
102
::gko::name_demangling::get_type_name( \
103
::gko::detail::get_dynamic_type(_obj))); \
104
} \
105
static_assert(true, \
106
"This assert is used to counter the false positive extra " \
107
"semi-colon warnings")
108
109
110
namespace
detail {
111
112
113
template
<
typename
T>
114
inline
dim<2> get_size(
const
T& op)
115
{
116
return
op->get_size();
117
}
118
119
inline
dim<2> get_size(
const
dim<2>& size) {
return
size; }
120
121
122
template
<
typename
T>
123
inline
batch_dim<2> get_batch_size(
const
T& op)
124
{
125
return
op->get_size();
126
}
127
128
inline
batch_dim<2> get_batch_size(
const
batch_dim<2>& size) {
return
size; }
129
130
131
template
<
typename
T>
132
inline
size_type
get_num_batch_items(
const
T& obj)
133
{
134
return
obj.get_num_batch_items();
135
}
136
137
138
}
// namespace detail
139
140
146
#define GKO_ASSERT_EQ(_val1, _val2) \
147
if (_val1 != _val2) { \
148
throw ::gko::ValueMismatch(__FILE__, __LINE__, __func__, _val1, _val2, \
149
"expected equal values"); \
150
}
151
152
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"); \
168
}
169
170
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"); \
182
}
183
184
190
#define GKO_ASSERT_IS_POWER_OF_TWO(_val) \
191
do { \
192
if (_val == 0 || (_val & (_val - 1)) != 0) { \
193
throw ::gko::BadDimension(__FILE__, __LINE__, __func__, #_val, \
194
_val, _val, \
195
"expected power-of-two dimension"); \
196
} \
197
} while (false)
198
199
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], \
211
#_op2, \
212
::gko::detail::get_size(_op2)[0], \
213
::gko::detail::get_size(_op2)[1], \
214
"expected matching inner dimensions"); \
215
}
216
217
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], \
229
#_op2, \
230
::gko::detail::get_size(_op2)[0], \
231
::gko::detail::get_size(_op2)[1], \
232
"expected matching inner dimensions"); \
233
}
234
235
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"); \
250
}
251
252
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], \
265
#_op2, \
266
::gko::detail::get_size(_op2)[0], \
267
::gko::detail::get_size(_op2)[1], \
268
"expected matching column length"); \
269
}
270
271
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"); \
286
}
287
288
294
#define GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2) \
295
{ \
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"); \
305
} \
306
}
307
308
314
#define GKO_ASSERT_BATCH_CONFORMANT(_op1, _op2) \
315
{ \
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], \
325
#_op2, \
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"); \
329
} \
330
}
331
332
338
#define GKO_ASSERT_BATCH_REVERSE_CONFORMANT(_op1, _op2) \
339
{ \
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], \
349
#_op2, \
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"); \
353
} \
354
}
355
356
362
#define GKO_ASSERT_BATCH_EQUAL_ROWS(_op1, _op2) \
363
{ \
364
GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
365
auto equal_rows = \
366
::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
367
::gko::detail::get_batch_size(_op2).get_common_size()[0]; \
368
if (!equal_rows) { \
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], \
373
#_op2, \
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"); \
377
} \
378
}
379
380
387
#define GKO_ASSERT_BATCH_EQUAL_COLS(_op1, _op2) \
388
{ \
389
GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
390
auto equal_cols = \
391
::gko::detail::get_batch_size(_op1).get_common_size()[1] == \
392
::gko::detail::get_batch_size(_op2).get_common_size()[1]; \
393
if (!equal_cols) { \
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], \
398
#_op2, \
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"); \
402
} \
403
}
404
405
412
#define GKO_ASSERT_BATCH_EQUAL_DIMENSIONS(_op1, _op2) \
413
{ \
414
GKO_ASSERT_BATCH_EQUAL_NUM_ITEMS(_op1, _op2); \
415
auto equal_size = \
416
::gko::detail::get_batch_size(_op1).get_common_size() == \
417
::gko::detail::get_batch_size(_op2).get_common_size(); \
418
if (!equal_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], \
423
#_op2, \
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"); \
427
} \
428
}
429
430
437
#define GKO_ASSERT_BATCH_HAS_SQUARE_DIMENSIONS(_op1) \
438
{ \
439
auto is_square = \
440
::gko::detail::get_batch_size(_op1).get_common_size()[0] == \
441
::gko::detail::get_batch_size(_op1).get_common_size()[1]; \
442
if (!is_square) { \
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"); \
448
} \
449
}
450
451
457
#define GKO_MPI_ERROR(_errcode) \
458
::gko::MpiError(__FILE__, __LINE__, __func__, _errcode)
459
460
466
#define GKO_CUDA_ERROR(_errcode) \
467
::gko::CudaError(__FILE__, __LINE__, __func__, _errcode)
468
469
475
#define GKO_CUBLAS_ERROR(_errcode) \
476
::gko::CublasError(__FILE__, __LINE__, __func__, _errcode)
477
478
484
#define GKO_CURAND_ERROR(_errcode) \
485
::gko::CurandError(__FILE__, __LINE__, __func__, _errcode)
486
487
493
#define GKO_CUSPARSE_ERROR(_errcode) \
494
::gko::CusparseError(__FILE__, __LINE__, __func__, _errcode)
495
496
502
#define GKO_CUFFT_ERROR(_errcode) \
503
::gko::CufftError(__FILE__, __LINE__, __func__, _errcode)
504
505
511
#define GKO_ASSERT_NO_CUDA_ERRORS(_cuda_call) \
512
do { \
513
auto _errcode = _cuda_call; \
514
if (_errcode != cudaSuccess) { \
515
throw GKO_CUDA_ERROR(_errcode); \
516
} \
517
} while (false)
518
519
525
#define GKO_ASSERT_NO_CUBLAS_ERRORS(_cublas_call) \
526
do { \
527
auto _errcode = _cublas_call; \
528
if (_errcode != CUBLAS_STATUS_SUCCESS) { \
529
throw GKO_CUBLAS_ERROR(_errcode); \
530
} \
531
} while (false)
532
533
539
#define GKO_ASSERT_NO_CURAND_ERRORS(_curand_call) \
540
do { \
541
auto _errcode = _curand_call; \
542
if (_errcode != CURAND_STATUS_SUCCESS) { \
543
throw GKO_CURAND_ERROR(_errcode); \
544
} \
545
} while (false)
546
547
553
#define GKO_ASSERT_NO_CUSPARSE_ERRORS(_cusparse_call) \
554
do { \
555
auto _errcode = _cusparse_call; \
556
if (_errcode != CUSPARSE_STATUS_SUCCESS) { \
557
throw GKO_CUSPARSE_ERROR(_errcode); \
558
} \
559
} while (false)
560
561
567
#define GKO_ASSERT_NO_CUFFT_ERRORS(_cufft_call) \
568
do { \
569
auto _errcode = _cufft_call; \
570
if (_errcode != CUFFT_SUCCESS) { \
571
throw GKO_CUFFT_ERROR(_errcode); \
572
} \
573
} while (false)
574
575
581
#define GKO_HIP_ERROR(_errcode) \
582
::gko::HipError(__FILE__, __LINE__, __func__, _errcode)
583
584
590
#define GKO_HIPBLAS_ERROR(_errcode) \
591
::gko::HipblasError(__FILE__, __LINE__, __func__, _errcode)
592
593
599
#define GKO_HIPRAND_ERROR(_errcode) \
600
::gko::HiprandError(__FILE__, __LINE__, __func__, _errcode)
601
602
608
#define GKO_HIPSPARSE_ERROR(_errcode) \
609
::gko::HipsparseError(__FILE__, __LINE__, __func__, _errcode)
610
611
617
#define GKO_HIPFFT_ERROR(_errcode) \
618
::gko::HipfftError(__FILE__, __LINE__, __func__, _errcode)
619
620
626
#define GKO_ASSERT_NO_HIP_ERRORS(_hip_call) \
627
do { \
628
auto _errcode = _hip_call; \
629
if (_errcode != hipSuccess) { \
630
throw GKO_HIP_ERROR(_errcode); \
631
} \
632
} while (false)
633
634
640
#define GKO_ASSERT_NO_HIPBLAS_ERRORS(_hipblas_call) \
641
do { \
642
auto _errcode = _hipblas_call; \
643
if (_errcode != HIPBLAS_STATUS_SUCCESS) { \
644
throw GKO_HIPBLAS_ERROR(_errcode); \
645
} \
646
} while (false)
647
648
654
#define GKO_ASSERT_NO_HIPRAND_ERRORS(_hiprand_call) \
655
do { \
656
auto _errcode = _hiprand_call; \
657
if (_errcode != HIPRAND_STATUS_SUCCESS) { \
658
throw GKO_HIPRAND_ERROR(_errcode); \
659
} \
660
} while (false)
661
662
668
#define GKO_ASSERT_NO_HIPSPARSE_ERRORS(_hipsparse_call) \
669
do { \
670
auto _errcode = _hipsparse_call; \
671
if (_errcode != HIPSPARSE_STATUS_SUCCESS) { \
672
throw GKO_HIPSPARSE_ERROR(_errcode); \
673
} \
674
} while (false)
675
676
682
#define GKO_ASSERT_NO_HIPFFT_ERRORS(_hipfft_call) \
683
do { \
684
auto _errcode = _hipfft_call; \
685
if (_errcode != HIPFFT_SUCCESS) { \
686
throw GKO_HIPFFT_ERROR(_errcode); \
687
} \
688
} while (false)
689
690
696
#define GKO_ASSERT_NO_MPI_ERRORS(_mpi_call) \
697
do { \
698
auto _errcode = _mpi_call; \
699
if (_errcode != MPI_SUCCESS) { \
700
throw GKO_MPI_ERROR(_errcode); \
701
} \
702
} while (false)
703
704
705
namespace
detail {
706
707
708
template
<
typename
T>
709
inline
T ensure_allocated_impl(T ptr,
const
std::string& file,
int
line,
710
const
std::string& dev,
size_type
size)
711
{
712
if
(ptr ==
nullptr
) {
713
throw
AllocationError
(file, line, dev, size);
714
}
715
return
ptr;
716
}
717
718
719
}
// namespace detail
720
721
736
#define GKO_ENSURE_ALLOCATED(_ptr, _dev, _size) \
737
::gko::detail::ensure_allocated_impl(_ptr, __FILE__, __LINE__, _dev, _size)
738
739
748
#define GKO_ENSURE_IN_BOUNDS(_index, _bound) \
749
if (_index >= _bound) { \
750
throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _index, _bound); \
751
} \
752
static_assert(true, \
753
"This assert is used to counter the false positive extra " \
754
"semi-colon warnings")
755
756
767
#define GKO_ENSURE_COMPATIBLE_BOUNDS(_source, _target) \
768
if (_source > _target) { \
769
throw ::gko::OutOfBoundsError(__FILE__, __LINE__, _source, _target); \
770
} \
771
static_assert(true, \
772
"This assert is used to counter the false positive extra " \
773
"semi-colon warnings")
774
775
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])
788
789
800
#define GKO_STREAM_ERROR(_message) \
801
::gko::StreamError(__FILE__, __LINE__, __func__, _message)
802
803
810
#define GKO_KERNEL_NOT_FOUND \
811
{ \
812
throw ::gko::KernelNotFound(__FILE__, __LINE__, __func__); \
813
} \
814
static_assert(true, \
815
"This assert is used to counter the false positive extra " \
816
"semi-colon warnings")
817
818
825
#define GKO_UNSUPPORTED_MATRIX_PROPERTY(_message) \
826
{ \
827
throw ::gko::UnsupportedMatrixProperty(__FILE__, __LINE__, _message); \
828
} \
829
static_assert(true, \
830
"This assert is used to counter the false positive extra " \
831
"semi-colon warnings")
832
833
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, \
847
_size); \
848
} \
849
static_assert(true, \
850
"This assert is used to counter the false positive extra " \
851
"semi-colon warnings")
852
853
861
#define GKO_ASSERT_IS_SCALAR(_op) \
862
{ \
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"); \
867
} \
868
} \
869
static_assert(true, \
870
"This assert is used to counter the false positive extra " \
871
"semi-colon warnings")
872
873
881
#define GKO_INVALID_STATE(_message) \
882
{ \
883
throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
884
_message); \
885
} \
886
static_assert(true, \
887
"This assert is used to counter the false positive extra " \
888
"semi-colon warnings")
889
890
899
#define GKO_THROW_IF_INVALID(_condition, _message) \
900
{ \
901
if (!(_condition)) { \
902
throw ::gko::InvalidStateError(__FILE__, __LINE__, __func__, \
903
_message); \
904
} \
905
} \
906
static_assert(true, \
907
"This assert is used to counter the false positive extra " \
908
"semi-colon warnings")
909
910
911
}
// namespace gko
912
913
914
#endif
// GKO_PUBLIC_CORE_BASE_EXCEPTION_HELPERS_HPP_
gko::AllocationError::AllocationError
AllocationError(const std::string &file, int line, const std::string &device, size_type bytes)
Initializes an allocation error.
Definition
exception.hpp:545
gko
The Ginkgo namespace.
Definition
abstract_factory.hpp:20
gko::size_type
std::size_t size_type
Integral type used for allocation quantities.
Definition
types.hpp:90
ginkgo
core
base
exception_helpers.hpp
Generated by
1.18.0