diff --git a/tests/reverse.apln b/tests/reverse.apln new file mode 100644 index 0000000..d698633 --- /dev/null +++ b/tests/reverse.apln @@ -0,0 +1,261 @@ +: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 ⍝ Model requires ⎕IO←1 for index generation to work correctly + n←(≢⍴⍵)⊃⍴⍵ + ({⍵[(n+1)-⍳n]}⍤1)⍵ + } + + ∇ 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 + :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