7#include <stratax/core/dtypes/Concepts.hpp>
8#include <stratax/exceptions/Exceptions.hpp>
10namespace stratax::core::validation {
12inline std::size_t nonnegative_size(std::ptrdiff_t value,
const char* message)
16 throw Exceptions::DimensionError(message);
19 return static_cast<std::size_t
>(value);
22inline void require_rank(std::size_t actual, std::size_t expected,
const char* message)
24 if (actual != expected)
26 throw Exceptions::DimensionError(message);
30template<
typename Ranked>
31requires requires(
const Ranked& object)
35const Ranked& require_rank(
const Ranked&
object, std::size_t expected,
const char* message)
37 require_rank(
object.rank(), expected, message);
41inline std::size_t checked_multiply(
46 if (rhs != 0 && lhs > std::numeric_limits<std::size_t>::max() / rhs)
48 throw Exceptions::DimensionError(message);
54inline std::size_t checked_add(
59 if (lhs > std::numeric_limits<std::size_t>::max() - rhs)
61 throw Exceptions::DimensionError(message);
67inline std::size_t nonnegative_index(std::ptrdiff_t value,
const char* message)
71 throw Exceptions::IndexError(message);
74 return static_cast<std::size_t
>(value);
77inline void require_index(std::size_t index, std::size_t size,
const char* message)
81 throw Exceptions::IndexError(message);
85inline void require_at_most(std::size_t value, std::size_t upper,
const char* message)
89 throw Exceptions::IndexError(message);
93inline std::size_t nonnegative_shape_dimension(std::ptrdiff_t value,
const char* message)
97 throw Exceptions::ShapeError(message);
100 return static_cast<std::size_t
>(value);
103inline std::size_t positive_shape_dimension(std::ptrdiff_t value,
const char* message)
107 throw Exceptions::ShapeError(message);
110 return static_cast<std::size_t
>(value);
113inline void require_positive_shape_dimension(std::size_t value,
const char* message)
117 throw Exceptions::ShapeError(message);
121template<
typename Lhs,
typename Rhs>
122[[nodiscard]]
bool same_shape(
const Lhs& lhs,
const Rhs& rhs)
124 return lhs.size() == rhs.size() && lhs.shape() == rhs.shape();
127template<
typename Lhs,
typename Rhs>
128void require_same_shape(
const Lhs& lhs,
const Rhs& rhs,
const char* message)
130 if (!same_shape(lhs, rhs))
132 throw Exceptions::ShapeError(message);
136inline void require_equal_size(std::size_t lhs, std::size_t rhs,
const char* message)
140 throw Exceptions::ShapeError(message);
144template<
typename Actual,
typename Expected>
145void require_type(
const char* message)
147 if constexpr (!std::same_as<std::remove_cvref_t<Actual>, std::remove_cvref_t<Expected>>)
149 throw Exceptions::TypeError(message);
154void require_numeric_type(
const char* message)
156 if constexpr (!Numeric<T>)
158 throw Exceptions::TypeError(message);
162template<
typename Lhs,
typename Rhs>
165 typename Lhs::value_type;
166 typename Rhs::value_type;
168void require_same_value_type(
const Lhs& lhs,
const Rhs& rhs,
const char* message)
172 require_type<typename Lhs::value_type, typename Rhs::value_type>(message);