Skip to content

Commit f3456a4

Browse files
committed
Separate ra::iota from ra::tindex
This also separates the concepts of Slice and Iterator. Before, ra::iota was both; now it's only a Slice. On the other hand, ra::tindex is Iterator but not Slice. * ra/expr.hh (Cell): Don't provide data(). (iter(Slice): Forbid that Slice is also Iterator. * ra/ply.hh (iota): Is view. (ii): Rename to iota, no need for two different names. * ra/arrays.hh (tindex): New type. Redefine _0, etc. as tindex<0>, etc. (reverse): Always return view. * docs/ra-ra.texi (iota): Update. Elsewhere replace iota<n> by tindex<n>.
1 parent 05c7c87 commit f3456a4

32 files changed

+339
-361
lines changed

TODO

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,14 @@ checkbox [C-ct] flip TODO
1111
- [ ] Fix reduction-1.cc: "real_part(iter<1>(m)) = real_part(iter<1>(c))"
1212
- [ ] Invalid expressions that aren't caught by Match, either bc it makes assumptions, or bc
1313
Match isn't even involved. See checks.cc.
14-
- [ ] const issues in View vs Container
15-
- [ ] conversion to const & op in ViewBig uses reinterpret_const
14+
- [ ] conversion to const & op in ViewBig uses reinterpret_const
1615
- [ ] Small/Big unification
17-
- [ ] Unify small and big views
16+
- [X] Unify small and big views
1817
- [ ] Unify small and big containers
1918
- [ ] Forbid initialization from higher rank
2019
- Cf 'Initialization of nested types' in the manual.
2120
- [ ] ambiguity / bad init in nested constructors [ra45]
22-
- [ ] ra::at(A, I) needs nested I, so the obvious ra::at(A, [i j]) doesn't work (although
23-
view.at([i j]) does). But I would get rid of view.at(i) if ra::at(view, i) worked the same
24-
way.
21+
- [ ] ra::at(A, I) needs nested I, so the obvious ra::at(A, [i j]) doesn't work.
2522
- [ ] be namespace clean except for possibly the scalar block in ra.hh. Document exactly what is exported to ::.
2623
- [ ] bad uses of assert [ra17]
2724
- [ ] poor shape mismatch report, e.g. [1 2] vs [2] produces 'len[0] is -192...' (magic number for MISS)

bench/bench-at.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ int main(int argc, char * * argv)
110110
}));
111111
};
112112
// at(i) can be a lot slower if i is var rank. FIXME But these are both static rank.
113-
auto iotav = ra::ii({100});
113+
auto iotav = ra::iota({100});
114114
static_assert(1==rank(iotav));
115115
auto iotai = ra::iota(100);
116116
static_assert(1==rank(iotai));

bench/bench-pack.cc

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,54 +20,47 @@ int main()
2020
TestRecorder tr(cout);
2121
cout.precision(4);
2222

23-
auto bench = [&tr](auto && f, auto A_, char const * tag, int size, int reps)
24-
{
25-
using A = decltype(A_);
26-
A a({size}, ra::none);
23+
auto bench = [&tr](auto && f, auto A_, char const * tag, int size, int reps){
24+
using A = decltype(A_);
25+
A a({size}, ra::none);
2726

28-
Benchmark bm { reps, 3 };
29-
auto bv = bm.run([&]() { f(a, size); });
30-
tr.info(Benchmark::report(bv, size), " ", tag)
31-
.test_eq(ra::pack<complex>(ra::iota(size, 0.), size-ra::iota(size, 0.)), a);
32-
};
27+
Benchmark bm { reps, 3 };
28+
auto bv = bm.run([&]() { f(a, size); });
29+
tr.info(Benchmark::report(bv, size), " ", tag)
30+
.test_eq(ra::pack<complex>(ra::iota(size, 0.), size-ra::iota(size, 0.)), a);
31+
};
3332

34-
auto f_raw = [](auto & a, int size)
35-
{
36-
real * p = reinterpret_cast<real *>(a.data());
37-
for (ra::dim_t i=0; i!=size; ++i, p+=2) {
38-
p[0] = i;
39-
p[1] = size-i;
40-
}
41-
};
42-
auto f_reim = [](auto & a, int size)
43-
{
44-
real_part(a) = ra::iota(size);
45-
imag_part(a) = size-ra::iota(size);
46-
};
47-
auto f_collapse = [](auto & a, int size)
48-
{
49-
auto areim = ra::collapse<real>(a);
50-
areim(ra::all, 0) = ra::iota(size);
51-
areim(ra::all, 1) = size-ra::iota(size);
52-
};
53-
auto f_pack = [](auto & a, int size)
54-
{
55-
a = ra::pack<complex>(ra::iota(size, 0.), size-ra::iota(size, 0.));
56-
};
57-
auto f_xi = [](auto & a, int size)
58-
{
59-
a = ra::iota(size, 0.) + xi(size-ra::iota(size, 0.));
60-
};
33+
auto f_raw = [](auto & a, int size){
34+
real * p = reinterpret_cast<real *>(a.data());
35+
for (ra::dim_t i=0; i!=size; ++i, p+=2) {
36+
p[0] = i;
37+
p[1] = size-i;
38+
}
39+
};
40+
auto f_reim = [](auto & a, int size){
41+
real_part(a) = ra::iota(size);
42+
imag_part(a) = size-ra::iota(size);
43+
};
44+
auto f_collapse = [](auto & a, int size){
45+
auto areim = ra::collapse<real>(a);
46+
areim(ra::all, 0) = ra::iota(size);
47+
areim(ra::all, 1) = size-ra::iota(size);
48+
};
49+
auto f_pack = [](auto & a, int size){
50+
a = ra::pack<complex>(ra::iota(size, 0.), size-ra::iota(size, 0.));
51+
};
52+
auto f_xi = [](auto & a, int size){
53+
a = ra::iota(size, 0.) + xi(size-ra::iota(size, 0.));
54+
};
6155

62-
auto bench_all = [&](auto A_, int size, int n)
63-
{
64-
tr.section("size ", size, ", n ", n);
65-
bench(f_raw, A_, "raw", size, n);
66-
bench(f_reim, A_, "re/im", size, n);
67-
bench(f_collapse, A_, "collapse", size, n);
68-
bench(f_pack, A_, "pack", size, n);
69-
bench(f_xi, A_, "xi", size, n);
70-
};
56+
auto bench_all = [&](auto A_, int size, int n){
57+
tr.section("size ", size, ", n ", n);
58+
bench(f_raw, A_, "raw", size, n);
59+
bench(f_reim, A_, "re/im", size, n);
60+
bench(f_collapse, A_, "collapse", size, n);
61+
bench(f_pack, A_, "pack", size, n);
62+
bench(f_xi, A_, "xi", size, n);
63+
};
7164

7265
bench_all(ra::Big<complex, 1>(), 10, 1000000);
7366
bench_all(ra::Big<complex, 1>(), 100, 100000);

bench/bench-tensorindex.cc

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,45 +19,41 @@ int main()
1919
{
2020
ra::Big<int, 1> a = {0, 0, 0};
2121
ra::ply(map([](auto && i) { std::cout << "i: " << i << std::endl; },
22-
a+ra::iota<0>()));
22+
a+ra::tindex<0>));
2323
ra::ply_ravel(map([](auto && i) { std::cout << "i: " << i << std::endl; },
24-
a+ra::iota<0>()));
24+
a+ra::tindex<0>));
2525
}
2626
// rank 2
2727
{
2828
ra::Big<int, 2> a = {{0, 0, 0}, {0, 0, 0}};
2929
ra::ply(map([](auto && i, auto && j) { std::cout << "i: " << i << ", " << j << std::endl; },
30-
a+ra::iota<0>(), a+ra::iota<1>()));
30+
a+ra::tindex<0>, a+ra::tindex<1>));
3131
ra::ply_ravel(map([](auto && i, auto && j) { std::cout << "i: " << i << ", " << j << std::endl; },
32-
a+ra::iota<0>(), a+ra::iota<1>()));
32+
a+ra::tindex<0>, a+ra::tindex<1>));
3333
}
3434
// benchmark
35-
auto taking_view =
36-
[](TestRecorder & tr, auto && a)
37-
{
38-
auto fa = [&a]()
39-
{
40-
int c = 0;
41-
ra::ply(ra::map([&c](auto && i, auto && j) { c += 2*i-j; },
42-
a+ra::iota<0>(), a+ra::iota<1>()));
43-
return c;
44-
};
45-
auto fb = [&a]()
46-
{
47-
int c = 0;
48-
ra::ply_ravel(ra::map([&c](auto && i, auto && j) { c += 2*i-j; },
49-
a+ra::iota<0>(), a+ra::iota<1>()));
50-
return c;
51-
};
35+
auto taking_view = [](TestRecorder & tr, auto && a){
36+
auto fa = [&a]{
37+
int c = 0;
38+
ra::ply(ra::map([&c](auto && i, auto && j) { c += 2*i-j; },
39+
a+ra::tindex<0>, a+ra::tindex<1>));
40+
return c;
41+
};
42+
auto fb = [&a]{
43+
int c = 0;
44+
ra::ply_ravel(ra::map([&c](auto && i, auto && j) { c += 2*i-j; },
45+
a+ra::tindex<0>, a+ra::tindex<1>));
46+
return c;
47+
};
5248

53-
tr.test_eq(499500000, fa());
54-
tr.test_eq(499500000, fb());
49+
tr.test_eq(499500000, fa());
50+
tr.test_eq(499500000, fb());
5551

56-
auto bench = Benchmark {/* repeats */ 30, /* runs */ 30};
52+
auto bench = Benchmark {/* repeats */ 30, /* runs */ 30};
5753

58-
bench.info("vala").report(std::cout, bench.run(fa), 1e-6);
59-
bench.info("valb").report(std::cout, bench.run(fb), 1e-6);
60-
};
54+
bench.info("vala").report(std::cout, bench.run(fa), 1e-6);
55+
bench.info("valb").report(std::cout, bench.run(fb), 1e-6);
56+
};
6157

6258
ra::Big<int, 2> const a({1000, 1000}, 0);
6359
taking_view(tr, a);

docs/index.html

Lines changed: 36 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/ra-ra.texi

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -865,11 +865,19 @@ Besides, when the subscripts @code{i, j, ...} are scalars or integer sequences o
865865

866866
@code{ra::} isn't smart enough to know when an arbitrary expression might be a integer sequence of the appropriate form, so it has a special type for those, the @ref{Sequence views,sequence view}. The following function creates a rank 1 sequence view:
867867

868+
@cindex TensorIndex
868869
@anchor{x-iota}
869-
@deffn @w{Special object} iota count [iter:0 [step:1]]
870-
Create a rank 1 sequence view @code{iter, iter+step, ... iter+step*(count-1)}.
870+
@anchor{x-tindex}
871+
@deffn @w{Function} iota [count:@code{UNB} [org:0 [step:1]]]
872+
@deffnx @w{Function} tindex<k>
873+
874+
These functions are closely related.
875+
876+
@code{iota(count, org, step)} creates a rank-1 @ref{Sequence views,sequence view} [@var{org}, @var{org}+@var{step}, ... @var{org}+@var{step}*(@var{count}-1)]. The default @var{count} results in an unbounded sequence [0, 1, ...].
877+
878+
@code{tindex<k>} creates an iterator over the unbounded sequence [0, 1, ...] at array index @var{k}. The rank of this expression is @var{k}+1.
871879

872-
This can used anywhere an array expression is expected.
880+
Either can be used anywhere an array expression is expected. @code{iota(...)} is also a view and so it can be subscripted in the usual way.
873881

874882
@example
875883
@verbatim
@@ -878,34 +886,33 @@ ra::Big<int, 1> a = ra::iota(4, 3 -2);
878886
@result{} a = @{3, 1, -1, -3@}
879887
@end example
880888

881-
Here, @code{b} and @code{c} are @code{ViewBig}s (@pxref{Containers and views}).
882889
@example
883890
@verbatim
884-
ra::Big<int, 1> a = {1, 2, 3, 4, 5, 6};
885-
auto b = a(iota(3));
886-
auto c = a(iota(3, 3));
891+
ra::Big<int, 2> a({3, 3}, 10*ra::tindex<0> + ra::tindex<1>)
887892
@end verbatim
888-
@result{} a = @{1, 2, 3@}
889-
@result{} a = @{4, 5, 6@}
893+
@result{} a = @{@{0, 1, 2@}, @{10, 11, 12@}, @{20, 21, 22@}@}
890894
@end example
891895

892-
@cindex TensorIndex
893-
@code{iota()} by itself is an expression of rank 1 and undefined length. It must be used with other terms whose lengths are defined, so that the overall shape of the array expression can be determined. In general, @code{iota<n>()} is an array expression of rank @code{n}+1 that represents the @code{n}-th index of an array expression. This is similar to Blitz++'s @code{TensorIndex}.
894-
895-
@code{ra::} offers the shortcut @code{ra::_0} for @code{ra::iota<0>()}, etc.
896+
@example
897+
@verbatim
898+
auto i = ra::iota(10, 1); // [1 2 3 4 5 6 7 8 9 10]
899+
auto j = i(ra::iota(3, 2, 2)); // i([2 4 5])
900+
@end verbatim
901+
@result{} j = @{3, 5, 7@}
902+
@end example
896903

904+
@code{j} above is a view, just like @code{b} and @code{c} in the following (@pxref{Containers and views}).
897905
@example
898906
@verbatim
899-
ra::Big<int, 1> v = {1, 2, 3};
900-
cout << (v - ra::_0) << endl; // { 1-0, 2-1, 3-2 }
901-
// cout << (ra::_0) << endl; // error: undefined length
902-
// cout << (v - ra::_1) << endl; // error: undefined length on axis 1
903-
ra::Big<int, 2> a({3, 2}, 0);
904-
cout << (a + ra::_0 - ra::_1) << endl; // {{0, -1, -2}, {1, 0, -1}, {2, 1, 0}}
907+
ra::Big<int, 1> a = {1, 2, 3, 4, 5, 6};
908+
auto b = a(iota(3));
909+
auto c = a(iota(3, 3));
905910
@end verbatim
911+
@result{} a = @{1, 2, 3@}
912+
@result{} a = @{4, 5, 6@}
906913
@end example
907914

908-
When undefined length @code{iota()} is used as a subscript by itself, the result isn't a view. This allows @code{view(iota())} to match with expressions of different lengths, as in the following example.
915+
However, when unbounded expressions are used as subscripts, the result isn't a view. This allows @code{view(iota())} to match with expressions of different lengths, as in the following example. @c FIXME
909916
@example
910917
@verbatim
911918
ra::Big<int, 1> a = {1, 2, 3, 4, 5, 6};
@@ -916,13 +923,20 @@ cout << (b + a(iota())) << endl; // a(iota()) is not a view
916923
2 4 6
917924
@end example
918925

919-
Note the difference between
920-
@itemize
921-
@item @code{ra::iota<3>()} —
922-
an expression of rank 4 and undefined length, representing a linear sequence over the tensor index of axis 3
923-
@item @code{ra::iota(3)} ≡ @code{ra::iota<0>(3)} —
924-
an expression of rank 1, representing the sequence @code{0, 1, 2}.
925-
@end itemize
926+
Unbounded expressions such as @code{iota()} cannot be traversed by themselves, but must be combined with other terms so that the overall expression is bounded. @code{tindex<k>} can be interpreted as representing the @code{k}-th index of an array expression. This is similar to Blitz++'s @code{TensorIndex}. For the 0-th index, @code{tindex<0>} and @code{iota()} are equivalent.
927+
928+
@example
929+
@verbatim
930+
ra::Big<int, 1> v = {1, 2, 3};
931+
cout << (v - ra::tindex<0>) << endl; // { 1-0, 2-1, 3-2 }
932+
// cout << (ra::tindex<0>) << endl; // error: undefined length
933+
// cout << (v - ra::tindex<1>) << endl; // error: undefined length on axis 1
934+
ra::Big<int, 2> a({3, 2}, 0);
935+
cout << (a + ra::tindex<0> - ra::tindex<1>) << endl; // {{0, -1, -2}, {1, 0, -1}, {2, 1, 0}}
936+
@end verbatim
937+
@end example
938+
939+
@code{ra::} offers the shortcuts @code{ra::_0}, @code{ra::_1}, ... for @code{ra::tindex<0>}, @code{ra::tindex<1>}, ...
926940

927941
@end deffn
928942

examples/agreement.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ int main()
5959
// shape. Therefore they need to be accompanied by some other expression
6060
// that does have a shape, or the overall expression is not valid.
6161
{
62-
constexpr auto i = ra::iota<0>();
63-
constexpr auto j = ra::iota<1>();
62+
constexpr auto i = ra::tindex<0>;
63+
constexpr auto j = ra::tindex<1>;
6464
// That's why you can do
6565
ra::Big<float, 2> X({3, 4}, i-j);
6666
cout << "\ni-j: " << X << endl;

0 commit comments

Comments
 (0)