Skip to content

Commit 1381121

Browse files
committed
View.back() is last item
The previous implementation for last element was broken. I don't see much use for a last element function tbh. This is only offered so that Big can be used like std::vector, so last item is ok. * ra/arrays.hh (ViewSmall, ViewBig): As stated; also fix constness. Elsewhere fix tests.
1 parent cd518e9 commit 1381121

File tree

5 files changed

+49
-66
lines changed

5 files changed

+49
-66
lines changed

ra/arrays.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ struct ViewSmall
101101
constexpr auto begin() const { if constexpr (c_order(dimv)) return cp; else return STLIterator(iter()); }
102102
constexpr auto end() const requires (c_order(dimv)) { return cp+size(); }
103103
constexpr static auto end() requires (!c_order(dimv)) { return std::default_sentinel; }
104-
constexpr decltype(auto) back() const { static_assert(size()>0, "Bad back()."); return cp[size()-1]; }
104+
constexpr decltype(auto) back(this auto && sf) { static_assert(size()>0, "Bad back()."); return RA_FW(sf)(len(0)-1); }
105105
constexpr decltype(auto) operator()(this auto && sf, auto && ... i) { return from(RA_FW(sf), RA_FW(i) ...); }
106106
constexpr decltype(auto) operator[](this auto && sf, auto && ... i) { return from(RA_FW(sf), RA_FW(i) ...); }
107107
constexpr decltype(auto) at(auto const & i) const { return *indexer(*this, cp, ra::iter(i)); }
@@ -172,7 +172,7 @@ struct ViewBig
172172
constexpr auto iter(rank_t c) const & { return Cell<P, Dimv const &, dim_t>(cp, dimv, c); }
173173
constexpr auto begin() const { return STLIterator(iter<0>()); }
174174
constexpr static auto end() { return std::default_sentinel; }
175-
constexpr decltype(auto) back() const { dim_t s=size(); RA_CK(s>0, "Bad back()."); return cp[s-1]; }
175+
constexpr decltype(auto) back(this auto && sf) { return RA_FW(sf)(sf.len(0)-1); }
176176
constexpr decltype(auto) operator()(this auto && sf, auto && ... i) { return from(RA_FW(sf), RA_FW(i) ...); }
177177
constexpr decltype(auto) operator[](this auto && sf, auto && ... i) { return from(RA_FW(sf), RA_FW(i) ...); }
178178
constexpr decltype(auto) at(auto const & i) const { return *indexer(*this, cp, ra::iter(i)); }

ra/expr.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,8 @@ constexpr rank_t rank_diff(rank_t a, rank_t b) { return ANY==a || ANY==b ? ANY :
225225
constexpr rank_t rank_cell(rank_t r, rank_t cr) { return cr>=0 ? cr : r==ANY ? ANY : (r+cr); }
226226
constexpr rank_t rank_frame(rank_t r, rank_t cr) { return r==ANY ? ANY : cr>=0 ? (r-cr) : -cr; }
227227

228-
template <class T, class Dimv> struct ViewSmall;
229-
template <class T, rank_t RANK=ANY> struct ViewBig;
228+
template <class P, class Dimv> struct ViewSmall;
229+
template <class P, rank_t RANK=ANY> struct ViewBig;
230230

231231
template <class P, class Dimv, class Cr>
232232
struct CellBase

ra/ra.hh

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,6 @@
1212
#include <cmath>
1313
#include <complex>
1414

15-
#ifndef RA_OPT
16-
#define RA_OPT opt
17-
#endif
18-
19-
#if defined(RA_FMA)
20-
#elif defined(FP_FAST_FMA)
21-
#define RA_FMA FP_FAST_FMA
22-
#else
23-
#define RA_FMA 0
24-
#endif
25-
2615
// ADL with explicit template args. See http://stackoverflow.com/questions/9838862.
2716
template <int A> constexpr void iter(ra::noarg<>);
2817
template <class T> constexpr void cast(ra::noarg<>);
@@ -126,6 +115,10 @@ template <class T> constexpr bool is_scalar_def<std::complex<T>> = true;
126115
// Optimization pass over expression templates.
127116
// --------------------------------
128117

118+
#ifndef RA_OPT
119+
#define RA_OPT opt
120+
#endif
121+
129122
constexpr decltype(auto) opt(auto && e) { return RA_FW(e); }
130123

131124
// FIXME only reduces exprs as operated on in ra.hh (operators), not a tree like wlen() does.
@@ -239,16 +232,10 @@ RA_FE(RA_USING, fma)
239232
#undef RA_NAME
240233

241234
template <class T> constexpr auto
242-
cast(auto && a)
243-
{
244-
return map([](auto && b) -> decltype(auto) { return T(b); }, RA_FW(a));
245-
}
235+
cast(auto && a) { return map([](auto && b) -> decltype(auto) { return T(b); }, RA_FW(a)); }
246236

247237
template <class T> constexpr auto
248-
pack(auto && ... a)
249-
{
250-
return map([](auto && ... a){ return T { RA_FW(a) ... }; }, RA_FW(a) ...);
251-
}
238+
pack(auto && ... a) { return map([](auto && ... a){ return T { RA_FW(a) ... }; }, RA_FW(a) ...); }
252239

253240
template <class A> constexpr decltype(auto)
254241
at(A && a, auto const & i) requires (Slice<std::decay_t<A>> || Iterator<std::decay_t<A>>)
@@ -275,25 +262,25 @@ at_view(A && a, auto && i)
275262
}
276263
}
277264

278-
template <class T, class F> requires (toreduce<T, F>)
279-
constexpr decltype(auto) where(bool const w, T && t, F && f) { return w ? VAL(t) : VAL(f); }
265+
template <class T, class F> requires (toreduce<T, F>) constexpr decltype(auto)
266+
where(bool const w, T && t, F && f) { return w ? VAL(t) : VAL(f); }
280267

281-
template <class W, class T, class F> requires (tomap<W, T, F>)
282-
constexpr auto where(W && w, T && t, F && f) { return pick(cast<bool>(RA_FW(w)), RA_FW(f), RA_FW(t)); }
268+
template <class W, class T, class F> requires (tomap<W, T, F>) constexpr auto
269+
where(W && w, T && t, F && f) { return pick(cast<bool>(RA_FW(w)), RA_FW(f), RA_FW(t)); }
283270

284271
// catch all for non-ra types.
285-
template <class T, class F> requires (!(tomap<T, F>) && !(toreduce<T, F>))
286-
constexpr decltype(auto) where(bool const w, T && t, F && f) { return w ? t : f; }
272+
template <class T, class F> requires (!(tomap<T, F>) && !(toreduce<T, F>)) constexpr decltype(auto)
273+
where(bool const w, T && t, F && f) { return w ? t : f; }
287274

288-
template <class A, class B> requires (tomap<A, B>)
289-
constexpr auto operator &&(A && a, B && b) { return where(RA_FW(a), cast<bool>(RA_FW(b)), false); }
275+
template <class A, class B> requires (tomap<A, B>) constexpr auto
276+
operator &&(A && a, B && b) { return where(RA_FW(a), cast<bool>(RA_FW(b)), false); }
290277

291-
template <class A, class B> requires (tomap<A, B>)
292-
constexpr auto operator ||(A && a, B && b) { return where(RA_FW(a), true, cast<bool>(RA_FW(b))); }
278+
template <class A, class B> requires (tomap<A, B>) constexpr auto
279+
operator ||(A && a, B && b) { return where(RA_FW(a), true, cast<bool>(RA_FW(b))); }
293280

294281
#define RA_BINOP_SHORT(OP) \
295-
template <class A, class B> requires (toreduce<A, B>) \
296-
constexpr auto operator OP(A && a, B && b) { return VAL(a) OP VAL(b); }
282+
template <class A, class B> requires (toreduce<A, B>) constexpr auto \
283+
operator OP(A && a, B && b) { return VAL(a) OP VAL(b); }
297284
RA_FE(RA_BINOP_SHORT, &&, ||)
298285
#undef RA_BINOP_SHORT
299286

@@ -389,6 +376,13 @@ prod(auto && a)
389376
return c;
390377
}
391378

379+
#if defined(RA_FMA)
380+
#elif defined(FP_FAST_FMA)
381+
#define RA_FMA FP_FAST_FMA
382+
#else
383+
#define RA_FMA 0
384+
#endif
385+
392386
constexpr void maybe_fma(auto && a, auto && b, auto & c) { if constexpr (RA_FMA) c=fma(a, b, c); else c+=a*b; }
393387
constexpr void maybe_fma_conj(auto && a, auto && b, auto & c) { if constexpr (RA_FMA) c=fma_conj(a, b, c); else c+=conj(a)*b; }
394388
constexpr void maybe_fma_sqrm(auto && a, auto & c) { if constexpr (RA_FMA) c=fma_sqrm(a, c); else c+=sqrm(a); }

test/big-1.cc

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,38 +32,29 @@ int main()
3232
tr.test_eq(check[0], b.back());
3333
tr.test_eq(int2 {1, 2}, b().back()); // back on views
3434
}
35-
tr.section(".back() is last element not last item");
35+
tr.section("behavior of resize with default Container");
3636
{
37-
ra::Big<int2, 0> b({}, ra::scalar(int2 {1, 3})); // cf [ma116]
38-
tr.test_eq(int2 {1, 3}, b.back());
37+
ra::Big<int, 1> a = {1, 2, 3, 4, 5, 6};
38+
a.resize(3);
39+
a.resize(6);
40+
tr.test_eq(ra::iota(6, 1), a);
3941
}
40-
tr.section("behavior of resize with default Container");
4142
{
42-
{
43-
ra::Big<int, 1> a = {1, 2, 3, 4, 5, 6};
44-
a.resize(3);
45-
a.resize(6);
46-
tr.test_eq(ra::iota(6, 1), a);
47-
}
48-
{
49-
BigValueInit<int, 1> a = {1, 2, 3, 4, 5, 6};
50-
a.resize(3);
51-
a.resize(6);
52-
tr.test_eq(ra::iter({1, 2, 3, 0, 0, 0}), a);
53-
}
43+
BigValueInit<int, 1> a = {1, 2, 3, 4, 5, 6};
44+
a.resize(3);
45+
a.resize(6);
46+
tr.test_eq(ra::iter({1, 2, 3, 0, 0, 0}), a);
5447
}
5548
tr.section("resize works on first dimension");
5649
{
57-
{
58-
ra::Big<int, 2> a({3, 2}, {1, 2, 3, 4, 5, 6});
59-
a.resize(2);
60-
tr.test_eq(1+ra::_1 + 2*ra::_0, a);
61-
}
62-
{
63-
ra::Big<int, 2> a({3, 2}, {1, 2, 3, 4, 5, 6});
64-
resize(a, 2);
65-
tr.test_eq(1+ra::_1 + 2*ra::_0, a);
66-
}
50+
ra::Big<int, 2> a({3, 2}, {1, 2, 3, 4, 5, 6});
51+
a.resize(2);
52+
tr.test_eq(1+ra::_1 + 2*ra::_0, a);
53+
}
54+
{
55+
ra::Big<int, 2> a({3, 2}, {1, 2, 3, 4, 5, 6});
56+
resize(a, 2);
57+
tr.test_eq(1+ra::_1 + 2*ra::_0, a);
6758
}
6859
tr.section("operator=");
6960
{

test/small-1.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -367,11 +367,9 @@ int main()
367367
tr.test_eq(3, a[1]);
368368
tr.test_eq(6, a[2]);
369369
tr.test_eq(6, a.back());
370-
}
371-
tr.section(".back() is last element not last item");
372-
{
373-
ra::Small<int2> b(ra::scalar(int2 {1, 3})); // cf [ma116]
374-
tr.test_eq(int2 {1, 3}, b.back());
370+
ra::Big<int, 2> b = ra::ii({3, 4});
371+
tr.test_eq(8, b(ra::all, 0).back());
372+
tr.test_eq(ra::iter({8, 9, 10, 11}), b.back()); // back() is last item
375373
}
376374
// TODO Replace with uniform subscripting (ra::iota).
377375
tr.section("compile time subscripting of ra::Small (as)");

0 commit comments

Comments
 (0)