Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 301 additions & 0 deletions tests/reverse.apln
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
:Namespace reverse
Assert←#.unittest.Assert
isDyalogClassic←#.utils.isClassic

⍝ Model implements reverse via rank operator and arithmetic indexing
⍝ Does not use ⌽, providing a truly independent implementation for verification
⍝ Guard handles rank-0 scalars where ⍤1 cannot operate
modelReverse←{
0=≢⍴⍵:⍵
⎕IO←1 ⍝ Index generation (⍳) requires ⎕IO←1
n←(≢⍴⍵)⊃⍴⍵
({⍵[(n+1)-⍳n]}⍤1)⍵
}

⍝ Model for bracket-axis reverse ⌽[k]
⍝ Implements reverse along a specified axis using Squad indexing (⌷)
⍝ ⍺ is the axis to reverse (1-indexed, per bracket-axis notation)
⍝ Uses vector of index vectors with Squad to reverse the specified axis
⍝ bracket-axis tests below are also commented
⍝modelReverseBracket←{
⍝ 0=≢⍴⍵:⍵
⍝ ⎕IO←1
⍝ axis←⍺
⍝ n←axis⊃⍴⍵
⍝ ⍝ Build index vectors for each axis
⍝ idxs←⍳¨⍴⍵
⍝ ⍝ Reverse the specified axis
⍝ idxs[axis]←⊂(n+1)-⍳n
⍝ ⍝ Use Squad indexing (⌷) with enclosed indices
⍝ idxs⌷⍵
⍝}

∇ r←testDesc
r←'for ',case

∇ {r}←test_reverse;bool;i1;i2;i3;dbl;Hdbl;fl;Hfl;cmplx;Hcmplx;char0;char1;char2;char3;case;data;desc;scalar;empty;matrix;array3d;empty2d;empty3d;largeData;hashedData;RunVariations;data_rand_i1;data_rand_i2;data_rand_i4;data_rand_char1;data_rand_char2;quadparams;len;rows;cols;size;i1_min;i1_max;i2_min;i2_max;i4_min;i4_max;dbl_small;dbl_boundary;fl_small;fl_boundary
r←⍬

⍝ Monadic reverse has no implicit system variable dependencies
⍝ quadparams are set to defaults as required by RunVariations
quadparams←(#.utils.ct_default) (#.utils.dct_default) (#.utils.fr_dbl) 1 (#.utils.div_0)

RunVariations←modelReverse #.testfns._RunVariationsWithModel_ ⌽

data_rand_i1←1000 #.random.Ints 8
data_rand_i2←1000 #.random.Ints 16
data_rand_i4←1000 #.random.Ints 32

:If ~isDyalogClassic
data_rand_char1←1000 #.random.Chars 8
data_rand_char2←1000 #.random.Chars 16
:EndIf

bool←0 1
i1←{⍵,-⍵}⍳120
i2←{⍵,-⍵}10000+⍳1000
i3←{⍵,-⍵}100000+⍳100

char0←⎕AV
:If ~isDyalogClassic
char1←⎕UCS⍳255
char2←⎕UCS(1000+⍳100)
char3←⎕UCS(100000+⍳100)
:EndIf

dbl←{⍵,-⍵}1000.5+⍳100
Hdbl←{⍵,-⍵}100000000000000+(2×⍳50)

⍝ Decimal floating point data requires ⎕FR←1287
⎕FR←#.utils.fr_decf
fl←{⍵,-⍵}1000.5+⍳100
Hfl←{⍵,-⍵}200000000000000000000000000000+(10000000000000000×⍳10)
⎕FR←#.utils.fr_dbl

cmplx←{⍵,-⍵}(0J1×⍳100)+⌽⍳100
Hcmplx←{⍵,-⍵}(100000000000000J100000000000000×⍳20)

⍝ Extreme value testing: boundary values for each type
i1_min←¯128
i1_max←127
i2_min←¯32768
i2_max←32767
i4_min←¯2147483648
i4_max←2147483647
dbl_small←1E¯300+⍳10 ⍝ Very small positive decimals
dbl_boundary←i4_max+0.1 0.5 0.9 ⍝ Near int32 boundary
fl_small←⍬
fl_boundary←⍬
⎕FR←#.utils.fr_decf
fl_small←1E¯6000+⍳10 ⍝ Very small positive decimals (decf)
fl_boundary←(2*127)+0.1 0.5 0.9 ⍝ Near decf boundary
⎕FR←#.utils.fr_dbl

:For case :In 'bool' 'i1' 'i2' 'i3' 'dbl' 'Hdbl' 'fl' 'Hfl' 'cmplx' 'Hcmplx' 'i1_min' 'i1_max' 'i2_min' 'i2_max' 'i4_min' 'i4_max' 'dbl_small' 'dbl_boundary' 'fl_small' 'fl_boundary'
data←⍎case
desc←testDesc

⍝ RunVariations: normal, scalar, empty, multiple shapes, shape with 0, model comparison, random data
r,←'T1'desc quadparams RunVariations,⊂data

desc←'Double reverse for ',case
r,←'T2'desc Assert data≡⌽⌽data

desc←'Datatype preserved for ',case
r,←'T3'desc Assert (⎕DR data)≡⎕DR ⌽data

⍝ Large array stress test
desc←'Large array (10000) for ',case
largeData←10000⍴data
r,←'T4'desc Assert largeData≡⌽⌽largeData

⍝ Hash collision handling test
:If 9=⎕NC'#.utils.hashArray'
hashedData←#.utils.hashArray data
desc←'Hashed array reverse for ',case
r,←'T5'desc Assert hashedData≡⌽⌽hashedData
:EndIf
:EndFor

⍝ Explicit tests with ⎕IO variation (not covered by RunVariations)
:For ⎕IO :In #.utils.io_default #.utils.io_0

⍝ Explicit decimal precision preservation tests
desc←'Decimal precision: 0.1 0.2 0.3'
data←0.1 0.2 0.3
r,←'TPrec1'desc Assert data≡⌽⌽data
r,←'TPrec2'desc Assert data≡modelReverse⌽data

desc←'Decimal precision: repeating decimals'
data←(⍳10)÷3
r,←'TPrec3'desc Assert data≡⌽⌽data

desc←'Decimal precision: very small values'
data←1E¯15×⍳10
r,←'TPrec4'desc Assert data≡⌽⌽data

desc←'Decimal precision: mixed magnitude'
data←1E15 1 1E¯15
r,←'TPrec5'desc Assert data≡⌽⌽data

⍝ Systematic shape variations for structural testing
⍝ Different vector lengths
:For len :In 1 10 100 1000 10000
data←len⍴i1
desc←'Vector length ',⍕len
r,←('TLen',⍕len)desc Assert data≡⌽⌽data
:EndFor

⍝ Tall matrices (many rows, few columns)
:For rows :In 10 100 1000
matrix←rows 11⍴i1
desc←'Tall matrix ',⍕rows,'x11'
r,←('TTall',⍕rows)desc Assert matrix≡⌽⌽matrix
:EndFor

⍝ Wide matrices (few rows, many columns)
:For cols :In 10 100 1000
matrix←11 cols⍴i1
desc←'Wide matrix 11x',⍕cols
r,←('TWide',⍕cols)desc Assert matrix≡⌽⌽matrix
:EndFor

⍝ Square matrices of different sizes
:For size :In 1 4 16 252
matrix←size size⍴i1
desc←'Square matrix ',⍕size,'x',⍕size
r,←('TSquare',⍕size)desc Assert matrix≡⌽⌽matrix
:EndFor

⍝ Nested arrays: reverse reorders top-level elements, preserves nesting structure
desc←'Simple nested array (numeric)'
data←(i1 i2)
r,←'TNest1'desc Assert data≡⌽⌽data
r,←'TNest2'desc Assert (modelReverse data)≡⌽data

desc←'Deeply nested array (numeric)'
data←(i1 (i2 (i3 dbl)))
r,←'TNest3'desc Assert data≡⌽⌽data
r,←'TNest4'desc Assert (modelReverse data)≡⌽data

desc←'Mixed rank nested (numeric)'
data←(matrix (2 3 4⍴⍳24) (2 3⍴i1))
r,←'TNest5'desc Assert data≡⌽⌽data
r,←'TNest6'desc Assert (modelReverse data)≡⌽data

⍝ Mixed numeric/character arrays (type 326)
desc←'Mixed array: numbers and characters'
data←(42 'Hello' 3.14)
r,←'TMix1'desc Assert data≡⌽⌽data
r,←'TMix2'desc Assert (modelReverse data)≡⌽data

desc←'Mixed array: numeric and character vectors'
data←(i1 char0 dbl)
r,←'TMix3'desc Assert data≡⌽⌽data
r,←'TMix4'desc Assert (modelReverse data)≡⌽data

desc←'Nested mixed array'
data←(i1 'ABC' dbl)
r,←'TMix5'desc Assert data≡⌽⌽data
r,←'TMix6'desc Assert (modelReverse data)≡⌽data

desc←'Deeply nested mixed array'
data←(42 ('Hello' 3.14) char0)
r,←'TMix7'desc Assert data≡⌽⌽data
r,←'TMix8'desc Assert (modelReverse data)≡⌽data

⍝ Namespace arrays
desc←'Namespace reverse'
r,←'Tns1'desc Assert ((# ⎕SE))≡⌽⌽(# ⎕SE)
r,←'Tns2'desc Assert (modelReverse(# ⎕SE))≡⌽(# ⎕SE)

desc←'Single namespace'
r,←'Tns3'desc Assert (,#)≡⌽,#

⍝ Scalar edge case: rank 0 arrays
scalar←42
desc←'Scalar unchanged'
r,←'TE1'desc Assert scalar≡⌽scalar

⍝ Empty vector
empty←⍬
desc←'Empty vector'
r,←'TE2'desc Assert empty≡⌽empty

⍝ Empty arrays with non-zero trailing dimensions
empty2d←0 5⍴⍬
desc←'Empty 2D array'
r,←'TEmpty1'desc Assert empty2d≡⌽empty2d
r,←'TEmpty2'desc Assert (⍴empty2d)≡⍴⌽empty2d

empty3d←0 0 5⍴⍬
desc←'Empty 3D array'
r,←'TEmpty3'desc Assert empty3d≡⌽empty3d

⍝ Multi-dimensional arrays: reverse along last axis
matrix←3 4⍴⍳12
desc←'Matrix reverse'
r,←'TE3'desc Assert matrix≡⌽⌽matrix
r,←'TE4'desc Assert (⍴matrix)≡⍴⌽matrix

array3d←2 3 4⍴⍳24
desc←'3D array reverse'
r,←'T3D1'desc Assert array3d≡⌽⌽array3d
r,←'T3D2'desc Assert (⍴array3d)≡⍴⌽array3d

array3d←4 5 6⍴⍳120
desc←'3D array (4x5x6) reverse'
r,←'T3D3'desc Assert array3d≡⌽⌽array3d

⍝ Bracket-axis reverse ⌽[k] tests
⍝ Test reversing along different axes of multi-dimensional arrays
⍝ Bracket-axis notation is 1-indexed (independent of ⎕IO per APL docs)
⍝ Uses Squad indexing (⌷) in model to reverse along specified axis
⍝ requires modelReverseBracket above
⍝desc←'Matrix reverse along axes'
⍝matrix←3 4⍴⍳12
⍝⎕IO←1 ⍝ Bracket-axis requires 1-based indexing
⍝:For axis :In ⍳≢⍴matrix
⍝ r,←('TAxisMat',⍕axis)desc Assert (axis modelReverseBracket matrix)≡⌽[axis]matrix
⍝:EndFor
⍝⍝ Verify first axis is ⊖
⍝r,←'TAxisFirst'desc Assert (⌽[1]matrix)≡⊖matrix
⍝desc←'3D array reverse along axes'
⍝array3d←2 3 4⍴⍳24
⍝:For axis :In ⍳≢⍴array3d
⍝ r,←('TAxis3D',⍕axis)desc Assert (axis modelReverseBracket array3d)≡⌽[axis]array3d
⍝:EndFor
⍝⍝ Verify last axis same as monadic
⍝r,←'TAxisLast'desc Assert (⌽[(≢⍴array3d)]array3d)≡⌽array3d
:EndFor

:For case :In 'char0' 'char1' 'char2' 'char3'
:If (isDyalogClassic)∧(case≢'char0')
:Continue
:EndIf
data←⍎case
desc←testDesc

r,←'TC1'desc quadparams RunVariations,⊂data

desc←'Char datatype preserved for ',case
r,←'TC2'desc Assert (⎕DR data)≡⎕DR ⌽data
:EndFor

:For case :In 'data_rand_i1' 'data_rand_i2' 'data_rand_i4'
data←⍎case
desc←testDesc
r,←'TRand1'desc quadparams RunVariations,⊂data
:EndFor

:If ~isDyalogClassic
:For case :In 'data_rand_char1' 'data_rand_char2'
data←⍎case
desc←testDesc
r,←'TRandC1'desc quadparams RunVariations,⊂data
:EndFor
:EndIf
:EndNamespace