Stratax
Scientific computing containers and operations
Loading...
Searching...
No Matches
Validation.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4#include <limits>
5#include <type_traits>
6
9
14
16
26template<typename Actual, typename Expected>
27void require_type(const char* message)
28{
29 if constexpr (!std::same_as<std::remove_cvref_t<Actual>, std::remove_cvref_t<Expected>>)
30 {
31 throw Exceptions::TypeError(message);
32 }
33}
34
43template<typename T>
44void require_numeric_type(const char* message)
45{
46 if constexpr (!Numeric<T>)
47 {
48 throw Exceptions::TypeError(message);
49 }
50}
51
61template<typename Lhs, typename Rhs>
62requires requires
63{
64 typename Lhs::value_type;
65 typename Rhs::value_type;
66}
67void require_same_value_type(const Lhs& lhs, const Rhs& rhs, const char* message)
68{
69 (void)lhs;
70 (void)rhs;
72}
73
84inline std::size_t nonnegative_size(long long value, const char* message)
85{
86 if (value < 0)
87 {
88 throw Exceptions::DimensionError(message);
89 }
90
91 return static_cast<std::size_t>(value);
92}
93
104inline std::size_t nonnegative_shape_dimension(long long value, const char* message)
105{
106 if (value < 0)
107 {
108 throw Exceptions::ShapeError(message);
109 }
110
111 return static_cast<std::size_t>(value);
112}
113
124inline std::size_t positive_shape_dimension(long long value, const char* message)
125{
126 if (value <= 0)
127 {
128 throw Exceptions::ShapeError(message);
129 }
130
131 return static_cast<std::size_t>(value);
132}
133
142inline void require_positive_shape_dimension(std::size_t value, const char* message)
143{
144 if (value == 0)
145 {
146 throw Exceptions::ShapeError(message);
147 }
148}
149
160inline std::size_t nonnegative_index(long long value, const char* message)
161{
162 if (value < 0)
163 {
164 throw Exceptions::IndexError(message);
165 }
166
167 return static_cast<std::size_t>(value);
168}
169
179inline void require_rank(std::size_t actual, std::size_t expected, const char* message)
180{
181 if (actual != expected)
182 {
183 throw Exceptions::DimensionError(message);
184 }
185}
186
198template<typename Ranked>
199requires requires(const Ranked& object)
200{
201 object.rank();
202}
203const Ranked& require_rank(const Ranked& object, std::size_t expected, const char* message)
204{
205 require_rank(object.rank(), expected, message);
206 return object;
207}
208
218inline void require_index(std::size_t index, std::size_t size, const char* message)
219{
220 if (index >= size)
221 {
222 throw Exceptions::IndexError(message);
223 }
224}
225
237inline void require_at_most(std::size_t value, std::size_t upper, const char* message)
238{
239 if (value > upper)
240 {
241 throw Exceptions::IndexError(message);
242 }
243}
244
256inline std::size_t checked_multiply(
257 std::size_t lhs,
258 std::size_t rhs,
259 const char* message)
260{
261 if (rhs != 0 && lhs > std::numeric_limits<std::size_t>::max() / rhs)
262 {
263 throw Exceptions::DimensionError(message);
264 }
265
266 return lhs * rhs;
267}
268
280inline std::size_t checked_add(
281 std::size_t lhs,
282 std::size_t rhs,
283 const char* message)
284{
285 if (lhs > std::numeric_limits<std::size_t>::max() - rhs)
286 {
287 throw Exceptions::DimensionError(message);
288 }
289
290 return lhs + rhs;
291}
292
301template<typename Lhs, typename Rhs>
302[[nodiscard]] bool same_shape(const Lhs& lhs, const Rhs& rhs)
303{
304 return lhs.size() == rhs.size() && lhs.shape() == rhs.shape();
305}
306
316template<typename Lhs, typename Rhs>
317void require_same_shape(const Lhs& lhs, const Rhs& rhs, const char* message)
318{
319 if (!same_shape(lhs, rhs))
320 {
321 throw Exceptions::ShapeError(message);
322 }
323}
324
334inline void require_equal_size(std::size_t lhs, std::size_t rhs, const char* message)
335{
336 if (lhs != rhs)
337 {
338 throw Exceptions::ShapeError(message);
339 }
340}
341
342}
Signals an invalid dimension count or dimension arithmetic failure.
Signals an invalid index access.
Signals an invalid or incompatible shape.
Signals an invalid or unsupported type.
Matches all scalar types supported by Stratax numeric containers.
Definition Concepts.hpp:152
void require_same_value_type(const Lhs &lhs, const Rhs &rhs, const char *message)
Requires two array-like objects to have the same value type.
std::size_t checked_multiply(std::size_t lhs, std::size_t rhs, const char *message)
Multiplies two sizes while checking for overflow.
void require_same_shape(const Lhs &lhs, const Rhs &rhs, const char *message)
Requires two array-like objects to have identical size and shape.
std::size_t nonnegative_index(long long value, const char *message)
Converts a signed index to std::size_t after rejecting negatives.
bool same_shape(const Lhs &lhs, const Rhs &rhs)
Returns whether two array-like objects have identical size and shape.
void require_equal_size(std::size_t lhs, std::size_t rhs, const char *message)
Requires two sizes to be equal.
std::size_t nonnegative_size(long long value, const char *message)
Converts a signed value to std::size_t after rejecting negatives.
void require_index(std::size_t index, std::size_t size, const char *message)
Requires an index to be less than a size.
std::size_t positive_shape_dimension(long long value, const char *message)
Converts a signed shape dimension to std::size_t after requiring it to be positive.
void require_at_most(std::size_t value, std::size_t upper, const char *message)
Requires a value to be less than or equal to an upper bound.
void require_positive_shape_dimension(std::size_t value, const char *message)
Requires an unsigned shape dimension to be positive.
void require_rank(std::size_t actual, std::size_t expected, const char *message)
Requires a rank value to match an expected rank.
void require_type(const char *message)
Requires a type to exactly match an expected type after cv/ref removal.
void require_numeric_type(const char *message)
Requires a type to satisfy Stratax's numeric type rules.
std::size_t nonnegative_shape_dimension(long long value, const char *message)
Converts a signed shape dimension to std::size_t after rejecting negatives.
std::size_t checked_add(std::size_t lhs, std::size_t rhs, const char *message)
Adds two sizes while checking for overflow.