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;
69 : std::runtime_error(
msg)
74 template <
class S1,
class S2>
86 : std::runtime_error(
msg)
91 template <
class S1,
class S2>
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 = (";
107 std::ostream_iterator<size_type1>
iter1(
buf,
", ");
110 buf <<
")\n RHS shape = (";
112 std::ostream_iterator<size_type2>
iter2(
buf,
", ");
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);
132 XTENSOR_THROW(broadcast_error, msg.c_str());
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);
152 XTENSOR_THROW(concatenate_error, msg.c_str());
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>
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&)
213 inline void check_index(
const S&, missing_type)
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" \
standard mathematical functions for xexpressions