diff --git a/Source/algorithms/simba.algo_difference.pas b/Source/algorithms/simba.algo_difference.pas index 68d28034a..aea2b0945 100644 --- a/Source/algorithms/simba.algo_difference.pas +++ b/Source/algorithms/simba.algo_difference.pas @@ -5,6 +5,7 @@ } unit simba.algo_difference; +{$DEFINE SIMBA_MAX_OPTIMIZATION} {$i simba.inc} interface diff --git a/Source/algorithms/simba.algo_intersection.pas b/Source/algorithms/simba.algo_intersection.pas index f9e26b544..99372df07 100644 --- a/Source/algorithms/simba.algo_intersection.pas +++ b/Source/algorithms/simba.algo_intersection.pas @@ -5,6 +5,7 @@ } unit simba.algo_intersection; +{$DEFINE SIMBA_MAX_OPTIMIZATION} {$i simba.inc} interface diff --git a/Source/algorithms/simba.algo_sort.pas b/Source/algorithms/simba.algo_sort.pas index 77b17b153..46b126a68 100644 --- a/Source/algorithms/simba.algo_sort.pas +++ b/Source/algorithms/simba.algo_sort.pas @@ -3,14 +3,12 @@ Project: Simba (https://github.com/MerlijnWajer/Simba) License: GNU General Public License (https://www.gnu.org/licenses/gpl-3.0) } + unit simba.algo_sort; +{$DEFINE SIMBA_MAX_OPTIMIZATION} {$i simba.inc} -{$IFOPT D-} - {$OPTIMIZATION LEVEL4} -{$ENDIF} - interface uses @@ -25,13 +23,11 @@ interface generic procedure QuickSort<_T>(var AValues: array of _T; ALeft, ARight: SizeInt); generic procedure QuickSortWeighted<_T, _W>(var Arr: array of _T; var Weights: array of _W; iLo, iHi: SizeInt; SortUp: Boolean); -generic procedure Sort<_T>(var Arr: array of _T); -generic procedure Sort<_T>(var Arr: array of _T; Weights: TIntegerArray; SortUp: Boolean); overload; -generic procedure Sort<_T>(var Arr: array of _T; Weights: TDoubleArray; SortUp: Boolean); overload; +generic procedure Sort<_T>(var Arr: specialize TArray<_T>); overload; +generic procedure Sort<_T, _W>(var Arr: specialize TArray<_T>; Weights: specialize TArray<_W>; SortUp: Boolean); overload; generic function Sorted<_T>(const Arr: specialize TArray<_T>): specialize TArray<_T>; overload; -generic function Sorted<_T>(const Arr: specialize TArray<_T>; Weights: TIntegerArray; SortUp: Boolean): specialize TArray<_T>; overload; -generic function Sorted<_T>(const Arr: specialize TArray<_T>; Weights: TDoubleArray; SortUp: Boolean): specialize TArray<_T>; overload; +generic function Sorted<_T, _W>(const Arr: specialize TArray<_T>; Weights: specialize TArray<_W>; SortUp: Boolean): specialize TArray<_T>; overload; implementation @@ -185,23 +181,16 @@ implementation until iLo >= iHi; end; -generic procedure Sort<_T>(var Arr: array of _T); +generic procedure Sort<_T>(var Arr: specialize TArray<_T>); begin specialize QuickSort<_T>(Arr, Low(Arr), High(Arr)); end; -generic procedure Sort<_T>(var Arr: array of _T; Weights: TIntegerArray; SortUp: Boolean); -begin - Weights := Copy(Weights); - - specialize QuickSortWeighted<_T, Integer>(Arr, Weights, Low(Arr), High(Arr), SortUp); -end; - -generic procedure Sort<_T>(var Arr: array of _T; Weights: TDoubleArray; SortUp: Boolean); +generic procedure Sort<_T, _W>(var Arr: specialize TArray<_T>; Weights: specialize TArray<_W>; SortUp: Boolean); begin Weights := Copy(Weights); - specialize QuickSortWeighted<_T, Double>(Arr, Weights, Low(Arr), High(Arr), SortUp); + specialize QuickSortWeighted<_T, _W>(Arr, Weights, Low(Arr), High(Arr), SortUp); end; generic function Sorted<_T>(const Arr: specialize TArray<_T>): specialize TArray<_T>; @@ -211,20 +200,12 @@ implementation specialize QuickSort<_T>(Result, Low(Result), High(Result)); end; -generic function Sorted<_T>(const Arr: specialize TArray<_T>; Weights: TIntegerArray; SortUp: Boolean): specialize TArray<_T>; -begin - Weights := Copy(Weights); - Result := Copy(Arr); - - specialize QuickSortWeighted<_T, Integer>(Result, Weights, Low(Result), High(Result), SortUp); -end; - -generic function Sorted<_T>(const Arr: specialize TArray<_T>; Weights: TDoubleArray; SortUp: Boolean): specialize TArray<_T>; +generic function Sorted<_T, _W>(const Arr: specialize TArray<_T>; Weights: specialize TArray<_W>; SortUp: Boolean): specialize TArray<_T>; begin Weights := Copy(Weights); Result := Copy(Arr); - specialize QuickSortWeighted<_T, Double>(Result, Weights, Low(Result), High(Result), SortUp); + specialize QuickSortWeighted<_T, _W>(Result, Weights, Low(Result), High(Result), SortUp); end; end. diff --git a/Source/algorithms/simba.algo_symmetricDifference.pas b/Source/algorithms/simba.algo_symmetricDifference.pas index 97c9b8295..ebe45d480 100644 --- a/Source/algorithms/simba.algo_symmetricDifference.pas +++ b/Source/algorithms/simba.algo_symmetricDifference.pas @@ -5,6 +5,7 @@ } unit simba.algo_symmetricDifference; +{$DEFINE SIMBA_MAX_OPTIMIZATION} {$i simba.inc} interface diff --git a/Source/algorithms/simba.algo_unique.pas b/Source/algorithms/simba.algo_unique.pas index 8372f2189..6f85fbe08 100644 --- a/Source/algorithms/simba.algo_unique.pas +++ b/Source/algorithms/simba.algo_unique.pas @@ -5,6 +5,7 @@ } unit simba.algo_unique; +{$DEFINE SIMBA_MAX_OPTIMIZATION} {$i simba.inc} interface diff --git a/Source/boxarray.inc b/Source/boxarray.inc index 0ed497abe..45e9f626f 100644 --- a/Source/boxarray.inc +++ b/Source/boxarray.inc @@ -299,12 +299,12 @@ end; function TBoxArrayHelper.Sort(Weights: TIntegerArray; LowToHigh: Boolean): TBoxArray; begin - Result := specialize Sorted(Self, Weights, LowToHigh); + Result := specialize Sorted(Self, Weights, LowToHigh); end; function TBoxArrayHelper.Sort(Weights: TDoubleArray; LowToHigh: Boolean): TBoxArray; begin - Result := specialize Sorted(Self, Weights, LowToHigh); + Result := specialize Sorted(Self, Weights, LowToHigh); end; {$ENDIF} diff --git a/Source/forms/simba.backupsform.lfm b/Source/forms/simba.backupsform.lfm index 10464ae9f..bb85a4478 100644 --- a/Source/forms/simba.backupsform.lfm +++ b/Source/forms/simba.backupsform.lfm @@ -3,7 +3,7 @@ object SimbaBackupsForm: TSimbaBackupsForm Height = 450 Top = 543 Width = 739 - Caption = 'SimbaBackupsForm' + Caption = 'Backups' ClientHeight = 450 ClientWidth = 739 DesignTimePPI = 120 diff --git a/Source/script/imports/simba/simba.import_matrix.pas b/Source/script/imports/simba/simba.import_matrix.pas index 43beffb3f..0b5dc175e 100644 --- a/Source/script/imports/simba/simba.import_matrix.pas +++ b/Source/script/imports/simba/simba.import_matrix.pas @@ -265,6 +265,16 @@ procedure _LapeSingleMatrix_Copy2(const Params: PParamArray; const Result: Point PSingleMatrix(Result)^ := PSingleMatrix(Params^[0])^.Copy(PInteger(Params^[1])^, PInteger(Params^[2])^); end; +procedure _LapeSingleMatrix_Rot90(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +begin + PSingleMatrix(Result)^ := PSingleMatrix(Params^[0])^.Rot90(); +end; + +procedure _LapeSingleMatrix_ArgExtrema(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +begin + PPointArray(Result)^ := PSingleMatrix(Params^[0])^.ArgExtrema(PInteger(Params^[1])^, PBoolean(Params^[2])^); +end; + // Double procedure _LapeDoubleMatrix_Width(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV begin @@ -330,6 +340,8 @@ procedure ImportMatrix(Compiler: TSimbaScript_Compiler); addGlobalFunc('function TSingleMatrix.Equals(Other: TSingleMatrix; Epsilon: Single = 0): Boolean;', @_LapeSingleMatrix_Equals); addGlobalFunc('function TSingleMatrix.Copy: TSingleMatrix; overload', @_LapeSingleMatrix_Copy1); addGlobalFunc('function TSingleMatrix.Copy(Y1, Y2: Integer): TSingleMatrix; overload', @_LapeSingleMatrix_Copy2); + addGlobalFunc('function TSingleMatrix.Rot90: TSingleMatrix;', @_LapeSingleMatrix_Rot90); + addGlobalFunc('function TSingleMatrix.ArgExtrema(Count: Int32; HiLo: Boolean = True): TPointArray;', @_LapeSingleMatrix_ArgExtrema); // integer addGlobalFunc('function TIntegerMatrix.Width: Integer;', @_LapeIntegerMatrix_Width); diff --git a/Source/simba.atpa.pas b/Source/simba.atpa.pas index 7e33bf3cd..767863a20 100644 --- a/Source/simba.atpa.pas +++ b/Source/simba.atpa.pas @@ -77,7 +77,7 @@ function T2DPointArrayHelper.Sort(Weights: TIntegerArray; LowToHigh: Boolean): T for I := 0 to High(Result) do Result[I] := Copy(Self[I]); - specialize Sort(Result, Weights, LowToHigh); + specialize Sort(Result, Weights, LowToHigh); end; function T2DPointArrayHelper.Sort(Weights: TDoubleArray; LowToHigh: Boolean): T2DPointArray; @@ -88,7 +88,7 @@ function T2DPointArrayHelper.Sort(Weights: TDoubleArray; LowToHigh: Boolean): T2 for I := 0 to High(Result) do Result[I] := Copy(Self[I]); - specialize Sort(Result, Weights, LowToHigh); + specialize Sort(Result, Weights, LowToHigh); end; function T2DPointArrayHelper.SortFromSize(Size: Integer): T2DPointArray; @@ -131,7 +131,7 @@ function T2DPointArrayHelper.SortFromFirstPoint(From: TPoint): T2DPointArray; for I := 0 to High(Self) do Weights[I] := Sqr(From.X - Self[I][0].X) + Sqr(From.Y - Self[I][0].Y); - specialize Sort(Result, Weights, True); + specialize Sort(Result, Weights, True); end; function T2DPointArrayHelper.SortFromFirstPointX(From: TPoint): T2DPointArray; @@ -145,7 +145,7 @@ function T2DPointArrayHelper.SortFromFirstPointX(From: TPoint): T2DPointArray; for I := 0 to High(Self) do Weights[I] := Sqr(From.X - Self[I][0].X); - specialize Sort(Result, Weights, True); + specialize Sort(Result, Weights, True); end; function T2DPointArrayHelper.SortFromFirstPointY(From: TPoint): T2DPointArray; @@ -159,7 +159,7 @@ function T2DPointArrayHelper.SortFromFirstPointY(From: TPoint): T2DPointArray; for I := 0 to High(Self) do Weights[I] := Sqr(From.Y - Self[I][0].Y); - specialize Sort(Result, Weights, True); + specialize Sort(Result, Weights, True); end; function T2DPointArrayHelper.SortFrom(From: TPoint): T2DPointArray; diff --git a/Source/simba.overallocatearray.pas b/Source/simba.overallocatearray.pas index 4931b97c1..9c3638c7f 100644 --- a/Source/simba.overallocatearray.pas +++ b/Source/simba.overallocatearray.pas @@ -65,8 +65,12 @@ procedure TSimbaOverAllocateArray.EnsureGrowth(const Len: Integer); begin FLength := FLength + Len; if (FLength < 32) then - FLength := 32; - FLength := FLength * 2; + FLength := 32 + else + if (FLength > 256000) then + FLength := FLength * 4 + else + FLength := FLength * 2; SetLength(FArr, FLength); end; diff --git a/Source/simba.singlematrix.pas b/Source/simba.singlematrix.pas index de03f7d41..c0a0ba9f1 100644 --- a/Source/simba.singlematrix.pas +++ b/Source/simba.singlematrix.pas @@ -1,3 +1,17 @@ +{ + Author: Raymond van Venetiƫ and Merlijn Wajer + Project: Simba (https://github.com/MerlijnWajer/Simba) + License: GNU General Public License (https://www.gnu.org/licenses/gpl-3.0) +} + +{ + Jarl Holta - https://github.com/slackydev + + - ArgMulti + - ArgExtrema + +} + unit simba.singlematrix; {$DEFINE SIMBA_MAX_OPTIMIZATION} @@ -10,6 +24,26 @@ interface simba.mufasatypes; type + TSingleSum = record + Value: Double; + + class operator :=(const Right: Single): TSingleSum; + + class operator +(const Left: TSingleSum; const Right: Single): TSingleSum; + class operator -(const Left: TSingleSum; const Right: Single): TSingleSum; + + class operator +(const Left, Right: TSingleSum): TSingleSum; + class operator -(const Left, Right: TSingleSum): TSingleSum; + end; + TSingleSumTable = array of array of TSingleSum; + + TSingleSumTableHelper = type helper for TSingleSumTable + public + class function Create(Mat: TSingleMatrix): TSingleSumTable; static; + + function Query(Area: TBox): TSingleSum; + end; + TSingleMatrixHelper = type Helper(TSingleMatrixBaseHelper) for TSingleMatrix public function GetSizeMinusOne(out AWidth, AHeight: Integer): Boolean; @@ -37,13 +71,73 @@ interface function Sum: Double; function Equals(Other: TSingleMatrix; Epsilon: Single = 0): Boolean; procedure ReplaceNaNAndInf(const ReplaceWith: Single); + function Rot90: TSingleMatrix; + function ArgExtrema(Count: Int32; HiLo: Boolean = True): TPointArray; end; implementation uses Math, - simba.math, simba.overallocatearray, simba.heaparray; + simba.math, simba.overallocatearray, simba.heaparray, simba.tpa; + +class operator TSingleSum.:=(const Right: Single): TSingleSum; +begin + Result.Value := Right; +end; + +class operator TSingleSum.+(const Left: TSingleSum; const Right: Single): TSingleSum; +begin + Result.Value := Left.Value + Right; +end; + +class operator TSingleSum.-(const Left: TSingleSum; const Right: Single): TSingleSum; +begin + Result.Value := Left.Value - Right; +end; + +class operator TSingleSum.+(const Left, Right: TSingleSum): TSingleSum; +begin + Result.Value := Left.Value + Right.Value; +end; + +class operator TSingleSum.-(const Left, Right: TSingleSum): TSingleSum; +begin + Result.Value := Left.Value - Right.Value; +end; + +class function TSingleSumTableHelper.Create(Mat: TSingleMatrix): TSingleSumTable; +var + W, H, X, Y: Integer; +begin + SetLength(Result, Mat.Height, Mat.Width); + + W := Mat.Width - 1; + H := Mat.Height - 1; + + for Y := 0 to H do + Result[Y, 0] := Mat[Y,0]; + + for Y := 1 to H do + for X := 0 to W do + Result[Y, X] := Mat[Y,X] + Result[Y-1, X]; + + for Y := 0 to H do + for X := 1 to W do + Result[Y, X] += Result[Y, X-1]; +end; + +function TSingleSumTableHelper.Query(Area: TBox): TSingleSum; +begin + Result := Self[Area.Y2, Area.X2]; + + if (Area.Y1 > 0) then + Result.Value := Result.Value - Self[Area.Y1 - 1, Area.X2].Value; + if (Area.X1 > 0) then + Result.Value := Result.Value - Self[Area.Y2, Area.X1 - 1].Value; + if (Area.Y1 > 0) and (Area.X1 > 0) then + Result.Value := Result.Value + Self[Area.Y1 - 1, Area.X1 - 1].Value; +end; function TSingleMatrixHelper.GetSizeMinusOne(out AWidth, AHeight: Integer): Boolean; begin @@ -392,6 +486,38 @@ function TSingleMatrixHelper.ArgMulti(Count: Integer; HiLo: Boolean): TPointArra end; end; +{ +procedure TSingleMatrixHelper.Smoothen(Block: Integer); +var + X, Y, W, H: Integer; + Size: Integer; + B: TBox; + SumTable: TSingleSumTable; +begin + Size := Sqr(Block); + if (Size <= 1) or (Block mod 2 = 0) then + Exit; + + Block := Block div 2; + SumTable := TSingleSumTable.Create(Self); + + Self.GetSizeMinusOne(W,H); + + for Y := 0 to H do + for X := 0 to W do + begin + B.X1 := Math.Max(X-Block, 0); + B.Y1 := Math.Max(Y-Block, 0); + B.X2 := Math.Min(X+Block, W); + B.Y2 := Math.Min(Y+Block, H); + + Size := B.Area; + with SumTable.Query(B) do + Self[Y,X] := Value / Size; + end; +end; +} + procedure TSingleMatrixHelper.Smoothen(Block: Integer); var W, H, X, Y, Radius, fx, fy, Count: Integer; @@ -479,5 +605,83 @@ procedure TSingleMatrixHelper.ReplaceNaNAndInf(const ReplaceWith: Single); Self[Y,X] := ReplaceWith; end; +function TSingleMatrixHelper.Rot90: TSingleMatrix; +var + W, H, X, Y: Integer; +begin + SetLength(Result, Self.Width, Self.Height); + + if Self.GetSizeMinusOne(W, H) then + for Y := 0 to H do + for X := 0 to W do + Result[X, Y] := Self[Y, X]; +end; + +function TSingleMatrixHelper.ArgExtrema(Count: Int32; HiLo: Boolean = True): TPointArray; +var + W, H: Integer; + Buffer: TSimbaPointBuffer; + + function pass_x(): TPointArray; + var + X,Y: Integer; + begin + Buffer.Clear(); + + for Y:=0 to H-1 do + begin + X := 1; + while (X < W) do + begin + while (X < W) and (Self[Y,X] >= Self[Y,X-1]) do Inc(X); + Buffer.Add(X-1,Y); + while (X < W) and (Self[Y,X] <= Self[Y,X-1]) do Inc(X); + end; + end; + + Result := Buffer.Copy(); + end; + + function pass_y(): TPointArray; + var + X,Y: Integer; + begin + Buffer.Clear(); + + for X:=0 to W-1 do + begin + Y := 1; + while (Y < H) do + begin + while (Y < H) and (Self[Y,X] >= Self[Y-1,X]) do Inc(Y); + Buffer.Add(X,Y-1); + while (Y < H) and (Self[Y,X] <= Self[Y-1,X]) do Inc(Y); + end; + end; + + Result := Buffer.Copy(); + end; + +var + I: Integer; + Weights: TSingleArray; +begin + W := Self.Width(); + H := Self.Height(); + + Buffer.Init(Math.Max(2, Ceil(Sqrt(W * H)))); + + Result := pass_x().Intersection(pass_y()); + + // just use sort, since there arn't that many peaks + SetLength(Weights, Length(Result)); + for I := 0 to High(Result) do + Weights[I] := Self[Result[I].Y, Result[I].X]; + + Result := Result.Sort(Weights, not HiLo); + if (Length(Result) > Count) then + SetLength(Result, Count); +end; + end. diff --git a/Source/simba.tpa.pas b/Source/simba.tpa.pas index ddb9816bb..c07343865 100644 --- a/Source/simba.tpa.pas +++ b/Source/simba.tpa.pas @@ -28,12 +28,9 @@ unit simba.tpa; +{$DEFINE SIMBA_MAX_OPTIMIZATION} {$i simba.inc} -{$IFOPT D-} - {$OPTIMIZATION LEVEL4} -{$ENDIF} - interface uses @@ -105,6 +102,7 @@ interface function NearestPoint(Other: TPoint): TPoint; function Sort(Weights: TIntegerArray; LowToHigh: Boolean = True): TPointArray; overload; + function Sort(Weights: TSingleArray; LowToHigh: Boolean = True): TPointArray; overload; function Sort(Weights: TDoubleArray; LowToHigh: Boolean = True): TPointArray; overload; function SortFrom(From: TPoint): TPointArray; @@ -128,6 +126,8 @@ interface function Partition(Dist: Integer): T2DPointArray; overload; function PartitionEx(StartPoint: TPoint; BoxWidth, BoxHeight: Integer): T2DPointArray; overload; function PartitionEx(BoxWidth, BoxHeight: Integer): T2DPointArray; overload; + + function Intersection(Other: TPointArray): TPointArray; end; implementation @@ -135,7 +135,7 @@ implementation uses math, simba.overallocatearray, simba.geometry, simba.math, - simba.algo_sort, simba.slacktree, simba.algo_unique, + simba.algo_sort, simba.algo_intersection, simba.slacktree, simba.algo_unique, simba.singlematrix, simba.integermatrix; procedure GetAdjacent4(var Adj: TPointArray; const P: TPoint); inline; @@ -1504,12 +1504,17 @@ function TPointArrayHelper.NearestPoint(Other: TPoint): TPoint; function TPointArrayHelper.Sort(Weights: TIntegerArray; LowToHigh: Boolean): TPointArray; begin - Result := specialize Sorted(Self, Weights, LowToHigh); + Result := specialize Sorted(Self, Weights, LowToHigh); +end; + +function TPointArrayHelper.Sort(Weights: TSingleArray; LowToHigh: Boolean): TPointArray; +begin + Result := specialize Sorted(Self, Weights, LowToHigh); end; function TPointArrayHelper.Sort(Weights: TDoubleArray; LowToHigh: Boolean): TPointArray; begin - Result := specialize Sorted(Self, Weights, LowToHigh); + Result := specialize Sorted(Self, Weights, LowToHigh); end; function TPointArrayHelper.SortFrom(From: TPoint): TPointArray; @@ -2116,5 +2121,10 @@ function TPointArrayHelper.PartitionEx(BoxWidth, BoxHeight: Integer): T2DPointAr Result := PartitionEx(TPoint.Create(Integer.MaxValue, Integer.MaxValue), BoxWidth, BoxHeight); end; +function TPointArrayHelper.Intersection(Other: TPointArray): TPointArray; +begin + Result := Algo_Point_Intersection(Self, Other); +end; + end.