1 /++
2 
3 Macros:
4     LREF = <a href="#$1">$1</a>
5     HREF = <a href="$1">$2</a>
6 
7 Authors: $(HREF https://github.com/TodNaz,TodNaz)
8 Copyright: Copyright (c) 2020 - 2021, TodNaz.
9 License: $(HREF https://github.com/TodNaz/Tida/blob/master/LICENSE,MIT)
10 +/
11 module tida.each;
12 
13 import tida.vector;
14 
15 enum WithoutParallel = 0; /// Without parallel operation.
16 enum WithParallel = 1; /// With parallel operation.
17 
18 /++
19 The operation of traversing a rectangle.
20 
21 Params:
22     Type = Type operation.
23     width = Width rectangle.
24     height = Height rectangle.
25     beginX = Begin x-axis position.
26     beginY = Begin y-axis position. 
27 +/
28 auto Coord(int Type = WithoutParallel)(uint width,uint height,int beginX = 0,int beginY = 0) @safe
29 {
30     import std.range : iota;
31     import std.parallelism : parallel;
32 
33     static if (Type == WithoutParallel)
34     {
35         return (int delegate(ref int x, ref int y) @safe dg) @safe 
36         {
37             for(int ix = beginX; ix < width; ix++)
38             {
39                 for(int iy = beginY; iy < height; iy++)
40                 {
41                     dg(ix,iy);
42                 }
43             }
44 
45             return 0;
46         };
47     }else
48     static if (Type == WithParallel)
49     {
50         return (int delegate(ref int x,ref int y) @safe dg) @trusted 
51         {
52             import std.parallelism, std.range;
53 
54             foreach(ix; parallel(iota(beginX, width)))
55             {
56                 foreach(iy; parallel(iota(beginY, height)))
57                 {
58                     int dx = ix;
59                     int dy = iy;
60 
61                     dg(dx,dy);
62                 }
63             }
64 
65             return 0;
66         };
67     }
68 }
69 
70 auto Line(Vecf begin, Vecf end) @safe
71 {
72     import std.math : abs;
73 
74     return (int delegate(ref int x,ref int y) @safe dh) @safe {
75         int x1 = cast(int) begin.x;
76         int y1 = cast(int) begin.y;
77         const x2 = cast(int) end.x;
78         const y2 = cast(int) end.y;
79 
80         const deltaX = abs(x2 - x1);
81         const deltaY = abs(y2 - y1);
82         const signX = x1 < x2 ? 1 : -1;
83         const signY = y1 < y2 ? 1 : -1;
84 
85         int error = deltaX - deltaY;
86 
87         while (x1 != x2 || y1 != y2) {
88             dh(x1,y1);
89 
90             const error2 = error * 2;
91 
92             if (error2 > -deltaY) {
93                 error -= deltaY;
94                 x1 += signX;
95             }
96 
97             if (error2 < deltaX) {
98                 error += deltaX;
99                 y1 += signY;
100             }
101         }
102 
103         return 0;
104     };
105 }
106 
107 auto LineNoThrowImpl(Vecf begin,Vecf end) @safe nothrow pure
108 {
109     import std.math : abs;
110 
111     return (int delegate(ref int x,ref int y) @safe nothrow pure dh) @safe nothrow pure {
112         int x1 = cast(int) begin.x;
113         int y1 = cast(int) begin.y;
114         const x2 = cast(int) end.x;
115         const y2 = cast(int) end.y;
116 
117         const deltaX = abs(x2 - x1);
118         const deltaY = abs(y2 - y1);
119         const signX = x1 < x2 ? 1 : -1;
120         const signY = y1 < y2 ? 1 : -1;
121 
122         int error = deltaX - deltaY;
123 
124         while(x1 != x2 || y1 != y2) {
125             dh(x1,y1);
126 
127             const error2 = error * 2;
128 
129             if(error2 > -deltaY) {
130                 error -= deltaY;
131                 x1 += signX;
132             }
133 
134             if(error2 < deltaX) {
135                 error += deltaX;
136                 y1 += signY;
137             }
138         }
139 
140         return 0;
141     };
142 }