1 module ggeD.iterator;
2 import mir.qualifier;
3 import mir.ndslice;
4 import std.traits;
5 
6 struct EinsumIterator(Iterator,SomeSlice,Node) if(is(SomeSlice == Slice!(T, Rank, kind),T,ulong Rank,SliceKind kind))
7 {
8     Iterator _iterator;
9     SomeSlice _slice;
10     Node node_;
11 
12     static enum Rank = SomeSlice.N;
13 
14     private size_t[Rank] ijk(Iterator itr)
15     {
16         size_t num = cast(size_t)(itr - _slice._iterator);
17         size_t[Rank] result;
18         static foreach(i; 0..Rank)
19         {
20             result[i] = cast(size_t)(num/_slice._stride!i);
21             num -= result[i]*_slice._stride!i;
22         }
23         return result;
24     }
25     auto lightConst()() const @property
26     {
27         return EinsumIterator!(LightConstOf!Iterator,SomeSlice, Node)(mir.qualifier.lightConst(_iterator),_slice,cast(Unqual!Node)node_);
28     }
29     auto lightImmutable()() immutable @property
30     {
31         return EinsumIterator!(LightImmutableOf!Iterator, SomeSlice, Node)(mir.qualifier.lightImmutable(_iterator),cast(Unqual!Node)_slice,node_);
32     }
33         import std.stdio;
34 
35     auto ref opUnary(string op : "*")()
36     {
37         return node_.calc(ijk(_iterator).tupleof);
38     }
39 
40     auto ref opIndex(ptrdiff_t index) scope
41     {
42         return node_.calc(ijk(_iterator+index).tupleof);
43     }
44     static if (!__traits(compiles, &opIndex(ptrdiff_t.init)))
45     {
46         auto ref opIndexAssign(T)(auto ref T value, ptrdiff_t index) scope
47         {
48             return _iterator[index] = value;
49         }
50 
51         auto ref opIndexUnary(string op)(ptrdiff_t index)
52         {
53             return mixin(op ~ "node_.calc(ijk(_iterator+index).tupleof)");
54         }
55 
56         auto ref opIndexOpAssign(string op, T)(T value, ptrdiff_t index)
57         {
58             return mixin("_iterator[index]" ~ op ~ "= value");
59         }
60     }
61     
62 
63     void opUnary(string op)() scope
64         if (op == "--" || op == "++")
65     { mixin(op ~ "_iterator;"); }
66 
67     void opOpAssign(string op)(ptrdiff_t index) scope
68         if (op == "-" || op == "+")
69     { mixin("_iterator " ~ op ~ "= index;"); }
70 
71     auto opBinary(string op)(ptrdiff_t index)
72         if (op == "+" || op == "-")
73     {
74         auto ret = this;
75         mixin(`ret ` ~ op ~ `= index;`);
76         return ret;
77     }
78 
79     ptrdiff_t opBinary(string op : "-")(scope ref const typeof(this) right) scope const
80     { return this._iterator - right._iterator; }
81 
82     bool opEquals()(scope ref const typeof(this) right) scope const
83     { return this._iterator == right._iterator; }
84 
85     ptrdiff_t opCmp()(scope ref const typeof(this) right) scope const
86     {
87         static if (isPointer!Iterator)
88             return this._iterator - right._iterator;
89         else
90             return this._iterator.opCmp(right._iterator);
91     }
92 
93 }