source: trunk/Packages/TemplateGenerics/Generic/GenericMatrix.inc

Last change on this file was 324, checked in by chronos, 6 months ago
File size: 8.3 KB
Line 
1// Work in progress...
2
3{$IFDEF INTERFACE}
4
5 // TGMatrix<TGMatrixIndex, TGMatrixIndex, TGMatrixItem> = class
6 TGMatrix = class
7 public
8 type
9 TSortCompare = function(const Item1, Item2: TGMatrixItem): Integer of object;
10 TToStringConverter = function(Item: TGMatrixItem): string;
11 TFromStringConverter = function(Text: string): TGMatrixItem;
12 TRow = array of TGMatrixItem;
13 TMerge = function(Item1, Item2: TGMatrixItem): TGMatrixItem of object;
14
15 TIndex = record
16 X: TGMatrixIndexX;
17 Y: TGMatrixIndexY;
18 end;
19 private
20 FItems: array of array of TGMatrixItem;
21 FCount: TIndex;
22 function GetItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY): TGMatrixItem;
23 function GetItem(Index: TIndex): TGMatrixItem;
24 function GetCapacity: TIndex;
25 procedure SetCapacity(const AValue: TIndex);
26 procedure PutItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY; const AValue: TGMatrixItem); virtual;
27 procedure PutItem(Index: TIndex; const AValue: TGMatrixItem); virtual;
28 procedure SetCount(const AValue: TIndex);
29 public
30 procedure Assign(Source: TGMatrix);
31 procedure Clear; virtual;
32 procedure Contract;
33 function CreateIndex(X: TGMatrixIndexY; Y: TGMatrixIndexX): TIndex;
34 procedure Expand;
35 procedure Exchange(Index1, Index2: TIndex);
36 procedure FillAll(Value: TGMatrixItem);
37 procedure Fill(Start, Count: TIndex; Value: TGMatrixItem);
38 function Implode(RowSeparator, ColSeparator: string; Converter: TToStringConverter): string;
39 procedure Merge(Index: TIndex; Source: TGMatrix; Proc: TMerge);
40 procedure Replace(Index: TIndex; Source: TGMatrix);
41 procedure Reverse;
42 procedure ReverseHorizontal;
43 procedure ReverseVertical;
44 property Count: TIndex read FCount write SetCount;
45 property Capacity: TIndex read GetCapacity write SetCapacity;
46 property ItemsXY[X: TGMatrixIndexX; Y: TGMatrixIndexY]: TGMatrixItem
47 read GetItemXY write PutItemXY; default;
48 property Items[Index: TIndex]: TGMatrixItem
49 read GetItem write PutItem;
50 end;
51
52{$UNDEF INTERFACE}
53{$ENDIF}
54
55{$IFDEF IMPLEMENTATION_USES}
56
57resourcestring
58 SMatrixIndexError = 'Matrix index error [X: %d, Y: %d]';
59
60{$UNDEF IMPLEMENTATION_USES}
61{$ENDIF}
62
63{$IFDEF IMPLEMENTATION}
64
65{ TGMatrix }
66
67procedure TGMatrix.Replace(Index: TIndex; Source: TGMatrix);
68var
69 X: TGMatrixIndexX;
70 Y: TGMatrixIndexY;
71begin
72 Y := 0;
73 while Y < Source.Count.Y do begin
74 X := 0;
75 while X < Source.Count.X do begin
76 ItemsXY[Index.X + X, Index.Y + Y] := Source.ItemsXY[X, Y];
77 X := X + 1;
78 end;
79 Y := Y + 1;
80 end;
81end;
82
83procedure TGMatrix.Merge(Index: TIndex; Source: TGMatrix; Proc: TMerge);
84var
85 X: TGMatrixIndexX;
86 Y: TGMatrixIndexY;
87begin
88 Y := 0;
89 while Y < Source.Count.Y do begin
90 X := 0;
91 while X < Source.Count.X do begin
92 ItemsXY[Index.X + X, Index.Y + Y] := Proc(ItemsXY[Index.X + X, Index.Y + Y], Source.ItemsXY[X, Y]);
93 X := X + 1;
94 end;
95 Y := Y + 1;
96 end;
97end;
98
99function TGMatrix.CreateIndex(X: TGMatrixIndexY; Y: TGMatrixIndexX): TIndex;
100begin
101 Result.X := X;
102 Result.Y := Y;
103end;
104
105function TGMatrix.GetCapacity: TIndex;
106begin
107 Result.Y := Length(FItems);
108 if Result.Y > 0 then Result.X := Length(FItems[0]) else Result.X := 0;
109end;
110
111procedure TGMatrix.SetCapacity(const AValue: TIndex);
112begin
113 if (Capacity.X <> AValue.X) and (Capacity.Y <> AValue.Y) then begin
114 SetLength(FItems, AValue.Y, AValue.X);
115 end;
116end;
117
118function TGMatrix.GetItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY): TGMatrixItem;
119begin
120 if (X < 0) or (X >= Count.X) or
121 (Y < 0) or (Y >= Count.Y) then
122 raise EListError.CreateFmt(SMatrixIndexError, [X, Y]);
123 Result := FItems[Y, X];
124end;
125
126function TGMatrix.GetItem(Index: TIndex): TGMatrixItem;
127begin
128 if (Index.X < 0) or (Index.X >= Count.X) or
129 (Index.Y < 0) or (Index.Y >= Count.Y) then
130 raise EListError.CreateFmt(SMatrixIndexError, [Index.X, Index.Y]);
131 Result := FItems[Index.Y, Index.X];
132end;
133
134procedure TGMatrix.PutItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY; const AValue: TGMatrixItem);
135begin
136 if (X < 0) or (X >= Count.X) or
137 (Y < 0) or (Y >= Count.Y) then
138 raise EListError.CreateFmt(SMatrixIndexError, [X, Y]);
139 FItems[Y, X] := AValue;
140end;
141
142procedure TGMatrix.PutItem(Index: TIndex; const AValue: TGMatrixItem);
143begin
144 if (Index.X < 0) or (Index.X >= Count.X) or
145 (Index.Y < 0) or (Index.Y >= Count.Y) then
146 raise EListError.CreateFmt(SMatrixIndexError, [Index.X, Index.Y]);
147 FItems[Index.Y, Index.X] := AValue;
148end;
149
150procedure TGMatrix.SetCount(const AValue: TIndex);
151begin
152 Capacity := AValue;
153 FCount := AValue;
154end;
155
156procedure TGMatrix.Assign(Source: TGMatrix);
157var
158 Index: TIndex;
159begin
160 Count := Source.Count;
161 Index.Y := 0;
162 while Index.Y < Count.Y do begin
163 Index.X := 0;
164 while Index.X < Count.X do begin
165 Items[Index] := Source.Items[Index];
166 Index.X := Index.X + 1;
167 end;
168 Index.Y := Index.Y + 1;
169 end;
170end;
171
172procedure TGMatrix.Expand;
173var
174 IncSize: TIndex;
175 NewCapacity: TIndex;
176begin
177 if (FCount.X = Capacity.X) then begin
178 IncSize.X := 4;
179 if Capacity.X > 3 then IncSize.X := IncSize.X + 4;
180 if Capacity.X > 8 then IncSize.X := IncSize.X + 8;
181 if Capacity.X > 63 then IncSize.X := IncSize.X + Capacity.X shr 2;
182 NewCapacity.X := Capacity.X + IncSize.X;
183 end;
184 if (FCount.Y = Capacity.Y) then begin
185 IncSize.Y := 4;
186 if Capacity.Y > 3 then IncSize.Y := IncSize.Y + 4;
187 if Capacity.Y > 8 then IncSize.Y := IncSize.Y + 8;
188 if Capacity.Y > 63 then IncSize.Y := IncSize.Y + Capacity.Y shr 2;
189 NewCapacity.Y := Capacity.Y + IncSize.Y;
190 end;
191 Capacity := NewCapacity;
192end;
193
194procedure TGMatrix.Contract;
195var
196 NewCapacity: TIndex;
197begin
198 if (Capacity.X > 256) and (FCount.X < Capacity.X shr 2) then
199 begin
200 NewCapacity.X := Capacity.X shr 1;
201 end;
202 if (Capacity.Y > 256) and (FCount.Y < Capacity.Y shr 2) then
203 begin
204 NewCapacity.Y := Capacity.Y shr 1;
205 end;
206 Capacity := NewCapacity;
207end;
208
209procedure TGMatrix.Reverse;
210var
211 X: TGMatrixIndexX;
212 Y: TGMatrixIndexY;
213begin
214 Y := 0;
215 while Y < (Count.Y - 1) do begin
216 X := 1 + Y;
217 while X < Count.X do begin
218 Exchange(CreateIndex(X, Y), CreateIndex(Y, X));
219 X := X + 1;
220 end;
221 Y := Y + 1;
222 end;
223end;
224
225procedure TGMatrix.ReverseHorizontal;
226var
227 X: TGMatrixIndexX;
228 Y: TGMatrixIndexY;
229begin
230 Y := 0;
231 while Y < Count.Y do begin
232 X := 0;
233 while X < (Count.X div 2) do begin
234 Exchange(CreateIndex(X, Y), CreateIndex(Count.X - 1 - X, Y));
235 X := X + 1;
236 end;
237 Y := Y + 1;
238 end;
239end;
240
241procedure TGMatrix.ReverseVertical;
242var
243 X: TGMatrixIndexX;
244 Y: TGMatrixIndexY;
245begin
246 X := 0;
247 while X < Count.X do begin
248 Y := 0;
249 while Y < (Count.Y div 2) do begin
250 Exchange(CreateIndex(X, Y), CreateIndex(X, Count.Y - 1 - Y));
251 Y := Y + 1;
252 end;
253 X := X + 1;
254 end;
255end;
256
257function TGMatrix.Implode(RowSeparator, ColSeparator: string; Converter: TToStringConverter): string;
258var
259 Y: TGMatrixIndexY;
260 X: TGMatrixIndexX;
261begin
262 Result := '';
263 Y := 0;
264 while Y < Count.Y do begin
265 X := 0;
266 while X < Count.X do begin
267 Result := Result + Converter(ItemsXY[X, Y]);
268 if X < (Count.X - 1) then
269 Result := Result + ColSeparator;
270 X := X + 1;
271 end;
272 if Y < (Count.Y - 1) then
273 Result := Result + RowSeparator;
274 Y := Y + 1;
275 end;
276end;
277
278procedure TGMatrix.Clear;
279begin
280 Count := CreateIndex(0, 0);
281 Capacity := CreateIndex(0, 0);
282end;
283
284procedure TGMatrix.Fill(Start, Count: TIndex; Value: TGMatrixItem);
285var
286 X: TGMatrixIndexX;
287 Y: TGMatrixIndexY;
288begin
289 Y := Start.Y;
290 while Y < Count.Y do begin
291 X := Start.X;
292 while X < Count.X do begin
293 ItemsXY[X, Y] := Value;
294 X := X + 1;
295 end;
296 Y := Y + 1;
297 end;
298end;
299
300procedure TGMatrix.FillAll(Value: TGMatrixItem);
301begin
302 Fill(CreateIndex(0, 0), CreateIndex(Count.X - 1, Count.Y - 1), Value);
303end;
304
305procedure TGMatrix.Exchange(Index1, Index2: TIndex);
306var
307 Temp: TGMatrixItem;
308begin
309 if (Index1.X < 0) or (Index1.X >= Count.X) or
310 (Index1.Y < 0) or (Index1.Y >= Count.Y) then
311 raise EListError.CreateFmt(SMatrixIndexError, [Index1.X, Index1.Y]);
312 if (Index2.X < 0) or (Index2.X >= Count.X) or
313 (Index2.Y < 0) or (Index2.Y >= Count.Y) then
314 raise EListError.CreateFmt(SMatrixIndexError, [Index2.X, Index2.Y]);
315 Temp := FItems[Index1.Y, Index1.X];
316 FItems[Index1.Y, Index1.X] := FItems[Index2.Y, Index2.X];
317 FItems[Index2.Y, Index2.X] := Temp;
318end;
319
320{$UNDEF IMPLEMENTATION}
321{$ENDIF}
Note: See TracBrowser for help on using the repository browser.