10#ifndef XTENSOR_EXCEPTION_HPP
11#define XTENSOR_EXCEPTION_HPP
20#include <xtl/xcompare.hpp>
21#include <xtl/xsequence.hpp>
22#include <xtl/xspan_impl.hpp>
24#include "xtensor_config.hpp"
27#define XTENSOR_UNUSED_VARIABLE __attribute__((unused))
29#define XTENSOR_UNUSED_VARIABLE
45 template <
class... Args>
46 struct last_type_is_missing_impl
47 : std::is_same<missing_type, xtl::mpl::back_t<xtl::mpl::vector<Args...>>>
52 struct last_type_is_missing_impl<> : std::false_type
56 template <
class... Args>
57 constexpr bool last_type_is_missing = last_type_is_missing_impl<Args...>::value;
64 class broadcast_error :
public std::runtime_error
68 explicit broadcast_error(
const char* msg)
69 : std::runtime_error(msg)
74 template <
class S1,
class S2>
75 [[noreturn]]
void throw_broadcast_error(
const S1& lhs,
const S2& rhs);
81 class concatenate_error :
public std::runtime_error
85 explicit concatenate_error(
const char* msg)
86 : std::runtime_error(msg)
91 template <
class S1,
class S2>
92 [[noreturn]]
void throw_concatenate_error(
const S1& lhs,
const S2& rhs);
100 template <
class S1,
class S2>
101 inline std::string shape_error_message(
const S1& lhs,
const S2& rhs)
103 std::ostringstream buf(
"Incompatible dimension of arrays:", std::ios_base::ate);
105 buf <<
"\n LHS shape = (";
106 using size_type1 =
typename S1::value_type;
107 std::ostream_iterator<size_type1> iter1(buf,
", ");
108 std::copy(lhs.cbegin(), lhs.cend(), iter1);
110 buf <<
")\n RHS shape = (";
111 using size_type2 =
typename S2::value_type;
112 std::ostream_iterator<size_type2> iter2(buf,
", ");
113 std::copy(rhs.cbegin(), rhs.cend(), iter2);
122 template <
class S1,
class S2>
123 [[noreturn]]
void throw_broadcast_error(
const S1&,
const S2&)
125 XTENSOR_THROW(
broadcast_error,
"Incompatible dimension of arrays, compile in DEBUG for more info");
128 template <
class S1,
class S2>
129 [[noreturn]]
void throw_broadcast_error(
const S1& lhs,
const S2& rhs)
131 std::string msg = detail::shape_error_message(lhs, rhs);
142 template <
class S1,
class S2>
143 [[noreturn]]
void throw_concatenate_error(
const S1&,
const S2&)
145 XTENSOR_THROW(
concatenate_error,
"Incompatible dimension of arrays, compile in DEBUG for more info");
148 template <
class S1,
class S2>
149 [[noreturn]]
void throw_concatenate_error(
const S1& lhs,
const S2& rhs)
151 std::string msg = detail::shape_error_message(lhs, rhs);
160 class transpose_error :
public std::runtime_error
164 explicit transpose_error(
const char* msg)
165 : std::runtime_error(msg)
174 template <
class S,
class... Args>
175 void check_index(
const S& shape, Args... args);
177 template <
class S,
class It>
178 void check_element_index(
const S& shape, It first, It last);
182 template <
class S, std::
size_t dim>
183 inline void check_index_impl(
const S&)
187 template <
class S, std::
size_t dim>
188 inline void check_index_impl(
const S&, missing_type)
192 template <
class S, std::size_t dim,
class T,
class... Args>
193 inline void check_index_impl(
const S& shape, T
arg, Args... args)
195 if (std::size_t(
arg) >= std::size_t(shape[dim]) && shape[dim] != 1)
199 "index " + std::to_string(
arg) +
" is out of bounds for axis " + std::to_string(dim)
200 +
" with size " + std::to_string(shape[dim])
203 check_index_impl<S, dim + 1>(shape, args...);
208 inline void check_index(
const S&)
217 template <
class S,
class Arg,
class... Args>
218 inline void check_index(
const S& shape, Arg
arg, Args... args)
220 constexpr std::size_t nargs =
sizeof...(Args) + 1;
221 if (nargs == shape.size())
223 detail::check_index_impl<S, 0>(shape,
arg, args...);
225 else if (nargs > shape.size())
228 check_index(shape, args...);
230 else if (detail::last_type_is_missing<Args...>)
233 detail::check_index_impl<S, 0>(shape,
arg, args...);
238 auto it = shape.end() - nargs;
239 detail::check_index_impl<decltype(it), 0>(it,
arg, args...);
243 template <
class S,
class It>
244 inline void check_element_index(
const S& shape, It first, It last)
246 using value_type =
typename std::iterator_traits<It>::value_type;
247 using size_type =
typename S::size_type;
248 auto dst =
static_cast<size_type
>(last - first);
249 It efirst = last -
static_cast<std::ptrdiff_t
>((std::min)(shape.size(), dst));
250 std::size_t axis = 0;
252 while (efirst != last)
254 if (*efirst >= value_type(shape[axis]) && shape[axis] != 1)
258 "index " + std::to_string(*efirst) +
" is out of bounds for axis " + std::to_string(axis)
259 +
" with size " + std::to_string(shape[axis])
270 template <
class S,
class... Args>
271 inline void check_dimension(
const S& shape, Args...)
273 if (
sizeof...(Args) > shape.size())
277 "Number of arguments (" + std::to_string(
sizeof...(Args))
278 +
") is greater than the number of dimensions (" + std::to_string(shape.size()) +
")"
287 template <
class A,
class D>
288 inline void check_axis_in_dim(A axis, D dim,
const char* subject =
"Axis")
290 const auto sdim =
static_cast<std::make_signed_t<D>
>(dim);
291 if (xtl::cmp_greater_equal(axis, dim) || xtl::cmp_less(axis, -sdim))
295 std::string(subject) +
" (" + std::to_string(axis)
296 +
") is not within the number of dimensions (" + std::to_string(dim) +
')'
305 template <
class S,
class... Args>
306 inline void check_access(
const S& shape, Args... args)
308 check_dimension(shape, args...);
309 check_index(shape, args...);
312#if (defined(XTENSOR_ENABLE_ASSERT) && !defined(XTENSOR_DISABLE_EXCEPTIONS))
313#define XTENSOR_TRY(expr) XTENSOR_TRY_IMPL(expr, __FILE__, __LINE__)
314#define XTENSOR_TRY_IMPL(expr, file, line) \
319 catch (std::exception & e) \
322 std::runtime_error, \
323 std::string(file) + ':' + std::to_string(line) + ": check failed\n\t" + std::string(e.what()) \
327#define XTENSOR_TRY(expr)
330#ifdef XTENSOR_ENABLE_ASSERT
331#define XTENSOR_ASSERT(expr) XTENSOR_ASSERT_IMPL(expr, __FILE__, __LINE__)
332#define XTENSOR_ASSERT_IMPL(expr, file, line) \
336 std::runtime_error, \
337 std::string(file) + ':' + std::to_string(line) + ": assertion failed (" #expr ") \n\t" \
341#define XTENSOR_ASSERT(expr)
344#ifdef XTENSOR_ENABLE_CHECK_DIMENSION
345#define XTENSOR_CHECK_DIMENSION(S, ARGS) XTENSOR_TRY(check_dimension(S, ARGS))
347#define XTENSOR_CHECK_DIMENSION(S, ARGS)
350#ifdef XTENSOR_ENABLE_ASSERT
351#define XTENSOR_ASSERT_MSG(expr, msg) \
355 std::runtime_error, \
356 std::string("Assertion error!\n") + msg + "\n " + __FILE__ + '(' + std::to_string(__LINE__) + ")\n" \
360#define XTENSOR_ASSERT_MSG(expr, msg)
363#define XTENSOR_PRECONDITION(expr, msg) \
367 std::runtime_error, \
368 std::string("Precondition violation!\n") + msg + "\n " + __FILE__ + '(' \
369 + std::to_string(__LINE__) + ")\n" \
auto arg(E &&e) noexcept
Calculates the phase angle (in radians) elementwise for the complex numbers in e.
standard mathematical functions for xexpressions