From help-request at octave dot org Mon Jan 30 21:42:00 2006 Subject: nnz and char From: "John W. Eaton" To: "Andrew Funk" Cc: Date: Mon, 30 Jan 2006 22:40:25 -0500 On 30-Jan-2006, Andrew Funk wrote: | I have some code that calls nnz on the result of a call to char, e.g. | | >> m=char(magic(3)+64) | | m = | | HAF | CEG | DIB | | >> nnz(m) | | ans = | | 9 | | This works in Matlab but in Octave I get an error: | | octave:27> nnz(m) | error: nnz: wrong type argument `sq_string' | | I'm wondering if this is considered a bug that would eventually be fixed | in Octave, or should I be thinking of a way to change the code to avoid | this situation? (In the actual code there can be zeros so it makes | sense to be calling nnz, I just created a toy example above). Here's a patch, relative to the current CVS sources. Thanks, jwe liboctave/ChangeLog: 2006-01-30 John W. Eaton * so-array.h (streamoff_array::nnz): New funtion. * boolNDArray.h (boolNDArray::nnz): New function. * MArrayN.h (MArrayN::nnz): New function. * MArray.h (MArray::nnz): New function. src/ChangeLog: 2006-01-30 John W. Eaton * gripes.cc (gripe_wrong_type_arg (const char*, const char*, bool)): New function. (gripe_wrong_type_arg (const char*, const std::string&, bool)): Define using const char*, const char*, bool version. (gripe_wrong_type_arg (const char*, const octave_value&, bool)): Define using const char*, const std::string&, bool version. * ov.h (octave_value::nnz): New function. * ov-base.cc (octave_base_value::nnz): New function. * ov-base.h: Provide decl. * ov-base-mat.h (octave_base_matrix::nnz): New function. * ov-base-scalar.h (octave_base_scalar::nnz): New function. * Cell.cc (Cell::nnz): New function. * Cell.h: Provide decl. * data.cc (Fnnz): New function. * DLD-FUNCTIONS/sparse.cc (Fnnz): Delete. Index: liboctave/MArray.h =================================================================== RCS file: /cvs/octave/liboctave/MArray.h,v retrieving revision 1.30 diff -u -r1.30 MArray.h --- liboctave/MArray.h 26 Apr 2005 19:24:28 -0000 1.30 +++ liboctave/MArray.h 31 Jan 2006 03:37:24 -0000 at @ -63,6 +63,24 @@ return *this; } + octave_idx_type nnz (void) const + { + octave_idx_type retval = 0; + + const T *d = this->data (); + + octave_idx_type nel = this->numel (); + + for (octave_idx_type i = 0; i < nel; i++) + { + if (d[i] != T ()) + retval++; + } + + return retval; + } + + // Currently, the OPS functions don't need to be friends, but that // may change. Index: liboctave/MArrayN.h =================================================================== RCS file: /cvs/octave/liboctave/MArrayN.h,v retrieving revision 1.7 diff -u -r1.7 MArrayN.h --- liboctave/MArrayN.h 26 Apr 2005 19:24:28 -0000 1.7 +++ liboctave/MArrayN.h 31 Jan 2006 03:37:24 -0000 at @ -70,6 +70,23 @@ return *this; } + octave_idx_type nnz (void) const + { + octave_idx_type retval = 0; + + const T *d = this->data (); + + octave_idx_type nel = this->numel (); + + for (octave_idx_type i = 0; i < nel; i++) + { + if (d[i] != T ()) + retval++; + } + + return retval; + } + MArrayN reshape (const dim_vector& new_dims) const { return ArrayN::reshape (new_dims); } Index: liboctave/boolNDArray.h =================================================================== RCS file: /cvs/octave/liboctave/boolNDArray.h,v retrieving revision 1.15 diff -u -r1.15 boolNDArray.h --- liboctave/boolNDArray.h 31 Oct 2005 03:18:22 -0000 1.15 +++ liboctave/boolNDArray.h 31 Jan 2006 03:37:24 -0000 at @ -93,6 +93,23 @@ // bool all_elements_are_real (void) const; // bool all_integers (double& max_val, double& min_val) const; + octave_idx_type nnz (void) const + { + octave_idx_type retval = 0; + + const bool *d = this->data (); + + octave_idx_type nel = this->numel (); + + for (octave_idx_type i = 0; i < nel; i++) + { + if (d[i]) + retval++; + } + + return retval; + } + private: boolNDArray (bool *d, dim_vector& dv) : ArrayN (d, dv) { } Index: liboctave/so-array.h =================================================================== RCS file: /cvs/octave/liboctave/so-array.h,v retrieving revision 1.5 diff -u -r1.5 so-array.h --- liboctave/so-array.h 26 Apr 2005 19:24:29 -0000 1.5 +++ liboctave/so-array.h 31 Jan 2006 03:37:24 -0000 at @ -62,6 +62,23 @@ streamoff_array squeeze (void) const { return ArrayN::squeeze (); } + octave_idx_type nnz (void) const + { + octave_idx_type retval = 0; + + const std::streamoff *d = this->data (); + + octave_idx_type nel = this->numel (); + + for (octave_idx_type i = 0; i < nel; i++) + { + if (d[i]) + retval++; + } + + return retval; + } + boolNDArray all (int dim = -1) const; boolNDArray any (int dim = -1) const; Index: src/Cell.cc =================================================================== RCS file: /cvs/octave/src/Cell.cc,v retrieving revision 1.19 diff -u -r1.19 Cell.cc --- src/Cell.cc 8 Dec 2005 21:01:50 -0000 1.19 +++ src/Cell.cc 31 Jan 2006 03:37:24 -0000 at @ -29,6 +29,7 @@ #include "Cell.h" #include "error.h" +#include "gripes.h" Cell::Cell (const string_vector& sv) : ArrayN () at @ -114,6 +115,13 @@ return *this; } +octave_idx_type +Cell::nnz (void) const +{ + gripe_wrong_type_arg ("nnz", "cell array"); + return -1; +} + Cell Cell::column (octave_idx_type i) const { Index: src/Cell.h =================================================================== RCS file: /cvs/octave/src/Cell.h,v retrieving revision 1.26 diff -u -r1.26 Cell.h --- src/Cell.h 8 Dec 2005 21:01:50 -0000 1.26 +++ src/Cell.h 31 Jan 2006 03:37:24 -0000 at @ -90,6 +90,8 @@ Cell reshape (const dim_vector& new_dims) const { return ArrayN::reshape (new_dims); } + octave_idx_type nnz (void) const; + Cell column (octave_idx_type i) const; // XXX FIXME XXX Index: src/data.cc =================================================================== RCS file: /cvs/octave/src/data.cc,v retrieving revision 1.146 diff -u -r1.146 data.cc --- src/data.cc 10 Nov 2005 21:40:48 -0000 1.146 +++ src/data.cc 31 Jan 2006 03:37:28 -0000 at @ -1077,6 +1077,23 @@ return retval; } +DEFUN (nnz, args, , + "-*- texinfo -*-\n\ + at deftypefn {Loadable Function} {@var{scalar} =} nnz (@var{a})\n\ +returns number of non zero elements in at var{a} dot \n\ + at seealso{sparse}\n\ + at end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + retval = args(0).nnz (); + else + print_usage ("nnz"); + + return retval; +} + DEFUN (sum, args, , "-*- texinfo -*-\n\ at deftypefn {Built-in Function} {} sum (@var{x}, @var{dim})\n\ Index: src/gripes.cc =================================================================== RCS file: /cvs/octave/src/gripes.cc,v retrieving revision 1.27 diff -u -r1.27 gripes.cc --- src/gripes.cc 26 Apr 2005 19:24:32 -0000 1.27 +++ src/gripes.cc 31 Jan 2006 03:37:28 -0000 at @ -124,12 +124,18 @@ } void -gripe_wrong_type_arg (const char *name, const std::string& s, bool is_error) +gripe_wrong_type_arg (const char *name, const char *s, bool is_error) { if (is_error) - error ("%s: wrong type argument `%s'", name, s.c_str ()); + error ("%s: wrong type argument `%s'", name, s); else - warning ("%s: wrong type argument `%s'", name, s.c_str ()); + warning ("%s: wrong type argument `%s'", name, s); +} + +void +gripe_wrong_type_arg (const char *name, const std::string& s, bool is_error) +{ + gripe_wrong_type_arg (name, s.c_str (), is_error); } void at @ -138,10 +144,7 @@ { std::string type = tc.type_name (); - if (is_error) - error ("%s: wrong type argument `%s'", name, type.c_str ()); - else - warning ("%s: wrong type argument `%s'", name, type.c_str ()); + gripe_wrong_type_arg (name, type, is_error); } void Index: src/gripes.h =================================================================== RCS file: /cvs/octave/src/gripes.h,v retrieving revision 1.25 diff -u -r1.25 gripes.h --- src/gripes.h 26 Apr 2005 19:24:32 -0000 1.25 +++ src/gripes.h 31 Jan 2006 03:37:28 -0000 at @ -76,6 +76,10 @@ gripe_data_conversion (const char *from, const char *to); extern void +gripe_wrong_type_arg (const char *name, const char *s, + bool is_error = true); + +extern void gripe_wrong_type_arg (const char *name, const std::string& s, bool is_error = true); Index: src/ov-base-mat.h =================================================================== RCS file: /cvs/octave/src/ov-base-mat.h,v retrieving revision 1.34 diff -u -r1.34 ov-base-mat.h --- src/ov-base-mat.h 26 Apr 2005 19:24:33 -0000 1.34 +++ src/ov-base-mat.h 31 Jan 2006 03:37:28 -0000 at @ -94,6 +94,8 @@ dim_vector dims (void) const { return matrix.dims (); } + octave_idx_type nnz (void) const { return matrix.nnz (); } + octave_value reshape (const dim_vector& new_dims) const { return MT (matrix.reshape (new_dims)); } Index: src/ov-base-scalar.h =================================================================== RCS file: /cvs/octave/src/ov-base-scalar.h,v retrieving revision 1.23 diff -u -r1.23 ov-base-scalar.h --- src/ov-base-scalar.h 26 Apr 2005 19:24:33 -0000 1.23 +++ src/ov-base-scalar.h 31 Jan 2006 03:37:28 -0000 at @ -81,6 +81,8 @@ dim_vector dims (void) const { static dim_vector dv (1, 1); return dv; } + octave_idx_type nnz (void) const { return (scalar != ST ()) ? 1 : 0; } + octave_value permute (const Array&, bool = false) const { return scalar; } Index: src/ov-base.cc =================================================================== RCS file: /cvs/octave/src/ov-base.cc,v retrieving revision 1.71 diff -u -r1.71 ov-base.cc --- src/ov-base.cc 18 May 2005 02:18:24 -0000 1.71 +++ src/ov-base.cc 31 Jan 2006 03:37:28 -0000 at @ -173,6 +173,13 @@ return retval; } +octave_idx_type +octave_base_value::nnz (void) const +{ + gripe_wrong_type_arg ("octave_base_value::nnz ()", type_name ()); + return -1; +} + octave_value octave_base_value::reshape (const dim_vector&) const { Index: src/ov-base.h =================================================================== RCS file: /cvs/octave/src/ov-base.h,v retrieving revision 1.81 diff -u -r1.81 ov-base.h --- src/ov-base.h 18 May 2005 02:18:24 -0000 1.81 +++ src/ov-base.h 31 Jan 2006 03:37:28 -0000 at @ -99,6 +99,8 @@ size_t byte_size (void) const { return 0; } + octave_idx_type nnz (void) const; + octave_value reshape (const dim_vector&) const; octave_value permute (const Array& vec, bool = false) const; Index: src/ov.h =================================================================== RCS file: /cvs/octave/src/ov.h,v retrieving revision 1.126 diff -u -r1.126 ov.h --- src/ov.h 26 Oct 2005 15:24:08 -0000 1.126 +++ src/ov.h 31 Jan 2006 03:37:28 -0000 at @ -376,6 +376,8 @@ virtual size_t byte_size (void) const { return rep->byte_size (); } + virtual octave_idx_type nnz (void) const { return rep->nnz (); } + virtual octave_value reshape (const dim_vector& dv) const { return rep->reshape (dv); } Index: src/DLD-FUNCTIONS/sparse.cc =================================================================== RCS file: /cvs/octave/src/DLD-FUNCTIONS/sparse.cc,v retrieving revision 1.8 diff -u -r1.8 sparse.cc --- src/DLD-FUNCTIONS/sparse.cc 10 Jan 2006 21:20:34 -0000 1.8 +++ src/DLD-FUNCTIONS/sparse.cc 31 Jan 2006 03:37:28 -0000 at @ -404,74 +404,6 @@ return retval; } -DEFUN_DLD (nnz, args, , - "-*- texinfo -*-\n\ - at deftypefn {Loadable Function} {@var{scalar} =} nnz (@var{SM})\n\ -returns number of non zero elements in SM\n\ - at seealso{sparse}\n\ - at end deftypefn") -{ - octave_value retval; - - if (args.length() < 1) - { - print_usage ("nnz"); - return retval; - } - - if (args(0).class_name () == "sparse") - { - // XXX FIXME XXX should nonzero be a method of octave_base_value so that the - // below can be replaced with "retval = (double) (args(0).nonzero ());" - const octave_value& rep = args(0).get_rep (); - - if (args(0).type_name () == "sparse matrix") - retval = (double) ((const octave_sparse_matrix&) rep) .nonzero (); - else if (args(0).type_name () == "sparse complex matrix") - retval = (double) ((const octave_sparse_complex_matrix&) rep) .nonzero (); - else if (args(0).type_name () == "sparse bool matrix") - retval = (double) ((const octave_sparse_bool_matrix&) rep) .nonzero (); - } - else if (args(0).type_name () == "complex matrix") - { - const ComplexMatrix M = args(0).complex_matrix_value(); - octave_idx_type nnz = 0; - for( octave_idx_type j = 0; j < M.cols(); j++) - for( octave_idx_type i = 0; i < M.rows(); i++) - if (M (i, j) != 0.) - nnz++; - retval = (double) nnz; - } - else if (args(0).type_name () == "matrix") - { - const Matrix M = args(0).matrix_value(); - octave_idx_type nnz = 0; - for( octave_idx_type j = 0; j < M.cols(); j++) - for( octave_idx_type i = 0; i < M.rows(); i++) - if (M (i, j) != 0.) - nnz++; - retval = (double) nnz; - } - else if (args(0).type_name () == "string") - { - const charMatrix M = args(0).char_matrix_value(); - octave_idx_type nnz = 0; - for( octave_idx_type j = 0; j < M.cols(); j++) - for( octave_idx_type i = 0; i < M.rows(); i++) - if (M (i, j) != 0) - nnz++; - retval = (double) nnz; - } - else if (args(0).type_name () == "scalar") - retval = args(0).scalar_value() != 0.0 ? 1.0 : 0.0; - else if (args(0).type_name () == "complex scalar") - retval = args(0).complex_value() != 0.0 ? 1.0 : 0.0; - else - gripe_wrong_type_arg ("nnz", args(0)); - - return retval; -} - DEFUN_DLD (nzmax, args, , "-*- texinfo -*-\n\ at deftypefn {Loadable Function} {@var{scalar} =} nzmax (@var{SM})\n\ ------------------------------------------------------------- Octave is freely available under the terms of the GNU GPL. Octave's home on the web: http://www.octave.org How to fund new projects: http://www.octave.org/funding.html Subscription information: http://www.octave.org/archive.html -------------------------------------------------------------