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

Last change on this file was 18, checked in by chronos, 12 years ago
  • Used external packages are now stored in uncompressed form rather in zipped files. This allow better package version synchronisation.
File size: 16.1 KB
Line 
1{$IFDEF INTERFACE}
2
3 TGMatrix = class;
4
5 TGMatrixSortCompare = function(const Item1, Item2: TGMatrixItem): Integer of object;
6 TGMatrixToStringConverter = function(Item: TGMatrixItem): string;
7 TGMatrixFromStringConverter = function(Text: string): TGMatrixItem;
8 TGMatrixRow = array of TGMatrixItem;
9 TGMatrixMerge = function(Item1, Item2: TGMatrixItem): TGMatrixItem of object;
10
11 TGMatrixIndex = record
12 X: TGMatrixIndexX;
13 Y: TGMatrixIndexY;
14 end;
15
16 // TGMatrix<TGMatrixIndex, TGMatrixIndex, TGMatrixItem> = class
17 TGMatrix = class
18 private
19 FItems: array of array of TGMatrixItem;
20 FCount: TGMatrixIndex;
21 function GetItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY): TGMatrixItem;
22 function GetItem(Index: TGMatrixIndex): TGMatrixItem;
23 function GetCapacity: TGMatrixIndex;
24 function GetLast: TGMatrixItem;
25 function GetFirst: TGMatrixItem;
26 procedure SetCapacity(const AValue: TGMatrixIndex);
27 procedure SetLast(AValue: TGMatrixItem);
28 procedure SetFirst(AValue: TGMatrixItem);
29 procedure PutItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY; const AValue: TGMatrixItem); virtual;
30 procedure PutItem(Index: TGMatrixIndex; const AValue: TGMatrixItem); virtual;
31 procedure SetCount(const AValue: TGMatrixIndex);
32 public
33 function Add(Item: TGMatrixItem): TGMatrixIndex;
34 procedure AddMatrix(Values: array of TGMatrixRow);
35 procedure AddList(List: TGMatrix);
36 procedure Assign(Source: TGMatrix);
37 procedure Clear; virtual;
38 procedure Contract;
39 function CreateIndex(X: TGMatrixIndexY; Y: TGMatrixIndexX): TGMatrixIndex;
40 procedure Delete(Index: TGMatrixIndex); virtual;
41 procedure DeleteItems(Index, Count: TGMatrixIndex);
42 function EqualTo(List: TGMatrix): Boolean;
43 procedure Expand;
44 function Extract(Item: TGMatrixItem): TGMatrixItem;
45 procedure Exchange(Index1, Index2: TGMatrixIndex);
46 property First: TGMatrixItem read GetFirst write SetFirst;
47 procedure FillAll(Value: TGMatrixItem);
48 procedure Fill(Start, Count: TGMatrixIndex; Value: TGMatrixItem);
49 function Implode(RowSeparator, ColSeparator: string; Converter: TGMatrixToStringConverter): string;
50 procedure Explode(Text, Separator: string; Converter: TGMatrixFromStringConverter; SlicesCount: Integer = -1);
51 function IndexOf(Item: TGMatrixItem; Start: TGMatrixIndex = 0): TGMatrixIndex;
52 function IndexOfList(List: TGMatrix; Start: TGMatrixIndex = 0): TGMatrixIndex;
53 procedure Insert(Index: TGMatrixIndex; Item: TGMatrixItem);
54 procedure InsertList(Index: TGMatrixIndex; List: TGMatrix);
55 procedure InsertArray(Index: TGMatrixIndex; Values: array of TGMatrixItem);
56 procedure Move(CurIndex, NewIndex: TGMatrixIndex);
57 procedure MoveItems(CurIndex, NewIndex, Count: TGMatrixIndex);
58 procedure Merge(Index: TGMatrixIndex; Source: TGMatrix; Proc: TGMatrixMerge);
59 procedure Replace(Index: TGMatrixIndex; Source: TGMatrix);
60 function Remove(Item: TGMatrixItem): TGMatrixIndex;
61 procedure Reverse;
62 procedure ReverseHorizontal;
63 procedure ReverseVertical;
64 procedure Sort(Compare: TGMatrixSortCompare);
65 procedure SetArray(Values: array of TGMatrixItem);
66 property Count: TGMatrixIndex read FCount write SetCount;
67 property Capacity: TGMatrixIndex read GetCapacity write SetCapacity;
68 property ItemsXY[X: TGMatrixIndexX; Y: TGMatrixIndexY]: TGMatrixItem
69 read GetItemXY write PutItemXY; default;
70 property Items[Index: TGMatrixIndex]: TGMatrixItem
71 read GetItem write PutItem;
72 property Last: TGMatrixItem read GetLast write SetLast;
73 end;
74
75{$UNDEF INTERFACE}
76{$ENDIF}
77
78{$IFDEF IMPLEMENTATION_USES}
79
80uses
81 RtlConsts;
82
83resourcestring
84 SMatrixIndexError = 'Matrix index error [X: %d, Y: %d]';
85
86{$UNDEF IMPLEMENTATION_USES}
87{$ENDIF}
88
89{$IFDEF IMPLEMENTATION}
90
91{ TGMatrix }
92
93procedure TGMatrix.Replace(Index: TGMatrixIndex; Source: TGMatrix);
94var
95 X: TGMatrixIndexX;
96 Y: TGMatrixIndexY;
97begin
98 Y := 0;
99 while Y < Source.Count.Y do begin
100 X := 0;
101 while X < Source.Count.X do begin
102 ItemsXY[Index.X + X, Index.Y + Y] := Source.ItemsXY[X, Y];
103 X := X + 1;
104 end;
105 Y := Y + 1;
106 end;
107end;
108
109procedure TGMatrix.Merge(Index: TGMatrixIndex; Source: TGMatrix; Proc: TGMatrixMerge);
110var
111 X: TGMatrixIndexX;
112 Y: TGMatrixIndexY;
113begin
114 Y := 0;
115 while Y < Source.Count.Y do begin
116 X := 0;
117 while X < Source.Count.X do begin
118 ItemsXY[Index.X + X, Index.Y + Y] := Proc(ItemsXY[Index.X + X, Index.Y + Y], Source.ItemsXY[X, Y]);
119 X := X + 1;
120 end;
121 Y := Y + 1;
122 end;
123end;
124
125function TGMatrix.CreateIndex(X: TGMatrixIndexY; Y: TGMatrixIndexX): TGMatrixIndex;
126begin
127 Result.X := X;
128 Result.Y := Y;
129end;
130
131function TGMatrix.GetCapacity: TGMatrixIndex;
132begin
133 Result.Y := Length(FItems);
134 if Result.Y > 0 then Result.X := Length(FItems[0]) else Result.X := 0;
135end;
136
137procedure TGMatrix.SetCapacity(const AValue: TGMatrixIndex);
138var
139 Y: TGMatrixIndexY;
140begin
141 if (Capacity.X <> AValue.X) and (Capacity.Y <> AValue.Y) then begin
142(* SetLength(FItems, AValue.Y);
143 Y := 0;
144 while Y < Length(FItems) do begin
145 SetLength(FItems[Y], AValue.X);
146 Y := Y + 1;
147 end;
148 end;
149 *)
150 SetLength(FItems, AValue.Y, AValue.X);
151 end;
152end;
153
154function TGMatrix.GetItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY): TGMatrixItem;
155begin
156 if (X < 0) or (X >= Count.X) or
157 (Y < 0) or (Y >= Count.Y) then
158 raise EListError.CreateFmt(SMatrixIndexError, [X, Y]);
159 Result := FItems[Y, X];
160end;
161
162function TGMatrix.GetItem(Index: TGMatrixIndex): TGMatrixItem;
163begin
164 if (Index.X < 0) or (Index.X >= Count.X) or
165 (Index.Y < 0) or (Index.Y >= Count.Y) then
166 raise EListError.CreateFmt(SMatrixIndexError, [Index.X, Index.Y]);
167 Result := FItems[Index.Y, Index.X];
168end;
169
170procedure TGMatrix.PutItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY; const AValue: TGMatrixItem);
171begin
172 if (X < 0) or (X >= Count.X) or
173 (Y < 0) or (Y >= Count.Y) then
174 raise EListError.CreateFmt(SMatrixIndexError, [X, Y]);
175 FItems[Y, X] := AValue;
176end;
177
178procedure TGMatrix.PutItem(Index: TGMatrixIndex; const AValue: TGMatrixItem);
179begin
180 if (Index.X < 0) or (Index.X >= Count.X) or
181 (Index.Y < 0) or (Index.Y >= Count.Y) then
182 raise EListError.CreateFmt(SMatrixIndexError, [Index.X, Index.Y]);
183 FItems[Index.Y, Index.X] := AValue;
184end;
185
186procedure TGMatrix.SetCount(const AValue: TGMatrixIndex);
187begin
188 Capacity := AValue;
189 FCount := AValue;
190end;
191
192procedure TGMatrix.Assign(Source: TGMatrix);
193var
194 Index: TGMatrixIndex;
195begin
196 Count := Source.Count;
197 Index.Y := 0;
198 while Index.Y < Count.Y do begin
199 Index.X := 0;
200 while Index.X < Count.X do begin
201 Items[Index] := Source.Items[Index];
202 Index.X := Index.X + 1;
203 end;
204 Index.Y := Index.Y + 1;
205 end;
206end;
207
208procedure TGMatrix.Expand;
209var
210 IncSize: TGMatrixIndex;
211 NewCapacity: TGMatrixIndex;
212begin
213 if (FCount.X = Capacity.X) then begin
214 IncSize.X := 4;
215 if Capacity.X > 3 then IncSize.X := IncSize.X + 4;
216 if Capacity.X > 8 then IncSize.X := IncSize.X + 8;
217 if Capacity.X > 63 then IncSize.X := IncSize.X + Capacity.X shr 2;
218 NewCapacity.X := Capacity.X + IncSize.X;
219 end;
220 if (FCount.Y = Capacity.Y) then begin
221 IncSize.Y := 4;
222 if Capacity.Y > 3 then IncSize.Y := IncSize.Y + 4;
223 if Capacity.Y > 8 then IncSize.Y := IncSize.Y + 8;
224 if Capacity.Y > 63 then IncSize.Y := IncSize.Y + Capacity.Y shr 2;
225 NewCapacity.Y := Capacity.Y + IncSize.Y;
226 end;
227 Capacity := NewCapacity;
228end;
229
230procedure TGMatrix.Contract;
231var
232 NewCapacity: TGMatrixIndex;
233begin
234 if (Capacity.X > 256) and (FCount.X < Capacity.X shr 2) then
235 begin
236 NewCapacity.X := Capacity.X shr 1;
237 end;
238 if (Capacity.Y > 256) and (FCount.Y < Capacity.Y shr 2) then
239 begin
240 NewCapacity.Y := Capacity.Y shr 1;
241 end;
242 Capacity := NewCapacity;
243end;
244
245function TGMatrix.Extract(Item: TGMatrixItem): TGMatrixItem;
246var
247 I: TGMatrixIndex;
248begin
249(* I := IndexOf(Item);
250 if I >= 0 then begin
251 Result := Item;
252 Delete(I);
253 end else
254 raise EListError.CreateFmt(SListIndexError, [0]);
255 *)
256end;
257
258function TGMatrix.IndexOf(Item: TGMatrixItem; Start: TGMatrixIndex): TGMatrixIndex;
259begin
260(* Result := Start;
261 while (Result < FCount) and
262 not CompareMem(Addr(FItems[Result]), Addr(Item), SizeOf(TGMatrixItem)) do
263 Result := Result + 1;
264 if Result = FCount then Result := -1;
265 *)
266end;
267
268procedure TGMatrix.Insert(Index: TGMatrixIndex; Item: TGMatrixItem);
269begin
270(* if (Index < 0) or (Index > FCount ) then
271 raise EListError.CreateFmt(SListIndexError, [Index]);
272 if FCount = Capacity then Expand;
273 if Index < FCount then
274 System.Move(FItems[Index], FItems[Index + 1], (FCount - Index) * SizeOf(TGMatrixItem));
275 FItems[Index] := Item;
276 FCount := FCount + 1;
277 *)
278end;
279
280procedure TGMatrix.InsertList(Index: TGMatrixIndex; List: TGMatrix);
281var
282 I: TGMatrixIndex;
283begin
284(* I := 0;
285 while (I < List.Count) do begin
286 Insert(Index + I, List[I]);
287 I := I + 1;
288 end;
289 *)
290end;
291
292function TGMatrix.IndexOfList(List: TGMatrix; Start: TGMatrixIndex): TGMatrixIndex;
293var
294 I: TGMatrixIndex;
295begin
296(* if List.Count > 0 then begin
297 Result := IndexOf(List[0], Start);
298 if Result <> -1 then begin
299 I := 1;
300 while I < List.Count do begin
301 if not CompareMem(Addr(FItems[Result + I]), Addr(List.FItems[I]), SizeOf(TGMatrixItem)) then begin
302 Result := -1;
303 Break;
304 end;
305 I := I + 1;
306 end;
307 end;
308 end else Result := -1;
309 *)
310end;
311
312function TGMatrix.GetLast: TGMatrixItem;
313begin
314(* if FCount = 0 then
315 raise EListError.CreateFmt(SListIndexError, [0])
316 else
317 Result := Items[FCount - 1];
318 *)
319end;
320
321procedure TGMatrix.SetLast(AValue: TGMatrixItem);
322begin
323(* if FCount = 0 then
324 raise EListError.CreateFmt(SListIndexError, [0])
325 else
326 Items[FCount - 1] := AValue;
327 *)
328end;
329
330function TGMatrix.GetFirst: TGMatrixItem;
331begin
332(* if FCount = 0 then
333 raise EListError.CreateFmt(SListIndexError, [0])
334 else
335 Result := Items[0];
336 *)
337end;
338
339procedure TGMatrix.SetFirst(AValue: TGMatrixItem);
340begin
341(* if FCount = 0 then
342 raise EListError.CreateFmt(SListIndexError, [0])
343 else
344 Items[0] := AValue;
345 *)
346end;
347
348procedure TGMatrix.Move(CurIndex, NewIndex: TGMatrixIndex);
349var
350 Temp: TGMatrixItem;
351begin
352(* if ((CurIndex < 0) or (CurIndex > Count - 1)) then
353 raise EListError.CreateFmt(SListIndexError, [CurIndex]);
354 if ((NewIndex < 0) or (NewIndex > Count -1)) then
355 raise EListError.CreateFmt(SlistIndexError, [NewIndex]);
356 Temp := FItems[CurIndex];
357 if NewIndex > CurIndex then begin
358 System.Move(FItems[CurIndex + 1], FItems[CurIndex], (NewIndex - CurIndex) * SizeOf(TGMatrixItem));
359 end else
360 if NewIndex < CurIndex then begin
361 System.Move(FItems[NewIndex], FItems[NewIndex + 1], (CurIndex - NewIndex) * SizeOf(TGMatrixItem));
362 end;
363 FItems[NewIndex] := Temp;
364 //Delete(CurIndex);
365 //Insert(NewIndex, Temp);*)
366end;
367
368procedure TGMatrix.MoveItems(CurIndex, NewIndex, Count: TGMatrixIndex);
369var
370 S: Integer;
371 D: Integer;
372begin
373(* if CurIndex < NewIndex then begin
374 S := CurIndex + Count - 1;
375 D := NewIndex + Count - 1;
376 while S >= CurIndex do begin
377 Move(S, D);
378 S := S - 1;
379 D := D - 1;
380 end;
381 end else
382 if CurIndex > NewIndex then begin
383 S := CurIndex;
384 D := NewIndex;
385 while S < (CurIndex + Count) do begin
386 Move(S, D);
387 S := S + 1;
388 D := D + 1;
389 end;
390 end;*)
391end;
392
393function TGMatrix.Remove(Item: TGMatrixItem): TGMatrixIndex;
394begin
395(* Result := IndexOf(Item);
396 if Result <> -1 then
397 Delete(Result); *)
398end;
399
400function TGMatrix.EqualTo(List: TGMatrix): Boolean;
401var
402 I: TGMatrixIndex;
403begin
404(* Result := Count = List.Count;
405 if Result then begin
406 I := 0;
407 while I < Count do begin
408 if not CompareMem(Addr(FItems[I]), Addr(List.FItems[I]), SizeOf(TGMatrixItem)) then begin
409 Result := False;
410 Break;
411 end;
412 I := I + 1;
413 end;
414 end; *)
415end;
416
417procedure TGMatrix.Reverse;
418var
419 X: TGMatrixIndexX;
420 Y: TGMatrixIndexY;
421begin
422 Y := 0;
423 while Y < (Count.Y - 1) do begin
424 X := 1 + Y;
425 while X < Count.X do begin
426 Exchange(CreateIndex(X, Y), CreateIndex(Y, X));
427 X := X + 1;
428 end;
429 Y := Y + 1;
430 end;
431end;
432
433procedure TGMatrix.ReverseHorizontal;
434var
435 X: TGMatrixIndexX;
436 Y: TGMatrixIndexY;
437begin
438 Y := 0;
439 while Y < Count.Y do begin
440 X := 0;
441 while X < (Count.X div 2) do begin
442 Exchange(CreateIndex(X, Y), CreateIndex(Count.X - 1 - X, Y));
443 X := X + 1;
444 end;
445 Y := Y + 1;
446 end;
447end;
448
449procedure TGMatrix.ReverseVertical;
450var
451 X: TGMatrixIndexX;
452 Y: TGMatrixIndexY;
453begin
454 X := 0;
455 while X < Count.X do begin
456 Y := 0;
457 while Y < (Count.Y div 2) do begin
458 Exchange(CreateIndex(X, Y), CreateIndex(X, Count.Y - 1 - Y));
459 Y := Y + 1;
460 end;
461 X := X + 1;
462 end;
463end;
464
465procedure TGMatrix.Sort(Compare: TGMatrixSortCompare);
466begin
467(* if FCount > 1 then
468 QuickSort(0, FCount - 1, Compare); *)
469end;
470
471procedure TGMatrix.AddMatrix(Values: array of TGMatrixRow);
472var
473 I: TGMatrixIndex;
474begin
475(* I := 0;
476 while I <= High(Values) do begin
477 Add(Values[I]);
478 I := I + 1;
479 end; *)
480end;
481
482procedure TGMatrix.SetArray(Values: array of TGMatrixItem);
483var
484 I: TGMatrixIndex;
485begin
486(* Clear;
487 I := 0;
488 while I <= High(Values) do begin
489 Add(Values[I]);
490 I := I + 1;
491 end; *)
492end;
493
494procedure TGMatrix.InsertArray(Index: TGMatrixIndex; Values: array of TGMatrixItem);
495var
496 I: TGMatrixIndex;
497begin
498(* I := 0;
499 while I <= High(Values) do begin
500 Insert(Index + I, Values[I]);
501 I := I + 1;
502 end; *)
503end;
504
505function TGMatrix.Implode(RowSeparator, ColSeparator: string; Converter: TGMatrixToStringConverter): string;
506var
507 Y: TGMatrixIndexY;
508 X: TGMatrixIndexX;
509begin
510 Result := '';
511 Y := 0;
512 while Y < Count.Y do begin
513 X := 0;
514 while X < Count.X do begin
515 Result := Result + Converter(ItemsXY[X, Y]);
516 if X < (Count.X - 1) then
517 Result := Result + ColSeparator;
518 X := X + 1;
519 end;
520 if Y < (Count.Y - 1) then
521 Result := Result + RowSeparator;
522 Y := Y + 1;
523 end;
524end;
525
526procedure TGMatrix.Explode(Text, Separator: string; Converter: TGMatrixFromStringConverter; SlicesCount: Integer = -1);
527begin
528(* Clear;
529 while (Pos(Separator, Text) > 0) and
530 ((Count < (SlicesCount - 1)) or (SlicesCount = -1)) do begin
531 Add(Converter(Copy(Text, 1, Pos(Separator, Text) - 1)));
532 System.Delete(Text, 1, Pos(Separator, Text) + Length(Separator) - 1);
533 end;
534 Add(Converter(Text)); *)
535end;
536
537function TGMatrix.Add(Item: TGMatrixItem): TGMatrixIndex;
538begin
539(* if FCount = Capacity then
540 Self.Expand;
541 FItems[FCount] := Item;
542 Result := FCount;
543 FCount := FCount + 1; *)
544end;
545
546procedure TGMatrix.AddList(List: TGMatrix);
547var
548 I: TGMatrixIndex;
549begin
550(* I := 0;
551 while I < List.Count do begin
552 Add(List[I]);
553 I := I + 1;
554 end; *)
555end;
556
557procedure TGMatrix.Clear;
558begin
559 Count := CreateIndex(0, 0);
560 Capacity := CreateIndex(0, 0);
561end;
562
563procedure TGMatrix.Delete(Index: TGMatrixIndex);
564begin
565(* if (Index < 0) or (Index >= FCount) then
566 raise EListError.CreateFmt(SListIndexError, [Index]);
567 FCount := FCount - 1;
568 System.Move(FItems[Index + 1], FItems[Index], (FCount - Index) * SizeOf(TGMatrixItem));
569 Contract;
570 *)
571end;
572
573procedure TGMatrix.DeleteItems(Index, Count: TGMatrixIndex);
574var
575 I: TGMatrixIndex;
576begin
577(* I := Index;
578 while I < (Index + Count) do begin
579 Delete(Index);
580 I := I + 1;
581 end;
582 *)
583end;
584
585procedure TGMatrix.Fill(Start, Count: TGMatrixIndex; Value: TGMatrixItem);
586var
587 X: TGMatrixIndexX;
588 Y: TGMatrixIndexY;
589begin
590 Y := Start.Y;
591 while Y < Count.Y do begin
592 X := Start.X;
593 while X < Count.X do begin
594 ItemsXY[X, Y] := Value;
595 X := X + 1;
596 end;
597 Y := Y + 1;
598 end;
599end;
600
601procedure TGMatrix.FillAll(Value: TGMatrixItem);
602begin
603 Fill(CreateIndex(0, 0), CreateIndex(Count.X - 1, Count.Y - 1), Value);
604end;
605
606procedure TGMatrix.Exchange(Index1, Index2: TGMatrixIndex);
607var
608 Temp: TGMatrixItem;
609begin
610 if (Index1.X < 0) or (Index1.X >= Count.X) or
611 (Index1.Y < 0) or (Index1.Y >= Count.Y) then
612 raise EListError.CreateFmt(SMatrixIndexError, [Index1.X, Index1.Y]);
613 if (Index2.X < 0) or (Index2.X >= Count.X) or
614 (Index2.Y < 0) or (Index2.Y >= Count.Y) then
615 raise EListError.CreateFmt(SMatrixIndexError, [Index2.X, Index2.Y]);
616 Temp := FItems[Index1.Y, Index1.X];
617 FItems[Index1.Y, Index1.X] := FItems[Index2.Y, Index2.X];
618 FItems[Index2.Y, Index2.X] := Temp;
619end;
620
621{$UNDEF IMPLEMENTATION}
622{$ENDIF}
Note: See TracBrowser for help on using the repository browser.