1 module ggeD.indexVec;
2 import ggeD;
3 import std;
4 
5 
6 private alias MakeSerialIndex(X) =  SerialIndex!X;
7 
8 package(ggeD):
9 struct IndexVec(IndexTypes...) 
10 {
11 
12 	alias SrialIndexes = staticMap!(MakeSerialIndex,IndexTypes);
13 	SrialIndexes idx;
14 	alias Dim = Alias!(IndexTypes.length);
15 	alias Rank = Dim;
16     alias idx this;
17 	@nogc typeof(this) unit(ulong n)
18 	{
19 		IndexVec!(IndexTypes) vec;
20 		static foreach(i;0..Dim)
21 		{
22 			vec[i] = i == n ? 1 : 0;
23 		}
24 		return vec;
25 	}
26 	
27 	alias tupleof = idx;
28     @nogc auto opBinary(string op,OtherIndexTypes...)(IndexVec!(OtherIndexTypes) rhs) if(OtherIndexTypes.length == Dim)
29     {
30         SrialIndexes result = idx;
31         static foreach(i; 0 .. Dim)
32         {
33             result[i] = mixin("idx[i]" ~ op ~ "rhs[i]");
34         }
35         return IndexVec!(IndexTypes)(result);
36     }
37     @nogc auto opBinary(string op,N)(N rhs) if(isNumeric!N && (op=="/" || op=="*"))
38     {
39         SrialIndexes result = idx;
40         static foreach(i; 0 .. Dim)
41         {
42             result[i] = mixin("idx[i]" ~ op ~ "rhs");
43         }
44         return IndexVec!(IndexTypes)(result);
45     }
46     @nogc auto opBinary(string op,N)(N[Dim] rhs)
47     {
48         SrialIndexes result = idx;
49         static foreach(i; 0 .. Dim)
50         {
51             result[i] = mixin("idx[i]" ~ op ~ "rhs[i]");
52         }
53         return IndexVec!(IndexTypes)(result);
54     }
55     @nogc auto opBinaryRight(string op,N)(N[Dim] lhs)
56     {
57         SrialIndexes result = idx;
58         static foreach(i; 0 .. Dim)
59         {
60             result[i] = mixin("lhs[i]" ~ op ~ "idx[i]");
61         }
62         return IndexVec!(IndexTypes)(result);
63     }
64     string toString()
65     {
66         string instantWrite(string sep="",Arg...)(Arg arg)
67         {
68             string result;
69             foreach(i,v;arg)
70             {
71                 result ~= v.to!string;
72                 if(i!=arg.length-1) result~= sep;
73             }
74             return result;
75         }
76         return "["~instantWrite!", "(idx)~"]";
77     }
78 	@nogc auto clamp()
79 	{
80         SrialIndexes result = idx;
81 		static foreach(i;0..Dim)
82 		{
83 			result[i] = idx[i].clamp;
84 		}
85 		return IndexVec!(IndexTypes)(result);
86 	}
87 	@nogc auto loop()
88 	{
89         SrialIndexes result = idx;
90 		static foreach(i;0..Dim)
91 		{
92 			result[i] = idx[i].loop;
93 		}
94 		return IndexVec!(IndexTypes)(result);
95 	}
96 }
97         
98 struct SerialIndex(IndexType = int)
99 {
100 	this(T)(T f,size_t len_,IndexType offset = 0)
101 	{
102 		_idx = cast(IndexType)f;
103         _len = len_;
104 	}
105 	@nogc const IndexType max()
106 	{
107 		return cast(IndexType)(_len+_offset);
108 	}
109 	@nogc const size_t len()
110 	{
111 		return _len;
112 	}
113 	
114 	IndexType _idx ;
115     size_t _len;
116 	IndexType _offset = 0;
117 	alias _idx this;
118 	@nogc void idx(IndexType i){
119 		_idx = i;
120 	}
121 	@nogc auto idx()
122 	{
123 		return _idx;
124 	}
125 	@nogc auto opAssign(T)(T value)
126 	{
127 		_idx = cast(IndexType)value;
128 	}
129 	@nogc SerialIndex opUnary(string op)()
130 	{
131 		auto r = SerialIndex(mixin(op~"_idx"),_len,_offset);
132 		return r;
133 	}
134 	@nogc SerialIndex opBinary(string op,T)(T value)
135 	{
136 		auto r = SerialIndex(mixin("_idx"~op~"value"),_len,_offset);
137 		return r;
138 	}
139 	@nogc SerialIndex opBinaryRight(string op,T)(T value)
140 	{
141 		auto r = SerialIndex(mixin("value"~op~"_idx"),_len,_offset);
142 		return r;
143 	}
144 	@nogc SerialIndex clamp()
145 	{
146 		auto r = SerialIndex(_idx < 0 ? 0 : _idx > max ? max : _idx,_len,_offset);
147 		return r;
148 	}
149 	@nogc SerialIndex loop()
150 	{
151 		auto r = SerialIndex(_idx < 0 ? _len+_idx : _idx > max ? _idx-_len : _idx,_len,_offset);
152 		return r;
153 	}
154     string toString()
155     {
156         return _idx.to!string;
157     }
158                     
159 }