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 "../core/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