Skip to content

Commit

Permalink
Clean up checks
Browse files Browse the repository at this point in the history
* ra/big.hh (ViewBig): Fix typo in conversion to scalar.
* ra/expr.hh (RA_ASSERT): Use __VA_OPT__ instead of ##__VA_ARGS__.
  (Match): Print full shapes on match error.
* test/checks.cc, test/throw.cc: Use __VA_OPT__ instead of ##__VA_ARGS__.
  • Loading branch information
lloda committed Mar 19, 2024
1 parent 3e77557 commit 66a0018
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 61 deletions.
6 changes: 5 additions & 1 deletion docs/ra-ra.texi
Original file line number Diff line number Diff line change
Expand Up @@ -1595,7 +1595,7 @@ Error handling in @code{ra::} is controlled by two macros:

@itemize
@item @code{RA_DO_CHECK}
is a binary flag that controls runtime checks. The default is 1 which means to check for errors. 0 means not to check. The checks themselves are done with @code{RA_ASSERT}.
is a binary flag that controls runtime checks. The default is 1 which means to check for errors. 0 means not to check. The checks themselves are done with @code{RA_ASSERT}. After including @code{ra/ra.hh}, this flag will always be defined.
@item @code{RA_ASSERT(cond, ...)}
is a function-like macro. @code{cond} is an expression that evaluates to true (in the @code{ra::} namespace) if the assertion is satisfied. The other arguments are informative and do not need to be used. If the assertion fails, the default definition of @code{RA_ASSERT(cond, ...)} prints those arguments to @code{std::cerr} and aborts.
@end itemize
Expand Down Expand Up @@ -1697,6 +1697,10 @@ Item 1
Item 2
@end enumerate

@section The cost of @code{RA_DO_CHECK}

FIXME

@c ------------------------------------------------
@node Internals
@chapter Internals
Expand Down
4 changes: 2 additions & 2 deletions examples/throw.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// -*- mode: c++; coding: utf-8 -*-
// ra-ra/examples - Customize ra:: reaction to errors.

// (c) Daniel Llorens - 2019-2023
// (c) Daniel Llorens - 2019-2024
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 3 of the License, or (at your option) any
Expand Down Expand Up @@ -30,7 +30,7 @@ struct ra_error: public std::exception
};

#define RA_ASSERT( cond, ... ) \
{ if (!( cond )) throw ra_error("ra:: assert [" STRINGIZE(cond) "] " __VA_OPT__(,) __VA_ARGS__); }
{ if (!( cond )) throw ra_error("ra::", std::source_location::current(), " (" STRINGIZE(cond) ") " __VA_OPT__(,) __VA_ARGS__); }

// The override will be in effect for the rest of ra::.

Expand Down
3 changes: 1 addition & 2 deletions ra/base.hh
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,7 @@ struct shape_manip_t
constexpr shape_manip_t
operator<<(std::ostream & o, print_shape_t shape) { return shape_manip_t { o, shape }; }

// include is_fov bc shape() may be std::vector or std::array.
// exclude std::string_view so it is is_fov but still prints as a string [ra13].
// exclude std::string_view so it still prints as a string [ra13].
template <class A> requires (is_ra<A> || (is_fov<A> && !std::is_convertible_v<A, std::string_view>))
constexpr std::ostream &
operator<<(std::ostream & o, A && a) { return o << format_array(a); }
Expand Down
44 changes: 21 additions & 23 deletions ra/big.hh
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ struct ViewBig
constexpr dim_t
select(Dim * dim, int k, dim_t i) const
{
RA_CHECK(inside(i, len(k)), "Bad index in len[", k, "]=", len(k), ": ", i, ".");
RA_CHECK(inside(i, len(k)), "Bad index ", i, " for len[", k, "]=", len(k), ".");
return step(k)*i;
}
constexpr dim_t
select(Dim * dim, int k, is_iota auto i) const
{
RA_CHECK(inside(i, len(k)), "Bad index in len[", k, "]=", len(k), ": iota [", i.n, " ", i.i, " ", i.s, "].");
RA_CHECK(inside(i, len(k)), "Bad index iota [", i.n, " ", i.i, " ", i.s, "] for len[", k, "]=", len(k), ".");
*dim = { .len = i.n, .step = step(k) * i.s };
return 0==i.n ? 0 : step(k)*i.i;
}
Expand Down Expand Up @@ -173,8 +173,7 @@ struct ViewBig
constexpr rank_t extended = (0 + ... + beatable<I>.add);
ViewBig<T, rank_sum(RANK, extended)> sub;
rank_t subrank = rank()+extended;
if constexpr (RANK==ANY) {
RA_CHECK(subrank>=0, "Bad rank.");
if constexpr (ANY==RANK) {
sub.dimv.resize(subrank);
}
sub.cp = cp + select_loop(sub.dimv.data(), 0, i ...);
Expand Down Expand Up @@ -207,7 +206,7 @@ struct ViewBig
operator T & () const
{
if constexpr (0!=RANK) {
RA_CHECK(1==size(), "Bad conversion to scalar from shape [", ra::noshape, ra::shape(this), "].");
RA_CHECK(1==size(), "Bad conversion to scalar from shape [", ra::noshape, ra::shape(*this), "].");
}
return cp[0];
}
Expand Down Expand Up @@ -241,7 +240,7 @@ struct storage_traits
{
using T = V::value_type;
static_assert(!std::is_same_v<std::remove_const_t<T>, bool>, "No pointers to bool in std::vector<bool>.");
constexpr static auto create(dim_t n) { RA_CHECK(n>=0); return V(n); }
constexpr static auto create(dim_t n) { RA_CHECK(0<=n, "Bad size ", n, "."); return V(n); }
template <class VV> constexpr static auto data(VV & v) { return v.data(); }
};

Expand All @@ -250,7 +249,7 @@ struct storage_traits<std::unique_ptr<P>>
{
using V = std::unique_ptr<P>;
using T = std::decay_t<decltype(*std::declval<V>().get())>;
constexpr static auto create(dim_t n) { RA_CHECK(n>=0); return V(new T[n]); }
constexpr static auto create(dim_t n) { RA_CHECK(0<=n, "Bad size ", n, "."); return V(new T[n]); }
template <class VV> constexpr static auto data(VV & v) { return v.get(); }
};

Expand All @@ -259,7 +258,7 @@ struct storage_traits<std::shared_ptr<P>>
{
using V = std::shared_ptr<P>;
using T = std::decay_t<decltype(*std::declval<V>().get())>;
constexpr static auto create(dim_t n) { RA_CHECK(n>=0); return V(new T[n], std::default_delete<T[]>()); }
constexpr static auto create(dim_t n) { RA_CHECK(0<=n, "Bad size ", n, "."); return V(new T[n], std::default_delete<T[]>()); }
template <class VV> constexpr static auto data(VV & v) { return v.get(); }
};

Expand Down Expand Up @@ -310,7 +309,7 @@ struct Container: public ViewBig<typename storage_traits<Store>::T, RANK>

// const/nonconst shims over View's methods. FIXME > gcc13 ? __cpp_explicit_this_parameter
#define RA_CONST_OR_NOT(CONST) \
constexpr T CONST & back() CONST { RA_CHECK(1==rank() && size()>0); return store[size()-1]; } \
constexpr T CONST & back() CONST { RA_CHECK(1==rank() && size()>0, "Bad back()."); return store[size()-1]; } \
constexpr auto data() CONST { return view().data(); } \
constexpr decltype(auto) operator()(auto && ... a) CONST { return view()(RA_FWD(a) ...); } \
constexpr decltype(auto) operator[](auto && ... a) CONST { return view()(RA_FWD(a) ...); } \
Expand Down Expand Up @@ -400,14 +399,14 @@ struct Container: public ViewBig<typename storage_traits<Store>::T, RANK>
// resize first axis or full shape. Only for some kinds of store.
void resize(dim_t const s)
{
static_assert(RANK==ANY || RANK>0); RA_CHECK(0<rank());
static_assert(ANY==RANK || 0<RANK); RA_CHECK(0<rank());
View::dimv[0].len = s;
store.resize(size());
View::cp = store.data();
}
void resize(dim_t const s, T const & t)
{
static_assert(RANK==ANY || RANK>0); RA_CHECK(0<rank());
static_assert(ANY==RANK || 0<RANK); RA_CHECK(0<rank());
View::dimv[0].len = s;
store.resize(size(), t);
View::cp = store.data();
Expand All @@ -422,31 +421,31 @@ struct Container: public ViewBig<typename storage_traits<Store>::T, RANK>
// lets us move. A template + RA_FWD wouldn't work for push_back(brace-enclosed-list).
void push_back(T && t)
{
static_assert(RANK==1 || RANK==ANY); RA_CHECK(1==rank());
static_assert(ANY==RANK || 1==RANK); RA_CHECK(1==rank());
store.push_back(std::move(t));
++View::dimv[0].len;
View::cp = store.data();
}
void push_back(T const & t)
{
static_assert(RANK==1 || RANK==ANY); RA_CHECK(1==rank());
static_assert(ANY==RANK || 1==RANK); RA_CHECK(1==rank());
store.push_back(t);
++View::dimv[0].len;
View::cp = store.data();
}
void emplace_back(auto && ... a)
{
static_assert(RANK==1 || RANK==ANY); RA_CHECK(1==rank());
static_assert(ANY==RANK || 1==RANK); RA_CHECK(1==rank());
store.emplace_back(RA_FWD(a) ...);
++View::dimv[0].len;
View::cp = store.data();
}
void pop_back()
{
static_assert(RANK==1 || RANK==ANY); RA_CHECK(1==rank());
RA_CHECK(View::dimv[0].len>0);
store.pop_back();
static_assert(ANY==RANK || 1==RANK); RA_CHECK(1==rank());
RA_CHECK(0<View::dimv[0].len, "Empty array trying to pop_back().");
--View::dimv[0].len;
store.pop_back();
}
};

Expand All @@ -456,12 +455,12 @@ void
swap(Container<Store, RANKA> & a, Container<Store, RANKB> & b)
{
if constexpr (ANY==RANKA) {
RA_CHECK(rank(a)==rank(b));
RA_CHECK(rank(a)==rank(b), "Mismatched ranks ", rank(a), " and ", rank(b), ".");
decltype(b.dimv) c = a.dimv;
start(a.dimv) = b.dimv;
std::swap(b.dimv, c);
} else if constexpr (ANY==RANKB) {
RA_CHECK(rank(a)==rank(b));
RA_CHECK(rank(a)==rank(b), "Mismatched ranks ", rank(a), " and ", rank(b), ".");
decltype(a.dimv) c = b.dimv;
start(b.dimv) = a.dimv;
std::swap(a.dimv, c);
Expand Down Expand Up @@ -590,7 +589,7 @@ template <class T, rank_t RANK>
inline ViewBig<T, RANK>
reverse(ViewBig<T, RANK> const & view, int k=0)
{
RA_CHECK(inside(k, view.rank()), "Bad reverse axis ", k, " for view of rank ", view.rank(), ".");
RA_CHECK(inside(k, view.rank()), "Bad axis ", k, " for rank ", view.rank(), ".");
ViewBig<T, RANK> r = view;
if (auto & dim=r.dimv[k]; dim.len!=0) {
r.cp += dim.step*(dim.len-1);
Expand Down Expand Up @@ -689,8 +688,7 @@ reshape_(ViewBig<T, RANK> const & a, S && sb_)
rank_t i = 0;
for (; i<a.rank() && i<b.rank(); ++i) {
if (sa[a.rank()-i-1]!=sb[b.rank()-i-1]) {
RA_CHECK(is_c_order(a, false), "Reshape with copy not implemented.");
RA_CHECK(la>=lb, "Reshape with copy not implemented.");
RA_CHECK(is_c_order(a, false) && la>=lb, "Reshape with copy not implemented.");
// FIXME ViewBig(SS const & s, T * p). Cf [ra37].
filldim(b.dimv, sb);
for (int j=0; j!=b.rank(); ++j) {
Expand All @@ -703,7 +701,7 @@ reshape_(ViewBig<T, RANK> const & a, S && sb_)
}
}
if (i==a.rank()) {
// tile & return
// tile
for (rank_t j=i; j<b.rank(); ++j) {
b.dimv[b.rank()-j-1] = { sb[b.rank()-j-1], 0 };
}
Expand Down
31 changes: 16 additions & 15 deletions ra/expr.hh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// -*- mode: c++; coding: utf-8 -*-
// ra-ra - Expression templates with prefix matching.

// (c) Daniel Llorens - 2011-2023
// (c) Daniel Llorens - 2011-2024
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 3 of the License, or (at your option) any
Expand All @@ -25,7 +25,7 @@
assert(cond /* FIXME show args */); \
} else { \
if (!(cond)) [[unlikely]] { \
std::cerr << ra::format("**** ra (", std::source_location::current(), "): ", ##__VA_ARGS__, " ****") << std::endl; \
std::cerr << ra::format("*** ra (", std::source_location::current(), "): " __VA_OPT__(,) __VA_ARGS__, " ***") << std::endl; \
std::abort(); \
} \
} \
Expand Down Expand Up @@ -131,7 +131,7 @@ struct Ptr
constexpr static bool keep_step(dim_t st, int z, int j) { return st*step(z)==step(j); }
constexpr decltype(auto) at(auto && j) const requires (std::random_access_iterator<I>)
{
RA_CHECK(BAD==nn || inside(j[0], n), "Out of range for len[0]=", n, ": ", j[0], ".");
RA_CHECK(BAD==nn || inside(j[0], n), "Bad index ", j[0], " for len[0]=", n, ".");
return i[j[0]*s];
}
constexpr decltype(auto) operator*() const { return *i; }
Expand Down Expand Up @@ -207,7 +207,7 @@ struct Iota
constexpr static bool keep_step(dim_t st, int z, int j) { return st*step(z)==step(j); }
constexpr auto at(auto && j) const
{
RA_CHECK(BAD==nn || inside(j[0], n), "Out of range for len[0]=", n, ": ", j[0], ".");
RA_CHECK(BAD==nn || inside(j[0], n), "Bad index ", j[0], " for len[0]=", n, ".");
return i + I(j[w])*I(s);
}
constexpr I operator*() const { return i; }
Expand Down Expand Up @@ -297,7 +297,7 @@ template <class T> requires (is_iterator<T> && !is_ra_scalar<T>)
constexpr auto
start(T & t) { return t; }

// FIXME const Iterator would still be unusable after start()
// FIXME const Iterator would still be unusable after start().
constexpr decltype(auto)
start(is_iterator auto && t) { return RA_FWD(t); }

Expand Down Expand Up @@ -334,21 +334,20 @@ struct Match<checkp, std::tuple<P ...>, mp::int_list<I ...>>
dim_t ls = len_s(k);
if (((k<ra::rank_s<P>() && ls!=choose_len(std::decay_t<P>::len_s(k), ls)) || ...)) {
return 0;
} else {
int anyk = ((k<ra::rank_s<P>() && (ANY==std::decay_t<P>::len_s(k))) + ...);
int fixk = ((k<ra::rank_s<P>() && (0<=std::decay_t<P>::len_s(k))) + ...);
tbc = tbc || (anyk>0 && anyk+fixk>1);
}
int anyk = ((k<ra::rank_s<P>() && (ANY==std::decay_t<P>::len_s(k))) + ...);
int fixk = ((k<ra::rank_s<P>() && (0<=std::decay_t<P>::len_s(k))) + ...);
tbc = tbc || (anyk>0 && anyk+fixk>1);
}
return tbc ? 1 : 2;
}
}
constexpr bool
check() const
{
if constexpr (sizeof...(P)<2) {
if constexpr (constexpr int c = check_s(); 2==c) {
return true;
} else if constexpr (constexpr int c = check_s(); 0==c) {
} else if constexpr (0==c) {
return false;
} else if constexpr (1==c) {
for (int k=0; k<rank(); ++k) {
Expand All @@ -357,7 +356,6 @@ struct Match<checkp, std::tuple<P ...>, mp::int_list<I ...>>
dim_t ls = len(k);
#pragma GCC diagnostic pop
if (((k<ra::rank(std::get<I>(t)) && ls!=choose_len(std::get<I>(t).len(k), ls)) || ...)) {
RA_CHECK(!checkp, "Mismatch on axis ", k, " [", (std::array { std::get<I>(t).len(k) ... }), "].");
return false;
}
}
Expand All @@ -368,10 +366,13 @@ struct Match<checkp, std::tuple<P ...>, mp::int_list<I ...>>
constexpr
Match(P ... p_): t(p_ ...) // [ra1]
{
// TODO Maybe on ply, would make checkp unnecessary, make agree_xxx() unnecessary.
// TODO Maybe on ply would make checkp, agree_xxx() unnecessary.
if constexpr (checkp && !(has_len<P> || ...)) {
static_assert(check_s(), "Shape mismatch.");
RA_CHECK(check());
constexpr int c = check_s();
static_assert(0!=c, "Mismatched shapes."); // FIXME c++26
if constexpr (1==c) {
RA_CHECK(check(), "Mismatched shapes", format_array(ra::shape(p_), {.shape=noshape, .open=" [", .close="]"}) ..., ".");
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions ra/ra.hh
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ template <class A, class Less = std::less<ncvalue_t<A>>>
constexpr decltype(auto)
refmin(A && a, Less && less = {})
{
RA_CHECK(a.size()>0);
RA_CHECK(a.size()>0, "refmin requires nonempty argument.");
decltype(auto) s = ra::start(a);
auto p = &(*s);
for_each([&less, &p](auto & a) { if (less(a, *p)) { p = &a; } }, s);
Expand All @@ -454,7 +454,7 @@ template <class A, class Less = std::less<ncvalue_t<A>>>
constexpr decltype(auto)
refmax(A && a, Less && less = {})
{
RA_CHECK(a.size()>0);
RA_CHECK(a.size()>0, "refmax requires nonempty argument.");
decltype(auto) s = ra::start(a);
auto p = &(*s);
for_each([&less, &p](auto & a) { if (less(*p, a)) { p = &a; } }, s);
Expand Down
6 changes: 3 additions & 3 deletions ra/small.hh
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ resize(A & a, dim_t s)
RA_CHECK(s>=0, "Bad resize ", s, ".");
a.resize(s);
} else {
RA_CHECK(s==start(a).len(0) || BAD==s, "Bad resize ", s, " vs ", start(a).len(0), ".");
RA_CHECK(s==start(a).len(0) || BAD==s, "Bad resize ", s, " needing ", start(a).len(0), ".");
}
}

Expand Down Expand Up @@ -461,7 +461,7 @@ struct ViewSmall: public SmallBase<T, lens, steps>
constexpr static dim_t
select(dim_t i)
{
RA_CHECK(inside(i, len(k)), "Bad index in len[", k, "]=", len(k), ": ", i, ".");
RA_CHECK(inside(i, len(k)), "Bad index ", i, " in len[", k, "]=", len(k), ".");
return step(k)*i;
}
template <int k>
Expand All @@ -471,7 +471,7 @@ struct ViewSmall: public SmallBase<T, lens, steps>
if constexpr ((1>=i.n ? 1 : (i.s<0 ? -i.s : i.s)*(i.n-1)+1) > len(k)) { // FIXME c++23 std::abs
static_assert(always_false<k>, "Bad index.");
} else {
RA_CHECK(inside(i, len(k)), "Bad index in len[", k, "]=", len(k), ": iota [", i.n, " ", i.i, " ", i.s, "]");
RA_CHECK(inside(i, len(k)), "Bad index iota [", i.n, " ", i.i, " ", i.s, "] in len[", k, "]=", len(k), ".");
}
return 0==i.n ? 0 : step(k)*i.i;
}
Expand Down
4 changes: 2 additions & 2 deletions ra/test.hh
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ struct TestRecorder
return c;
} else {
test(false,
RA_LAZYINFO("Mismatched args [", ra::noshape, ra::shape(a), "] [", ra::noshape, ra::shape(b), "]",
RA_LAZYINFO("Mismatched shapes [", ra::noshape, ra::shape(a), "] [", ra::noshape, ra::shape(b), "]",
willstrictshape ? " (strict shape)" : ""),
RA_LAZYINFO("Shape mismatch", willstrictshape ? " (strict shape)" : ""),
RA_LAZYINFO("Mismatched shapes", willstrictshape ? " (strict shape)" : ""),
loc);
return false;
}
Expand Down
6 changes: 3 additions & 3 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8; mode: cmake -*-
# (c) Daniel Llorens - 2018, 2019
# (c) Daniel Llorens - 2018-2024

cmake_minimum_required (VERSION 3.5)
project (ra-test)
Expand All @@ -8,8 +8,8 @@ include_directories ("..")
SET (TARGETS at bench big-0 big-1 bug83 checks compatibility concrete const constexpr dual
early explode-0 foreign frame-new frame-old fromb fromu headers io iota iterator-small len
list9 macros mem-fn nested-0 old operators optimize owned ownership ply ra-0 ra-1 ra-10 ra-11
ra-12 ra-13 ra-14 ra-2 ra-3 ra-4 ra-5 ra-6 ra-7 ra-8 ra-9 ra-dual reduction reexported
reshape return-expr self-assign sizeof small-0 small-1 stl-compat swap tensorindex
ra-12 ra-13 ra-14 ra-15 ra-16 ra-2 ra-3 ra-4 ra-5 ra-6 ra-7 ra-8 ra-9 ra-dual reduction
reexported reshape return-expr self-assign sizeof small-0 small-1 stl-compat swap tensorindex
tuples types vector-array view-ops wedge where wrank)

include ("../config/cc.cmake")
Loading

0 comments on commit 66a0018

Please sign in to comment.