Mercurial > octave
view test/mk-sparse-tst.sh @ 32062:ada96a467a28
quiver: Improve plotting with non-float numeric inputs (bug #59695)
* scripts/plot/draw/private/__quiver__.m: Change firstnonnumeric check to look
for char instead of numeric to allow for logical inputs. Recast all inputs
up to firstnonnumeric as doubles. Check if firstnonnumeric element is 'off'
and if so set scale factor to 0 and increment firstnonnumeric.
* scripts/plot/draw/quiver.m: Update docstring to include scaling factor
option 'off'. Add BIST for int and logical input types.
* scripts/plot/draw/quiver3.m: Update docstring to include scaling factor
option 'off'. Add BISTs for too-few inputs.
* etc/NEWS.9.md: Appended details of changes to quiver note under General
Improvements and noted it also applies to quiver3.
author | Nicholas R. Jankowski <jankowski.nicholas@gmail.com> |
---|---|
date | Wed, 26 Apr 2023 17:18:50 -0400 |
parents | bade9602c5a1 |
children | 3b9305e62bb7 |
line wrap: on
line source
#! /bin/sh ######################################################################## ## ## Copyright (C) 2006-2023 The Octave Project Developers ## ## See the file COPYRIGHT.md in the top-level directory of this ## distribution or <https://octave.org/copyright/>. ## ## This file is part of Octave. ## ## Octave is free software: you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## ######################################################################## # Some tests are commented out because they are known to be broken! # Search for "# fails" # ./build-sparse-tests.sh preset # creates sparse.tst with preset tests. # Use "test sparse.tst" from octave to run the tests. # # ./build-sparse-tests.sh random # Creates sprandom.tst with randomly generated matrices. # Use "test sprandom.tst" from octave to run the tests. # build-sparse-tests.sh generates tests for real and complex sparse matrices. # Also, we want to run both fixed tests with known outputs (quick tests) # and longer tests with unknown outputs (thorough tests). This requires # two sets of tests -- one which uses preset matrices and another which # uses randomly generated matrices. # # The tests are mostly identical for each case but the code is different, # so it is important that the tests be run on all cases. Because our test # harness doesn't have support for looping or macros (it is only needed # for new data types), but sh does, we use sh to generate inline versions of # the tests for each case. # # Our 'macros' use shared variables as parameters. This allows us to # for example define A complex and include all the unary ops tests, # then set A=real(A) and include all the unary ops tests. Thus the # same tests work for real and complex. For binary tests it is even # more complicated because we want full X sparse, sparse X full and # sparse X sparse tested. # # We use the following macros: # # gen_section # place a separator in the test file # gen_function # define the function definion # helper gen_specific # specific tests such as error handling and null input # helper gen_eat_zeros # make sure sparse-scalar ops which generate 0 work # gen_specific_tests # specific and eat zeros tests # helper gen_ordering_tests # ordered comparison operators for real valued tests # helper gen_sparsesparse_ordering_tests # ordered comparison operators for real valued sparse-sparse tests # helper gen_elementop_tests # element-wise matrix binary operators, including scalar-matrix ops. # horizontal/vertical concatenation are here as well. # helper gen_sparsesparse_elementop_tests # element-wise matrix binary operators, for sparse-sparse ops. # horizontal/vertical concatenation are here as well. # helper gen_divop_tests # left and right matrix division operators of rectangular matrices. # Needs QR solvers # helper gen_square_divop_tests # left and right matrix division operators of square matrices. # helper gen_matrixop_tests # rectangular matrix binary operators: * # helper gen_matrixdiag_tests # Tests extract of diag and creation of diagonal matrices using # diag and spdiags functions # helper gen_matrixreshape_tests # Test the reshape function on sparse matrices # helper print_mapper_test # sub-helper function of gen_mapper_tests to print individual tests # helper gen_mapper_tests # Tests all of the one argument mapper functions. There are a few # specific tests that abs, real and imag return real values. # helper gen_unaryop_tests # functions and operators which transform a single matrix # helper gen_save_tests # Tests the load/save functionality for ascii/binary and hdf5 formats # gen_scalar_tests # element ops for real and complex scalar and sparse # gen_rectangular_tests # unary, element, and matrix tests for a and full/sparse b # gen_square_tests # operations which require square matrices: lu, inv, \ # A square non-singular matrix is defined from the rectangular # inputs A and B. # gen_assembly_tests # test for sparse constructors with 'sum' vs. 'unique' # gen_select_tests # indexing and assignment tests # gen_solver_tests # Tests the solve function with triangular/banded, etc matrices case $1 in random) preset=false ;; preset) preset=true ;; '') preset=true ;; *) echo "build-sparse-tests.sh random|preset" && exit 1 ;; esac # create initial file cat <<EOF ## !!! DO NOT EDIT !!! ## THIS IS AN AUTOMATICALLY GENERATED FILE ## modify build-sparse-tests.sh to generate the tests you need. EOF # define all functions # ======================================================= # Section separator gen_section() { cat <<EOF # ============================================================== EOF } # ======================================================= # Specific preset tests # ======================================================= # If a sparse operation yields zeros, then those elements # of the returned sparse matrix should be eaten. gen_eat_zeros() { cat <<EOF %% Make sure newly introduced zeros get eaten %!assert (nnz (sparse ([bf,bf,1]).^realmax), 1) %!assert (nnz (sparse ([1,bf,bf]).^realmax), 1) %!assert (nnz (sparse ([bf,bf,bf]).^realmax), 0) %!assert (nnz (sparse ([bf;bf;1]).^realmax), 1) %!assert (nnz (sparse ([1;bf;bf]).^realmax), 1) %!assert (nnz (sparse ([0.5;bf;bf]).^realmax), 0) %!assert (nnz (sparse ([bf,bf,1])*realmin), 1) %!assert (nnz (sparse ([1,bf,bf])*realmin), 1) %!assert (nnz (sparse ([bf,bf,bf])*realmin), 0) %!assert (nnz (sparse ([bf;bf;1])*realmin), 1) %!assert (nnz (sparse ([1;bf;bf])*realmin), 1) %!assert (nnz (sparse ([bf;bf;bf])*realmin), 0) EOF } gen_specific() { cat <<EOF %% error handling in constructor %!error <Invalid call> sparse () %!error <Invalid call> sparse (1,2,3,4,5,6,7) %!warning <input array cast to double> %! warning ("on", "Octave:sparse:double-conversion", "local"); %! s = sparse (single ([1 2])); %!error <wrong type argument 'uint8 matrix'> %! s = sparse (uint8 ([1 2])); %!error <M must be a non-negative integer> sparse ({1}, 2) %!error <N must be a non-negative integer> sparse (1, {2}) %!error <dimensions M and N must be non-negative> sparse (-1, 2) %!error <dimensions M and N must be non-negative> sparse (1, -2) %!error <dimension mismatch> sparse (1,[2,3],[1,2,3]) %!error <invalid option: foobar> sparse ([1,1],[1,1],[1,2],"foobar") %% negative subscripts are disallowed %!error <subscripts must be> sparse ([1,3],[1,-4],[3,5],2,2) %!error <subscripts must be> sparse ([1,3],[1,-4],[3,5i],2,2) %!error <M must be a non-negative integer> sparse ([1,1],[1,1],[1,2], {1}, 2) %!error <N must be a non-negative integer> sparse ([1,1],[1,1],[1,2], 1, {2}) %!error <dimensions M and N must be non-negative> sparse ([1,1],[1,1],[1,2], -1, 2) %!error <dimensions M and N must be non-negative> sparse ([1,1],[1,1],[1,2], 1, -2) %!warning <input array cast to double> %! warning ("on", "Octave:sparse:double-conversion", "local"); %! s = sparse ([1,1],[1,1], single ([1,2]), 2, 2); %!error <wrong type argument 'uint8 matrix'> %! s = sparse ([1,1],[1,1], uint8 ([1,2]), 2, 2); %!test # segfault test from edd@debian.org %! n = 510; %! sparse (kron ((1:n)', ones (n,1)), kron (ones (n,1), (1:n)'), ones (n)); %% segfault tests from Fabian@isas-berlin.de %% Note that the last four do not fail, but rather give a warning %% of a singular matrix, which is consistent with the full matrix %% behavior. They are therefore disabled. %!testif HAVE_UMFPACK %! assert (inv (sparse ([1,1;1,1+i])), sparse ([1-1i,1i;1i,-1i]), 10*eps); %#!error inv ( sparse ([1,1;1,1] ) ); %#!error inv ( sparse ([0,0;0,1] ) ); %#!error inv ( sparse ([0,0;0,1+i]) ); %#!error inv ( sparse ([0,0;0,0] ) ); EOF } gen_specific_tests() { gen_section gen_specific gen_section echo '%!shared bf' echo '%!test bf=realmin;' gen_eat_zeros echo '%!test bf=realmin+realmin*1i;' gen_eat_zeros cat <<EOF %!assert (nnz (sparse ([-1,realmin,realmin]).^1.5), 1) %!assert (nnz (sparse ([-1,realmin,realmin,1]).^1.5), 2) ## Make sure scalar v==0 doesn't confuse matters %!assert (nnz (sparse (1,1,0)), 0) %!assert (nnz (sparse (eye (3))*0), 0) %!assert (nnz (sparse (eye (3))-sparse (eye (3))), 0) %!assert (full (sparse (eye (3))/0), full (eye (3)/0)) EOF } # ======================================================= # Main function definition gen_function() { if $preset; then cat <<EOF ## ## test_sparse ## ## run preset sparse tests. All should pass. function [passes, tests] = test_sparse disp ("writing test output to sptest.log"); test ("sparse.tst", "normal", "sptest.log"); endfunction EOF else cat <<EOF ## ## test_sprandom ## ## total_passes=0; total_tests=0; ## for i=1:10 ## [passes,tests] = sprandomtest; ## total_passes += passes; ## total_tests += tests; ## end ## The test log is appended to sprandomtest.log function [passes,total] = test_sprandom warning ("untested --- fix the source in build-sparse-tests.sh"); disp ("appending test output to sprandomtest.log"); fid = fopen ("sprandomtest.log", "at"); test ("sprandom.tst", "normal", fid); ##[passes, total] = test ("sprandomtest", "normal", fid); fclose (fid); endfunction EOF fi } # ======================================================= # matrix ops # test ordered comparisons: uses as,af,bs,bf gen_ordering_tests() { cat <<EOF %% real values can be ordered (uses as,af) %!assert (as<=bf, sparse (af<=bf)) %!assert (bf<=as, sparse (bf<=af)) %!assert (as>=bf, sparse (af>=bf)) %!assert (bf>=as, sparse (bf>=af)) %!assert (as<bf, sparse (af<bf)) %!assert (bf<as, sparse (bf<af)) %!assert (as>bf, sparse (af>bf)) %!assert (bf>as, sparse (bf>af)) EOF } gen_sparsesparse_ordering_tests() { cat <<EOF %!assert (as<=bs, sparse (af<=bf)) %!assert (as>=bs, sparse (af>=bf)) %!assert (as<bs, sparse (af<bf)) %!assert (as>bs, sparse (af>bf)) EOF } # test element-wise binary operations: uses as,af,bs,bf,scalar gen_elementop_tests() { cat <<EOF %% Elementwise binary tests (uses as,af,bs,bf,scalar) %!assert (as==bs, sparse (af==bf)) %!assert (bf==as, sparse (bf==af)) %!assert (as!=bf, sparse (af!=bf)) %!assert (bf!=as, sparse (bf!=af)) %!assert (as+bf, af+bf) %!assert (bf+as, bf+af) %!assert (as-bf, af-bf) %!assert (bf-as, bf-af) %!assert (as.*bf, sparse (af.*bf)) %!assert (bf.*as, sparse (bf.*af)) %!assert (as./bf, sparse (af./bf), 100*eps) %!assert (bf.\as, sparse (bf.\af), 100*eps) %!test %! sv = as.^bf; %! fv = af.^bf; %! idx = find (af!=0); %! assert (sv(:)(idx), sparse (fv(:)(idx)), 100*eps); EOF } gen_sparsesparse_elementop_tests() { cat <<EOF %!assert (as==bs, sparse (af==bf)) %!assert (as!=bs, sparse (af!=bf)) %!assert (as+bs, sparse (af+bf)) %!assert (as-bs, sparse (af-bf)) %!assert (as.*bs, sparse (af.*bf)) %!assert (as./bs, sparse (af./bf), 100*eps) %!test %! sv = as.^bs; %! fv = af.^bf; %! idx = find (af!=0); %! assert(sv(:)(idx), sparse (fv(:)(idx)), 100*eps); EOF } # test matrix-matrix left and right division: uses as,af,bs,bf gen_divop_tests() { cat <<EOF %% Matrix-matrix operators (uses af,as,bs,bf) %!assert (as/bf, af/bf, 100*eps) %!assert (af/bs, af/bf, 100*eps) %!assert (as/bs, sparse (af/bf), 100*eps) %!assert (bs\af', bf\af', 100*eps) %!assert (bf\as', bf\af', 100*eps) %!assert (bs\as', sparse (bf\af'), 100*eps) EOF } # test matrix-matrix left and right division: uses as,af,bs,bf gen_square_divop_tests() { cat <<EOF %% Matrix-matrix operators (uses af,as,bs,bf) %!assert (as/bf, af/bf, 100*eps) %!assert (af/bs, af/bf, 100*eps) %!assert (as/bs, sparse (af/bf), 100*eps) %!assert (bs\af', bf\af', 100*eps) %!assert (bf\as', bf\af', 100*eps) %!assert (bs\as', sparse (bf\af'), 100*eps) EOF } # test matrix-matrix operations: uses as,af,bs,bf gen_matrixop_tests() { cat <<EOF %% Matrix-matrix operators (uses af,as,bs,bf) %!assert (as*bf', af*bf') %!assert (af*bs', af*bf') %!assert (as*bs', sparse (af*bf')) EOF } # test diagonal operations gen_matrixdiag_tests() { cat <<EOF %% Matrix diagonal tests (uses af,as,bf,bs) %!assert (diag (as), sparse (diag (af))) %!assert (diag (bs), sparse (diag (bf))) %!assert (diag (as,1), sparse (diag (af,1))) %!assert (diag (bs,1), sparse (diag (bf,1))) %!assert (diag (as,-1), sparse (diag (af,-1))) %!assert (diag (bs,-1), sparse (diag (bf,-1))) %!assert (diag (as(:)), sparse (diag (af(:)))) %!assert (diag (as(:),1), sparse (diag (af(:),1))) %!assert (diag (as(:),-1), sparse (diag (af(:),-1))) %!assert (diag (as(:)'), sparse (diag (af(:)'))) %!assert (diag (as(:)',1), sparse (diag (af(:)',1))) %!assert (diag (as(:)',-1), sparse (diag (af(:)',-1))) %!assert (spdiags (as,[0,1]), [diag(af,0), diag(af,1)]) %!test %! [tb,tc] = spdiags (as); %! assert (spdiags (tb,tc,sparse (zeros (size (as)))), as); %! assert (spdiags (tb,tc,rows (as),columns (as)), as); EOF } # test matrix reshape operations gen_matrixreshape_tests() { cat <<EOF %% Matrix diagonal tests (uses af,as,bf,bs) %!assert (reshape (as,1,prod(size(as))), sparse (reshape (af,1,prod(size(af))))) %!assert (reshape (as,prod(size(as)),1), sparse (reshape (af,prod(size(af)),1))) %!assert (reshape (as,fliplr(size(as))), sparse (reshape (af,fliplr(size(af))))) %!assert (reshape (bs,1,prod(size(as))), sparse (reshape (bf,1,prod(size(af))))) %!assert (reshape (bs,prod(size(as)),1), sparse (reshape (bf,prod(size(af)),1))) %!assert (reshape (bs,fliplr(size(as))), sparse (reshape (bf,fliplr(size(af))))) EOF } # test mapper matrix operations: uses as,af print_mapper_test() { echo "%!assert ($1(as), sparse ($1(af)))" } print_real_mapper_test() { cat <<EOF %!test %! wn2s = warning ("query", "Octave:num-to-str"); %! warning ("off", "Octave:num-to-str"); %! if (isreal (af)) %! if ($2) %! assert ($1(as), sparse ($1(af))); %! else %! assert ($1(as), $1(af)); %! endif %! endif %! warning (wn2s.state, "Octave:num-to-str"); EOF } gen_mapper_tests() { echo "%% Unary matrix tests (uses af,as)" print_mapper_test abs print_mapper_test acos print_mapper_test acosh print_mapper_test angle print_mapper_test arg print_mapper_test asin print_mapper_test asinh print_mapper_test atan print_mapper_test atanh print_mapper_test ceil print_mapper_test conj print_mapper_test cos print_mapper_test cosh print_mapper_test exp print_mapper_test isfinite print_mapper_test fix print_mapper_test floor print_mapper_test imag print_mapper_test isinf print_mapper_test isna print_mapper_test isnan print_mapper_test log #print_mapper_test log10 ## fails with different NaN, not a problem print_mapper_test real print_mapper_test round print_mapper_test sign print_mapper_test sin print_mapper_test sinh print_mapper_test sqrt print_mapper_test tan print_mapper_test tanh # Specific tests for certain mapper functions cat <<EOF %!assert (issparse (abs (as)) && isreal (abs (as))) %!assert (issparse (real (as)) && isreal (real (as))) %!assert (issparse (imag (as)) && isreal (imag (as))) EOF } gen_real_mapper_tests() { echo "%% Unary matrix tests (uses af,as)" print_real_mapper_test erf 1 print_real_mapper_test erfc 1 #print_real_mapper_test gamma 1 print_real_mapper_test isalnum 0 print_real_mapper_test isalpha 0 print_real_mapper_test isascii 0 print_real_mapper_test iscntrl 0 print_real_mapper_test isdigit 0 print_real_mapper_test isgraph 0 print_real_mapper_test islower 0 print_real_mapper_test isprint 0 print_real_mapper_test ispunct 0 print_real_mapper_test isspace 0 print_real_mapper_test isupper 0 print_real_mapper_test isxdigit 0 #print_real_mapper_test gammaln 1 # Specific tests for certain mapper functions cat <<EOF %!test %! wn2s = warning ("query", "Octave:num-to-str"); %! warning ("off", "Octave:num-to-str"); %! if (isreal (af)) %! assert (lower (as), as); %! assert (upper (as), as); %! endif %! warning (wn2s.state, "Octave:num-to-str"); EOF } # test matrix operations: uses as,af gen_unaryop_tests() { cat <<EOF %% Unary matrix tests (uses af,as) %!assert (issparse (as)) %!assert (!issparse (af)) %!assert (! (issparse (af) && iscomplex (af))) %!assert (! (issparse (af) && isreal (af))) %!assert (sum (as), sparse (sum (af))) %!assert (sum (as,1), sparse (sum (af,1))) %!assert (sum (as,2), sparse (sum (af,2))) %!assert (cumsum (as), sparse (cumsum (af))) %!assert (cumsum (as,1), sparse (cumsum (af,1))) %!assert (cumsum (as,2), sparse (cumsum (af,2))) %!assert (sumsq (as), sparse (sumsq (af))) %!assert (sumsq (as,1), sparse (sumsq (af,1))) %!assert (sumsq (as,2), sparse (sumsq (af,2))) %!assert (prod (as), sparse (prod (af))) %!assert (prod (as,1), sparse (prod (af,1))) %!assert (prod (as,2), sparse (prod (af,2))) %!assert (cumprod (as), sparse (cumprod (af))) %!assert (cumprod (as,1), sparse (cumprod (af,1))) %!assert (cumprod (as,2), sparse (cumprod (af,2))) %!assert (min (as), sparse (min (af))) %!assert (full (min (as(:))), min (af(:))) %!assert (min (as,[],1), sparse (min (af,[],1))) %!assert (min (as,[],2), sparse (min (af,[],2))) %!assert (min (as,[],1), sparse (min (af,[],1))) %!assert (min (as,0), sparse (min (af,0))) %!assert (min (as,bs), sparse (min (af,bf))) %!assert (max (as), sparse (max (af))) %!assert (full (max (as(:))), max (af(:))) %!assert (max (as,[],1), sparse (max (af,[],1))) %!assert (max (as,[],2), sparse (max (af,[],2))) %!assert (max (as,[],1), sparse (max (af,[],1))) %!assert (max (as,0), sparse (max (af,0))) %!assert (max (as,bs), sparse (max (af,bf))) %!assert (as==as) %!assert (as==af) %!assert (af==as) %!test %! [ii,jj,vv,nr,nc] = find (as); %! assert (af, full (sparse (ii,jj,vv,nr,nc))); %!assert (nnz (as), sum (af(:)!=0)) %!assert (nnz (as), nnz (af)) %!assert (issparse (as.')) %!assert (issparse (as')) %!assert (issparse (-as)) %!assert (!as, sparse (!af)) %!assert (as.', sparse (af.')) %!assert (as', sparse (af')) %!assert (-as, sparse (-af)) %!assert (!as, sparse (!af)) %!error [i,j] = size (af);as(i-1,j+1) %!error [i,j] = size (af);as(i+1,j-1) %!test %! [Is,Js,Vs] = find (as); %! [If,Jf,Vf] = find (af); %! assert (Is, If); %! assert (Js, Jf); %! assert (Vs, Vf); %!error as(0,1) %!error as(1,0) %!assert (find (as), find (af)) %!test %! [i,j,v] = find (as); %! [m,n] = size (as); %! x = sparse (i,j,v,m,n); %! assert (x, as); %!test %! [i,j,v,m,n] = find (as); %! x = sparse (i,j,v,m,n); %! assert (x, as); %!assert (issparse (horzcat (as,as))) %!assert (issparse (vertcat (as,as))) %!assert (issparse (cat (1,as,as))) %!assert (issparse (cat (2,as,as))) %!assert (issparse ([as,as])) %!assert (issparse ([as;as])) %!assert (horzcat (as,as), sparse ([af,af])) %!assert (vertcat (as,as), sparse ([af;af])) %!assert (horzcat (as,as,as), sparse ([af,af,af])) %!assert (vertcat (as,as,as), sparse ([af;af;af])) %!assert ([as,as], sparse ([af,af])) %!assert ([as;as], sparse ([af;af])) %!assert ([as,as,as], sparse ([af,af,af])) %!assert ([as;as;as], sparse ([af;af;af])) %!assert (cat (2,as,as), sparse ([af,af])) %!assert (cat (1,as,as), sparse ([af;af])) %!assert (cat (2,as,as,as), sparse ([af,af,af])) %!assert (cat (1,as,as,as), sparse ([af;af;af])) %!assert (issparse ([as,af])) %!assert (issparse ([af,as])) %!assert ([as,af], sparse ([af,af])) %!assert ([as;af], sparse ([af;af])) EOF } # operations which require square matrices. gen_square_tests() { # The \ and / operator tests on square matrices gen_square_divop_tests cat <<EOF %!testif HAVE_UMFPACK %! assert(det(bs+speye(size(bs))), det(bf+eye(size(bf))), 100*eps*abs(det(bf+eye(size(bf))))); %!testif HAVE_UMFPACK %! [l,u] = lu (sparse ([1,1;1,1])); %! assert (l*u, [1,1;1,1], 10*eps); %!testif HAVE_UMFPACK %! [l,u] = lu (sparse ([1,1;1,1+i])); %! assert (l, sparse ([1,2,2],[1,1,2],1), 10*eps); %! assert (u, sparse ([1,1,2],[1,2,2],[1,1,1i]), 10*eps); %!testif HAVE_UMFPACK # permuted LU %! [L,U] = lu (bs); %! assert (L*U, bs, 1e-10); %!testif HAVE_UMFPACK # simple LU + row permutations %! [L,U,P] = lu (bs); %! assert (P'*L*U, bs, 1e-10); %! ## triangularity %! [i,j,v] = find (L); %! assert (i-j>=0); %! [i,j,v] = find (U); %! assert (j-i>=0); %!testif HAVE_UMFPACK # simple LU + row/col permutations %! [L,U,P,Q] = lu (bs); %! assert (P'*L*U*Q', bs, 1e-10); %! ## triangularity %! [i,j,v] = find (L); %! assert (i-j>=0); %! [i,j,v] = find (U); %! assert (j-i>=0); %!testif HAVE_UMFPACK # LU with vector permutations %! [L,U,P,Q] = lu (bs,'vector'); %! assert (L(P,:)*U(:,Q), bs, 1e-10); %! ## triangularity %! [i,j,v] = find (L); %! assert (i-j>=0); %! [i,j,v] = find (U); %! assert (j-i>=0); %!testif HAVE_UMFPACK # LU with scaling %! [L,U,P,Q,R] = lu (bs); %! assert (R*P'*L*U*Q', bs, 1e-10); %! ## triangularity %! [i,j,v] = find (L); %! assert (i-j>=0); %! [i,j,v] = find (U); %! assert (j-i>=0); %!testif HAVE_UMFPACK # inverse %! assert (inv (bs)*bs, sparse (eye (rows (bs))), 1e-10); %!assert (bf\as', bf\af', 100*eps) %!assert (bs\af', bf\af', 100*eps) %!assert (bs\as', sparse (bf\af'), 100*eps) EOF } # Cholesky tests gen_cholesky_tests() { cat <<EOF %!testif HAVE_CHOLMOD %! assert (chol (bs)'*chol (bs), bs, 1e-10); %!testif HAVE_CHOLMOD %! assert (chol (bs,'lower')*chol (bs,'lower')', bs, 1e-10); %!testif HAVE_CHOLMOD %! assert (chol (bs,'lower'), chol (bs)', 1e-10); %!testif HAVE_CHOLMOD # Return Partial Cholesky factorization %! [RS,PS] = chol (bs); %! assert (RS'*RS, bs, 1e-10); %! assert (PS, 0); %! [LS,PS] = chol (bs,'lower'); %! assert (LS*LS', bs, 1e-10); %! assert (PS, 0); %!testif HAVE_CHOLMOD # Permuted Cholesky factorization %! [RS,PS,QS] = chol (bs); %! assert (RS'*RS, QS*bs*QS', 1e-10); %! assert (PS, 0); %! [LS,PS,QS] = chol (bs,'lower'); %! assert (LS*LS', QS*bs*QS', 1e-10); %! assert (PS, 0); EOF } # test scalar operations: uses af and real scalar bf; modifies as,bf,bs gen_scalar_tests() { echo '%!test as = sparse (af);' echo '%!test bs = bf;' gen_elementop_tests gen_ordering_tests echo '%!test bf = bf+1i;' echo '%!test bs = bf;' gen_elementop_tests } # test matrix operations: uses af and bf; modifies as,bs gen_rectangular_tests() { echo '%!test as = sparse(af);' echo '%!test bs = sparse(bf);' gen_mapper_tests gen_real_mapper_tests gen_unaryop_tests gen_elementop_tests gen_sparsesparse_elementop_tests gen_matrixop_tests # gen_divop_tests # Disable rectangular \ and / for now gen_matrixdiag_tests gen_matrixreshape_tests cat <<EOF %!testif HAVE_UMFPACK # permuted LU %! [L,U] = lu (bs); %! assert (L*U, bs, 1e-10); %!testif HAVE_UMFPACK # simple LU + row permutations %! [L,U,P] = lu (bs); %! assert (P'*L*U, bs, 1e-10); %! ## triangularity %! [i,j,v] = find (L); %! assert (i-j>=0); %! [i,j,v] = find (U); %! assert (j-i>=0); %!testif HAVE_UMFPACK # simple LU + row/col permutations %! [L,U,P,Q] = lu (bs); %! assert (P'*L*U*Q', bs, 1e-10); %! ## triangularity %! [i,j,v] = find (L); %! assert (i-j>=0); %! [i,j,v] = find (U); %! assert (j-i>=0); %!testif HAVE_UMFPACK # LU with vector permutations %! [L,U,P,Q] = lu (bs,'vector'); %! assert (L (P,:)*U (:,Q), bs, 1e-10); %! ## triangularity %! [i,j,v] = find (L); %! assert (i-j>=0); %! [i,j,v] = find (U); %! assert (j-i>=0); %!testif HAVE_UMFPACK # LU with scaling %! [L,U,P,Q,R] = lu (bs); %! assert (R*P'*L*U*Q', bs, 1e-10); %! ## triangularity %! [i,j,v] = find (L); %! assert (i-j>=0); %! [i,j,v] = find (U); %! assert (j-i>=0); EOF } # ======================================================= # sparse assembly tests gen_assembly_tests() { cat <<EOF %%Assembly tests %!test %! m = max ([m;r(:)]); %! n = max ([n;c(:)]); %! funiq = fsum = zeros (m,n); %! funiq(r(:) + m*(c(:)-1) ) = ones (size (r(:))); %! funiq = sparse (funiq); %! for k=1:length (r) %! fsum(r(k),c(k)) += 1; %! endfor %! fsum = sparse (fsum); %!assert (sparse (r,c,1), sparse (fsum(1:max(r), 1:max(c)))) %!assert (sparse (r,c,1,"sum"), sparse (fsum(1:max (r),1:max (c)))) %!assert (sparse (r,c,1,"unique"), sparse (funiq(1:max (r),1:max (c)))) %!assert (sparse (r,c,1,m,n), sparse (fsum)) %!assert (sparse (r,c,1,m,n,"sum"), sparse (fsum)) %!assert (sparse (r,c,1,m,n,"unique"), sparse (funiq)) %!assert (sparse (r,c,1i), sparse (fsum(1:max (r),1:max (c))*1i)) %!assert (sparse (r,c,1i,"sum"), sparse (fsum(1:max (r),1:max (c))*1i)) %!assert (sparse (r,c,1i,"unique"), sparse (funiq(1:max (r),1:max (c))*1i)) %!assert (sparse (r,c,1i,m,n), sparse (fsum*1i)) %!assert (sparse (r,c,1i,m,n,"sum"), sparse (fsum*1i)) %!assert (sparse (r,c,1i,m,n,"unique"), sparse (funiq*1i)) %!test %! if (issparse (funiq)) %! assert (sparse (full (1i*funiq)), sparse (1i*funiq)); %! endif %!assert (sparse (full (funiq)), funiq) EOF } # ======================================================= # sparse selection tests gen_scalar_select_tests () { cat <<EOF %!assert (sparse (42)([1,1]), sparse ([42,42])) %!assert (sparse (42*1i)([1,1]), sparse ([42,42].*1i)) EOF } gen_select_tests() { cat <<EOF %!test as = sparse (af); %% Point tests %!test idx = ridx(:) + rows (as) * (cidx (:)-1); %!assert (sparse (as(idx)), sparse (af(idx))) %!assert (as(idx), sparse (af(idx))) %!assert (as(idx'), sparse (af(idx'))) %!assert (as(flipud (idx(:))), sparse (af(flipud (idx(:))))) %!assert (as([idx,idx]), sparse (af([idx,idx]))) %!assert (as(reshape ([idx;idx], [1,length(idx),2])), sparse(af(reshape ([idx;idx], [1,length(idx),2])))) %% Slice tests %!assert (as(ridx,cidx), sparse (af(ridx,cidx))) %!assert (as(ridx,:), sparse (af(ridx,:))) %!assert (as(:,cidx), sparse (af(:,cidx))) %!assert (as(:,:), sparse (af(:,:))) %!assert (as((rows (as):-1:1),:), sparse (af((size (af,1):-1:1),:))) %!assert (as(:,(columns (as):-1:1)), sparse (af(:, (size (af,2):-1:1)))) %% Indexing tests %!assert (full (as([1,1],:)), af([1,1],:)) %!assert (full (as(:,[1,1])), af(:,[1,1])) %!test %! [i,j,v] = find (as); %! assert (as(i(1),j(1))([1,1]), sparse ([v(1), v(1)])); %% Assignment test %!test %! ts = as; ts(:,:) = ts(fliplr (1:rows (as)),:); %! tf = af; tf(:,:) = tf(fliplr (1:rows (af)),:); %! assert (ts, sparse (tf)); %!test %! ts = as; ts(fliplr (1:rows (as)),:) = ts; %! tf = af; tf(fliplr (1:rows (af)),:) = tf; %! assert (ts, sparse (tf)); %!test %! ts = as; ts(:,fliplr (1:columns (as))) = ts; %! tf = af; tf(:,fliplr (1:columns (af))) = tf; %! assert (ts, sparse (tf)); %!test %! ts(fliplr (1:rows (as))) = as(:,1); %! tf(fliplr (1:rows (af))) = af(:,1); %! assert (ts, sparse (tf)); %% Deletion tests %!test %! ts = as; ts(1,:) = []; tf = af; tf(1,:) = []; %! assert (ts, sparse (tf)); %!test %! ts = as; ts(:,1) = []; tf = af; tf(:,1) = []; %! assert (ts, sparse (tf)); %% Test "end" keyword %!assert (full (as(end)), af(end)) %!assert (full (as(1,end)), af(1,end)) %!assert (full (as(end,1)), af(end,1)) %!assert (full (as(end,end)), af(end,end)) %!assert (as(2:end,2:end), sparse (af(2:end,2:end))) %!assert (as(1:end-1,1:end-1), sparse (af(1:end-1,1:end-1))) EOF } # ======================================================= # sparse save and load tests gen_save_tests() { cat <<EOF %!test # save ascii %! savefile = tempname (); %! as_save = as; %! save ("-text", savefile, "bf", "as_save", "af"); %! clear as_save; %! load (savefile, "as_save"); %! unlink (savefile); %! assert (as_save, sparse (af)); %!test # save binary %! savefile = tempname (); %! as_save = as; %! save ("-binary", savefile, "bf", "as_save", "af"); %! clear as_save; %! load (savefile, "as_save"); %! unlink (savefile); %! assert (as_save, sparse (af)); %!testif HAVE_HDF5 # save hdf5 %! savefile = tempname (); %! as_save = as; %! save ("-hdf5", savefile, "bf", "as_save", "af"); %! clear as_save; %! load (savefile, "as_save"); %! unlink (savefile); %! assert (as_save, sparse (af)); ## FIXME: We should skip (or mark as a known bug) the test for ## saving sparse matrices to MAT files when using 64-bit indexing since ## that is not implemented yet. %!test # save matlab %! savefile = tempname (); %! as_save = as; %! save ("-mat", savefile, "bf", "as_save", "af"); %! clear as_save; %! load (savefile, "as_save"); %! unlink (savefile); %! assert (as_save, sparse (af)); EOF } # ============================================================= # Specific solver tests for matrices that will test all of the solver # code. Uses alpha and beta gen_solver_tests() { if $preset; then cat <<EOF %! n=8; %! lf=diag (1:n); lf(n-1,1)=0.5*alpha; lf(n,2)=0.25*alpha; ls=sparse (lf); %! uf=diag (1:n); uf(1,n-1)=2*alpha; uf(2,n)=alpha; us=sparse (uf); %! ts=spdiags (ones (n,3),-1:1,n,n) + diag (1:n); tf = full (ts); EOF else cat <<EOF %! n = floor (lognrnd (8,2)+1)'; %! ls = tril (sprandn (8,8,0.2),-1).*alpha + n*speye (8); lf = full (ls); %! us = triu (sprandn (8,8,0.2),1).*alpha + n*speye (8); uf = full (us); %! ts = spdiags (randn (8,3),-1:1,8,8).*alpha; tf = full (ts); EOF fi cat <<EOF %! df = diag (1:n).* alpha; ds = sparse (df); %! pdf = df(randperm (n), randperm (n)); %! pds = sparse (pdf); %! plf = lf(randperm (n), randperm (n)); %! pls = sparse (plf); %! puf = uf(randperm (n), randperm (n)); %! pus = sparse (puf); %! bs = spdiags (repmat ([1:n]',1,4),-2:1,n,n).*alpha; %! bf = full (bs); %! cf = lf + lf'; cs = sparse (cf); %! bcf = bf + bf'; bcs = sparse (bcf); %! tcf = tf + tf'; tcs = sparse (tcf); %! xf = diag (1:n) + fliplr (diag (1:n)).*beta; %! xs = sparse (xf); %!assert (ds\xf, df\xf, 1e-10) %!assert (ds\xs, sparse (df\xf), 1e-10) %!assert (pds\xf, pdf\xf, 1e-10) %!assert (pds\xs, sparse (pdf\xf), 1e-10) %!assert (ls\xf, lf\xf, 1e-10) %!assert (sparse (ls\xs), sparse (lf\xf), 1e-10) %!testif HAVE_UMFPACK %! assert (pls\xf, plf\xf, 1e-10); %!testif HAVE_UMFPACK %! assert (sparse (pls\xs), sparse (plf\xf), 1e-10); %!assert (us\xf, uf\xf, 1e-10) %!assert (sparse (us\xs), sparse (uf\xf), 1e-10) %!testif HAVE_UMFPACK %! assert (pus\xf, puf\xf, 1e-10); %!testif HAVE_UMFPACK %! assert (sparse (pus\xs), sparse (puf\xf), 1e-10); %!assert (bs\xf, bf\xf, 1e-10) %!assert (sparse (bs\xs), sparse (bf\xf), 1e-10) %!testif HAVE_UMFPACK %! assert (cs\xf, cf\xf, 1e-10); %!testif HAVE_UMFPACK %! assert (sparse (cs\xs), sparse (cf\xf), 1e-10); %!testif HAVE_UMFPACK %! assert (bcs\xf, bcf\xf, 1e-10); %!testif HAVE_UMFPACK %! assert (sparse (bcs\xs), sparse (bcf\xf), 1e-10); %!assert (ts\xf, tf\xf, 1e-10) %!assert (sparse (ts\xs), sparse (tf\xf), 1e-10) %!assert (tcs\xf, tcf\xf, 1e-10) %!assert (sparse (tcs\xs), sparse (tcf\xf), 1e-10) EOF cat <<EOF %% QR solver tests %!function f (a, sz, feps) %! b = randn (sz); %! x = a \ b; %! assert (a * x, b, feps); %! b = randn (sz) + 1i*randn (sz); %! x = a \ b; %! assert (a * x, b, feps); %! b = sprandn (sz(1),sz(2),0.2); %! x = a \ b; %! assert (sparse (a * x), b, feps); %! b = sprandn (sz(1),sz(2),0.2) + 1i*sprandn (sz(1),sz(2),0.2); %! x = a \ b; %! assert (sparse (a * x), b, feps); %!endfunction %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! a = alpha*sprandn (10,11,0.2) + speye (10,11); %! f (a,[10,2],1e-10); %! ## Test this by forcing matrix_type, as can't get a certain %! ## result for over-determined systems. %! a = alpha*sprandn (10,10,0.2) + speye (10,10); %! matrix_type (a, "Singular"); %! f (a,[10,2],1e-10); %% Rectanguar solver tests that don't use QR %!test %! ds = alpha * spdiags ([1:11]',0,10,11); %! df = full (ds); %! xf = beta * ones (10,2); %! xs = speye (10,10); %!assert (ds\xf, df\xf, 100*eps) %!assert (ds\xs, sparse (df\xs), 100*eps) %!test %! pds = ds([2,1,3:10],:); %! pdf = full (pds); %!assert (pds\xf, pdf\xf, 100*eps) %!assert (pds\xs, sparse (pdf\xs), 100*eps) %!test %! ds = alpha * spdiags ([1:11]',0,11,10); %! df = full (ds); %! xf = beta * ones (11,2); %! xs = speye (11,11); %!assert (ds\xf, df\xf, 100*eps) %!assert (ds\xs, sparse (df\xs), 100*eps) %!test %! pds = ds([2,1,3:11],:); %! pdf = full (pds); %!assert (pds\xf, pdf\xf, 100*eps) %!assert (pds\xs, sparse (pdf\xs), 100*eps) %!test %! us = alpha*[[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]]; %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! assert (us*(us\xf), xf, 100*eps); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! assert (us*(us\xs), xs, 100*eps); %!test %! pus = us(:,[2,1,3:12]); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! assert (pus*(pus\xf), xf, 100*eps); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! assert (pus*(pus\xs), xs, 100*eps); %!test %! us = alpha*[speye(11,9),[1;sparse(8,1);1;0]]; %!testif HAVE_CXSPARSE %! [c,r] = qr (us, xf); %! assert (us\xf, r\c, 100*eps); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! [c,r] = qr (us, xs); %! r = matrix_type (r, "Singular"); ## Force Matrix Type %! assert (us\xs, r\c, 100*eps); %!test %! pus = us(:,[1:8,10,9]); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! [c,r] = qr (pus, xf); %! r = matrix_type (r, "Singular"); ## Force Matrix Type %! assert (pus\xf, r\c, 100*eps); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! [c,r] = qr (pus, xs); %! r = matrix_type (r, "Singular"); ## Force Matrix Type %! assert (pus\xs, r\c, 100*eps); %!test %! ls = alpha*[speye(9,11);[1, sparse(1,8),1,0]]; %! xf = beta * ones (10,2); %! xs = speye (10,10); %!assert (ls*(ls\xf), xf, 100*eps) %!assert (ls*(ls\xs), xs, 100*eps) %!test %! pls = ls([1:8,10,9],:); %!assert (pls*(pls\xf), xf, 100*eps) %!assert (pls*(pls\xs), xs, 100*eps) %!test %! ls = alpha*[speye(10,10), sparse(10,1);[1;1], sparse(2,9),[1;1]]; %! xf = beta * ones (12,2); %! xs = speye (12,12); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! [c,r] = qr (ls, xf); %! assert (ls\xf, r\c, 100*eps); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! [c,r] = qr (ls, xs); %! r = matrix_type (r, "Singular"); ## Force Matrix Type %! assert (ls\xs, r\c, 100*eps); %!test %! pls = ls(:,[1:8,10,9]); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! [c,r] = qr (pls, xf); %! r = matrix_type (r, "Singular"); ## Force Matrix Type %! assert (pls\xf, r\c, 100*eps); %!testif HAVE_UMFPACK, HAVE_CXSPARSE %! [c,r] = qr (pls, xs); %! r = matrix_type (r, "Singular"); ## Force Matrix Type %! assert (pls\xs, r\c, 100*eps); EOF } # ============================================================= # Putting it all together: defining the combined tests # initial function gen_function gen_section # specific tests if $preset; then gen_specific_tests gen_section fi # scalar operations echo '%!shared as,af,bs,bf' if $preset; then echo '%!test af=[1+1i,2-1i,0,0;0,0,0,3+2i;0,0,0,4];' echo '%!test bf=3;' else cat <<EOF %!test %! % generate m,n from 1 to <5000 %! m = floor (lognrnd (8,2)+1); %! n = floor (lognrnd (8,2)+1); %! as = sprandn (m,n,0.3); %! af = full (as + 1i*sprandn (as)); %! bf = randn; EOF fi gen_scalar_tests gen_section # rectangular operations if $preset; then echo '%!test af=[1+1i,2-1i,0,0;0,0,0,3+2i;0,0,0,4];' echo '%!test bf=[0,1-1i,0,0;2+1i,0,0,0;3-1i,2+3i,0,0];' else cat <<EOF %!test %! m = floor (lognrnd (8,2)+1); %! n = floor (lognrnd (8,2)+1); %! as = sprandn (m,n,0.3); %! af = full (as + 1i*sprandn (as)); %! bs = sprandn (m,n,0.3); %! bf = full (bs + 1i*sprandn (bs)); EOF fi gen_rectangular_tests gen_section gen_save_tests gen_section echo '%!test bf = real (bf);' gen_rectangular_tests gen_section gen_sparsesparse_ordering_tests gen_section echo '%!test af = real (af);' gen_rectangular_tests gen_section gen_save_tests gen_section echo '%!test bf = bf+1i*(bf!=0);' gen_rectangular_tests gen_section # square operations if $preset; then echo '%!test af = [1+1i,2-1i,0,0;0,0,0,3+2i;0,0,0,4];' echo '%! as = sparse (af);' echo '%!test bf = [0,1-1i,0,0;2+1i,0,0,0;3-1i,2+3i,0,0];' else cat <<EOF %!test %! m = floor (lognrnd (8,2)+1); %! n = floor (lognrnd (8,2)+1); %! as = sprandn (m,n,0.3); %! af = full (as + 1i*sprandn (as)); %! bs = sprandn (m,n,0.3); %! bf = full (bs + 1i*sprandn (bs)); EOF fi cat <<EOF %!test ;# invertible matrix %! bf = af'*bf+max (abs ([af(:);bf(:)]))*sparse (eye (columns (as))); %! bs = sparse (bf); EOF gen_square_tests gen_section echo '%!test bf = real (bf);' echo '%! bs = sparse (bf);' gen_square_tests gen_section echo '%!test af = real (af);' echo '%! as = sparse (af);' gen_square_tests gen_section echo '%!test bf = bf+1i*(bf!=0);' echo '%! bs = sparse (bf);' gen_square_tests gen_section # cholesky tests if $preset; then echo '%!test bf = [5,0,1+1i,0;0,5,0,1-2i;1-1i,0,5,0;0,1+2i,0,5];' echo '%! bs = sparse (bf);' else echo '# This has a small chance of failing to create a positive definite matrix' echo '%!test n = floor (lognrnd (8,2)+1)' echo '%! bs = n*speye (n,n) + sprandn (n,n,0.3);' echo '%! bf = full (bs);' fi gen_cholesky_tests gen_section echo '%!test bf = real (bf);' echo '%! bs = sparse (bf);' gen_cholesky_tests gen_section # assembly tests echo '%!shared r,c,m,n,fsum,funiq' if $use_preset; then cat <<EOF %!test %! r = [1,1,2,1,2,3]; %! c = [2,1,1,1,2,1]; %! m = n = 0; EOF else cat <<EOF %!test %! % generate m,n from 1 to <5000 %! m = floor (lognrnd (8,2)+1); %! n = floor (lognrnd (8,2)+1); %! nz = ceil ((m+n)/2); %! r = floor (rand (5,nz)*n)+1; %! c = floor (rand (5,nn)*m)+1; EOF fi gen_assembly_tests #includes real and complex tests gen_section # slicing tests echo '%!shared ridx,cidx,idx,as,af' if $use_preset; then cat <<EOF %!test %! af = [1+1i,2-1i,0,0;0,0,0,3+2i;0,0,0,4]; %! ridx = [1,3]; %! cidx = [2,3]; EOF else cat <<EOF %!test %! % generate m,n from 1 to <5000 %! m = floor (lognrnd (8,2)+1); %! n = floor (lognrnd (8,2)+1); %! as = sprandn (m,n,0.3); %! af = full (as + 1i*sprandn (as)); %! ridx = ceil (m*rand (1,ceil (rand*m)); %! cidx = ceil (n*rand (1,ceil (rand*n)); EOF fi gen_scalar_select_tests gen_select_tests echo '%!test af = real (af);' gen_select_tests gen_section echo '%!shared alpha,beta,df,pdf,lf,plf,uf,puf,bf,cf,bcf,tf,tcf,xf,ds,pds,ls,pls,us,pus,bs,cs,bcs,ts,tcs,xs' echo '%!test alpha=1; beta=1;' gen_solver_tests echo '%!test alpha=1; beta=1i;' gen_solver_tests echo '%!test alpha=1i; beta=1;' gen_solver_tests echo '%!test alpha=1i; beta=1i;' gen_solver_tests gen_section