1#[cfg(test)]
2mod tests {
3 #[test]
4 fn it_works() {
5 assert_eq!(2 + 2, 4);
6 }
7}
8
9pub type Idx=i32;
11use std::ops::Range;
12use std::ops::{Add,Sub,Mul,Div,Rem,BitOr,BitAnd,BitXor,Index,IndexMut};
13extern crate lininterp;
14use lininterp::{Lerp,avr};
15
16#[derive(Copy,Debug,Clone)]
19pub struct Vec2<X,Y=X>{pub x:X,pub y:Y} #[derive(Copy,Debug,Clone)]
21pub struct Vec3<X,Y=X,Z=Y>{pub x:X,pub y:Y,pub z:Z} #[derive(Copy,Debug,Clone)]
23pub struct Vec4<X,Y=X,Z=Y,W=Z>{pub x:X,pub y:Y,pub z:Z,pub w:W} pub type V2i=Vec2<Idx>;
25pub type V3i=Vec3<Idx>;
26pub type V4i=Vec4<Idx>;type Axis_t=i32;
28const XAxis:Axis_t=0; const YAxis:Axis_t=1; const ZAxis:Axis_t=2;
29
30impl<T> Index<i32> for Vec3<T>{
31 type Output=T;
32 fn index(&self,i:Axis_t)->&T{match i{ XAxis=>&self.x,YAxis=>&self.y,ZAxis=>&self.z,_=>panic!("Vec3 index out of range")}}
33}
34impl<T> IndexMut<i32> for Vec3<T>{
35 fn index_mut(&mut self,i:Axis_t)->&mut T{match i{ XAxis=>&mut self.x,YAxis=>&mut self.y,ZAxis=>&mut self.z,_=>panic!("Vec3 index out of range")}}
36}
37
38pub fn v2i(x:i32,y:i32)->V2i{Vec2{x:x,y:y}}
39pub fn v3i(x:i32,y:i32,z:i32)->V3i{Vec3{x:x,y:y,z:z}}
40pub fn v3izero()->V3i{v3i(0,0,0)}
41pub fn v3ione()->V3i{v3i(1,1,1)}
42pub fn v3iadd_axis(a:V3i,axis:i32, value:i32)->V3i{let mut r=a; r[axis]+=value; r}
43pub struct Neighbours<T>{pub prev:T,pub next:T}
44type Neighbours2d<T>=Vec2<Neighbours<T>>;
45type Neighbours3d<T>=Vec3<Neighbours<T>>;
46type Neighbours4d<T>=Vec4<Neighbours<T>>;
47
48macro_rules! v3i_operators{[$(($fname:ident=>$op:ident)),*]=>{
49 $(pub fn $fname(a:V3i,b:V3i)->V3i{v3i(a.x.$op(b.x),a.y.$op(b.y),a.z.$op(b.z))})*
50}}
51macro_rules! v3i_permute_v2i{[$($pname:ident($u:ident,$v:ident)),*]=>{
52 $(pub fn $pname(a:V3i)->V2i{v2i(a.$u,a.$v)})*
53}}
54
55pub trait MyMod :Add+Sub+Div+Mul+Sized{
56 fn mymod(&self,b:Self)->Self;
57}
58impl MyMod for i32{
59 fn mymod(&self,b:Self)->Self{ if *self>=0{*self%b}else{ b-((-*self) %b)} }
60}
61v3i_operators![(v3iadd=>add),(v3isub=>sub),(v3imul=>mul),(v3idiv=>div),(v3irem=>rem),(v3imin=>min),(v3imax=>max),(v3imymod=>mymod)];
62v3i_permute_v2i![v3i_xy(x,y), v3i_yz(y,z), v3i_xz(x,z)];
63
64pub fn v3i_hmul_usize(a:V3i)->usize{ a.x as usize*a.y as usize *a.z as usize}
65pub fn v2i_hmul_usize(a:V2i)->usize{ a.x as usize*a.y as usize}
66
67pub struct Array2d<T>{pub shape:V2i,pub data:Vec<T>}
68pub struct Array3d<T>{pub shape:V3i,pub data:Vec<T>}
69pub struct Array4d<T>{pub shape:V4i,pub data:Vec<T>}
70
71impl<T:Clone> Array2d<T>{
72 pub fn new()->Self{Array2d{shape:v2i(0,0),data:Vec::new()}}
73 pub fn len(&self)->usize{ v2i_hmul_usize(self.shape) }
74 pub fn linear_index(&self, pos:V2i)->usize{
75 (pos.x as usize)+
77 (self.shape.x as usize) *(pos.y as usize)
78 }
79 pub fn map_pos<B:Clone,F:Fn(V2i,&T)->B> (&self,f:F) -> Array2d<B>{
80 let mut r=Array2d::new();
82 r.data.reserve(self.data.len());
83
84 for y in 0..self.shape.y { for x in 0.. self.shape.x{
85 let pos=v2i(x,y);
86 r.data.push( f(pos,self.index(pos)) );
87 }}
88 r
89 }
90 pub fn from_fn<F:Fn(V2i)->T> (s:V2i, f:F)->Array2d<T>{
91 let mut d=Array2d{shape:s,data:Vec::new()};
92 d.data.reserve(s.x as usize * s.y as usize);
93 for y in 0..s.y{ for x in 0..s.x{
94 d.data.push(f(v2i(x,y)))
95 }
96 }
97 d
98 }
99}
100
101impl<T:Clone> Index<V2i> for Array2d<T>{
102 type Output=T;
103 fn index(&self, pos:V2i)->&T{
104 let i=self.linear_index(pos);
105 &self.data[i]
106
107 }
108}
109
110impl<T:Clone> IndexMut<V2i> for Array2d<T>{
111 fn index_mut(&mut self, pos:V2i)->&mut T{
112 let i=self.linear_index(pos);
113 &mut self.data[i]
114 }
115}
116
117impl<T:Clone> Array3d<T>{
118 pub fn from_fn<F:Fn(V3i)->T> (s:V3i,f:F) -> Array3d<T> {
119 let mut a=Array3d{shape:s, data:Vec::new()};
120 a.data.reserve(v3i_hmul_usize(s));
121 for z in 0..a.shape.z{ for y in 0..a.shape.y { for x in 0.. a.shape.x{
122 a.data.push( f(v3i(x,y,z)) )
123 }}}
124 a
125 }
126
127 pub fn from_fn_doubled<F:Fn(V3i)->(T,T)> (sz:V3i,axis:i32, f:F)->Array3d<T>{
132 let mut scale=v3i(1,1,1); scale[axis]*=2;
133 let mut d=Array3d{shape:v3imul(sz,scale),data:Vec::new()};
134 d.data.reserve(sz.x as usize * sz.y as usize * sz.z as usize);
135 for z in 0..sz.z {for y in 0..sz.y{ for x in 0..sz.x{
136 let (v0,v1)=f(v3i(x,y,z));
137 d.data.push(v0);
138 d.data.push(v1);
139 }
140 }
141 }
142 d
143 }
144
145 pub fn fill_val(size:V3i,val:T)->Array3d<T>{let pval=&val;Self::from_fn(size,|_|pval.clone())}
146
147
148
149 pub fn len(&self)->usize{ v3i_hmul_usize(self.shape) }
150 pub fn linear_index(&self, pos:V3i)->usize{
151 (pos.x as usize)+
153 (self.shape.x as usize)*(
154 (pos.y as usize)+
155 (pos.z as usize)*(self.shape.y as usize)
156 )
157 }
158 pub fn size(&self)->V3i{self.shape}
159 pub fn map_xyz<B:Clone,F:Fn(V3i,&T)->B> (&self,f:F) -> Array3d<B>{
161 Array3d::from_fn(self.shape,
162 |pos:V3i|f(pos,self.index(pos))
163 )
164 }
165 pub fn map_strided_region<B:Clone,F:Fn(V3i,&T)->B>
166 (&self,range:Range<V3i>,stride:V3i, f:F) -> Array3d<B>
167 {
168 Array3d::from_fn(v3idiv(v3isub(range.end,range.start),stride),
169 |outpos:V3i|{
170 let inpos=v3iadd(v3imul(outpos,stride),range.start);
171 f(inpos,self.index(inpos))
172 }
173 )
174 }
175
176 pub fn for_each<F:Fn(V3i,&mut T)> (&mut self,f:F){
178 for z in 0..self.shape.z{ for y in 0..self.shape.y { for x in 0.. self.shape.x{
179 let pos=v3i(x,y,z);
180 f(pos,self.index_mut(pos))
181 }}}
182 }
183
184 pub fn map_xy<F,B>(&self, a_func:F)->Array2d<B>
188 where F:Fn(&Self,i32,i32)->B, B:Clone
189 {
190 Array2d::from_fn(v3i_xy(self.shape),
191 |pos:V2i|{a_func(self,pos.x,pos.y)}
192 )
193 }
194 pub fn map_xz<F,B>(&self, a_func:F)->Array2d<B>
195 where F:Fn(&Self,i32,i32)->B, B:Clone
196 {
197 Array2d::from_fn(v3i_xz(self.shape),
198 |pos:V2i|{a_func(self,pos.x,pos.y)}
199 )
200 }
201 pub fn map_yz<F,B>(&self, a_func:F)->Array2d<B>
202 where F:Fn(&Self,i32,i32)->B, B:Clone
203 {
204 Array2d::from_fn(v3i_yz(self.shape),
205 |pos:V2i|{a_func(self,pos.x,pos.y)}
206 )
207 }
208
209 pub fn reshape(&mut self, s:V3i){
210 assert!(v3i_hmul_usize(self.shape)==v3i_hmul_usize(s));
213 self.shape=s;
214 }
215
216 pub fn fold_z<B,F> (&self,init_val:B, f:F) -> Array2d<B>
220 where B:Clone,F:Fn(V3i,B,&T)->B
221 {
222 self.map_xy(|s:&Self,x:i32,y:i32|{
223 let mut acc=init_val.clone();
224 for z in 0..s.shape.z{
225 let pos=v3i(x,y,z);
226 acc=f(pos,acc,self.index(pos))
227 }
228 acc
229 })
230 }
231pub fn fold_x<B:Clone,F:Fn(V3i,B,&T)->B> (&self,input:B, f:F) -> Array2d<B>{
248 let mut out=Array2d::new();
249 out.data.reserve(self.shape.y as usize *self.shape.z as usize);
250 for z in 0..self.shape.z {
251 for y in 0.. self.shape.y{
252 let mut acc=input.clone();
253 for x in 0..self.shape.x{
254 let pos=v3i(x,y,z);
255 acc=f(pos,acc, self.index(pos));
256 }
257 out.data.push(acc);
258 }
259 }
260 out.shape=v2i(self.shape.y,self.shape.z);
261 out
262 }
263 pub fn fold_xyz<A,B,C,FOLDX,FOLDY,FOLDZ>(
265 &self,
266 (input_x,fx):(A,FOLDX), (input_y,fy):(B,FOLDY), (input_z,fz):(C,FOLDZ)
267 )->A
268 where
269 A:Clone,B:Clone,C:Clone,
270 FOLDZ:Fn(V3i,C,&T)->C,
271 FOLDY:Fn(i32,i32,B,&C)->B,
272 FOLDX:Fn(i32,A,&B)->A,
273 {
274 let mut ax=input_x.clone();
275 for x in 0..self.shape.x{
276 let mut ay=input_y.clone();
277 for y in 0..self.shape.y{
278 let mut az=input_z.clone();for z in 0..self.shape.z{
280 let pos=v3i(x,y,z);
281 az=fz(pos,az,self.index(pos));
282 }
283 ay=fy(x,y,ay,&az);
284 }
285 ax= fx(x, ax,&ay);
286 }
287 ax
288 }
289 pub fn fold_zyx<A,B,C,FOLDX,FOLDY,FOLDZ>(
291 &self,
292 (input_x,fx):(A,FOLDX), (input_y,fy):(B,FOLDY), (input_z,fz):(C,FOLDZ)
293 )->C
294 where
295 A:Clone,B:Clone,C:Clone,
296 FOLDZ:Fn(i32,C,&B)->C,
297 FOLDY:Fn(i32,i32,B,&A)->B,
298 FOLDX:Fn(V3i,A,&T)->A,
299 {
300 let mut az=input_z.clone();
301 for z in 0..self.shape.z{
302 let mut ay=input_y.clone();
303 for y in 0..self.shape.y{
304 let mut ax=input_x.clone();for x in 0..self.shape.x{
306 let pos=v3i(x,y,z);
307 ax=fx(pos,ax,self.index(pos));
308 }
309 ay=fy(y,z,ay,&ax);
310 }
311 az= fz(z, az,&ay);
312 }
313 az
314 }
315
316 pub fn fold<B,F> (&self,input:B, f:F) -> B
318 where F:Fn(V3i,B,&T)->B,B:Clone
319 {
320 let mut acc=input;
321 for z in 0..self.shape.z { for y in 0.. self.shape.y{ for x in 0..self.shape.x{
322 let pos=v3i(x,y,z);
323 acc=f(pos, acc,self.index(pos));
324 }}}
325 acc
326 }
327
328 pub fn fold_tiles<B,F>(&self,tilesize:V3i, input:B,f:&F)->Array3d<B>
332 where F:Fn(V3i,B,&T)->B,B:Clone
333 {
334 self.map_strided(tilesize,
335 |pos,_:&T|{self.fold_region(pos..v3iadd(pos,tilesize),input.clone(),f)})
336 }
337
338 pub fn fold_region<B,F>(&self,r:Range<V3i>, input:B,f:&F)->B
341 where F:Fn(V3i,B,&T)->B, B:Clone
342 {
343 let mut acc=input.clone();
344 for z in r.start.z..r.end.z{
345 for y in r.start.y..r.end.y{
346 for x in r.start.x..r.end.x{
347 let pos=v3i(x,y,z);
348 acc=f(pos,acc,self.index(pos));
349 }
350 }
351 }
352 acc
353 }
354 pub fn get_indexed(&self,pos:V3i)->(V3i,&T){(pos,self.index(pos))}
355 pub fn region_all(&self)->Range<V3i>{v3i(0,0,0)..self.shape}
356 pub fn map_region_strided<F,B>(&self,region:Range<V3i>,stride:V3i, f:F)->Array3d<B>
357 where F:Fn(V3i,&T)->B, B:Clone{
358 Array3d::from_fn(v3idiv(v3isub(region.end,region.start),stride),
359 |outpos:V3i|{
360 let inpos=v3iadd(region.start,v3imul(outpos,stride));
361 f(inpos,self.index(inpos))
362 }
363 )
364 }
365 pub fn map_strided<F,B>(&self,stride:V3i,f:F)->Array3d<B>
366 where F:Fn(V3i,&T)->B, B:Clone{
367 self.map_region_strided(self.region_all(),stride,f)
368 }
369 pub fn map_region<F,B>(&self,region:Range<V3i>,f:F)->Array3d<B>
370 where F:Fn(V3i,&T)->B, B:Clone{
371 self.map_region_strided(region, v3ione(), f)
372 }
373 pub fn convolute_neighbours<F,B>(&self,f:F)->Array3d<B>
377 where F:Fn(&T,Vec3<Neighbours<&T>>)->B ,B:Clone
378 {
379 self.map_region(v3ione()..v3isub(self.shape,v3ione()),
380 |pos:V3i,current_cell:&T|{
381 f( current_cell,
382 self::Vec3{
383 x:Neighbours{
384 prev:self.index(v3i(pos.x-1,pos.y,pos.z)),
385 next:self.index(v3i(pos.x+1,pos.y,pos.z))},
386 y:Neighbours{
387 prev:self.index(v3i(pos.x,pos.y-1,pos.z)),
388 next:self.index(v3i(pos.x,pos.y+1,pos.z))},
389 z:Neighbours{
390 prev:self.index(v3i(pos.x,pos.y,pos.z-1)),
391 next:self.index(v3i(pos.x,pos.y,pos.z+1))}})
392 })
393 }
394 pub fn index_wrap(&self,pos:V3i)->&T{self.get_wrap(pos)}
395 pub fn get_wrap(&self,pos:V3i)->&T{
396 self.index( v3imymod(pos, self.shape) )
397 }
398 pub fn get_ofs_wrap(&self,pos:V3i,dx:i32,dy:i32,dz:i32)->&T{
399 self.get_wrap(v3iadd(pos, v3i(dx,dy,dz)))
400 }
401 pub fn convolute_neighbours_wrap<F,B>(&self,f:F)->Array3d<B>
402 where F:Fn(&T,Vec3<Neighbours<&T>>)->B,B:Clone
403 {
404 self.map_region(v3izero()..self.shape,
408 |pos:V3i,current_cell:&T|{
409 f( current_cell,
410 Vec3{
411 x:Neighbours{
412 prev:self.get_wrap(v3i(pos.x-1,pos.y,pos.z)),
413 next:self.get_wrap(v3i(pos.x+1,pos.y,pos.z))},
414 y:Neighbours{
415 prev:self.get_wrap(v3i(pos.x,pos.y-1,pos.z)),
416 next:self.get_wrap(v3i(pos.x,pos.y+1,pos.z))},
417 z:Neighbours{
418 prev:self.get_wrap(v3i(pos.x,pos.y,pos.z-1)),
419 next:self.get_wrap(v3i(pos.x,pos.y,pos.z+1))}})
420 })
421 }
422 pub fn convolute_2x2x2_wrap<F,B>(&self,f:F)->Array3d<B>
424 where F:Fn(V3i,[[[&T;2];2];2])->B,B:Clone
425 {
426 self.map_region(v3izero()..self.shape,|pos,_|{
427 f(pos,[
428 [ [self.get_ofs_wrap(pos,0, 0, 0),self.get_ofs_wrap(pos, 1, 0, 0)],
429 [self.get_ofs_wrap(pos,0, 1, 0),self.get_ofs_wrap(pos, 1, 1, 0)]
430 ],
431 [ [self.get_ofs_wrap(pos,0, 0, 1),self.get_ofs_wrap(pos, 1, 0, 1)],
432 [self.get_ofs_wrap(pos,0, 1, 1),self.get_ofs_wrap(pos, 1, 1, 1)]
433 ]
434 ])
435 })
436 }
437
438 pub fn fold_half<F,B>(&self,fold_fn:F)->Array3d<B>
440 where F:Fn(V3i,[[[&T;2];2];2])->B,B:Clone
441 {
442 Array3d::from_fn( v3idiv(self.shape,v3i(2,2,2)), |dpos:V3i|{
443 let spos=v3imul(dpos,v3i(2,2,2));
444 fold_fn(dpos,
445 [ [ [self.index(v3iadd(spos,v3i(0,0,0))),self.index(v3iadd(spos,v3i(1,0,0)))],
446 [self.index(v3iadd(spos,v3i(0,1,0))),self.index(v3iadd(spos,v3i(1,1,0)))]
447 ],
448 [ [self.index(v3iadd(spos,v3i(0,0,0))),self.index(v3iadd(spos,v3i(1,0,0)))],
449 [self.index(v3iadd(spos,v3i(0,0,0))),self.index(v3iadd(spos,v3i(1,0,0)))]
450 ]
451 ]
452 )
453 })
454 }
455}
456
457
458impl<T:Clone+Lerp> Array3d<T>
469{
470 fn downsample_half(&self)->Array3d<T>{
472 self.fold_half(|pos:V3i,cell:[[[&T;2];2];2]|->T{
473
474 avr(
475 &avr(
476 &avr(&cell[0][0][0],&cell[1][0][0]),
477 &avr(&cell[0][1][0],&cell[1][1][0])),
478 &avr(
479 &avr(&cell[0][0][1],&cell[1][0][1]),
480 &avr(&cell[0][1][1],&cell[1][1][1])
481 )
482 )
483
484 })
485 }
486
487 fn upsample_double_axis(&self,axis:i32)->Array3d<T>{
489 Array3d::from_fn_doubled(self.shape,axis,|pos:V3i|->(T,T){
490 let v0=self.index(pos); let v1=self.get_wrap(v3iadd_axis(pos,axis,1));
491 let vm=avr(v0,v1);
492 (v0.clone(),vm)
493 })
494 }
495 fn upsample_double_xyz(&self)->Array3d<T>{
497 self.upsample_double_axis(XAxis).upsample_double_axis(YAxis).upsample_double_axis(ZAxis)
499 }
500
501}
502
503impl<T:Clone> Index<V3i> for Array3d<T>{
504 type Output=T;
505 fn index(&self, pos:V3i)->&T{
506 let i=self.linear_index(pos);
507 &self.data[i]
508
509 }
510}
511
512impl<T:Clone> IndexMut<V3i> for Array3d<T>{
513 fn index_mut(&mut self, pos:V3i)->&mut T{
514 let i=self.linear_index(pos);
515 &mut self.data[i]
516 }
517}
518
519
520
521
522
523