Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for not (monadic ~) #90

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
58 changes: 58 additions & 0 deletions iso_defs.apln
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
:Namespace iso_defs
⍝ This namespace contains definitions from
⍝ the Extended APL ISO standard (ISO/IEC 13751:2001)

⍝ Every function or value is defined within
⍝ a :Section with the corresponding section number,
⍝ which makes it easier to find what we are looking
⍝ for.

:Section 5.2.3
∇ r←IsBoolean A
r←∨/A∘.Equals 0 1
:EndSection

:Section 5.2.5

∇ r←A Equals B
r←A≡⍥(11∘⎕DR)B

∇ r←B TolerantFloor A;⎕CT
⎕CT←B
r←⌊A

∇ r←B IntegralWithin A;F1;F2
:If 0∊⍴A
r←(⍴A)⍴0
:Return
:EndIf

F1←B TolerantFloor¨-A
F2←-B TolerantFloor¨A
r←F1 Equals F2

∇ r←NearInteger data
r←IntegerTolerance IntegralWithin data

∇ r←NearBoolean data
:If ∧⌿∊NearInteger data
r←IsBoolean IntegerNearestTo data
:Else
r←0
:EndIf

∇ r←IntegerNearestTo data
r←IntegerTolerance TolerantFloor data
:EndSection

:Section 5.3.10
IntegerTolerance←1E¯14 ⍝ aka SYSFUZZ
:EndSection
:EndNamespace
Empty file modified run.apls
100644 → 100755
Empty file.
272 changes: 131 additions & 141 deletions testfns.apln
Original file line number Diff line number Diff line change
@@ -1,141 +1,131 @@
:Namespace testfns
Assert←#.unittest.Assert
numOrChar←#.utils.numOrChar
change0sto1←#.utils.change0sto1

giveBound←{
type←(181⌶)⍵
type=11:0 1 ⍝ 11 : 1 bit boolean arrays
type=80:⎕UCS 0 255 ⍝ 80 : 8 bits character
type=83:¯128 127 ⍝ 83 : 8 bits signed integer
type=160:⎕UCS 0 65535 ⍝ 160 : 16 bits character
type=163:¯32768 32767 ⍝ 163 : 16 bits signed integer
type=320:⎕UCS 0 1114111 ⍝ 320 : 32 bits character
type=323:¯2147483648 2147483647 ⍝ 323 : 32 bits signed integer
type=645:(⌈/⍬)(⌊/⍬) ⍝ 645 : 64 bits floating
⎕FR←1287 ⋄ type=1287:(⌈/⍬)(⌊/⍬) ⋄ ⎕FR←645 ⍝ 1287: 128 bits decimal
type=1289:{(-⍵),⍵,(+⍵),(-+⍵)}(⌈/⍬)(⊣+¯11○⊢)(⌊/⍬) ⍝ 1289: 128 bits complex
}

⍝ shouldNotRandTest checks what test is running and returns a 0
⍝ if the test mentioned in ⍵ are running to simplify the if case
⍝ in RandModelTest to skip the test for certain primitives
shouldNotRandTest←{~∨/⊃,/{∨/⍵⍷↑#.unittest.tests}¨⍵}

⍝ -------------------------
⍝ Generating Random Numbers
⍝ -------------------------

⍝ generating big random numbers upto 1E6144
rollLimit←{⎕fr←1287 ⋄ ⍵<¯1+2*63 ⋄⎕fr←645} ⍝ limit of the roll(X?Y) primitive

⍝ generate 3 to 18 random numbers smaller than 1E17 and multiply them to get
⍝ a random number between 1E49 to 1E306
bigRand308←{×/?(2+?16)/1E17}

⍝ takes a number from bigRand308 and picks 3 to 20 random numbers and multiplies
⍝ all of them to generate a random number between 1E308 to 1E6144
bigRand308to6144←{×/change0sto1(2+?18)↑}

⍝ rarg bigRand bound
⍝ uses bigRand308to6144 and bigRand308 to use the required random number generator
⍝ to generate a appropriate random number based on the bounds and the datatype
⍝ <---cmplx---> <-----decimal numbers running with 128 bit arithmetic-----> <numbers under ? limit> <floating point nos>
bigRand←{1289≡⎕dr ⍵:⍺⋄(1287≡⎕dr ⍵) ∧ ⎕fr≡1287: {bigRand308to6144 bigRand308¨⍳20}¨⍺ ⋄ ⍺{rollLimit ⍵:?(≢⍺)/⍵ ⋄ (bigRand308¨⍺)}⍵}

⍝ todo: add this for characters when this runs for it
⍝ ⎕UCS ⍵ bigRand (⎕UCS 2⊃⍺)
⍝ normal cmplx number random:
⍝ {1⊃⍵ (⊣+¯11○⊢) 2⊃⍵}¨?⌊|(9 11○⊂)¨rarg

⍝ uses the appropriate random number generator for mixed, numeric or char arrays
⍝ ⍝ mixed array ⍝ numeric ⍝ char
getRand←{¯1≡numOrChar ⍺:⍺ ⋄ ⍺{numOrChar ⍵: ⍺ bigRand 2⊃⍵ ⋄ ⍺}⍵}

⍝ -----------------------------
⍝ Generating Random Numbers End
⍝ -----------------------------

⍝ tests that don't use this are:
⍝ use a different runvariations:
⍝ - unique
⍝ - uniquemask
⍝ - indexof
⍝ - membership

⍝ Run Variations of each test with normal, empty and multiple shaped data
∇ {tRes}←tData (model _RunVariations_ op) exp;⎕CT;⎕DCT;⎕FR;⎕IO;⎕DIV;expectedR;larg;rarg;tID;tCmt;actualR;actualRE;shape;actualRS;shapeW0;actualRSW0;val;randr;trimmedrarg
:If 3≡≢exp ⍝ dyadic op
val←2 ⍝ valence
(expectedR larg rarg)←exp
:Else ⍝ monadic op
val←1
(expectedR rarg)←exp
:EndIf
(tID tCmt quadparams)←tData
⎕CT ⎕DCT ⎕FR ⎕IO ⎕DIV←quadparams
tRes←⍬

⍝ normal
actualR←{val≡2:larg op rarg ⋄ op rarg}⍬
tRes,←(tID tCmt) Assert expectedR≡actualR

:If val≡1
⍝ scalar
randr←?≢rarg
trimmedrarg←randr↓rarg ⍝ so that not always the first is selected
shape←⍬ ⍝ scalar shape
actualRS←op shape⍴trimmedrarg
tRes,←('Scalar',tID) tCmt Assert (shape⍴randr↓expectedR)≡actualRS
:EndIf

⍝ empty
actualRE←{val≡2:(0⍴larg) op (0⍴rarg) ⋄ op (0⍴rarg)}⍬ ⍝ 0 in the shape means we have no elements in the array, i.e. it's empty.
tRes,←('EmptyL',tID) tCmt Assert ⍬≡actualRE ⍝ empty array is expectedR

⍝ different shapes
shape←?(?4)/4
actualRS←{val≡2:(shape⍴larg) op (shape⍴rarg) ⋄ op (shape⍴rarg)}⍬
tRes,←('Multiple',tID) tCmt Assert (shape⍴expectedR)≡actualRS

⍝ different shapes with 0 in shape
shapeW0←(0@(?(≢shape)))shape
actualRSW0←{val≡2:(shapeW0⍴larg) op (shapeW0⍴rarg) ⋄ op (shapeW0⍴rarg)}⍬
tRes,←('ShapeW0',tID) tCmt Assert (shapeW0⍴0) ≡ actualRSW0

⍝ testing larg and rarg specifically from model
tRes,←('ModelTest',tID) tCmt Assert ({val≡2:(larg model rarg)≡larg op rarg ⋄ (model¨ rarg)≡op rarg}⍬)

⍝ This test creates a random element based on the datatype of the rarg and larg
⍝ it is then tested using models of the function.
⍝ The purpose of this test is to use the entire range of the datatype so a dataset
⍝ is generated in the longer run to test more data.
⍝ skipping big rand test for mentioned primitives because of issues with the model
:If (shouldNotRandTest 'residue' 'floor' 'multiply')
boundR←giveBound rarg ⍝ get boundaries of rarg
⎕fr←645
nrarg←rarg getRand boundR ⍝ generate a random element in range of rarg
⎕fr←3⊃quadparams
:If val=2
boundL←giveBound larg
⎕fr←645
nlarg←larg getRand boundL
⎕fr←3⊃quadparams
:EndIf
tRes,←('RandModelTest',tID) tCmt Assert ({val≡2:(nlarg model nrarg)≡nlarg op nrarg ⋄ (model¨ nrarg)≡op nrarg}⍬)
:EndIf

⍝ todo:
⍝ new variations needs more tests of:
⍝ lengths of arrays from 1 to 10000
⍝ and
⍝ of kind
⍝ scalar
⍝ vector
⍝ tall matrix, 11-column matrix with 10*0 1 2 4 rows
⍝ wide matrix, 11-row matrix with 10*0 1 2 4 columns
⍝ square matrix with ⌈10*0 1 2 4×0.6 (1 4 16 252) rows/columns
:EndNamespace
:Namespace testfns
Assert←#.unittest.Assert
numOrChar←#.utils.numOrChar
change0sto1←#.utils.change0sto1

giveBound←{
type←(181⌶)⍵
type=11:0 1 ⍝ 11 : 1 bit boolean arrays
type=80:⎕UCS 0 255 ⍝ 80 : 8 bits character
type=83:¯128 127 ⍝ 83 : 8 bits signed integer
type=160:⎕UCS 0 65535 ⍝ 160 : 16 bits character
type=163:¯32768 32767 ⍝ 163 : 16 bits signed integer
type=320:⎕UCS 0 1114111 ⍝ 320 : 32 bits character
type=323:¯2147483648 2147483647 ⍝ 323 : 32 bits signed integer
type=645:(⌈/⍬)(⌊/⍬) ⍝ 645 : 64 bits floating
⎕FR←1287 ⋄ type=1287:(⌈/⍬)(⌊/⍬) ⋄ ⎕FR←645 ⍝ 1287: 128 bits decimal
type=1289:{(-⍵),⍵,(+⍵),(-+⍵)}(⌈/⍬)(⊣+¯11○⊢)(⌊/⍬) ⍝ 1289: 128 bits complex
}

⍝ isCurrentlyRunning checks what test is running and returns a 1
⍝ if the test mentioned in ⍵ are running to simplify the if case
⍝ in RandModelTest to skip the test for certain primitives
isCurrentlyRunning←{∨/⊃,/{∨/⍵⍷↑#.unittest.tests}¨⍵}

⍝ -------------------------
⍝ Generating Random Numbers
⍝ -------------------------

⍝ generating big random numbers upto 1E6144
rollLimit←{⎕fr←1287 ⋄ ⍵<¯1+2*63 ⋄⎕fr←645} ⍝ limit of the roll(X?Y) primitive

⍝ generate 3 to 18 random numbers smaller than 1E17 and multiply them to get
⍝ a random number between 1E49 to 1E306
bigRand308←{×/?(2+?16)/1E17}

⍝ takes a number from bigRand308 and picks 3 to 20 random numbers and multiplies
⍝ all of them to generate a random number between 1E308 to 1E6144
bigRand308to6144←{×/change0sto1(2+?18)↑⍵}

⍝ rarg bigRand bound
⍝ uses bigRand308to6144 and bigRand308 to use the required random number generator
⍝ to generate a appropriate random number based on the bounds and the datatype
⍝ <---cmplx---> <-----decimal numbers running with 128 bit arithmetic-----> <numbers under ? limit> <floating point nos>
bigRand←{1289≡⎕dr ⍵:⍺⋄(1287≡⎕dr ⍵) ∧ ⎕fr≡1287: {bigRand308to6144 bigRand308¨⍳20}¨⍺ ⋄ ⍺{rollLimit ⍵:?(≢⍺)/⍵ ⋄ (bigRand308¨⍺)}⍵}

⍝ todo: add this for characters when this runs for it
⍝ ⎕UCS ⍵ bigRand (⎕UCS 2⊃⍺)
⍝ normal cmplx number random:
⍝ {1⊃⍵ (⊣+¯11○⊢) 2⊃⍵}¨?⌊|(9 11○⊂)¨rarg

⍝ uses the appropriate random number generator for mixed, numeric or char arrays
⍝ ⍝ mixed array ⍝ numeric ⍝ char
getRand←{¯1≡numOrChar ⍺:⍺ ⋄ ⍺{numOrChar ⍵: ⍺ bigRand 2⊃⍵ ⋄ ⍺}⍵}

⍝ -----------------------------
⍝ Generating Random Numbers End
⍝ -----------------------------

⍝ tests that don't use this are:
⍝ use a different runvariations:
⍝ - unique
⍝ - uniquemask
⍝ - indexof
⍝ - membership

⍝ Run Variations of each test with normal, empty and multiple shaped data
∇ {tRes}←spec(rawModel _RunVariations_ rawOp)args;ChkEqual;Eval;quadparams;runOrErr;shape;tCmt;tID;⎕CT;⎕DCT;⎕DIV;⎕FR;⎕IO
tRes←⍬
(tID tCmt quadparams)←spec
⎕CT ⎕DCT ⎕FR ⎕IO ⎕DIV←quadparams
runOrErr←{
0::⊂0 ⎕DMX.(EN Message)
⍺←⊢
⊂1(⍺ ⍺⍺ ⍵)
}

Eval←{
2=≢args:⍺ ⍺⍺ ⍵
1=≢args:⍺⍺ ⍵
⎕SIGNAL 5
}
ChkEqual←{
(larg rarg)←2⍴⍺⍺¨args
model←rawModel runOrErr
op←rawOp runOrErr
expected←larg model Eval rarg
actual←larg op Eval rarg
tRes,←(tID,' - ',⍵)tCmt Assert expected≡actual
}

⍝ Base test: check that the function behaves as the model with the provided data
{⍵}ChkEqual'Base'

⍝ scalar test: Pick a random item and check.
{⍵[⊂?⍴⍵]}ChkEqual'RandomScalar'

⍝ Empty test: check that the function behaves as the model when given an empty vector of the given type.
{0⍴⍵}ChkEqual'Empty'

⍝ High rank test: generate a random shape, and check.
shape←{⎕IO←1 ⋄ ?(?⍵)/⍵}4
{shape⍴⍵}ChkEqual'RandomHighRank'

⍝ High rank with 0 in shape test
shape[?≢shape]←0
{shape⍴⍵}ChkEqual'RandomEmptyHighRank'

⍝ Random data test:
⍝ This test creates a random element based on the datatype of the rarg and larg
⍝ it is then tested using models of the function.
⍝ The purpose of this test is to use the entire range of the datatype so a dataset
⍝ is generated in the longer run to test more data.

⍝ skipping big rand test for mentioned primitives because of issues with the model
:If ~isCurrentlyRunning'residue' 'floor' 'multiply'
{⎕FR←645 ⋄ ⍵ getRand giveBound ⍵}ChkEqual'RandModelTest'
:EndIf

⍝ todo:
⍝ new variations needs more tests of:
⍝ lengths of arrays from 1 to 10000
⍝ and
⍝ of kind
⍝ scalar
⍝ vector
⍝ tall matrix, 11-column matrix with 10*0 1 2 4 rows
⍝ wide matrix, 11-row matrix with 10*0 1 2 4 columns
⍝ square matrix with ⌈10*0 1 2 4×0.6 (1 4 16 252) rows/columns
:EndNamespace
61 changes: 61 additions & 0 deletions tests/not.apln
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
:Namespace not
Assert←#.unittest.Assert
NearBoolean←#.iso_defs.NearBoolean
IntegerNearestTo←#.iso_defs.IntegerNearestTo

∇ r←model data
⍝ ISO 7.1.12

:If ∧⌿∊NearBoolean data
r←1≠IntegerNearestTo data
:Else
⎕SIGNAL 11
:EndIf

∇ r←testDesc
r←'for ',case,' & ⎕CT ⎕DCT ⎕FR:',⍕⎕CT ⎕DCT ⎕FR

∇ {r}←test_not;RunVariations;case;caselist;ct;data;data_bool;data_char1;data_char2;data_i1;data_i2;data_i4;data_largercomplex;data_nearbool;data_notnearbool;data_smallcomplex;desc;fr;id;ints;ok;quadparams
r←⍬
RunVariations←model #.testfns._RunVariations_~
ints←{ ⍝ ⍺ integers of size ⍵ (bits), excluding the booleans
⎕IO←0
⍺⍴0 1~⍨(2*⍵-1)-⍨?2*⍵
}

:For ct :In 0 1 10 0.1
(⎕CT ⎕DCT)←ct×#.utils.(ct_default dct_default)
:For fr :In 1 2
⎕FR←fr⊃#.utils.(fr_dbl fr_decf)
⎕IO←1

quadparams←⎕CT ⎕DCT ⎕FR ⎕IO ⎕DIV

data_bool←1 0
data_nearbool←0 1∘.+{⍵,-⍵}0,#.iso_defs.IntegerTolerance÷⍳10
data_notnearbool←0 1∘.+{⍵,-⍵}#.iso_defs.(IntegerTolerance+IntegerTolerance÷⍳10)

data_smallcomplex←,∘.{⍺+¯11○⍵}⍨1⊃↓data_nearbool
data_largercomplex←,∘.{⍺+¯11○⍵}⍨2⊃↓data_nearbool
data_largercomplex,←,∘.{⍺+¯11○⍵}⍨,data_notnearbool

data_i1←100 ints 8
data_i2←100 ints 16
data_i4←100 ints 32
data_char1←'apl'
data_char2←'⍺⍵÷'

caselist←⎕NL ¯2
caselist←caselist⌿⍨{'data_'⊃⍤⍷⍵}¨caselist

:For case :In caselist
data←⍎case
desc←testDesc
r,←'Not (~)'desc quadparams RunVariations⊂data
:EndFor
:EndFor
:EndFor
:EndNamespace
Loading