diff --git a/modules/std/syntax/primitives/arrays.wx b/modules/std/syntax/primitives/arrays.wx index a1c87a09..a118cd30 100644 --- a/modules/std/syntax/primitives/arrays.wx +++ b/modules/std/syntax/primitives/arrays.wx @@ -13,8 +13,9 @@ List of functionality: - Interleaving (Interleave) - Patterned rearrangement (Twirl, Swap) - Fill: Fill with single value or pattern - - Aggregation: Sum, Min, Max with inverse step + - Aggregation: Sum, Min, Max with inverse step, Average - Clamp/Clip: Bound all elements to a range + - Chunking/Splitting: Split into fixed-size blocks TODO: A test To know which one is the faster: @@ -22,9 +23,8 @@ A test To know which one is the faster: - c=a[n];out = c < out ? c Else out Missing or possible extensions: - - Aggregation: Average, complete min/max - Set operations: Union, Intersection, Difference, Unique/Distinct - - Chunking/Splitting: Split into fixed-size blocks, group by predicate + - Chunking/Splitting: group by predicate - Flatten/Concat: For arrays-of-arrays - Sliding window: Windowed views for DSP, stats, ML - Reorganize the file, it's crappy actually @@ -37,6 +37,129 @@ Completion: - For full "batteries-included" status, add functional, searching, set, and chunking utilities. #end +'TO TEST: +Function SlidingRead( this:T[], + + 'data to write into: + data:T Ptr, + + 'dimension x,y of the unidimensional array: + length:ChunkFormat Ptr, + height:ChunkFormat Ptr, + + 'position of the window: + offsetX:UInt, + offsetY:UInt, + offsetLength:ChunkFormat, + offsetHeight:ChunkFormat, + + 'Pointer in the window: + ptrX:UInt, + ptrY:UInt ) + + 'Return the content + data[0]=this[ SlidingGetPtr( Varptr(length), + Varptr(height), + + Varptr(offsetX), + Varptr(offsetY), + Varptr(offsetLength), + Varptr(offsetHeight), + + Varptr(ptrX), + Varptr(ptrY)) ] +End + +'TO TEST: +Function SlidingWrite( this:T[], + + 'data to write/set: + data:T Ptr, + + 'dimension x,y of the unidimensional array: + length:ChunkFormat Ptr, + height:ChunkFormat Ptr, + + 'position of the window: + offsetX:UInt, + offsetY:UInt, + offsetLength:ChunkFormat, + offsetHeight:ChunkFormat, + + 'Pointer in the window: + ptrX:UInt, + ptrY:UInt ) + + 'Return the content + data[0]=this[ SlidingGetPtr( Varptr(length), + Varptr(height), + + Varptr(offsetX), + Varptr(offsetY), + Varptr(offsetLength), + Varptr(offsetHeight), + + Varptr(ptrX), + Varptr(ptrY)) ] +End + +Private 'Get a pointer for read/write in a virtual 2d array from a sliding window +Function SlidingGetPtr:ChunkFormat Ptr( this:T[], + + 'dimension x,y of the unidimensional array: + length:ChunkFormat Ptr, + height:ChunkFormat Ptr, + + 'position of the window: + offsetX:UInt Ptr, + offsetY:UInt Ptr, + offsetLength:ChunkFormat Ptr, + offsetHeight:ChunkFormat Ptr, + + 'Pointer in the window: + ptrX:UInt Ptr, + ptrY:UInt Ptr ) + + 'The pointer is inside the window + ptrX[0]=ptrX[0]>offsetLength[0] ? offsetLength[0] Else ptrX[0] 'guard + ptrY[0]=ptrY[0]>offsetHeight[0] ? offsetHeight[0] Else ptrY[0] 'guard + + 'The window is inside the 2d array + offsetX[0]=offsetX[0]<=length[0]-offsetLength[0] ? offsetX[0] Else length[0]-offsetLength[0] 'guard, here <= avoids sub (edge case) + offsetY[0]=offsetY[0]<=height[0]-offsetHeight[0] ? offsetY[0] Else height[0]-offsetHeight[0] 'guard, here <= avoids sub (edge case) + + 'Shift the pointer inside the 2d array + ptrX[0]+=offsetX[0] + ptrY[0]+=offsetY[0] + + 'Pointer from 2d array to 1d array + ptrY[0]*=length[0]-1 + ptrX[0]+=ptrY[0] + + 'Return the content + Return ptrX +End +Public + +'TO TEST: +Function Splitting:T[][]( this:T[],chunksLength:Int ) + 'ToTest + Local thisLength:=this.Length + Local chunckNb:=Ceil(thisLength/chunksLength) + Local result:T[]=T[chunckNb] + Local toEnd:Int + Local limEnd:Int + For Local n:=0 Until chunckNb + T[n]=T[chunksLength] + limEnd=n*chunksLength+chunksLength + toEnd=limEnd>thisLength ? thisLength Else limEnd + this.CopyTo(result[n],n*chunksLength,0,toEnd) + End + Return result +End + +'--- + Function CopyTo:T[]( this:T[],out:T[],srcOffset:Int=0,dstOffset:Int=0,count:Int=Null ) ' 'A CopyTo who can be inlined @@ -53,7 +176,7 @@ Function CopyTo:T[]( this:T[],out:T[],srcOffset:Int=0,dstOffset:Int=0,count:I Return out End -#rem monkeydoc @pro Return a copy of the array is needed +#rem wonkeydoc @pro Return a copy of the array is needed #end Function Cpynd:T[]( data:T[],needed:Bool ) 'Both useful and elegant^^ @@ -95,32 +218,16 @@ End ' --- Aggregations: -Function Min:T( this:T[],minlim:T=0 ) Where T Implements INumeric - Local thisSize:=this.Size - Local result:T=minlim 'implicit casting - For Local n:=0 Until thisSize - AssignIff(Min(Varptr(this[n]),Varptr(result))[0]<>this[n],Varptr(result)) - End -End - -Function Max:T( this:T[],maxlim:T=LongMax ) Where T Implements INumeric - Local thisSize:=this.Size - Local result:T=maxlim 'auto and implicit casting - For Local n:=0 Until thisSize - AssignIff(Max(Varptr(this[n]),Varptr(result))[0]<>this[n],Varptr(result)) - End -End - -Function Min:T(a:T[],inverse:Bool8) Where T Implements INumeric +Function Min:T(a:T[],inverse:Boolean=False8,minlim:T=0) Where T Implements INumeric and + Boolean=Bool Or Boolean=Bool8 'iDkP from GaragePixel - '2025-02-18 + '2025-02-18 - 2025-07-19 'Order n - Local out:T + Local out:T=minlim 'implicit casting Local len:=T.Length - Local c:=out Local starts:Int, ends:Int, shift:Int If inverse=False8 @@ -134,54 +241,28 @@ Function Min:T(a:T[],inverse:Bool8) Where T Implements INumeric End For Local n:=starts Until ends Step shift - c=a[n];out = c < out ? c Else out +' c=a[n];out = c < out ? c Else out + AssignIff(Min(Varptr(this[n]),Varptr(out))[0]:T(a:T[],inverse:Bool8) Where T Implements INumeric - +Function Max:T( this:T[],inverse:Boolean=False8,maxlim:T=LongMax ) Where T Implements INumeric And + Boolean=Bool Or Boolean=Bool8 + 'iDkP from GaragePixel - '2025-02-18 + '2025-02-18 - 2025-07-19 'Order n - - Local out:T - Local len:=T.Length - Local c:=out - Local starts:Int, ends:Int, shift:Int - - If last=False8 - starts=len - ends=0 - shift=-1 - Else - starts=0 - ends=len - shift=1 - End - - For Local n:=starts Until ends Step shift - c=a[n];out = c>=out ? c Else out - End - - Return out -End -Function Min:T(a:T[],inverse:Bool) Where T Implements INumeric + Local out:T=maxlim 'auto and implicit casting - 'iDkP from GaragePixel - '2025-02-18 - - 'Order n - - Local out:T + 'Local out:T Local len:=T.Length - Local c:=out Local starts:Int, ends:Int, shift:Int - If inverse=False + If inverse=False8 starts=len ends=0 shift=-1 @@ -190,42 +271,14 @@ Function Min:T(a:T[],inverse:Bool) Where T Implements INumeric ends=len shift=1 End - - For Local n:=starts Until ends Step shift - c=a[n];out = c < out ? c Else out - End - - Return out -End -Function Max:T(a:T[],inverse:Bool) Where T Implements INumeric - - 'iDkP from GaragePixel - '2025-02-18 - - 'Order n - - Local out:T - Local len:=T.Length - Local c:=out - Local starts:Int, ends:Int, shift:Int - - If last=False - starts=len - ends=0 - shift=-1 - Else - starts=0 - ends=len - shift=1 - End - For Local n:=starts Until ends Step shift - c=a[n];out = c>=out ? c Else out + 'c=a[n];out = c>=out ? c Else out + AssignIff(Max(Varptr(this[n]),Varptr(out))[0]<>this[n],Varptr(out)) End Return out -End +End Function Sum:T( this:T[] ) Where T Implements INumeric 'Unsafe version, potentially faster @@ -254,7 +307,20 @@ Function SumSafe:T( this:T[] ) Where T Implements INumeric Return Null End -#rem monkeydoc @expert The length of the array. +#rem wonkeydoc Average the values from a stack. +@author iDkP from GaragePixel +@since 2025-07-19 +#end +Function Avr:T( this:T[] ) Where T Implements INumeric And T<>Bool + Local s:Double=0 'Sure that we'll fall in the larger range + Local len:=this.Size + For Local n:T=0 Until len + s+=this[n] + End + Return s/len +End + +#rem wonkeydoc @expert The length of the array. In the case of multi-dimensional arrays, the length of the array is the product of the sizes of all dimensions. #end @@ -319,7 +385,7 @@ End '------------ -#rem monkeydoc hidden Merges two sorted arrays into a single sorted array. +#rem wonkeydoc hidden Merges two sorted arrays into a single sorted array. Merges the elements of arrays a and b, preserving order and stability. On elements: @@ -364,7 +430,7 @@ Function Merge:T[]( a:T[],b:T[] ) Return res End -#rem monkeydoc Reverses an array in place. +#rem wonkeydoc Reverses an array in place. Swaps elements from both ends toward the center, modifying the original array. Used for reversing descending runs in TimSort_g and similar algorithms. @@ -392,7 +458,7 @@ Function Reverse:T[]( arr:T[],copy:Bool=True ) Return out End -#rem monkeydoc Reverses a subrange of an array in place. +#rem wonkeydoc Reverses a subrange of an array in place. Swaps elements between the specified start and end indices, reversing the segment. Useful for in-place reversal of partial runs or subsequences (e.g., in TimSort_g). @@ -630,7 +696,7 @@ Function Tile:T[]( this:T[],factor:Int=0,copy:Bool=True ) Return this End -#rem monkeydoc Rot - Cyclically rotates an array left/right by shift +#rem wonkeydoc Rot - Cyclically rotates an array left/right by shift @author: iDkP for GaragePixel, @since 2021? #end