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

\  Permutations of math operations (+, -,  *, /) for numbers and 
\  matrices dense and sparse.

\-----------------------------------------------------------------------

   3 3 random into DENSE 
   DENSE into DENSE_SAVE
   DENSE DENSE complex into CDENSE

   DENSE sparse into SPARSE
   SPARSE into SPARSE_SAVE
   SPARSE SPARSE complex into CSPARSE

   10 into NUMBER
   20 into 2NUMBER
   100 into NUMBER^2

   zero "errors" book

   inline: dense_if (hA --- hA) \ A is made dense if it is sparse
      dup is_sparse IF dense ELSE drop THEN ;

\-----------------------------------------------------------------------

\  Addition:
      nl "Addition:" . nl

      DENSE SPARSE + 
      SPARSE DENSE + = not null? not
      IF " error: DENSE + SPARSE" 1 errors bump
      ELSE " sparse+dense, dense+sparse Ok" 
      THEN . nl

      DENSE DENSE +
      SPARSE SPARSE + dense_if = not null? not
      IF " error: DENSE + DENSE" 1 errors bump
      ELSE " dense+dense, sparse+sparse Ok" 
      THEN . nl

      NUMBER DENSE + 
      DENSE NUMBER + = not null? not
      IF " error: NUMBER + DENSE" 1 errors bump
      ELSE " number+dense, dense+number Ok" 
      THEN . nl

      NUMBER SPARSE + 
      SPARSE NUMBER + = not null? not
      IF " error: NUMBER + SPARSE" 1 errors bump 
      ELSE " number+sparse, sparse+number Ok" 
      THEN . nl

      NUMBER NUMBER + 2NUMBER = not 
      IF " error: NUMBER + NUMBER" 1 errors bump
      ELSE " number+number Ok" 
      THEN . nl

      DENSE DENSE_SAVE = not null? not
      IF " error: DENSE_SAVE addition" 1 errors bump
      ELSE " dense memory after add Ok" 
      THEN . nl

      SPARSE dense SPARSE_SAVE dense = not null? not
      IF " error: SPARSE_SAVE addition" 1 errors bump
      ELSE " sparse memory after add Ok" 
      THEN . nl

\     A few complex tests:
      DENSE CSPARSE +
      SPARSE CDENSE + = not null? not
      IF " error: DENSE + CSPARSE" 1 errors bump
      ELSE " dense+complex_sparse, complex_dense+sparse Ok"
      THEN . nl

      NUMBER CSPARSE +
      CSPARSE NUMBER + = not null? not
      IF " error: NUMBER + CSPARSE" 1 errors bump
      ELSE " number+complex_sparse, complex_sparse+number Ok"
      THEN . nl

\-----------------------------------------------------------------------

\  Subtraction:
      nl "Subtraction:" . nl

      DENSE SPARSE - 
      SPARSE DENSE - = not null? not
      IF " error: DENSE - SPARSE" 1 errors bump
      ELSE " sparse-dense, dense-sparse Ok"
      THEN . nl

      DENSE DENSE -
      SPARSE SPARSE - dense_if = not null? not
      IF " error: DENSE - DENSE" 1 errors bump
      ELSE " dense-dense, sparse-sparse Ok"
      THEN . nl
   
      NUMBER DENSE - 
      DENSE NUMBER - negate = not null? not
      IF " error: NUMBER - DENSE" 1 errors bump 
      ELSE " number-dense, dense-number Ok"
      THEN . nl
   
      NUMBER SPARSE - 
      SPARSE NUMBER - negate = not null? not
      IF " error: NUMBER - SPARSE" 1 errors bump 
      ELSE " number-sparse, sparse-number Ok"
      THEN . nl

      NUMBER NUMBER - 0= not
      IF " error: NUMBER - NUMBER" 1 errors bump 
      ELSE " number-number Ok"
      THEN . nl

      DENSE DENSE_SAVE = not null? not
      IF " error: DENSE_SAVE subtraction" 1 errors bump
      ELSE " dense memory after subtraction Ok"
      THEN . nl

      SPARSE dense SPARSE_SAVE dense = not null? not
      IF " error: SPARSE_SAVE subtraction" 1 errors bump 
      ELSE " sparse memory after subtraction Ok"
      THEN . nl

\     A few complex tests:
      DENSE CSPARSE -
      SPARSE CDENSE - = not null? not
      IF " error: DENSE + CSPARSE" 1 errors bump
      ELSE " dense-complex_sparse, complex_dense-sparse Ok"
      THEN . nl
  
      NUMBER CSPARSE -
      CSPARSE NUMBER - negate = not null? not
      IF " error: NUMBER - CSPARSE" 1 errors bump
      ELSE " number-complex_sparse, complex_sparse-number Ok"
      THEN . nl

\-----------------------------------------------------------------------

\  Multiplication:
      nl "Multiplication:" . nl

      DENSE SPARSE *
      SPARSE DENSE * - 1E-12 filter null? not
      IF " error: DENSE * SPARSE" 1 errors bump
      ELSE " sparse*dense, dense*sparse Ok"
      THEN . nl

      DENSE DENSE *
      SPARSE SPARSE * - 1E-12 filter null? not
      IF " error: DENSE * DENSE" 1 errors bump
      ELSE " dense*dense, sparse*sparse Ok"
      THEN . nl

      NUMBER DENSE *
      DENSE NUMBER * - 1E-12 filter null? not
      IF " error: NUMBER * DENSE" 1 errors bump
      ELSE " number*dense, dense*number Ok"
      THEN . nl

      NUMBER SPARSE *
      SPARSE NUMBER * - 1E-12 filter null? not
      IF " error: NUMBER * SPARSE" 1 errors bump
      ELSE " number*sparse, sparse*number Ok"
      THEN . nl

      NUMBER NUMBER * NUMBER^2 = not
      IF " error: NUMBER * NUMBER" 1 errors bump 
      ELSE " number*number Ok"
      THEN . nl

      DENSE DENSE_SAVE = not null? not
      IF " error: DENSE_SAVE multiplication" 1 errors bump
      ELSE " dense memory after multiplication Ok"
      THEN . nl

      SPARSE dense SPARSE_SAVE dense = not null? not
      IF " error: SPARSE_SAVE multiplication" 1 errors bump
      ELSE " sparse memory after add Ok"
      THEN . nl

\-----------------------------------------------------------------------

\  Division:
      nl "Division term-by-term:" . nl

      DENSE SPARSE /
      SPARSE DENSE / - 1E-12 filter null? not
      IF " error: DENSE / SPARSE" 1 errors bump
      ELSE " sparse/dense, dense/sparse Ok"
      THEN . nl

      DENSE DENSE /
      SPARSE SPARSE / - 1E-12 filter null? not
      IF " error: DENSE / DENSE" 1 errors bump
      ELSE " dense/dense, sparse/sparse Ok"
      THEN . nl

      1 NUMBER / DENSE *
      DENSE NUMBER / - 1E-12 filter null? not
      IF " error: NUMBER / DENSE" 1 errors bump
      ELSE " number/dense, dense/number Ok"
      THEN . nl

      NUMBER DENSE /
      NUMBER DENSE dims fill DENSE / - 1E-12 filter null? not
      IF " error: NUMBER / DENSE" 1 errors bump
      ELSE " number/dense Ok"
      THEN . nl

      NUMBER CDENSE /
      NUMBER CDENSE dims fill CDENSE / - 1E-12 filter null? not
      IF " error: NUMBER / CDENSE" 1 errors bump
      ELSE " number/cdense Ok"
      THEN . nl

      NUMBER 0 complex DENSE /
      NUMBER 0 complex DENSE dims fill DENSE / - 1E-12 filter null? not
      IF " error: CNUMBER / DENSE" 1 errors bump
      ELSE " cnumber/dense Ok"
      THEN . nl

      1 NUMBER / SPARSE *
      SPARSE NUMBER / - 1E-12 filter null? not
      IF " error: NUMBER / SPARSE" 1 errors bump
      ELSE " number/sparse, sparse/number Ok"
      THEN . nl

      NUMBER NUMBER / 1 = not
      IF " error: NUMBER / NUMBER" 1 errors bump
      ELSE " number/number Ok"
      THEN . nl

      DENSE DENSE_SAVE = not null? not
      IF " error: DENSE_SAVE division" 1 errors bump
      ELSE " dense memory after division Ok"
      THEN . nl

      SPARSE dense SPARSE_SAVE dense = not null? not
      IF " error: SPARSE_SAVE division" 1 errors bump
      ELSE " sparse memory after division Ok"
      THEN . nl

\-----------------------------------------------------------------------

      " math_premute:" nl .
      errors any
      IF " ERRORS = " . errors .u
      ELSE " NO ERRORS" .
      THEN nl
