#!../src/tops  -s ../sys  -u ../usr

CATMSG push no catmsg
"ranint" missing
IF
    "math.v" source
THEN
"to_file_N" missing
IF
    "easy_io.v" source
THEN

# define: to_file ( qFile hSp --- ) # {{{1
#     # Writes the sparse matrix on tos to the specified file
#     swap forn binary "SP" file SP fwrite drop drop SP fclose
#     ; # 1}}}
# define: sp_read ( qFile --- hSp ) # {{{1
#     # Loads the sparse matrix from the specified file to tos.
#     old binary "SP" file SP SP file.size pry fget SP fclose
#     ; # 1}}}
define: chk_sprand ( n --- ) # {{{1
    # Word tested:  sprand
    # Creates a random sparse matrix of i x j, where i & j are random values
    # less than <= n.  The sparse matrix is first duplicated and a dense
    # version is made.  Then a number of operations are done to both dense
    # and sparse copies, and the results compared.
    dup
    rand * integer 1 + into R       # rows
    rand * integer 1 + into C       # columns 
    rand               into rho     # density
    R "%3.0f x " format . C "%3.0f" format . rho " %6.4f" format .
    R C rho sprand is A
    A sperror swap drop  \ leaving the error code on the stack
    is ErrorCode
    ErrorCode dup .i
    0 > 
    IF  
        " sprand index ERROR= " . ErrorCode .i " " .
        A "rand.stk" to_file
        A spdump
        " sprand ERROR; wrote sparse matrix to 'rand.stk' " . nl
        halt
    ELSE  
        " sprand OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spbend ( n --- ) # {{{1
    # Word tested:  spbend
    # Creates a random sparse matrix of i x j, where i & j are random values
    # less than <= n.  The sparse matrix is first duplicated and a dense
    # version is made.  Then a number of operations are done to both dense
    # and sparse copies, and the results compared.
    dup
    rand * integer 1 + into R       \ rows
    rand * integer 1 + into C       \ columns 
    rand               into rho     \ density
    R "%3.0f x " format . C "%3.0f" format . rho " %6.4f" format .
    R C rho                         \ ( i j rho )
    sprand dup into mSp             \ mSp <- ( hA_sp hA_sp --- hA_sp )
    dense      into mDn             \ mDn <- ( hA_sp --- )
    mSp spbend dense
    mDn bend
    - maxfetch drop drop 0 > 
    IF  
        " spbend ERROR " . 
        mSp "junk.stk" to_file
        mSp spdump
        " spbend ERROR; wrote sparse matrix to 'junk.stk' " . nl
        halt
    ELSE  
        " spbend OK    " . 
    THEN
    mSp sperror dup "%5.0f " format . 0 > 
    IF 
        " index ERROR "  . 
        mSp "junk.stk" to_file
        mSp spdump
        " spbend ERROR; wrote sparse matrix to 'junk.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN
    nl
    xx
    ; # 1}}}
define: chk_spadd ( n --- ) # {{{1
    # Word tested:  spadd
    # Creates two random sparse matrices of i x j, where i & j are random
    # values less than <= n.  They are added with the sparse code, then
    # converted to dense and added that way.  The sparse sum is compared
    # to the dense sum.
    1.0e-18 is TOLERANCE

    dup
    dup
rand drop # for some reason the first random number is always the same???
    rand * integer 1 + into R       \ rows
    rand * integer 1 + into C       \ columns 
    rand               into rhoA    \ density [A]
    rand               into rhoB    \ density [B]
    R "%3.0f x " format . C "%3.0f" format . rhoA " rA=%5.3f," format . rhoB "rB=%5.3f " format .
    R C rhoA sprand dup into A
    R C rhoB sprand dup into B
    A B spadd into C            # C  = A + B    all sparse
    A dense B dense + into Cd   # Cd = dense(A) + dense(B)

    C dense Cd -                # dense(C) - Cd
    abs maxfetch drop drop 
    dup .
    TOLERANCE > 
    IF  
        " spadd ERROR ". 
         A B "AB.stk" 2 to_file_N
        " spadd ERROR; Wrote A and B to AB.stk " . nl
        halt
    ELSE  
        " spadd  OK" . 
    THEN

    C sperror dup "%5.0f " format . 0 > 
    IF 
        " index ERROR "  . nl
         A B "AB.stk" 2 to_file_N
        " spadd ERROR; Wrote A and B to AB.stk " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN
    nl
    xx

    ; # 1}}}
define: chk_sp_real_complex ( n --- ) # {{{1
    # Word tested:  sparse (for complex input)
    # 1. Create two sparse random matrices.
    # 2. Convert them to dense.
    # 3. Merge the dense matrices into a complex dense matrix.
    # 4. Convert the dense complex matrix into a sparse complex matrix.
    # 5. Convert the sparse complex matrix back to a dense complex matrix
    #    and compare with the result of step 4.
    1.0e-18 is TOLERANCE

    dup
    rand * integer 1 + into R       \ rows
    rand * integer 1 + into C       \ columns 
    rand               into rhoA    \ density [A]
    rand               into rhoB    \ density [B]
    R "%3.0f x " format . C "%3.0f" format . rhoA " rA=%5.3f," format . rhoB "rB=%5.3f " format .
    R C rhoA sprand dup into A
    R C rhoB sprand dup into B

    A dense B dense complex is C # C = A + iB   ; C is dense
    C    sparse is C_sp
    C_sp dense  is C_recon

    C C_recon -
    abs maxfetch drop drop 
    dup .
    TOLERANCE > 
    IF  
        " complex/real ERROR " . 
        C_sp "C.stk" to_file
        " sparse (C) ERROR; Wrote C to C.stk " . nl
        halt
    ELSE  
        " complex/real  OK" . 
    THEN

    C_sp sperror dup "%5.0f " format . 0 > 
    IF 
        " index ERROR "  . nl
        C_sp "C.stk" to_file
        " sparse (C) ERROR; Wrote C to C.stk " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN
    nl
    xx
    ; # 1}}}
define: chk_spreal_imag ( n --- ) # {{{1
    # Word tested:  spreal_imag
    # 1. Create two sparse random matrices.
    # 2. Convert them to dense.
    # 3. Merge the dense matrices into a complex dense matrix.
    # 4. Convert the dense complex matrix into a sparse complex matrix.
    # 5. Split the sparse complex matrix apart into Re,Im parts with
    #    spreal_imag
    # 6. Convert the separated Re,Im parts into dense matrices and
    #    compare with the matrices of step 2.
    1.0e-18 is TOLERANCE

    dup
    rand * integer 1 + into R       \ rows
    rand * integer 1 + into C       \ columns 
    rand               into rhoA    \ density [A]
    rand               into rhoB    \ density [B]
    R "%3.0f x " format . C "%3.0f" format . rhoA " rA=%5.3f," format . rhoB "rB=%5.3f " format .
    R C rhoA sprand dense into A
    R C rhoB sprand dense into B

    A B complex is C # C = A + iB   ; C is dense
    C    sparse is C_sp
    C_sp spreal_imag

    dense is b_recon
    dense is a_recon

    " spreal_imag " . 

    A a_recon -
    abs maxfetch drop drop 
    dup .
    TOLERANCE > 
    IF  
        " Im ERROR " . 
        C_sp "C.stk" to_file
        " spreal_imag ERROR; Wrote C to C.stk " . nl
        halt
    ELSE  
        " Im OK" . 
    THEN

    B b_recon -
    abs maxfetch drop drop 
    dup .
    TOLERANCE > 
    IF  
        " Re ERROR " . 
        C_sp "C.stk" to_file
        " spreal_imag ERROR; Wrote C to C.stk " . nl
        halt
    ELSE  
        " Re OK" . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spparkn_real ( n --- ) # {{{1
    # Word tested:  spparkn (real input)
    # 1. Create four sparse random matrices.  Each matrix has the same
    #    number of rows but different numbers of columns.
    # 2. Convert them to dense.
    # 3. Append columns of the dense matrix columns into a single
    #    dense matrix with "4 parkn".
    # 4. Append columns of the sparse matrices into a single sparse
    #    matrix with "4 spparkn".
    # 5. Convert the sparse appended matrix into a dense matrix and
    #    compare with the matrix of step 3.
    1.0e-18 is TOLERANCE

    dup
    dup
    dup
    dup
    rand * integer 1 + into C1      \ columns 
    rand * integer 1 + into C2      \ columns 
    rand * integer 1 + into C3      \ columns 
    rand * integer 1 + into C4      \ columns 
    rand * integer 1 + into R       \ rows
    rand               into rho1    \ density [1]
    rand               into rho2    \ density [2]
    rand               into rho3    \ density [3]
    rand               into rho4    \ density [4]
    R "%3.0f x " format .  C1 "[%3.0f," format .  C2 "%3.0f," format .  C3 "%3.0f," format .  C4 "%3.0f]" format .  rho1 " [%4.2f," format .  rho2 "%4.2f," format .  rho3 "%4.2f," format .  rho4 "%4.2f]" format .
    R C1 rho1 sprand into A_sp
    R C2 rho2 sprand into B_sp
    R C3 rho3 sprand into C_sp
    R C4 rho4 sprand into D_sp

    A_sp dense 
    B_sp dense 
    C_sp dense 
    D_sp dense 4 parkn is E_dn

    A_sp  
    B_sp  
    C_sp  
    D_sp       4 spparkn is E_sp

    " spparkn R" . 

    E_dn E_sp dense -
    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A_sp B_sp C_sp D_sp E_sp 5 "ABCDE_sp.stk" to_file_N
        " spparkn (R) ERROR; Wrote [A-E]_sp to ABCDE_sp.stk " . nl
        halt
    ELSE  
        " OK" . 
    THEN

    E_sp sperror
    dup .i
    0 >
    IF
        " index ERROR " . 
        A_sp B_sp C_sp D_sp E_sp 5 "ABCDE_sp.stk" to_file_N
        " spparkn (R) ERROR; Wrote [A-E]_sp to ABCDE_sp.stk " . nl
        halt
    ELSE
        " OK" . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spparkn_cmplx ( n --- ) # {{{1
    # Word tested:  spparkn (complex input)
    # 1. Create eight sparse random matrices.  Each matrix has the same
    #    number of rows but different numbers of columns.  Pair them up
    #    as Re,Im.
    # 2. Pair the eight sparse matrices into four Re,Im pairs then
    #    make sparse complex matrices via dense -> complex -> sparse
    # 3. Convert the sparse complex matrices into dense complex matrices.
    # 4. Append columns of the dense matrix columns into a single
    #    dense matrix with "4 parkn".
    # 5. Append columns of the sparse matrices into a single sparse
    #    matrix with "4 spparkn".
    # 6. Convert the sparse appended matrix into a dense matrix and
    #    compare with the matrix of step 3.
    1.0e-18 is TOLERANCE

    dup dup dup dup
    rand * integer 1 + into C1      # columns 
    rand * integer 1 + into C2      # columns 
    rand * integer 1 + into C3      # columns 
    rand * integer 1 + into C4      # columns 
    rand * integer 1 + into R       # rows
    rand               into rho1    # density [1]
    rand               into rho2    # density [2]
    rand               into rho3    # density [3]
    rand               into rho4    # density [4]
    R "%3.0f x " format .  C1 "[%3.0f," format .  C2 "%3.0f," format .  C3 "%3.0f," format .  C4 "%3.0f]" format .  rho1 " [%4.2f," format .  rho2 "%4.2f," format .  rho3 "%4.2f," format .  rho4 "%4.2f]" format .
    R C1 rho1 sprand into Ar_sp
    R C2 rho2 sprand into Br_sp
    R C3 rho3 sprand into Cr_sp
    R C4 rho4 sprand into Dr_sp
    R C1 rho1 sprand into Ai_sp
    R C2 rho2 sprand into Bi_sp
    R C3 rho3 sprand into Ci_sp
    R C4 rho4 sprand into Di_sp

    Ar_sp dense Ai_sp dense complex sparse is A_sp
    Br_sp dense Bi_sp dense complex sparse is B_sp
    Cr_sp dense Ci_sp dense complex sparse is C_sp
    Dr_sp dense Di_sp dense complex sparse is D_sp

    A_sp dense is A_dn 
    B_sp dense is B_dn 
    C_sp dense is C_dn 
    D_sp dense is D_dn      
    
    A_sp B_sp C_sp D_sp 4 spparkn is E_sp
    A_dn B_dn C_dn D_dn 4   parkn is E_dn

    " spparkn C" . 

    E_dn E_sp dense -
    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A_sp B_sp C_sp D_sp E_sp 5 "ABCDE_sp.stk" to_file_N
        " spparkn (R) ERROR; Wrote [A-E]_sp to ABCDE_sp.stk " . nl
        halt
    ELSE  
        " OK" . 
    THEN

    E_sp sperror
    dup .i
    0 >
    IF
        " index ERROR " . 
        A_sp B_sp C_sp D_sp E_sp 5 "ABCDE_sp.stk" to_file_N
        " spparkn (R) ERROR; Wrote [A-E]_sp to ABCDE_sp.stk " . nl
        halt
    ELSE
        " OK" . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_sp_ijv_real ( n --- ) # {{{1
    # Words tested:  spconvert, sp2ijv
    # 1. Create a real sparse random matrix.
    # 2. Convert it to IJV format, then convert the IJV format back to
    #    a sparse matrix.
    # 3. Compare the sparse reconstruction to the matrix of step 1.
    1.0e-18 is TOLERANCE

    dup
    rand * integer 1 + into C       # columns 
    rand * integer 1 + into R       # rows
    rand               into rho     # density
    R "%3.0f x " format .  C "%3.0f " format . rho " rho=%4.2f" format .
    R C  rho  sprand into A
    A sp2ijv spconvert is B

    " sp2ijv <-> spconvert (R) " . 

    A dense B dense -
    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A B 2 "AB.stk" to_file_N
        " sp_ijv ERROR; Wrote A, B to AB.stk " . nl
        halt
    ELSE  
        " OK" . 
    THEN

    B sperror dup .i 0 > 
    IF 
        " index ERROR "  . 
        B "B.stk" to_file
        A spdump
        " sp_ijv index ERROR; wrote sparse matrix to 'B.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_sp_ijv_cmplx ( n --- ) # {{{1
    # Words tested:  spconvert, sp2ijv
    # 1. Create a complex sparse random matrix.
    # 2. Convert it to IJV format, then convert the IJV format back to
    #    a sparse matrix.
    # 3. Compare the sparse reconstruction to the matrix of step 1.
    1.0e-18 is TOLERANCE

    dup dup
    rand * integer 1 + into C       # columns 
    rand * integer 1 + into R       # rows
    rand               into rho     # density
    R "%3.0f x " format .  C "%3.0f " format . rho " rho=%4.2f" format .
    R C  rho  sprand dense
    R C  rho  sprand dense complex sparse is A
    A sp2ijv spconvert is B

    " sp2ijv <-> spconvert (C) " . 

    A dense B dense -
    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A "A.stk" to_file
        " sp_ijv ERROR; Wrote A to A.stk " . nl
        halt
    ELSE  
        " OK" . 
    THEN

    B sperror dup .i 0 > 
    IF 
        " index ERROR "  . 
        B "B.stk" to_file
        A spdump
        " sp_ijv index ERROR; wrote sparse matrix to 'B.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_sppilen_real ( n --- ) # {{{1
    # Word tested:  sppilen (real input)
    # 1. Create four sparse random matrices.  Each matrix has the same
    #    number of columns but different numbers of rows.
    # 2. Convert them to dense.
    # 3. Stack rows of the dense matrix into a single
    #    dense matrix with "4 pilen".
    # 4. Stack rows of the sparse matrices into a single sparse
    #    matrix with "4 sppilen".
    # 5. Convert the sparse stacked matrix into a dense matrix and
    #    compare with the matrix of step 3.
    1.0e-18 is TOLERANCE

    dup
    dup
    dup
    dup
    rand * integer 1 + into R1      \ rows 
    rand * integer 1 + into R2      \ rows 
    rand * integer 1 + into R3      \ rows 
    rand * integer 1 + into R4      \ rows 
    rand * integer 1 + into C       \ columns
    rand               into rho1    \ density [1]
    rand               into rho2    \ density [2]
    rand               into rho3    \ density [3]
    rand               into rho4    \ density [4]
    R1 "[%3.0f," format .  R2 "%3.0f," format .  R3 "%3.0f," format .  R4 "%3.0f]" format . C " x %3.0f" format .  rho1 " [%4.2f," format .  rho2 "%4.2f," format .  rho3 "%4.2f," format .  rho4 "%4.2f]" format .
    R1 C rho1 sprand into A_sp
    R2 C rho2 sprand into B_sp
    R3 C rho3 sprand into C_sp
    R4 C rho4 sprand into D_sp

    A_sp dense 
    B_sp dense 
    C_sp dense 
    D_sp dense 4 pilen is E_dn

    A_sp  
    B_sp  
    C_sp  
    D_sp       4 sppilen is E_sp

    " sppilen R" . 

    E_dn E_sp dense -
    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A_sp B_sp C_sp D_sp E_sp 5 "ABCDE_sp.stk" to_file_N
        " sppilen (R) ERROR; Wrote [A-E]_sp to ABCDE_sp.stk " . nl
        halt
    ELSE  
        " OK" . 
    THEN

    E_sp sperror
    dup .i
    0 >
    IF
        " index ERROR " . 
        A_sp B_sp C_sp D_sp E_sp 5 "ABCDE_sp.stk" to_file_N
        " sppilen (R) ERROR; Wrote [A-E]_sp to ABCDE_sp.stk " . nl
        halt
    ELSE
        " OK" . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_sppilen_cmplx ( n --- ) # {{{1
    # Word tested:  sppilen (real input)
    # 1. Create four sparse random matrices.  Each matrix has the same
    #    number of columns but different numbers of rows.
    # 2. Convert them to dense.
    # 3. Stack rows of the dense matrix into a single
    #    dense matrix with "4 pilen".
    # 4. Stack rows of the sparse matrices into a single sparse
    #    matrix with "4 sppilen".
    # 5. Convert the sparse stacked matrix into a dense matrix and
    #    compare with the matrix of step 3.
    1.0e-18 is TOLERANCE

    dup
    dup
    dup
    dup
    rand * integer 1 + into R1      \ rows 
    rand * integer 1 + into R2      \ rows 
    rand * integer 1 + into R3      \ rows 
    rand * integer 1 + into R4      \ rows 
    rand * integer 1 + into C       \ columns
    rand               into rho1    \ density [1]
    rand               into rho2    \ density [2]
    rand               into rho3    \ density [3]
    rand               into rho4    \ density [4]
    R1 "[%3.0f," format .  R2 "%3.0f," format .  R3 "%3.0f," format .  R4 "%3.0f]" format . C " x %3.0f" format .  rho1 " [%4.2f," format .  rho2 "%4.2f," format .  rho3 "%4.2f," format .  rho4 "%4.2f]" format .

    R1 C rho1 sprand into Ar_sp
    R2 C rho2 sprand into Br_sp
    R3 C rho3 sprand into Cr_sp
    R4 C rho4 sprand into Dr_sp
    R1 C rho1 sprand into Ai_sp
    R2 C rho2 sprand into Bi_sp
    R3 C rho3 sprand into Ci_sp
    R4 C rho4 sprand into Di_sp

    Ar_sp dense Ai_sp dense complex is A
    Br_sp dense Bi_sp dense complex is B
    Cr_sp dense Ci_sp dense complex is C
    Dr_sp dense Di_sp dense complex is D
    A 
    B 
    C 
    D     4 pilen is E_dn
#   nl E_dn .m nl

    A sparse is A_sp
    B sparse is B_sp
    C sparse is C_sp
    D sparse is D_sp
    A_sp  
    B_sp  
    C_sp  
    D_sp  4 sppilen is E_sp
#   nl E_sp dense .m nl

    " sppilen C" . 

    E_dn E_sp dense -
    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A_sp B_sp C_sp D_sp E_sp 5 "ABCDE_sp.stk" to_file_N
        " sppilen (C) ERROR; Wrote [A-E]_sp to ABCDE_sp.stk " . nl
        halt
    ELSE  
        " OK" . 
    THEN

    E_sp sperror
    dup .i
    0 >
    IF
        " index ERROR " . 
        A_sp B_sp C_sp D_sp E_sp 5 "ABCDE_sp.stk" to_file_N
        " sppilen (C) ERROR; Wrote [A-E]_sp to ABCDE_sp.stk " . nl
        halt
    ELSE
        " OK" . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spcatch_real ( n --- ) # {{{1
    # Words tested:  spcatch
    # 1. Create a real sparse random matrix.
    # 2. Create a random column rake vector.
    # 3. Convert the sparse matrix to dense then extract 'raked' columns
    #    with catch.
    # 4. Extract 'raked' columns from the sparse matrix with spcatch.
    # 5. Compare the dense and sparse raked submatrices.
    1.0e-18 is TOLERANCE

    dup
    rand * integer 1 + into C       # columns 
    rand * integer 1 + into R       # rows
    rand               into rho     # density
    rand C * integer 1 + is RakeSize
    R "%3.0f x " format .  C "%3.0f " format . rho " rho=%4.2f" format . RakeSize " rake size=%3.0f" format .
    R C  rho  sprand into A
    1 C 1 RakeSize ranint bend is Rake

    " spcatch (R) " . 

    A dense Rake   catch is Rdn
    A       Rake spcatch is Rsp
    Rdn Rsp dense -

    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A Rake sparse 2 "AR.stk" to_file_N
        " spcatch ERROR; Wrote A, Rake to AR.stk" . nl
        halt
    ELSE  
        " OK" . 
    THEN

    Rsp sperror dup .i 0 > 
    IF 
        " index ERROR "  . 
        Rsp "Rsp.stk" to_file
        " spcatch index ERROR; wrote Rsp to 'Rsp.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spcatch_cmplx ( n --- ) # {{{1
    # Words tested:  spcatch
    # 1. Create a complex sparse random matrix.
    # 2. Create a random column rake vector.
    # 3. Convert the sparse matrix to dense then extract 'raked' columns
    #    with catch.
    # 4. Extract 'raked' columns from the sparse matrix with spcatch.
    # 5. Compare the dense and sparse raked submatrices.
    1.0e-18 is TOLERANCE

    dup
    rand * integer 1 + into C       # columns 
    rand * integer 1 + into R       # rows
    rand               into rho     # density
    rand C * integer 1 + is RakeSize
    R "%3.0f x " format .  C "%3.0f " format . rho " rho=%4.2f" format . RakeSize " rake size=%3.0f" format .
    R C  rho  sprand into Are
    R C  rho  sprand into Aim
    Are dense Aim dense complex sparse is A
    1 C 1 RakeSize ranint bend is Rake

    " spcatch (C) " . 

    A dense Rake   catch is Rdn
    A       Rake spcatch is Rsp
    Rdn Rsp dense -

    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A Rake sparse 2 "AR.stk" to_file_N
        " spcatch ERROR; Wrote A, Rake to AR.stk" . nl
        halt
    ELSE  
        " OK" . 
    THEN

    Rsp sperror dup .i 0 > 
    IF 
        " index ERROR "  . 
        Rsp "Rsp.stk" to_file
        " spcatch index ERROR; wrote Rsp to 'Rsp.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spreach_real ( n --- ) # {{{1
    # Words tested:  spreach
    # 1. Create a real sparse random matrix.
    # 2. Create a random column rake vector.
    # 3. Convert the sparse matrix to dense then extract 'raked' columns
    #    with reach.
    # 4. Extract 'raked' columns from the sparse matrix with spreach.
    # 5. Compare the dense and sparse raked submatrices.
    1.0e-18 is TOLERANCE

    dup
    rand * integer 1 + into C       # columns 
    rand * integer 1 + into R       # rows
    rand               into rho     # density
    rand R * integer 1 + is RakeSize
    R "%3.0f x " format .  C "%3.0f " format . rho " rho=%4.2f" format . RakeSize " rake size=%3.0f" format .
    R C  rho  sprand into A
    1 R 1 RakeSize ranint bend is Rake

    " spreach (R) " . 

    A dense Rake   reach is Rdn
    A       Rake spreach is Rsp
    Rdn Rsp dense -

    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A Rake sparse 2 "AR.stk" to_file_N
        " spreach ERROR; Wrote A, Rake to AR.stk" . nl
        halt
    ELSE  
        " OK" . 
    THEN

    Rsp sperror dup .i 0 > 
    IF 
        " index ERROR "  . 
        Rsp "Rsp.stk" to_file
        " spreach index ERROR; wrote Rsp to 'Rsp.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spreach_cmplx ( n --- ) # {{{1
    # Words tested:  spreach
    # 1. Create a complex sparse random matrix.
    # 2. Create a random column rake vector.
    # 3. Convert the sparse matrix to dense then extract 'raked' columns
    #    with reach.
    # 4. Extract 'raked' columns from the sparse matrix with spreach.
    # 5. Compare the dense and sparse raked submatrices.
    1.0e-18 is TOLERANCE

    dup
    rand * integer 1 + into C       # columns 
    rand * integer 1 + into R       # rows
    rand               into rho     # density
    rand R * integer 1 + is RakeSize
    R "%3.0f x " format .  C "%3.0f " format . rho " rho=%4.2f" format . RakeSize " rake size=%3.0f" format .
    R C  rho  sprand into Are
    R C  rho  sprand into Aim
    Are dense Aim dense complex sparse is A
    1 R 1 RakeSize ranint bend is Rake

    " spreach (C) " . 

    A dense Rake   reach is Rdn
    A       Rake spreach is Rsp
    Rdn Rsp dense -

    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A Rake sparse 2 "AR.stk" to_file_N
        " spreach ERROR; Wrote A, Rake to AR.stk" . nl
        halt
    ELSE  
        " OK" . 
    THEN

    Rsp sperror dup .i 0 > 
    IF 
        " index ERROR "  . 
        Rsp "Rsp.stk" to_file
        " spreach index ERROR; wrote Rsp to 'Rsp.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spcomb_real ( n --- ) # {{{1
    # Words tested:  spcomb
    # 1. Create a real sparse random matrix.
    # 2. Create a random column comb vector ( 0's and 1's to mask A0, A1)
    # 3. Convert the sparse matrix to dense then apply comb.
    # 4. Save the dense combed partitions A0 and A1.
    # 5. Use spcomb to apply the comb to the original sparse matrix.
    # 6. Compare the dense and sparse partitions A0 and A1.
    #
    # Note:  null comb vectors, ie, those with all 0's or all 1's are
    #        deliberately not tested since there is no concept of a 
    #        purged sparse matrix.
    #
    1.0e-18 is TOLERANCE

    dup
    rand * integer 1 + into C       # columns 
    rand * integer 1 + into R       # rows
    rand               into rho     # density
    rand R * integer 1 + is RakeSize
    R "%3.0f x " format .  C "%3.0f " format . rho " rho=%4.2f" format . RakeSize " rake size=%3.0f" format .
    R C  rho  sprand into A
    1 R 1 RakeSize ranint bend is Rake

    " spreach (R) " . 

    A dense Rake   reach is Rdn
    A       Rake spreach is Rsp
    Rdn Rsp dense -

    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        A Rake sparse 2 "AR.stk" to_file_N
        " spreach ERROR; Wrote A, Rake to AR.stk" . nl
        halt
    ELSE  
        " OK" . 
    THEN

    Rsp sperror dup .i 0 > 
    IF 
        " index ERROR "  . 
        Rsp "Rsp.stk" to_file
        " spreach index ERROR; wrote Rsp to 'Rsp.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spflip_sym ( n --- ) # {{{1
    1.0e-18 is TOLERANCE

    dup
    rand * integer 2 + into C       # columns 
    rand               into rho     # density
    C "%3.0f x " format .  C "%3.0f " format . rho " rho=%4.2f" format .
    C C  rho  sprand dense 0 tril sparse into L

    " spflip_sym " . 

    L dense dup 1 tril bend + is Ld_full
    L spflip_sym              is LLt
    Ld_full LLt dense -

    abs maxfetch drop drop 
    dup " %6.3e" format .
    TOLERANCE > 
    IF  
        " ERROR " . 
        L "L.stk" to_file
        " spflip_sym ERROR; Wrote L to L.stk" . nl
        halt
    ELSE  
        " OK" . 
    THEN

    LLt sperror dup .i 0 > 
    IF 
        " index ERROR "  . 
        LLt "LLt.stk" to_file
        " spflip_sym index ERROR; wrote LLt to 'LLt.stk' " . nl
        halt
    ELSE    
        " index OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: chk_spinflate ( n --- ) # {{{1
    # Word tested:  spinflate
    # Compares the results of dense and sparse matrix inflations for
    # random input vectors.
1.0e-10 is TOLERANCE

    dup
    dup
    dup
    rand * integer 1 + into RA       # rows     [A]
    rand * integer 1 + into CA       # columns  [A]
    rand * integer 1 + RA + into RB  # rows     [B]
    rand * integer 1 + CA + into CB  # columns  [B]
    rand               into rhoR     # density  [Ar]
    rand               into rhoI     # density  [Ai]
    RA CA rhoR sprand is Ar
    RA CA rhoI sprand is Ai
    flip IF
        Ar            is A
        true          is CMPLX
    ELSE  
        Ar Ai complex is A
        false         is CMPLX
    THEN  
    RA "%3.0f x " format . CA "%3.0f" format . 
    rhoR " %6.4f" format . 
    CMPLX IF
        rhoI ",%6.4f" format . 
    ELSE
        "       " . 
    THEN
    RB " -> %2.0f " format . CB " x %2.0f " format .


    # creating row & column index vectors without repeated values 
    1 RB uniform  1 + shuffle RA endmost is Rind
    1 CB uniform  1 + shuffle CA endmost is Cind

    A dense  Rind Cind RB CB   inflate is B_dense
    A        Rind Cind RB CB spinflate is B_sparse

    B_dense B_sparse dense -
    abs maxfetch drop drop
    dup " spinflate %6.3e" format .
    TOLERANCE > 
    IF  
        A Rind Cind RB CB 5 'inflate.stk' to_file_N
        " spinflate ERROR; wrote A Rind Cind RB CB to 'inflate.stk' " . nl
        halt
    ELSE  
        " OK    " . 
    THEN

    nl
    xx
    ; # 1}}}
define: n_sprand_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_sprand nIter times for a random sized systems (up to nSize)
    into nSize
    1 DO I nSize 
        I "%5.0f.  " format .
        chk_sprand 
        xx
    LOOP
    ; # 1}}}
define: n_spbend_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_spbend nIter times for a random sized systems (up to nSize)
    into nSize
    1 DO I nSize 
        I "%5.0f.  " format .
        chk_spbend 
        xx
    LOOP
    ; # 1}}}
define: n_spadd_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_spadd nIter times for a random sized systems (up to nSize)
    into nSize
    1 DO I nSize 
        I "%5.0f.  " format .
        chk_spadd 
        xx
    LOOP
    ; # 1}}}
define: n_sp_real_complex_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_sp_real_complex nIter times for a random sized systems 
    # (up to nSize)
    into nSize
    1 DO I nSize 
        I "%5.0f.  " format .
        chk_sp_real_complex 
        xx
    LOOP
    ; # 1}}}
define: n_spreal_imag_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_sp_real_imag nIter times for a random sized systems 
    # (up to nSize)
    into nSize
    1 DO I nSize 
        I "%5.0f.  " format .
        chk_spreal_imag 
        xx
    LOOP
    ; # 1}}}
define: n_spparkn_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_spparkn nIter times for a random sized systems (up to nSize)
    into nSize
    into nIter
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_spparkn_real
    LOOP
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_spparkn_cmplx
    LOOP
    xx
    ; # 1}}}
define: n_sp_ijv_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_sp_ijv nIter times for a random sized systems (up to nSize)
    into nSize
    into nIter
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_sp_ijv_real
    LOOP
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_sp_ijv_cmplx
    LOOP
    xx
    ; # 1}}}
define: n_sppilen_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_sppilen nIter times for a random sized systems (up to nSize)
    into nSize
    into nIter
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_sppilen_real
    LOOP
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_sppilen_cmplx
    LOOP
    xx
    ; # 1}}}
define: n_spcatch_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_spcatch nIter times for a random sized systems (up to nSize)
    into nSize
    into nIter
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_spcatch_real
    LOOP
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_spcatch_cmplx
    LOOP
    xx
    ; # 1}}}
define: n_spreach_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_spreach nIter times for a random sized systems (up to nSize)
    into nSize
    into nIter
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_spreach_real
    LOOP
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_spreach_cmplx
    LOOP
    xx
    ; # 1}}}
define: n_spcomb_tests ( nIter nSize  --- ) # {{{1
    # Invokes chk_spcomb nIter times for a random sized systems (up to nSize)
    into nSize
    into nIter
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_spcomb_real
    LOOP
#   nIter 1 DO I nSize 
#       I "%5.0f.  " format .
#       nSize chk_spcomb_cmplx
#   LOOP
    xx
    ; # 1}}}
define: n_spflip_sym_tests ( nIter nSize  --- ) # {{{1
    into nSize
    into nIter
    nIter 1 DO I nSize 
        I "%5.0f.  " format .
        nSize chk_spflip_sym
    LOOP
    xx
    ; # 1}}}
define: n_spinflate_tests ( nIter nSize  --- ) # {{{1
    into nSize
    1 DO I nSize 
        I "%5.0f.  " format .
        chk_spinflate 
        xx
    LOOP
    ; # 1}}}

time seedset
# Iter Size
  50   50 n_sprand_tests              nl
  50   50 n_spbend_tests              nl
  50   50 n_spadd_tests               nl
  50   50 n_sp_real_complex_tests     nl
  50   50 n_spreal_imag_tests         nl
  50   50 n_spcatch_tests             nl
  50   50 n_spreach_tests             nl
  50   50 n_spparkn_tests             nl
  50   50 n_sp_ijv_tests              nl
  50   50 n_sppilen_tests             nl
  50   50 n_spflip_sym_tests          nl
  50   20 n_spinflate_tests           nl
