Mercurial > hg > octave-nkf
changeset 493:1391e7ed65f6
[project @ 1994-07-06 14:54:58 by jwe]
author | jwe |
---|---|
date | Wed, 06 Jul 1994 14:54:58 +0000 |
parents | d45bdf960233 |
children | 2c4d694b87e9 |
files | src/pt-const.cc |
diffstat | 1 files changed, 1092 insertions(+), 5811 deletions(-) [+] |
line wrap: on
line diff
--- a/src/pt-const.cc +++ b/src/pt-const.cc @@ -29,2482 +29,35 @@ #pragma implementation #endif -#include <ctype.h> -#include <string.h> -#include <fstream.h> +#include <strstream.h> #include <iostream.h> -#include <strstream.h> -#include <math.h> +#include <fstream.h> +#include <string.h> +#include <ctype.h> + +#include "EIG.h" -#include "mx-base.h" -#include "Range.h" - +#include "unwind-prot.h" +#include "tree-const.h" +#include "user-prefs.h" #include "variables.h" +#include "octave.h" #include "error.h" #include "gripes.h" -#include "user-prefs.h" -#include "utils.h" -#include "pager.h" -#include "mappers.h" -#include "pr-output.h" -#include "tree-const.h" -#include "arith-ops.h" -#include "idx-vector.h" -#include "unwind-prot.h" -#include "octave.h" #include "input.h" #include "octave-hist.h" +#include "pager.h" +#include "utils.h" #include "parse.h" #include "lex.h" -#include "tc-inlines.cc" - -// A couple of handy helper functions. - -static int -any_element_less_than (const Matrix& a, double val) -{ - int nr = a.rows (); - int nc = a.columns (); - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - if (a.elem (i, j) < val) - return 1; - return 0; -} - -static int -any_element_greater_than (const Matrix& a, double val) -{ - int nr = a.rows (); - int nc = a.columns (); - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - if (a.elem (i, j) > val) - return 1; - return 0; -} - -static int -any_element_is_complex (const ComplexMatrix& a) -{ - int nr = a.rows (); - int nc = a.columns (); - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - if (imag (a.elem (i, j)) != 0.0) - return 1; - return 0; -} - -// Now, the classes. - -/* - * The real representation of constants. - */ -tree_constant_rep::tree_constant_rep (void) -{ - type_tag = unknown_constant; -} - -tree_constant_rep::tree_constant_rep (double d) -{ - scalar = d; - type_tag = scalar_constant; -} - -tree_constant_rep::tree_constant_rep (const Matrix& m) -{ - if (m.rows () == 1 && m.columns () == 1) - { - scalar = m.elem (0, 0); - type_tag = scalar_constant; - } - else - { - matrix = new Matrix (m); - type_tag = matrix_constant; - } -} - -tree_constant_rep::tree_constant_rep (const DiagMatrix& d) -{ - if (d.rows () == 1 && d.columns () == 1) - { - scalar = d.elem (0, 0); - type_tag = scalar_constant; - } - else - { - matrix = new Matrix (d); - type_tag = matrix_constant; - } -} - -tree_constant_rep::tree_constant_rep (const RowVector& v, int - prefer_column_vector) -{ - int len = v.capacity (); - if (len == 1) - { - scalar = v.elem (0); - type_tag = scalar_constant; - } - else - { - int pcv = (prefer_column_vector < 0) - ? user_pref.prefer_column_vectors - : prefer_column_vector; - - if (pcv) - { - Matrix m (len, 1); - for (int i = 0; i < len; i++) - m.elem (i, 0) = v.elem (i); - matrix = new Matrix (m); - type_tag = matrix_constant; - } - else - { - Matrix m (1, len); - for (int i = 0; i < len; i++) - m.elem (0, i) = v.elem (i); - matrix = new Matrix (m); - type_tag = matrix_constant; - } - } -} - -tree_constant_rep::tree_constant_rep (const ColumnVector& v, - int prefer_column_vector) -{ - int len = v.capacity (); - if (len == 1) - { - scalar = v.elem (0); - type_tag = scalar_constant; - } - else - { - int pcv = (prefer_column_vector < 0) - ? user_pref.prefer_column_vectors - : prefer_column_vector; - - if (pcv) - { - Matrix m (len, 1); - for (int i = 0; i < len; i++) - m.elem (i, 0) = v.elem (i); - matrix = new Matrix (m); - type_tag = matrix_constant; - } - else - { - Matrix m (1, len); - for (int i = 0; i < len; i++) - m.elem (0, i) = v.elem (i); - matrix = new Matrix (m); - type_tag = matrix_constant; - } - } -} - -tree_constant_rep::tree_constant_rep (const Complex& c) -{ - complex_scalar = new Complex (c); - type_tag = complex_scalar_constant; -} - -tree_constant_rep::tree_constant_rep (const ComplexMatrix& m) -{ - if (m.rows () == 1 && m.columns () == 1) - { - complex_scalar = new Complex (m.elem (0, 0)); - type_tag = complex_scalar_constant; - } - else - { - complex_matrix = new ComplexMatrix (m); - type_tag = complex_matrix_constant; - } -} - -tree_constant_rep::tree_constant_rep (const ComplexDiagMatrix& d) -{ - if (d.rows () == 1 && d.columns () == 1) - { - complex_scalar = new Complex (d.elem (0, 0)); - type_tag = complex_scalar_constant; - } - else - { - complex_matrix = new ComplexMatrix (d); - type_tag = complex_matrix_constant; - } -} - -tree_constant_rep::tree_constant_rep (const ComplexRowVector& v, - int prefer_column_vector) -{ - int len = v.capacity (); - if (len == 1) - { - complex_scalar = new Complex (v.elem (0)); - type_tag = complex_scalar_constant; - } - else - { - int pcv = (prefer_column_vector < 0) - ? user_pref.prefer_column_vectors - : prefer_column_vector; - - if (pcv) - { - ComplexMatrix m (len, 1); - for (int i = 0; i < len; i++) - m.elem (i, 0) = v.elem (i); - complex_matrix = new ComplexMatrix (m); - type_tag = complex_matrix_constant; - } - else - { - ComplexMatrix m (1, len); - for (int i = 0; i < len; i++) - m.elem (0, i) = v.elem (i); - complex_matrix = new ComplexMatrix (m); - type_tag = complex_matrix_constant; - } - } -} - -tree_constant_rep::tree_constant_rep (const ComplexColumnVector& v, - int prefer_column_vector) -{ - int len = v.capacity (); - if (len == 1) - { - complex_scalar = new Complex (v.elem (0)); - type_tag = complex_scalar_constant; - } - else - { - int pcv = (prefer_column_vector < 0) - ? user_pref.prefer_column_vectors - : prefer_column_vector; - - if (pcv) - { - ComplexMatrix m (len, 1); - for (int i = 0; i < len; i++) - m.elem (i, 0) = v.elem (i); - complex_matrix = new ComplexMatrix (m); - type_tag = complex_matrix_constant; - } - else - { - ComplexMatrix m (1, len); - for (int i = 0; i < len; i++) - m.elem (0, i) = v.elem (i); - complex_matrix = new ComplexMatrix (m); - type_tag = complex_matrix_constant; - } - } -} - -tree_constant_rep::tree_constant_rep (const char *s) -{ - string = strsave (s); - type_tag = string_constant; -} - -tree_constant_rep::tree_constant_rep (double b, double l, double i) -{ - range = new Range (b, l, i); - int nel = range->nelem (); - if (nel < 0) - { - delete range; - type_tag = unknown_constant; - if (nel == -1) - ::error ("number of elements in range exceeds INT_MAX"); - else - ::error ("invalid range"); - } - else if (nel > 1) - type_tag = range_constant; - else - { - delete range; - if (nel == 1) - { - scalar = b; - type_tag = scalar_constant; - } - else if (nel == 0) - { - matrix = new Matrix (); - type_tag = matrix_constant; - } - else - panic_impossible (); - } -} - -tree_constant_rep::tree_constant_rep (const Range& r) -{ - if (r.nelem () > 1) - { - range = new Range (r); - type_tag = range_constant; - } - else if (r.nelem () == 1) - { - scalar = r.base (); - type_tag = scalar_constant; - } - else if (r.nelem () == 0) - { - matrix = new Matrix (); - type_tag = matrix_constant; - } - else - panic_impossible (); -} - -tree_constant_rep::tree_constant_rep (tree_constant_rep::constant_type t) -{ - assert (t == magic_colon); - - type_tag = magic_colon; -} - -tree_constant_rep::tree_constant_rep (const tree_constant_rep& t) -{ - type_tag = t.type_tag; - - switch (t.type_tag) - { - case unknown_constant: - break; - case scalar_constant: - scalar = t.scalar; - break; - case matrix_constant: - matrix = new Matrix (*(t.matrix)); - break; - case string_constant: - string = strsave (t.string); - break; - case complex_matrix_constant: - complex_matrix = new ComplexMatrix (*(t.complex_matrix)); - break; - case complex_scalar_constant: - complex_scalar = new Complex (*(t.complex_scalar)); - break; - case range_constant: - range = new Range (*(t.range)); - break; - case magic_colon: - break; - default: - panic_impossible (); - break; - } -} - -tree_constant_rep::~tree_constant_rep (void) -{ - switch (type_tag) - { - case unknown_constant: - break; - case scalar_constant: - break; - case matrix_constant: - delete matrix; - break; - case complex_scalar_constant: - delete complex_scalar; - break; - case complex_matrix_constant: - delete complex_matrix; - break; - case string_constant: - delete [] string; - break; - case range_constant: - delete range; - break; - case magic_colon: - break; - default: - panic_impossible (); - break; - } -} - -#if defined (MDEBUG) -void * -tree_constant_rep::operator new (size_t size) -{ - tree_constant_rep *p = ::new tree_constant_rep; - cerr << "tree_constant_rep::new(): " << p << "\n"; - return p; -} - -void -tree_constant_rep::operator delete (void *p, size_t size) -{ - cerr << "tree_constant_rep::delete(): " << p << "\n"; - ::delete p; -} +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif -void -tree_constant_rep::resize (int i, int j) -{ - switch (type_tag) - { - case matrix_constant: - matrix->resize (i, j); - break; - case complex_matrix_constant: - complex_matrix->resize (i, j); - break; - default: - panic_impossible (); - break; - } -} - -void -tree_constant_rep::resize (int i, int j, double val) -{ - switch (type_tag) - { - case matrix_constant: - matrix->resize (i, j, val); - break; - case complex_matrix_constant: - complex_matrix->resize (i, j, val); - break; - default: - panic_impossible (); - break; - } -} - -void -tree_constant_rep::maybe_resize (int i, int j) -{ - int nr = rows (); - int nc = columns (); - - i++; - j++; - - assert (i > 0 && j > 0); - - if (i > nr || j > nc) - { - if (user_pref.resize_on_range_error) - resize (MAX (i, nr), MAX (j, nc), 0.0); - else - { - if (i > nr) - ::error ("row index = %d exceeds max row dimension = %d", i, nr); - - if (j > nc) - ::error ("column index = %d exceeds max column dimension = %d", - j, nc); - } - } -} - -void -tree_constant_rep::maybe_resize (int i, force_orient f_orient = no_orient) -{ - int nr = rows (); - int nc = columns (); - - i++; - - assert (i >= 0 && (nr <= 1 || nc <= 1)); - -// This function never reduces the size of a vector, and all vectors -// have dimensions of at least 0x0. If i is 0, it is either because -// a vector has been indexed with a vector of all zeros (in which case -// the index vector is empty and nothing will happen) or a vector has -// been indexed with 0 (an error which will be caught elsewhere). - if (i == 0) - return; - - if (nr <= 1 && nc <= 1 && i >= 1) - { - if (user_pref.resize_on_range_error) - { - if (f_orient == row_orient) - resize (1, i, 0.0); - else if (f_orient == column_orient) - resize (i, 1, 0.0); - else if (user_pref.prefer_column_vectors) - resize (i, 1, 0.0); - else - resize (1, i, 0.0); - } - else - ::error ("matrix index = %d exceeds max dimension = %d", i, nc); - } - else if (nr == 1 && i > nc) - { - if (user_pref.resize_on_range_error) - resize (1, i, 0.0); - else - ::error ("matrix index = %d exceeds max dimension = %d", i, nc); - } - else if (nc == 1 && i > nr) - { - if (user_pref.resize_on_range_error) - resize (i, 1, 0.0); - else - ::error ("matrix index = %d exceeds max dimension = ", i, nc); - } -} - -double -tree_constant_rep::to_scalar (void) const -{ - tree_constant tmp = make_numeric (); - - double retval = 0.0; - - switch (tmp.const_type ()) - { - case tree_constant_rep::scalar_constant: - case tree_constant_rep::complex_scalar_constant: - retval = tmp.double_value (); - break; - case tree_constant_rep::matrix_constant: - if (user_pref.do_fortran_indexing) - { - Matrix m = tmp.matrix_value (); - retval = m (0, 0); - } - break; - case tree_constant_rep::complex_matrix_constant: - if (user_pref.do_fortran_indexing) - { - int flag = user_pref.ok_to_lose_imaginary_part; - if (flag == -1) - warning ("implicit conversion of complex value to real value"); - - if (flag != 0) - { - ComplexMatrix m = tmp.complex_matrix_value (); - return ::real (m (0, 0)); - } - else - jump_to_top_level (); - } - else - { - ::error ("complex matrix used in invalid context"); - jump_to_top_level (); - } - break; - default: - break; - } - return retval; -} - -ColumnVector -tree_constant_rep::to_vector (void) const -{ - tree_constant tmp = make_numeric (); - - ColumnVector retval; - - switch (tmp.const_type ()) - { - case tree_constant_rep::scalar_constant: - case tree_constant_rep::complex_scalar_constant: - retval.resize (1); - retval.elem (0) = tmp.double_value (); - break; - case tree_constant_rep::complex_matrix_constant: - case tree_constant_rep::matrix_constant: - { - Matrix m = tmp.matrix_value (); - int nr = m.rows (); - int nc = m.columns (); - if (nr == 1) - { - retval.resize (nc); - for (int i = 0; i < nc; i++) - retval.elem (i) = m (0, i); - } - else if (nc == 1) - { - retval.resize (nr); - for (int i = 0; i < nr; i++) - retval.elem (i) = m.elem (i, 0); - } - } - break; - default: - panic_impossible (); - break; - } - return retval; -} - -Matrix -tree_constant_rep::to_matrix (void) const -{ - tree_constant tmp = make_numeric (); - - Matrix retval; - - switch (tmp.const_type ()) - { - case tree_constant_rep::scalar_constant: - retval.resize (1, 1); - retval.elem (0, 0) = tmp.double_value (); - break; - case tree_constant_rep::matrix_constant: - retval = tmp.matrix_value (); - break; - default: - break; - } - return retval; -} - -tree_constant_rep::constant_type -tree_constant_rep::force_numeric (int force_str_conv = 0) -{ - switch (type_tag) - { - case scalar_constant: - case matrix_constant: - case complex_scalar_constant: - case complex_matrix_constant: - break; - case string_constant: - { - if (! force_str_conv && ! user_pref.implicit_str_to_num_ok) - { - ::error ("failed to convert `%s' to a numeric type --", string); - ::error ("default conversion turned off"); -// Abort! - jump_to_top_level (); - } - - int len = strlen (string); - if (len > 1) - { - type_tag = matrix_constant; - Matrix *tm = new Matrix (1, len); - for (int i = 0; i < len; i++) - tm->elem (0, i) = toascii ((int) string[i]); - matrix = tm; - } - else if (len == 1) - { - type_tag = scalar_constant; - scalar = toascii ((int) string[0]); - } - else if (len == 0) - { - type_tag = matrix_constant; - matrix = new Matrix (0, 0); - } - else - panic_impossible (); - } - break; - case range_constant: - { - int len = range->nelem (); - if (len > 1) - { - type_tag = matrix_constant; - Matrix *tm = new Matrix (1, len); - double b = range->base (); - double increment = range->inc (); - for (int i = 0; i < len; i++) - tm->elem (0, i) = b + i * increment; - matrix = tm; - } - else if (len == 1) - { - type_tag = scalar_constant; - scalar = range->base (); - } - } - break; - case magic_colon: - default: - panic_impossible (); - break; - } - return type_tag; -} - -tree_constant -tree_constant_rep::make_numeric (int force_str_conv = 0) const -{ - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - retval = tree_constant (scalar); - break; - case matrix_constant: - retval = tree_constant (*matrix); - break; - case complex_scalar_constant: - retval = tree_constant (*complex_scalar); - break; - case complex_matrix_constant: - retval = tree_constant (*complex_matrix); - break; - case string_constant: - retval = tree_constant (string); - retval.force_numeric (force_str_conv); - break; - case range_constant: - retval = tree_constant (*range); - retval.force_numeric (force_str_conv); - break; - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -do_binary_op (tree_constant& a, tree_constant& b, tree::expression_type t) -{ - tree_constant ans; - - int first_empty = (a.rows () == 0 || a.columns () == 0); - int second_empty = (b.rows () == 0 || b.columns () == 0); - - if (first_empty || second_empty) - { - int flag = user_pref.propagate_empty_matrices; - if (flag < 0) - warning ("binary operation on empty matrix"); - else if (flag == 0) - { - ::error ("invalid binary operation on empty matrix"); - return ans; - } - } - - tree_constant tmp_a = a.make_numeric (); - tree_constant tmp_b = b.make_numeric (); - - tree_constant_rep::constant_type a_type = tmp_a.const_type (); - tree_constant_rep::constant_type b_type = tmp_b.const_type (); - - double d1, d2; - Matrix m1, m2; - Complex c1, c2; - ComplexMatrix cm1, cm2; - - switch (a_type) - { - case tree_constant_rep::scalar_constant: - d1 = tmp_a.double_value (); - switch (b_type) - { - case tree_constant_rep::scalar_constant: - d2 = tmp_b.double_value (); - ans = do_binary_op (d1, d2, t); - break; - case tree_constant_rep::matrix_constant: - m2 = tmp_b.matrix_value (); - ans = do_binary_op (d1, m2, t); - break; - case tree_constant_rep::complex_scalar_constant: - c2 = tmp_b.complex_value (); - ans = do_binary_op (d1, c2, t); - break; - case tree_constant_rep::complex_matrix_constant: - cm2 = tmp_b.complex_matrix_value (); - ans = do_binary_op (d1, cm2, t); - break; - case tree_constant_rep::magic_colon: - default: - panic_impossible (); - break; - } - break; - case tree_constant_rep::matrix_constant: - m1 = tmp_a.matrix_value (); - switch (b_type) - { - case tree_constant_rep::scalar_constant: - d2 = tmp_b.double_value (); - ans = do_binary_op (m1, d2, t); - break; - case tree_constant_rep::matrix_constant: - m2 = tmp_b.matrix_value (); - ans = do_binary_op (m1, m2, t); - break; - case tree_constant_rep::complex_scalar_constant: - c2 = tmp_b.complex_value (); - ans = do_binary_op (m1, c2, t); - break; - case tree_constant_rep::complex_matrix_constant: - cm2 = tmp_b.complex_matrix_value (); - ans = do_binary_op (m1, cm2, t); - break; - case tree_constant_rep::magic_colon: - default: - panic_impossible (); - break; - } - break; - case tree_constant_rep::complex_scalar_constant: - c1 = tmp_a.complex_value (); - switch (b_type) - { - case tree_constant_rep::scalar_constant: - d2 = tmp_b.double_value (); - ans = do_binary_op (c1, d2, t); - break; - case tree_constant_rep::matrix_constant: - m2 = tmp_b.matrix_value (); - ans = do_binary_op (c1, m2, t); - break; - case tree_constant_rep::complex_scalar_constant: - c2 = tmp_b.complex_value (); - ans = do_binary_op (c1, c2, t); - break; - case tree_constant_rep::complex_matrix_constant: - cm2 = tmp_b.complex_matrix_value (); - ans = do_binary_op (c1, cm2, t); - break; - case tree_constant_rep::magic_colon: - default: - panic_impossible (); - break; - } - break; - case tree_constant_rep::complex_matrix_constant: - cm1 = tmp_a.complex_matrix_value (); - switch (b_type) - { - case tree_constant_rep::scalar_constant: - d2 = tmp_b.double_value (); - ans = do_binary_op (cm1, d2, t); - break; - case tree_constant_rep::matrix_constant: - m2 = tmp_b.matrix_value (); - ans = do_binary_op (cm1, m2, t); - break; - case tree_constant_rep::complex_scalar_constant: - c2 = tmp_b.complex_value (); - ans = do_binary_op (cm1, c2, t); - break; - case tree_constant_rep::complex_matrix_constant: - cm2 = tmp_b.complex_matrix_value (); - ans = do_binary_op (cm1, cm2, t); - break; - case tree_constant_rep::magic_colon: - default: - panic_impossible (); - break; - } - break; - case tree_constant_rep::magic_colon: - default: - panic_impossible (); - break; - } - return ans; -} - -tree_constant -do_unary_op (tree_constant& a, tree::expression_type t) -{ - tree_constant ans; - - if (a.rows () == 0 || a.columns () == 0) - { - int flag = user_pref.propagate_empty_matrices; - if (flag < 0) - warning ("unary operation on empty matrix"); - else if (flag == 0) - { - ::error ("invalid unary operation on empty matrix"); - return ans; - } - } - - tree_constant tmp_a = a.make_numeric (); - - switch (tmp_a.const_type ()) - { - case tree_constant_rep::scalar_constant: - ans = do_unary_op (tmp_a.double_value (), t); - break; - case tree_constant_rep::matrix_constant: - { - Matrix m = tmp_a.matrix_value (); - ans = do_unary_op (m, t); - } - break; - case tree_constant_rep::complex_scalar_constant: - ans = do_unary_op (tmp_a.complex_value (), t); - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix m = tmp_a.complex_matrix_value (); - ans = do_unary_op (m, t); - } - break; - case tree_constant_rep::magic_colon: - default: - panic_impossible (); - break; - } - return ans; -} - -void -tree_constant_rep::bump_value (tree::expression_type etype) -{ - switch (etype) - { - case tree::increment: - switch (type_tag) - { - case scalar_constant: - scalar++; - break; - case matrix_constant: - *matrix = *matrix + 1.0; - break; - case complex_scalar_constant: - *complex_scalar = *complex_scalar + 1.0; - break; - case complex_matrix_constant: - *complex_matrix = *complex_matrix + 1.0; - break; - case string_constant: - ::error ("string++ and ++string not implemented yet, ok?"); - break; - case range_constant: - range->set_base (range->base () + 1.0); - range->set_limit (range->limit () + 1.0); - break; - case magic_colon: - default: - panic_impossible (); - break; - } - break; - case tree::decrement: - switch (type_tag) - { - case scalar_constant: - scalar--; - break; - case matrix_constant: - *matrix = *matrix - 1.0; - break; - case string_constant: - ::error ("string-- and -- string not implemented yet, ok?"); - break; - case range_constant: - range->set_base (range->base () - 1.0); - range->set_limit (range->limit () - 1.0); - break; - case magic_colon: - default: - panic_impossible (); - break; - } - break; - default: - panic_impossible (); - break; - } -} - -void -tree_constant_rep::eval (int print) -{ - if (error_state) - return; - - switch (type_tag) - { - case complex_scalar_constant: - if (::imag (*complex_scalar) == 0.0) - { - double d = ::real (*complex_scalar); - delete complex_scalar; - scalar = d; - type_tag = scalar_constant; - } - break; - case complex_matrix_constant: - if (! any_element_is_complex (*complex_matrix)) - { - Matrix *m = new Matrix (::real (*complex_matrix)); - delete complex_matrix; - matrix = m; - type_tag = matrix_constant; - } - break; - case scalar_constant: - case matrix_constant: - case string_constant: - case range_constant: - case magic_colon: - break; - default: - panic_impossible (); - break; - } - -// Avoid calling rows() and columns() for things like magic_colon. - - int nr = 1; - int nc = 1; - if (type_tag == matrix_constant - || type_tag == complex_matrix_constant - || type_tag == range_constant) - { - nr = rows (); - nc = columns (); - } - - switch (type_tag) - { - case matrix_constant: - if (nr == 1 && nc == 1) - { - double d = matrix->elem (0, 0); - delete matrix; - scalar = d; - type_tag = scalar_constant; - } - break; - case complex_matrix_constant: - if (nr == 1 && nc == 1) - { - Complex c = complex_matrix->elem (0, 0); - delete complex_matrix; - complex_scalar = new Complex (c); - type_tag = complex_scalar_constant; - } - break; - case range_constant: - if (nr == 1 && nc == 1) - { - double d = range->base (); - delete range; - scalar = d; - type_tag = scalar_constant; - } - break; - default: - break; - } - - if (print) - { - ostrstream output_buf; - switch (type_tag) - { - case scalar_constant: - octave_print_internal (output_buf, scalar); - break; - case matrix_constant: - if (nr == 0 || nc == 0) - { - output_buf << "[]"; - if (user_pref.print_empty_dimensions) - output_buf << "(" << nr << "x" << nc << ")"; - output_buf << "\n"; - } - else - octave_print_internal (output_buf, *matrix); - break; - case complex_scalar_constant: - octave_print_internal (output_buf, *complex_scalar); - break; - case complex_matrix_constant: - if (nr == 0 || nc == 0) - { - output_buf << "[]"; - if (user_pref.print_empty_dimensions) - output_buf << "(" << nr << "x" << nc << ")"; - output_buf << "\n"; - } - else - octave_print_internal (output_buf, *complex_matrix); - break; - case string_constant: - output_buf << string << "\n"; - break; - case range_constant: - octave_print_internal (output_buf, *range); - break; - case magic_colon: - default: - panic_impossible (); - break; - } - - output_buf << ends; - maybe_page_output (output_buf); - } -} - -tree_constant * -tree_constant_rep::eval (const tree_constant *args, int nargin, int nargout, - int print) -{ - if (error_state) - return NULL_TREE_CONST; - - tree_constant *retval = new tree_constant [2]; - switch (type_tag) - { - case complex_scalar_constant: - case scalar_constant: - retval[0] = do_scalar_index (args, nargin); - break; - case complex_matrix_constant: - case matrix_constant: - retval[0] = do_matrix_index (args, nargin); - break; - case string_constant: - gripe_string_invalid (); -// retval[0] = do_string_index (args, nargin); - break; - case magic_colon: - case range_constant: -// This isn\'t great, but it\'s easier than implementing a lot of -// range indexing functions. - force_numeric (); - assert (type_tag != magic_colon && type_tag != range_constant); - return eval (args, nargin, nargout, print); - break; - default: - panic_impossible (); - break; - } - - if (retval[0].is_defined ()) - retval[0].eval (print); - return retval; -} - -int -tree_constant_rep::save (ostream& os, int mark_as_global, int precision) -{ - switch (type_tag) - { - case scalar_constant: - case matrix_constant: - case complex_scalar_constant: - case complex_matrix_constant: - case string_constant: - case range_constant: - if (mark_as_global) - os << "# type: global "; - else - os << "# type: "; - break; - case magic_colon: - default: - break; - } - - long old_precision = os.precision (); - os.precision (precision); - - switch (type_tag) - { - case scalar_constant: - os << "scalar\n" - << scalar << "\n"; - break; - case matrix_constant: - os << "matrix\n" - << "# rows: " << rows () << "\n" - << "# columns: " << columns () << "\n" - << *matrix ; - break; - case complex_scalar_constant: - os << "complex scalar\n" - << *complex_scalar << "\n"; - break; - case complex_matrix_constant: - os << "complex matrix\n" - << "# rows: " << rows () << "\n" - << "# columns: " << columns () << "\n" - << *complex_matrix ; - break; - case string_constant: - os << "string\n" - << "# length: " << strlen (string) << "\n" - << string << "\n"; - break; - case range_constant: - { - os << "range\n" - << "# base, limit, increment\n" - << range->base () << " " - << range->limit () << " " - << range->inc () << "\n"; - } - break; - case magic_colon: - default: - panic_impossible (); - break; - } - - os.precision (old_precision); - -// Really want to return 1 only if write is successful. - return 1; -} - -int -tree_constant_rep::save_three_d (ostream& os, int parametric) -{ - int nr = rows (); - int nc = columns (); - - switch (type_tag) - { - case matrix_constant: - os << "# 3D data...\n" - << "# type: matrix\n" - << "# total rows: " << nr << "\n" - << "# total columns: " << nc << "\n"; - - if (parametric) - { - int extras = nc % 3; - if (extras) - warning ("ignoring last %d columns", extras); - - for (int i = 0; i < nc-extras; i += 3) - { - os << matrix->extract (0, i, nr-1, i+2); - if (i+3 < nc-extras) - os << "\n"; - } - } - else - { - for (int i = 0; i < nc; i++) - { - os << matrix->extract (0, i, nr-1, i); - if (i+1 < nc) - os << "\n"; - } - } - break; - default: - ::error ("for now, I can only save real matrices in 3D format"); - return 0; - break; - } -// Really want to return 1 only if write is successful. - return 1; -} - -int -tree_constant_rep::load (istream& is) -{ - int is_global = 0; - - type_tag = unknown_constant; - -// Look for type keyword - - char *tag = extract_keyword (is, "type"); - - if (tag != (char *) NULL && *tag != '\0') - { - char *ptr = strchr (tag, ' '); - if (ptr != (char *) NULL) - { - *ptr = '\0'; - is_global = (strncmp (tag, "global", 6) == 0); - *ptr = ' '; - if (is_global) - ptr++; - else - ptr = tag; - } - else - ptr = tag; - - if (strncmp (ptr, "scalar", 6) == 0) - type_tag = load (is, scalar_constant); - else if (strncmp (ptr, "matrix", 6) == 0) - type_tag = load (is, matrix_constant); - else if (strncmp (ptr, "complex scalar", 14) == 0) - type_tag = load (is, complex_scalar_constant); - else if (strncmp (ptr, "complex matrix", 14) == 0) - type_tag = load (is, complex_matrix_constant); - else if (strncmp (ptr, "string", 6) == 0) - type_tag = load (is, string_constant); - else if (strncmp (ptr, "range", 5) == 0) - type_tag = load (is, range_constant); - else - ::error ("unknown constant type `%s'", tag); - } - else - ::error ("failed to extract keyword specifying value type"); - - delete [] tag; - - return is_global; -} - -tree_constant_rep::constant_type -tree_constant_rep::load (istream& is, tree_constant_rep::constant_type t) -{ - tree_constant_rep::constant_type status = unknown_constant; - - switch (t) - { - case scalar_constant: - is >> scalar; - if (is) - status = scalar_constant; - else - ::error ("failed to load scalar constant"); - break; - case matrix_constant: - { - int nr = 0, nc = 0; - - if (extract_keyword (is, "rows", nr) && nr > 0 - && extract_keyword (is, "columns", nc) && nc > 0) - { - matrix = new Matrix (nr, nc); - is >> *matrix; - if (is) - status = matrix_constant; - else - ::error ("failed to load matrix constant"); - } - else - ::error ("failed to extract number of rows and columns"); - } - break; - case complex_scalar_constant: - complex_scalar = new Complex; - is >> *complex_scalar; - if (is) - status = complex_scalar_constant; - else - ::error ("failed to load complex scalar constant"); - break; - case complex_matrix_constant: - { - int nr = 0, nc = 0; - - if (extract_keyword (is, "rows", nr) && nr > 0 - && extract_keyword (is, "columns", nc) && nc > 0) - { - complex_matrix = new ComplexMatrix (nr, nc); - is >> *complex_matrix; - if (is) - status = complex_matrix_constant; - else - ::error ("failed to load complex matrix constant"); - } - else - ::error ("failed to extract number of rows and columns"); - } - break; - case string_constant: - { - int len; - if (extract_keyword (is, "length", len) && len > 0) - { - string = new char [len+1]; - is.get (string, len+1, EOF); - if (is) - status = string_constant; - else - ::error ("failed to load string constant"); - } - else - ::error ("failed to extract string length"); - } - break; - case range_constant: - skip_comments (is); - range = new Range (); - is >> *range; - if (is) - status = range_constant; - else - ::error ("failed to load range constant"); - break; - default: - panic_impossible (); - break; - } - return status; -} - -double -tree_constant_rep::double_value (void) const -{ - switch (type_tag) - { - case scalar_constant: - return scalar; - case complex_scalar_constant: - { - int flag = user_pref.ok_to_lose_imaginary_part; - if (flag == -1) - warning ("implicit conversion of complex value to real value"); - - if (flag != 0) - return ::real (*complex_scalar); - - ::error ("implicit conversion of complex value to real value"); - ::error ("not allowed"); - jump_to_top_level (); - } - default: - panic_impossible (); - break; - } -} - -Matrix -tree_constant_rep::matrix_value (void) const -{ - switch (type_tag) - { - case scalar_constant: - return Matrix (1, 1, scalar); - case matrix_constant: - return *matrix; - case complex_scalar_constant: - case complex_matrix_constant: - { - int flag = user_pref.ok_to_lose_imaginary_part; - if (flag == -1) - warning ("implicit conversion of complex matrix to real matrix"); - - if (flag != 0) - { - if (type_tag == complex_scalar_constant) - return Matrix (1, 1, ::real (*complex_scalar)); - else if (type_tag == complex_matrix_constant) - return ::real (*complex_matrix); - else - panic_impossible (); - } - else - { - ::error ("implicit conversion of complex matrix to real matrix"); - ::error ("not allowed"); - } - jump_to_top_level (); - } - default: - panic_impossible (); - break; - } -} - -Complex -tree_constant_rep::complex_value (void) const -{ - switch (type_tag) - { - case complex_scalar_constant: - return *complex_scalar; - case scalar_constant: - return Complex (scalar); - default: - panic_impossible (); - break; - } -} - -ComplexMatrix -tree_constant_rep::complex_matrix_value (void) const -{ - switch (type_tag) - { - case scalar_constant: - { - return ComplexMatrix (1, 1, Complex (scalar)); - } - case complex_scalar_constant: - { - return ComplexMatrix (1, 1, *complex_scalar); - } - case matrix_constant: - { - return ComplexMatrix (*matrix); - } - case complex_matrix_constant: - return *complex_matrix; - break; - default: - panic_impossible (); - break; - } -} - -char * -tree_constant_rep::string_value (void) const -{ - assert (type_tag == string_constant); - return string; -} - -Range -tree_constant_rep::range_value (void) const -{ - assert (type_tag == range_constant); - return *range; -} - -int -tree_constant_rep::rows (void) const -{ - int retval = -1; - switch (type_tag) - { - case scalar_constant: - case complex_scalar_constant: - retval = 1; - break; - case string_constant: - case range_constant: - retval = (columns () > 0) ? 1 : 0; - break; - case matrix_constant: - retval = matrix->rows (); - break; - case complex_matrix_constant: - retval = complex_matrix->rows (); - break; - case magic_colon: - ::error ("invalid use of colon operator"); - break; - case unknown_constant: - retval = 0; - break; - default: - panic_impossible (); - break; - } - return retval; -} - -int -tree_constant_rep::columns (void) const -{ - int retval = -1; - switch (type_tag) - { - case scalar_constant: - case complex_scalar_constant: - retval = 1; - break; - case matrix_constant: - retval = matrix->columns (); - break; - case complex_matrix_constant: - retval = complex_matrix->columns (); - break; - case string_constant: - retval = strlen (string); - break; - case range_constant: - retval = range->nelem (); - break; - case magic_colon: - ::error ("invalid use of colon operator"); - break; - case unknown_constant: - retval = 0; - break; - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::all (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.all (); - } - - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - { - double status = (scalar != 0.0); - retval = tree_constant (status); - } - break; - case matrix_constant: - { - Matrix m = matrix->all (); - retval = tree_constant (m); - } - break; - case complex_scalar_constant: - { - double status = (*complex_scalar != 0.0); - retval = tree_constant (status); - } - break; - case complex_matrix_constant: - { - Matrix m = complex_matrix->all (); - retval = tree_constant (m); - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::any (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.any (); - } - - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - { - double status = (scalar != 0.0); - retval = tree_constant (status); - } - break; - case matrix_constant: - { - Matrix m = matrix->any (); - retval = tree_constant (m); - } - break; - case complex_scalar_constant: - { - double status = (*complex_scalar != 0.0); - retval = tree_constant (status); - } - break; - case complex_matrix_constant: - { - Matrix m = complex_matrix->any (); - retval = tree_constant (m); - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::isstr (void) const -{ - double status = 0.0; - if (type_tag == string_constant) - status = 1.0; - tree_constant retval (status); - return retval; -} - -tree_constant -tree_constant_rep::convert_to_str (void) -{ - tree_constant retval; - - switch (type_tag) - { - case complex_scalar_constant: - case scalar_constant: - { - double d = double_value (); - int i = NINT (d); -// Warn about out of range conversions? - char s[2]; - s[0] = (char) i; - s[1] = '\0'; - retval = tree_constant (s); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - ColumnVector v = to_vector (); - int len = v.length (); - if (len == 0) - ::error ("can only convert vectors and scalars to strings"); - else - { - char *s = new char [len+1]; - s[len] = '\0'; - for (int i = 0; i < len; i++) - { - double d = v.elem (i); - int ival = NINT (d); -// Warn about out of range conversions? - s[i] = (char) ival; - } - retval = tree_constant (s); - delete [] s; - } - } - break; - case range_constant: - { - Range r = range_value (); - double b = r.base (); - double incr = r.inc (); - int nel = r.nelem (); - char *s = new char [nel+1]; - s[nel] = '\0'; - for (int i = 0; i < nel; i++) - { - double d = b + i * incr; - int ival = NINT (d); -// Warn about out of range conversions? - s[i] = (char) ival; - } - retval = tree_constant (s); - delete [] s; - } - break; - case string_constant: - retval = tree_constant (*this); - break; - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -void -tree_constant_rep::convert_to_row_or_column_vector (void) -{ - assert (type_tag == matrix_constant || type_tag == complex_matrix_constant); - - int nr = rows (); - int nc = columns (); - - int len = nr * nc; - - assert (len > 0); - - int new_nr = 1; - int new_nc = 1; - - if (user_pref.prefer_column_vectors) - new_nr = len; - else - new_nc = len; - - if (type_tag == matrix_constant) - { - Matrix *m = new Matrix (new_nr, new_nc); - - double *cop_out = matrix->fortran_vec (); - - for (int i = 0; i < len; i++) - { - if (new_nr == 1) - m->elem (0, i) = *cop_out++; - else - m->elem (i, 0) = *cop_out++; - } - - delete matrix; - matrix = m; - } - else - { - ComplexMatrix *cm = new ComplexMatrix (new_nr, new_nc); - - Complex *cop_out = complex_matrix->fortran_vec (); - - for (int i = 0; i < len; i++) - { - if (new_nr == 1) - cm->elem (0, i) = *cop_out++; - else - cm->elem (i, 0) = *cop_out++; - } - - delete complex_matrix; - complex_matrix = cm; - } -} - -int -tree_constant_rep::is_true (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.is_true (); - } - - int retval; - switch (type_tag) - { - case scalar_constant: - retval = (scalar != 0.0); - break; - case matrix_constant: - { - Matrix m = (matrix->all ()) . all (); - retval = (m.rows () == 1 - && m.columns () == 1 - && m.elem (0, 0) != 0.0); - } - break; - case complex_scalar_constant: - retval = (*complex_scalar != 0.0); - break; - case complex_matrix_constant: - { - Matrix m = (complex_matrix->all ()) . all (); - retval = (m.rows () == 1 - && m.columns () == 1 - && m.elem (0, 0) != 0.0); - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::cumprod (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.cumprod (); - } - - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - retval = tree_constant (scalar); - break; - case matrix_constant: - { - Matrix m = matrix->cumprod (); - retval = tree_constant (m); - } - break; - case complex_scalar_constant: - retval = tree_constant (*complex_scalar); - break; - case complex_matrix_constant: - { - ComplexMatrix m = complex_matrix->cumprod (); - retval = tree_constant (m); - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::cumsum (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.cumsum (); - } - - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - retval = tree_constant (scalar); - break; - case matrix_constant: - { - Matrix m = matrix->cumsum (); - retval = tree_constant (m); - } - break; - case complex_scalar_constant: - retval = tree_constant (*complex_scalar); - break; - case complex_matrix_constant: - { - ComplexMatrix m = complex_matrix->cumsum (); - retval = tree_constant (m); - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::prod (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.prod (); - } - - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - retval = tree_constant (scalar); - break; - case matrix_constant: - { - Matrix m = matrix->prod (); - retval = tree_constant (m); - } - break; - case complex_scalar_constant: - retval = tree_constant (*complex_scalar); - break; - case complex_matrix_constant: - { - ComplexMatrix m = complex_matrix->prod (); - retval = tree_constant (m); - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::sum (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.sum (); - } - - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - retval = tree_constant (scalar); - break; - case matrix_constant: - { - Matrix m = matrix->sum (); - retval = tree_constant (m); - } - break; - case complex_scalar_constant: - retval = tree_constant (*complex_scalar); - break; - case complex_matrix_constant: - { - ComplexMatrix m = complex_matrix->sum (); - retval = tree_constant (m); - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::sumsq (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.sumsq (); - } - - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - retval = tree_constant (scalar * scalar); - break; - case matrix_constant: - { - Matrix m = matrix->sumsq (); - retval = tree_constant (m); - } - break; - case complex_scalar_constant: - { - Complex c (*complex_scalar); - retval = tree_constant (c * c); - } - break; - case complex_matrix_constant: - { - ComplexMatrix m = complex_matrix->sumsq (); - retval = tree_constant (m); - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -static tree_constant -make_diag (const Matrix& v, int k) -{ - int nr = v.rows (); - int nc = v.columns (); - assert (nc == 1 || nr == 1); - - tree_constant retval; - - int roff = 0; - int coff = 0; - if (k > 0) - { - roff = 0; - coff = k; - } - else if (k < 0) - { - roff = -k; - coff = 0; - } - - if (nr == 1) - { - int n = nc + ABS (k); - Matrix m (n, n, 0.0); - for (int i = 0; i < nc; i++) - m.elem (i+roff, i+coff) = v.elem (0, i); - retval = tree_constant (m); - } - else - { - int n = nr + ABS (k); - Matrix m (n, n, 0.0); - for (int i = 0; i < nr; i++) - m.elem (i+roff, i+coff) = v.elem (i, 0); - retval = tree_constant (m); - } - - return retval; -} - -static tree_constant -make_diag (const ComplexMatrix& v, int k) -{ - int nr = v.rows (); - int nc = v.columns (); - assert (nc == 1 || nr == 1); - - tree_constant retval; - - int roff = 0; - int coff = 0; - if (k > 0) - { - roff = 0; - coff = k; - } - else if (k < 0) - { - roff = -k; - coff = 0; - } - - if (nr == 1) - { - int n = nc + ABS (k); - ComplexMatrix m (n, n, 0.0); - for (int i = 0; i < nc; i++) - m.elem (i+roff, i+coff) = v.elem (0, i); - retval = tree_constant (m); - } - else - { - int n = nr + ABS (k); - ComplexMatrix m (n, n, 0.0); - for (int i = 0; i < nr; i++) - m.elem (i+roff, i+coff) = v.elem (i, 0); - retval = tree_constant (m); - } - - return retval; -} - -tree_constant -tree_constant_rep::diag (void) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.diag (); - } - - tree_constant retval; - switch (type_tag) - { - case scalar_constant: - retval = tree_constant (scalar); - break; - case matrix_constant: - { - int nr = rows (); - int nc = columns (); - if (nr == 0 || nc == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else if (nr == 1 || nc == 1) - retval = make_diag (matrix_value (), 0); - else - { - ColumnVector v = matrix->diag (); - if (v.capacity () > 0) - retval = tree_constant (v); - } - } - break; - case complex_scalar_constant: - retval = tree_constant (*complex_scalar); - break; - case complex_matrix_constant: - { - int nr = rows (); - int nc = columns (); - if (nr == 0 || nc == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else if (nr == 1 || nc == 1) - retval = make_diag (complex_matrix_value (), 0); - else - { - ComplexColumnVector v = complex_matrix->diag (); - if (v.capacity () > 0) - retval = tree_constant (v); - } - } - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::diag (const tree_constant& a) const -{ - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.diag (a); - } - - tree_constant tmp_a = a.make_numeric (); - - tree_constant_rep::constant_type a_type = tmp_a.const_type (); - - tree_constant retval; - - switch (type_tag) - { - case scalar_constant: - if (a_type == scalar_constant) - { - int k = NINT (tmp_a.double_value ()); - int n = ABS (k) + 1; - if (k == 0) - retval = tree_constant (scalar); - else if (k > 0) - { - Matrix m (n, n, 0.0); - m.elem (0, k) = scalar; - retval = tree_constant (m); - } - else if (k < 0) - { - Matrix m (n, n, 0.0); - m.elem (-k, 0) = scalar; - retval = tree_constant (m); - } - } - break; - case matrix_constant: - if (a_type == scalar_constant) - { - int k = NINT (tmp_a.double_value ()); - int nr = rows (); - int nc = columns (); - if (nr == 0 || nc == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else if (nr == 1 || nc == 1) - retval = make_diag (matrix_value (), k); - else - { - ColumnVector d = matrix->diag (k); - retval = tree_constant (d); - } - } - else - ::error ("diag: invalid second argument"); - - break; - case complex_scalar_constant: - if (a_type == scalar_constant) - { - int k = NINT (tmp_a.double_value ()); - int n = ABS (k) + 1; - if (k == 0) - retval = tree_constant (*complex_scalar); - else if (k > 0) - { - ComplexMatrix m (n, n, 0.0); - m.elem (0, k) = *complex_scalar; - retval = tree_constant (m); - } - else if (k < 0) - { - ComplexMatrix m (n, n, 0.0); - m.elem (-k, 0) = *complex_scalar; - retval = tree_constant (m); - } - } - break; - case complex_matrix_constant: - if (a_type == scalar_constant) - { - int k = NINT (tmp_a.double_value ()); - int nr = rows (); - int nc = columns (); - if (nr == 0 || nc == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else if (nr == 1 || nc == 1) - retval = make_diag (complex_matrix_value (), k); - else - { - ComplexColumnVector d = complex_matrix->diag (k); - retval = tree_constant (d); - } - } - else - ::error ("diag: invalid second argument"); - - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - return retval; -} - -tree_constant -tree_constant_rep::mapper (Mapper_fcn& m_fcn, int print) const -{ - tree_constant retval; - - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.mapper (m_fcn, print); - } - - switch (type_tag) - { - case scalar_constant: - if (m_fcn.can_return_complex_for_real_arg - && (scalar < m_fcn.lower_limit - || scalar > m_fcn.upper_limit)) - { - if (m_fcn.c_c_mapper != NULL) - { - Complex c = m_fcn.c_c_mapper (Complex (scalar)); - retval = tree_constant (c); - } - else - panic_impossible (); - } - else - { - if (m_fcn.d_d_mapper != NULL) - { - double d = m_fcn.d_d_mapper (scalar); - retval = tree_constant (d); - } - else - panic_impossible (); - } - break; - case matrix_constant: - if (m_fcn.can_return_complex_for_real_arg - && (any_element_less_than (*matrix, m_fcn.lower_limit) - || any_element_greater_than (*matrix, m_fcn.upper_limit))) - { - if (m_fcn.c_c_mapper != NULL) - { - ComplexMatrix cm = map (m_fcn.c_c_mapper, - ComplexMatrix (*matrix)); - retval = tree_constant (cm); - } - else - panic_impossible (); - } - else - { - if (m_fcn.d_d_mapper != NULL) - { - Matrix m = map (m_fcn.d_d_mapper, *matrix); - retval = tree_constant (m); - } - else - panic_impossible (); - } - break; - case complex_scalar_constant: - if (m_fcn.d_c_mapper != NULL) - { - double d; - d = m_fcn.d_c_mapper (*complex_scalar); - retval = tree_constant (d); - } - else if (m_fcn.c_c_mapper != NULL) - { - Complex c; - c = m_fcn.c_c_mapper (*complex_scalar); - retval = tree_constant (c); - } - else - panic_impossible (); - break; - case complex_matrix_constant: - if (m_fcn.d_c_mapper != NULL) - { - Matrix m; - m = map (m_fcn.d_c_mapper, *complex_matrix); - retval = tree_constant (m); - } - else if (m_fcn.c_c_mapper != NULL) - { - ComplexMatrix cm; - cm = map (m_fcn.c_c_mapper, *complex_matrix); - retval = tree_constant (cm); - } - else - panic_impossible (); - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } - - if (retval.is_defined ()) - return retval.eval (print); - else - return retval; -} +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif tree_constant::~tree_constant (void) { @@ -2565,2567 +118,1154 @@ return retval; } - -/* - * Top-level tree-constant function that handles assignments. Only - * decide if the left-hand side is currently a scalar or a matrix and - * hand off to other functions to do the real work. - */ -void -tree_constant_rep::assign (tree_constant& rhs, tree_constant *args, int nargs) +Matrix +max (const Matrix& a, const Matrix& b) { - tree_constant rhs_tmp = rhs.make_numeric (); - -// This is easier than actually handling assignments to strings. -// An assignment to a range will normally require a conversion to a -// vector since it will normally destroy the equally-spaced property -// of the range elements. - - if (type_tag == string_constant || type_tag == range_constant) - force_numeric (); + int nr = a.rows (); + int nc = a.columns (); + if (nr != b.rows () || nc != b.columns ()) + { + error ("two-arg max expecting args of same size"); + return Matrix (); + } - switch (type_tag) - { - case complex_scalar_constant: - case scalar_constant: - case unknown_constant: - do_scalar_assignment (rhs_tmp, args, nargs); - break; - case complex_matrix_constant: - case matrix_constant: - do_matrix_assignment (rhs_tmp, args, nargs); - break; - case string_constant: - ::error ("invalid assignment to string type"); - break; - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } + Matrix result (nr, nc); + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + double a_elem = a.elem (i, j); + double b_elem = b.elem (i, j); + result.elem (i, j) = MAX (a_elem, b_elem); + } + + return result; } -/* - * Assignments to scalars. If resize_on_range_error is true, - * this can convert the left-hand size to a matrix. - */ -void -tree_constant_rep::do_scalar_assignment (tree_constant& rhs, - tree_constant *args, int nargs) +ComplexMatrix +max (const ComplexMatrix& a, const ComplexMatrix& b) { - assert (type_tag == unknown_constant - || type_tag == scalar_constant - || type_tag == complex_scalar_constant); - - if ((rhs.is_scalar_type () || rhs.is_zero_by_zero ()) - && valid_scalar_indices (args, nargs)) - { - if (rhs.is_zero_by_zero ()) - { - if (type_tag == complex_scalar_constant) - delete complex_scalar; - - matrix = new Matrix (0, 0); - type_tag = matrix_constant; - } - else if (type_tag == unknown_constant || type_tag == scalar_constant) - { - if (rhs.const_type () == scalar_constant) - { - scalar = rhs.double_value (); - type_tag = scalar_constant; - } - else if (rhs.const_type () == complex_scalar_constant) - { - complex_scalar = new Complex (rhs.complex_value ()); - type_tag = complex_scalar_constant; - } - else - { - ::error ("invalid assignment to scalar"); - return; - } - } - else - { - if (rhs.const_type () == scalar_constant) - { - delete complex_scalar; - scalar = rhs.double_value (); - type_tag = scalar_constant; - } - else if (rhs.const_type () == complex_scalar_constant) - { - *complex_scalar = rhs.complex_value (); - type_tag = complex_scalar_constant; - } - else - { - ::error ("invalid assignment to scalar"); - return; - } - } - } - else if (user_pref.resize_on_range_error) + int nr = a.rows (); + int nc = a.columns (); + if (nr != b.rows () || nc != b.columns ()) { - tree_constant_rep::constant_type old_type_tag = type_tag; - - if (type_tag == complex_scalar_constant) - { - Complex *old_complex = complex_scalar; - complex_matrix = new ComplexMatrix (1, 1, *complex_scalar); - type_tag = complex_matrix_constant; - delete old_complex; - } - else if (type_tag == scalar_constant) - { - matrix = new Matrix (1, 1, scalar); - type_tag = matrix_constant; - } - -// If there is an error, the call to do_matrix_assignment should not -// destroy the current value. tree_constant_rep::eval(int) will take -// care of converting single element matrices back to scalars. - - do_matrix_assignment (rhs, args, nargs); - -// I don't think there's any other way to revert back to unknown -// constant types, so here it is. - - if (old_type_tag == unknown_constant && error_state) - { - if (type_tag == matrix_constant) - delete matrix; - else if (type_tag == complex_matrix_constant) - delete complex_matrix; - - type_tag = unknown_constant; - } - } - else if (nargs > 3 || nargs < 2) - ::error ("invalid index expression for scalar type"); - else - ::error ("index invalid or out of range for scalar type"); -} - -/* - * Assignments to matrices (and vectors). - * - * For compatibility with Matlab, we allow assignment of an empty - * matrix to an expression with empty indices to do nothing. - */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant *args, int nargs) -{ - assert (type_tag == unknown_constant - || type_tag == matrix_constant - || type_tag == complex_matrix_constant); - - if (type_tag == matrix_constant && rhs.is_complex_type ()) - { - Matrix *old_matrix = matrix; - complex_matrix = new ComplexMatrix (*matrix); - type_tag = complex_matrix_constant; - delete old_matrix; - } - else if (type_tag == unknown_constant) - { - if (rhs.is_complex_type ()) - { - complex_matrix = new ComplexMatrix (); - type_tag = complex_matrix_constant; - } - else - { - matrix = new Matrix (); - type_tag = matrix_constant; - } + error ("two-arg max expecting args of same size"); + return ComplexMatrix (); } -// The do_matrix_assignment functions can't handle empty matrices, so -// don't let any pass through here. - switch (nargs) - { - case 2: - if (args == NULL_TREE_CONST) - ::error ("matrix index is null"); - else if (args[1].is_undefined ()) - ::error ("matrix index is undefined"); - else - do_matrix_assignment (rhs, args[1]); - break; - case 3: - if (args == NULL_TREE_CONST) - ::error ("matrix indices are null"); - else if (args[1].is_undefined ()) - ::error ("first matrix index is undefined"); - else if (args[2].is_undefined ()) - ::error ("second matrix index is undefined"); - else if (args[1].is_empty () || args[2].is_empty ()) - { - if (! rhs.is_empty ()) - { - ::error ("in assignment expression, a matrix index is empty"); - ::error ("but hte right hand side is not an empty matrix"); - } -// XXX FIXME XXX -- to really be correct here, we should probably -// check to see if the assignment conforms, but that seems like more -// work than it's worth right now... - } - else - do_matrix_assignment (rhs, args[1], args[2]); - break; - default: - ::error ("too many indices for matrix expression"); - break; - } + ComplexMatrix result (nr, nc); + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + double abs_a_elem = abs (a.elem (i, j)); + double abs_b_elem = abs (b.elem (i, j)); + if (abs_a_elem > abs_b_elem) + result.elem (i, j) = a.elem (i, j); + else + result.elem (i, j) = b.elem (i, j); + } + + return result; } -/* - * Matrix assignments indexed by a single value. - */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant& i_arg) +Matrix +min (const Matrix& a, const Matrix& b) { - int nr = rows (); - int nc = columns (); - - if (user_pref.do_fortran_indexing || nr <= 1 || nc <= 1) + int nr = a.rows (); + int nc = a.columns (); + if (nr != b.rows () || nc != b.columns ()) { - if (i_arg.is_empty ()) - { - if (! rhs.is_empty ()) - { - ::error ("in assignment expression, matrix index is empty but"); - ::error ("right hand side is not an empty matrix"); - } -// XXX FIXME XXX -- to really be correct here, we should probably -// check to see if the assignment conforms, but that seems like more -// work than it's worth right now... + error ("two-arg min expecting args of same size"); + return Matrix (); + } + + Matrix result (nr, nc); -// The assignment functions can't handle empty matrices, so don't let -// any pass through here. - return; - } - -// We can't handle the case of assigning to a vector first, since even -// then, the two operations are not equivalent. For example, the -// expression V(:) = M is handled differently depending on whether the -// user specified do_fortran_indexing = "true". + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + double a_elem = a.elem (i, j); + double b_elem = b.elem (i, j); + result.elem (i, j) = MIN (a_elem, b_elem); + } - if (user_pref.do_fortran_indexing) - fortran_style_matrix_assignment (rhs, i_arg); - else if (nr <= 1 || nc <= 1) - vector_assignment (rhs, i_arg); - else - panic_impossible (); - } - else - ::error ("single index only valid for row or column vector"); + return result; } -/* - * Fortran-style assignments. Matrices are assumed to be stored in - * column-major order and it is ok to use a single index for - * multi-dimensional matrices. - */ -void -tree_constant_rep::fortran_style_matrix_assignment (tree_constant& rhs, - tree_constant& i_arg) +ComplexMatrix +min (const ComplexMatrix& a, const ComplexMatrix& b) { - tree_constant tmp_i = i_arg.make_numeric_or_magic (); - - tree_constant_rep::constant_type itype = tmp_i.const_type (); - - int nr = rows (); - int nc = columns (); - - int rhs_nr = rhs.rows (); - int rhs_nc = rhs.columns (); - - switch (itype) + int nr = a.rows (); + int nc = a.columns (); + if (nr != b.rows () || nc != b.columns ()) { - case complex_scalar_constant: - case scalar_constant: - { - int i = NINT (tmp_i.double_value ()); - int idx = i - 1; - - if (rhs_nr == 0 && rhs_nc == 0) - { - if (idx < nr * nc) - { - convert_to_row_or_column_vector (); - - nr = rows (); - nc = columns (); + error ("two-arg min expecting args of same size"); + return ComplexMatrix (); + } - if (nr == 1) - delete_column (idx); - else if (nc == 1) - delete_row (idx); - else - panic_impossible (); - } - return; - } - - if (index_check (idx, "") < 0) - return; - - if (nr <= 1 || nc <= 1) - { - maybe_resize (idx); - if (error_state) - return; - } - else if (range_max_check (idx, nr * nc) < 0) - return; - - nr = rows (); - nc = columns (); - - if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc)) - { - ::error ("for A(int) = X: X must be a scalar"); - return; - } - int ii = fortran_row (i, nr) - 1; - int jj = fortran_column (i, nr) - 1; - do_matrix_assignment (rhs, ii, jj); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mi = tmp_i.matrix_value (); - int len = nr * nc; - idx_vector ii (mi, 1, "", len); // Always do fortran indexing here... - if (! ii) - return; + ComplexMatrix result (nr, nc); - if (rhs_nr == 0 && rhs_nc == 0) - { - ii.sort_uniq (); - int num_to_delete = 0; - for (int i = 0; i < ii.length (); i++) - { - if (ii.elem (i) < len) - num_to_delete++; - else - break; - } - - if (num_to_delete > 0) - { - if (num_to_delete != ii.length ()) - ii.shorten (num_to_delete); - - convert_to_row_or_column_vector (); - - nr = rows (); - nc = columns (); - - if (nr == 1) - delete_columns (ii); - else if (nc == 1) - delete_rows (ii); - else - panic_impossible (); - } - return; - } - - if (nr <= 1 || nc <= 1) - { - maybe_resize (ii.max ()); - if (error_state) - return; - } - else if (range_max_check (ii.max (), len) < 0) - return; + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + double abs_a_elem = abs (a.elem (i, j)); + double abs_b_elem = abs (b.elem (i, j)); + if (abs_a_elem < abs_b_elem) + result.elem (i, j) = a.elem (i, j); + else + result.elem (i, j) = b.elem (i, j); + } - int ilen = ii.capacity (); - - if (ilen != rhs_nr * rhs_nc) - { - ::error ("A(matrix) = X: X and matrix must have the same number"); - ::error ("of elements"); - } - else if (ilen == 1 && rhs.is_scalar_type ()) - { - int nr = rows (); - int idx = ii.elem (0); - int ii = fortran_row (idx + 1, nr) - 1; - int jj = fortran_column (idx + 1, nr) - 1; - - if (rhs.const_type () == scalar_constant) - matrix->elem (ii, jj) = rhs.double_value (); - else if (rhs.const_type () == complex_scalar_constant) - complex_matrix->elem (ii, jj) = rhs.complex_value (); - else - panic_impossible (); - } - else - fortran_style_matrix_assignment (rhs, ii); - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - gripe_range_invalid (); - break; - case magic_colon: -// a(:) = [] is equivalent to a(:,:) = foo. - if (rhs_nr == 0 && rhs_nc == 0) - do_matrix_assignment (rhs, magic_colon, magic_colon); - else - fortran_style_matrix_assignment (rhs, magic_colon); - break; - default: - panic_impossible (); - break; - } + return result; } -/* - * Fortran-style assignment for vector index. - */ -void -tree_constant_rep::fortran_style_matrix_assignment (tree_constant& rhs, - idx_vector& i) +static void +get_dimensions (const tree_constant& a, const char *warn_for, + int& nr, int& nc) { - assert (rhs.is_matrix_type ()); - - int ilen = i.capacity (); - - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - int len = rhs_nr * rhs_nc; - - if (len == ilen) - { - int nr = rows (); - if (rhs.const_type () == matrix_constant) - { - double *cop_out = rhs_m.fortran_vec (); - for (int k = 0; k < len; k++) - { - int ii = fortran_row (i.elem (k) + 1, nr) - 1; - int jj = fortran_column (i.elem (k) + 1, nr) - 1; - - matrix->elem (ii, jj) = *cop_out++; - } - } - else - { - Complex *cop_out = rhs_cm.fortran_vec (); - for (int k = 0; k < len; k++) - { - int ii = fortran_row (i.elem (k) + 1, nr) - 1; - int jj = fortran_column (i.elem (k) + 1, nr) - 1; + tree_constant tmpa = a.make_numeric (); - complex_matrix->elem (ii, jj) = *cop_out++; - } - } - } - else - ::error ("number of rows and columns must match for indexed assignment"); -} - -/* - * Fortran-style assignment for colon index. - */ -void -tree_constant_rep::fortran_style_matrix_assignment - (tree_constant& rhs, tree_constant_rep::constant_type mci) -{ - assert (rhs.is_matrix_type () && mci == tree_constant_rep::magic_colon); - - int nr = rows (); - int nc = columns (); - - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - int rhs_size = rhs_nr * rhs_nc; - if (rhs_size == 0) + if (tmpa.is_scalar_type ()) { - if (rhs.const_type () == matrix_constant) - { - delete matrix; - matrix = new Matrix (0, 0); - return; - } - else - panic_impossible (); - } - else if (nr*nc != rhs_size) - { - ::error ("A(:) = X: X and A must have the same number of elements"); - return; - } - - if (rhs.const_type () == matrix_constant) - { - double *cop_out = rhs_m.fortran_vec (); - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - matrix->elem (i, j) = *cop_out++; + double tmp = tmpa.double_value (); + nr = nc = NINT (tmp); } else { - Complex *cop_out = rhs_cm.fortran_vec (); - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - complex_matrix->elem (i, j) = *cop_out++; + nr = tmpa.rows (); + nc = tmpa.columns (); + + if ((nr == 1 && nc == 2) || (nr == 2 && nc == 1)) + { + ColumnVector v = tmpa.to_vector (); + + nr = NINT (v.elem (0)); + nc = NINT (v.elem (1)); + } + else + warning ("%s (A): use %s (size (A)) instead", warn_for, warn_for); + } + + check_dimensions (nr, nc, warn_for); // May set error_state. +} + +static void +get_dimensions (const tree_constant& a, const tree_constant& b, + const char *warn_for, int& nr, int& nc) +{ + tree_constant tmpa = a.make_numeric (); + tree_constant tmpb = b.make_numeric (); + + if (tmpa.is_scalar_type () && tmpb.is_scalar_type ()) + { + nr = NINT (tmpa.double_value ()); + nc = NINT (tmpb.double_value ()); + + check_dimensions (nr, nc, warn_for); // May set error_state. } + else + error ("%s: expecting two scalar arguments", warn_for); +} + +tree_constant +fill_matrix (const tree_constant& a, double val, const char *warn_for) +{ + int nr, nc; + get_dimensions (a, warn_for, nr, nc); + + if (error_state) + return tree_constant (); + + Matrix m (nr, nc, val); + + return tree_constant (m); +} + +tree_constant +fill_matrix (const tree_constant& a, const tree_constant& b, + double val, const char *warn_for) +{ + int nr, nc; + get_dimensions (a, b, warn_for, nr, nc); // May set error_state. + + if (error_state) + return tree_constant (); + + Matrix m (nr, nc, val); + + return tree_constant (m); } -/* - * Assignments to vectors. Hand off to other functions once we know - * what kind of index we have. For a colon, it is the same as - * assignment to a matrix indexed by two colons. - */ -void -tree_constant_rep::vector_assignment (tree_constant& rhs, tree_constant& i_arg) +tree_constant +identity_matrix (const tree_constant& a) { - int nr = rows (); - int nc = columns (); + int nr, nc; + get_dimensions (a, "eye", nr, nc); // May set error_state. + + if (error_state) + return tree_constant (); + + Matrix m (nr, nc, 0.0); - assert ((nr == 1 || nc == 1 || (nr == 0 && nc == 0)) - && ! user_pref.do_fortran_indexing); + if (nr > 0 && nc > 0) + { + int n = MIN (nr, nc); + for (int i = 0; i < n; i++) + m.elem (i, i) = 1.0; + } - tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type itype = tmp_i.const_type (); + return tree_constant (m); +} - switch (itype) +tree_constant +identity_matrix (const tree_constant& a, const tree_constant& b) +{ + int nr, nc; + get_dimensions (a, b, "eye", nr, nc); // May set error_state. + + if (error_state) + return tree_constant (); + + Matrix m (nr, nc, 0.0); + + if (nr > 0 && nc > 0) { - case complex_scalar_constant: - case scalar_constant: - { - int i = tree_to_mat_idx (tmp_i.double_value ()); - if (index_check (i, "") < 0) - return; - do_vector_assign (rhs, i); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mi = tmp_i.matrix_value (); - int len = nr * nc; - idx_vector iv (mi, user_pref.do_fortran_indexing, "", len); - if (! iv) - return; + int n = MIN (nr, nc); + for (int i = 0; i < n; i++) + m.elem (i, i) = 1.0; + } + + return tree_constant (m); +} - do_vector_assign (rhs, iv); - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range ri = tmp_i.range_value (); - int len = nr * nc; - if (len == 2 && is_zero_one (ri)) - { - do_vector_assign (rhs, 1); - } - else if (len == 2 && is_one_zero (ri)) - { - do_vector_assign (rhs, 0); - } - else +static tree_constant +find_nonzero_elem_idx (const Matrix& m) +{ + int count = 0; + int m_nr = m.rows (); + int m_nc = m.columns (); + + int i; + for (int j = 0; j < m_nc; j++) + for (i = 0; i < m_nr; i++) + if (m.elem (i, j) != 0) + count++; + + Matrix result; + + if (count == 0) + return result; + + if (m_nr == 1) + { + result.resize (1, count); + count = 0; + for (j = 0; j < m_nc; j++) + if (m.elem (0, j) != 0) { - if (index_check (ri, "") < 0) - return; - do_vector_assign (rhs, ri); + result (0, count) = j + 1; + count++; } - } - break; - case magic_colon: - { - int rhs_nr = rhs.rows (); - int rhs_nc = rhs.columns (); - - if (! indexed_assign_conforms (nr, nc, rhs_nr, rhs_nc)) - { - ::error ("A(:) = X: X and A must have the same dimensions"); - return; - } - do_matrix_assignment (rhs, magic_colon, magic_colon); - } - break; - default: - panic_impossible (); - break; + return tree_constant (result); + } + else + { + ColumnVector v (count); + count = 0; + for (j = 0; j < m_nc; j++) + for (i = 0; i < m_nr; i++) + if (m.elem (i, j) != 0) + { + v.elem (count) = m_nr * j + i + 1; + count++; + } + return tree_constant (v, 1); // Always make a column vector. } } -/* - * Check whether an indexed assignment to a vector is valid. - */ -void -tree_constant_rep::check_vector_assign (int rhs_nr, int rhs_nc, - int ilen, const char *rm) -{ - int nr = rows (); - int nc = columns (); - - if ((nr == 1 && nc == 1) || nr == 0 || nc == 0) // No orientation. - { - if (! (ilen == rhs_nr || ilen == rhs_nc)) - { - ::error ("A(%s) = X: X and %s must have the same number of elements", - rm, rm); - } - } - else if (nr == 1) // Preserve current row orientation. - { - if (! (rhs_nr == 1 && rhs_nc == ilen)) - { - ::error ("A(%s) = X: where A is a row vector, X must also be a", rm); - ::error ("row vector with the same number of elements as %s", rm); - } - } - else if (nc == 1) // Preserve current column orientation. - { - if (! (rhs_nc == 1 && rhs_nr == ilen)) - { - ::error ("A(%s) = X: where A is a column vector, X must also be", rm); - ::error ("a column vector with the same number of elements as %s", rm); - } - } - else - panic_impossible (); -} - -/* - * Assignment to a vector with an integer index. - */ -void -tree_constant_rep::do_vector_assign (tree_constant& rhs, int i) +static tree_constant +find_nonzero_elem_idx (const ComplexMatrix& m) { - int rhs_nr = rhs.rows (); - int rhs_nc = rhs.columns (); + int count = 0; + int m_nr = m.rows (); + int m_nc = m.columns (); - if (indexed_assign_conforms (1, 1, rhs_nr, rhs_nc)) + for (int j = 0; j < m_nc; j++) { - maybe_resize (i); - if (error_state) - return; + for (int i = 0; i < m_nr; i++) + if (m.elem (i, j) != 0) + count++; + } - int nr = rows (); - int nc = columns (); + Matrix result; - if (nr == 1) - { - REP_ELEM_ASSIGN (0, i, rhs.double_value (), rhs.complex_value (), - rhs.is_real_type ()); - } - else if (nc == 1) - { - REP_ELEM_ASSIGN (i, 0, rhs.double_value (), rhs.complex_value (), - rhs.is_real_type ()); - } - else - panic_impossible (); - } - else if (rhs_nr == 0 && rhs_nc == 0) + if (count == 0) + return result; + + if (m_nr == 1) { - int nr = rows (); - int nc = columns (); - - int len = nr > nc ? nr : nc; - - if (i < 0 || i >= len) - { - ::error ("A(int) = []: index out of range"); - return; - } - - if (nr == 1) - delete_column (i); - else if (nc == 1) - delete_row (i); - else - panic_impossible (); + result.resize (1, count); + count = 0; + for (j = 0; j < m_nc; j++) + if (m.elem (0, j) != 0) + { + result (0, count) = j + 1; + count++; + } + return tree_constant (result); } else { - ::error ("for A(int) = X: X must be a scalar"); - return; + ColumnVector v (count); + count = 0; + for (j = 0; j < m_nc; j++) + { + for (int i = 0; i < m_nr; i++) + if (m.elem (i, j) != 0) + { + v.elem (count) = m_nr * j + i + 1; + count++; + } + } + return tree_constant (v, 1); // Always make a column vector. } } -/* - * Assignment to a vector with a vector index. - */ -void -tree_constant_rep::do_vector_assign (tree_constant& rhs, idx_vector& iv) +tree_constant +find_nonzero_elem_idx (const tree_constant& a) { - if (rhs.is_zero_by_zero ()) - { - int nr = rows (); - int nc = columns (); - - int len = nr > nc ? nr : nc; + tree_constant retval; - if (iv.max () >= len) - { - ::error ("A(matrix) = []: index out of range"); - return; - } - - if (nr == 1) - delete_columns (iv); - else if (nc == 1) - delete_rows (iv); - else - panic_impossible (); - } - else if (rhs.is_scalar_type ()) - { - int nr = rows (); - int nc = columns (); - - if (iv.capacity () == 1) - { - int idx = iv.elem (0); + tree_constant tmp = a.make_numeric (); - if (nr == 1) - { - REP_ELEM_ASSIGN (0, idx, rhs.double_value (), - rhs.complex_value (), rhs.is_real_type ()); - } - else if (nc == 1) - { - REP_ELEM_ASSIGN (idx, 0, rhs.double_value (), - rhs.complex_value (), rhs.is_real_type ()); - } - else - panic_impossible (); - } - else - { - if (nr == 1) - { - ::error ("A(matrix) = X: where A is a row vector, X must also be a"); - ::error ("row vector with the same number of elements as matrix"); - } - else if (nc == 1) - { - ::error ("A(matrix) = X: where A is a column vector, X must also be a"); - ::error ("column vector with the same number of elements as matrix"); - } - else - panic_impossible (); - } - } - else if (rhs.is_matrix_type ()) + Matrix result; + + switch (tmp.const_type ()) { - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - int ilen = iv.capacity (); - check_vector_assign (rhs_nr, rhs_nc, ilen, "matrix"); - if (error_state) - return; - - force_orient f_orient = no_orient; - if (rhs_nr == 1 && rhs_nc != 1) - f_orient = row_orient; - else if (rhs_nc == 1 && rhs_nr != 1) - f_orient = column_orient; - - maybe_resize (iv.max (), f_orient); - if (error_state) - return; - - int nr = rows (); - int nc = columns (); - - if (nr == 1) - { - for (int i = 0; i < iv.capacity (); i++) - REP_ELEM_ASSIGN (0, iv.elem (i), rhs_m.elem (0, i), - rhs_cm.elem (0, i), rhs.is_real_type ()); - } - else if (nc == 1) - { - for (int i = 0; i < iv.capacity (); i++) - REP_ELEM_ASSIGN (iv.elem (i), 0, rhs_m.elem (i, 0), - rhs_cm.elem (i, 0), rhs.is_real_type ()); - } - else - panic_impossible (); + case tree_constant_rep::matrix_constant: + { + Matrix m = tmp.matrix_value (); + return find_nonzero_elem_idx (m); + } + break; + case tree_constant_rep::scalar_constant: + { + double d = tmp.double_value (); + if (d != 0.0) + return tree_constant (1.0); + else + return tree_constant (result); + } + break; + case tree_constant_rep::complex_matrix_constant: + { + ComplexMatrix m = tmp.complex_matrix_value (); + return find_nonzero_elem_idx (m); + } + break; + case tree_constant_rep::complex_scalar_constant: + { + Complex c = tmp.complex_value (); + if (c != 0.0) + return tree_constant (1.0); + else + return tree_constant (result); + } + break; + default: + break; } - else - panic_impossible (); + return retval; } -/* - * Assignment to a vector with a range index. - */ -void -tree_constant_rep::do_vector_assign (tree_constant& rhs, Range& ri) +// XXX FIXME XXX -- the next two functions (and expm) should really be just +// one... + +tree_constant * +matrix_log (const tree_constant& a) { - if (rhs.is_zero_by_zero ()) - { - int nr = rows (); - int nc = columns (); - - int len = nr > nc ? nr : nc; - - int b = tree_to_mat_idx (ri.min ()); - int l = tree_to_mat_idx (ri.max ()); - if (b < 0 || l >= len) - { - ::error ("A(range) = []: index out of range"); - return; - } + tree_constant *retval = new tree_constant [2]; - if (nr == 1) - delete_columns (ri); - else if (nc == 1) - delete_rows (ri); - else - panic_impossible (); - } - else if (rhs.is_scalar_type ()) + tree_constant tmp = a.make_numeric ();; + + if (tmp.rows () == 0 || tmp.columns () == 0) { - int nr = rows (); - int nc = columns (); - - if (nr == 1) + int flag = user_pref.propagate_empty_matrices; + if (flag != 0) { - ::error ("A(range) = X: where A is a row vector, X must also be a"); - ::error ("row vector with the same number of elements as range"); - } - else if (nc == 1) - { - ::error ("A(range) = X: where A is a column vector, X must also be a"); - ::error ("column vector with the same number of elements as range"); + if (flag < 0) + gripe_empty_arg ("logm", 0); + Matrix m; + retval = new tree_constant [2]; + retval[0] = tree_constant (m); + return retval; } else - panic_impossible (); + gripe_empty_arg ("logm", 1); } - else if (rhs.is_matrix_type ()) - { - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - int ilen = ri.nelem (); - check_vector_assign (rhs_nr, rhs_nc, ilen, "range"); - if (error_state) - return; - force_orient f_orient = no_orient; - if (rhs_nr == 1 && rhs_nc != 1) - f_orient = row_orient; - else if (rhs_nc == 1 && rhs_nr != 1) - f_orient = column_orient; + switch (tmp.const_type ()) + { + case tree_constant_rep::matrix_constant: + { + Matrix m = tmp.matrix_value (); - maybe_resize (tree_to_mat_idx (ri.max ()), f_orient); - if (error_state) - return; - - int nr = rows (); - int nc = columns (); - - double b = ri.base (); - double increment = ri.inc (); + int nr = m.rows (); + int nc = m.columns (); - if (nr == 1) - { - for (int i = 0; i < ri.nelem (); i++) - { - double tmp = b + i * increment; - int col = tree_to_mat_idx (tmp); - REP_ELEM_ASSIGN (0, col, rhs_m.elem (0, i), rhs_cm.elem (0, i), - rhs.is_real_type ()); - } - } - else if (nc == 1) - { - for (int i = 0; i < ri.nelem (); i++) - { - double tmp = b + i * increment; - int row = tree_to_mat_idx (tmp); - REP_ELEM_ASSIGN (row, 0, rhs_m.elem (i, 0), rhs_cm.elem (i, 0), - rhs.is_real_type ()); - } - } - else - panic_impossible (); - } - else - panic_impossible (); -} + if (nr == 0 || nc == 0 || nr != nc) + gripe_square_matrix_required ("logm"); + else + { + EIG m_eig (m); + ComplexColumnVector lambda (m_eig.eigenvalues ()); + ComplexMatrix Q (m_eig.eigenvectors ()); -/* - * Matrix assignment indexed by two values. This function determines - * the type of the first arugment, checks as much as possible, and - * then calls one of a set of functions to handle the specific cases: - * - * M (integer, arg2) = RHS (MA1) - * M (vector, arg2) = RHS (MA2) - * M (range, arg2) = RHS (MA3) - * M (colon, arg2) = RHS (MA4) - * - * Each of those functions determines the type of the second argument - * and calls another function to handle the real work of doing the - * assignment. - */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant& i_arg, - tree_constant& j_arg) -{ - tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); + for (int i = 0; i < nr; i++) + { + Complex elt = lambda.elem (i); + if (imag (elt) == 0.0 && real (elt) > 0.0) + lambda.elem (i) = log (real (elt)); + else + lambda.elem (i) = log (elt); + } - tree_constant_rep::constant_type itype = tmp_i.const_type (); + ComplexDiagMatrix D (lambda); + ComplexMatrix result = Q * D * Q.inverse (); - switch (itype) - { - case complex_scalar_constant: - case scalar_constant: - { - int i = tree_to_mat_idx (tmp_i.double_value ()); - if (index_check (i, "row") < 0) - return; - do_matrix_assignment (rhs, i, j_arg); + retval[0] = tree_constant (result); + } } break; - case complex_matrix_constant: - case matrix_constant: + case tree_constant_rep::complex_matrix_constant: { - Matrix mi = tmp_i.matrix_value (); - idx_vector iv (mi, user_pref.do_fortran_indexing, "row", rows ()); - if (! iv) - return; + ComplexMatrix m = tmp.complex_matrix_value (); - do_matrix_assignment (rhs, iv, j_arg); - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range ri = tmp_i.range_value (); - int nr = rows (); - if (nr == 2 && is_zero_one (ri)) - { - do_matrix_assignment (rhs, 1, j_arg); - } - else if (nr == 2 && is_one_zero (ri)) - { - do_matrix_assignment (rhs, 0, j_arg); - } + int nr = m.rows (); + int nc = m.columns (); + + if (nr == 0 || nc == 0 || nr != nc) + gripe_square_matrix_required ("logm"); else { - if (index_check (ri, "row") < 0) - return; - do_matrix_assignment (rhs, ri, j_arg); + EIG m_eig (m); + ComplexColumnVector lambda (m_eig.eigenvalues ()); + ComplexMatrix Q (m_eig.eigenvectors ()); + + for (int i = 0; i < nr; i++) + { + Complex elt = lambda.elem (i); + if (imag (elt) == 0.0 && real (elt) > 0.0) + lambda.elem (i) = log (real (elt)); + else + lambda.elem (i) = log (elt); + } + + ComplexDiagMatrix D (lambda); + ComplexMatrix result = Q * D * Q.inverse (); + + retval[0] = tree_constant (result); } } break; - case magic_colon: - do_matrix_assignment (rhs, magic_colon, j_arg); - break; - default: - panic_impossible (); - break; - } -} - -/* MA1 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, - tree_constant& j_arg) -{ - tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type jtype = tmp_j.const_type (); - - int rhs_nr = rhs.rows (); - int rhs_nc = rhs.columns (); - - switch (jtype) - { - case complex_scalar_constant: - case scalar_constant: + case tree_constant_rep::scalar_constant: { - int j = tree_to_mat_idx (tmp_j.double_value ()); - if (index_check (j, "column") < 0) - return; - if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc)) - { - ::error ("A(int,int) = X, X must be a scalar"); - return; - } - maybe_resize (i, j); - if (error_state) - return; - - do_matrix_assignment (rhs, i, j); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mj = tmp_j.matrix_value (); - idx_vector jv (mj, user_pref.do_fortran_indexing, "column", - columns ()); - if (! jv) - return; - - if (! indexed_assign_conforms (1, jv.capacity (), rhs_nr, rhs_nc)) - { - ::error ("A(int,matrix) = X: X must be a row vector with the same"); - ::error ("number of elements as matrix"); - return; - } - maybe_resize (i, jv.max ()); - if (error_state) - return; - - do_matrix_assignment (rhs, i, jv); - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range rj = tmp_j.range_value (); - if (! indexed_assign_conforms (1, rj.nelem (), rhs_nr, rhs_nc)) - { - ::error ("A(int,range) = X: X must be a row vector with the same"); - ::error ("number of elements as range"); - return; - } - - int nc = columns (); - if (nc == 2 && is_zero_one (rj) && rhs_nc == 1) - { - do_matrix_assignment (rhs, i, 1); - } - else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1) - { - do_matrix_assignment (rhs, i, 0); - } + double d = tmp.double_value (); + if (d > 0.0) + retval[0] = tree_constant (log (d)); else { - if (index_check (rj, "column") < 0) - return; - maybe_resize (i, tree_to_mat_idx (rj.max ())); - if (error_state) - return; - - do_matrix_assignment (rhs, i, rj); + Complex dtmp (d); + retval[0] = tree_constant (log (dtmp)); } } break; - case magic_colon: + case tree_constant_rep::complex_scalar_constant: { - int nc = columns (); - int nr = rows (); - if (nc == 0 && nr == 0 && rhs_nr == 1) - { - if (rhs.is_complex_type ()) - { - complex_matrix = new ComplexMatrix (); - type_tag = complex_matrix_constant; - } - else - { - matrix = new Matrix (); - type_tag = matrix_constant; - } - maybe_resize (i, rhs_nc-1); - if (error_state) - return; - } - else if (indexed_assign_conforms (1, nc, rhs_nr, rhs_nc)) - { - maybe_resize (i, nc-1); - if (error_state) - return; - } - else if (rhs_nr == 0 && rhs_nc == 0) - { - if (i < 0 || i >= nr) - { - ::error ("A(int,:) = []: row index out of range"); - return; - } - } - else - { - ::error ("A(int,:) = X: X must be a row vector with the same"); - ::error ("number of columns as A"); - return; - } - - do_matrix_assignment (rhs, i, magic_colon); + Complex c = tmp.complex_value (); + retval[0] = tree_constant (log (c)); } break; default: - panic_impossible (); break; } + return retval; } -/* MA2 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, idx_vector& iv, - tree_constant& j_arg) +tree_constant * +matrix_sqrt (const tree_constant& a) { - tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); + tree_constant *retval = new tree_constant [2]; - tree_constant_rep::constant_type jtype = tmp_j.const_type (); - - int rhs_nr = rhs.rows (); - int rhs_nc = rhs.columns (); - - switch (jtype) + tree_constant tmp = a.make_numeric ();; + + if (tmp.rows () == 0 || tmp.columns () == 0) { - case complex_scalar_constant: - case scalar_constant: - { - int j = tree_to_mat_idx (tmp_j.double_value ()); - if (index_check (j, "column") < 0) - return; - if (! indexed_assign_conforms (iv.capacity (), 1, rhs_nr, rhs_nc)) - { - ::error ("A(matrix,int) = X: X must be a column vector with the"); - ::error ("same number of elements as matrix"); - return; - } - maybe_resize (iv.max (), j); - if (error_state) - return; + int flag = user_pref.propagate_empty_matrices; + if (flag != 0) + { + if (flag < 0) + gripe_empty_arg ("sqrtm", 0); + Matrix m; + retval = new tree_constant [2]; + retval[0] = tree_constant (m); + return retval; + } + else + gripe_empty_arg ("sqrtm", 1); + } - do_matrix_assignment (rhs, iv, j); - } - break; - case complex_matrix_constant: - case matrix_constant: + switch (tmp.const_type ()) + { + case tree_constant_rep::matrix_constant: { - Matrix mj = tmp_j.matrix_value (); - idx_vector jv (mj, user_pref.do_fortran_indexing, "column", - columns ()); - if (! jv) - return; - - if (! indexed_assign_conforms (iv.capacity (), jv.capacity (), - rhs_nr, rhs_nc)) - { - ::error ("A(r_mat,c_mat) = X: the number of rows in X must match"); - ::error ("the number of elements in r_mat and the number of"); - ::error ("columns in X must match the number of elements in c_mat"); - return; - } - maybe_resize (iv.max (), jv.max ()); - if (error_state) - return; + Matrix m = tmp.matrix_value (); - do_matrix_assignment (rhs, iv, jv); - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range rj = tmp_j.range_value (); - if (! indexed_assign_conforms (iv.capacity (), rj.nelem (), - rhs_nr, rhs_nc)) - { - ::error ("A(matrix,range) = X: the number of rows in X must match"); - ::error ("the number of elements in matrix and the number of"); - ::error ("columns in X must match the number of elements in range"); - return; - } + int nr = m.rows (); + int nc = m.columns (); - int nc = columns (); - if (nc == 2 && is_zero_one (rj) && rhs_nc == 1) - { - do_matrix_assignment (rhs, iv, 1); - } - else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1) - { - do_matrix_assignment (rhs, iv, 0); - } + if (nr == 0 || nc == 0 || nr != nc) + gripe_square_matrix_required ("sqrtm"); else { - if (index_check (rj, "column") < 0) - return; - maybe_resize (iv.max (), tree_to_mat_idx (rj.max ())); - if (error_state) - return; + EIG m_eig (m); + ComplexColumnVector lambda (m_eig.eigenvalues ()); + ComplexMatrix Q (m_eig.eigenvectors ()); - do_matrix_assignment (rhs, iv, rj); + for (int i = 0; i < nr; i++) + { + Complex elt = lambda.elem (i); + if (imag (elt) == 0.0 && real (elt) > 0.0) + lambda.elem (i) = sqrt (real (elt)); + else + lambda.elem (i) = sqrt (elt); + } + + ComplexDiagMatrix D (lambda); + ComplexMatrix result = Q * D * Q.inverse (); + + retval[0] = tree_constant (result); } } break; - case magic_colon: + case tree_constant_rep::complex_matrix_constant: { - int nc = columns (); - int new_nc = nc; - if (nc == 0) - new_nc = rhs_nc; + ComplexMatrix m = tmp.complex_matrix_value (); - if (indexed_assign_conforms (iv.capacity (), new_nc, - rhs_nr, rhs_nc)) + int nr = m.rows (); + int nc = m.columns (); + + if (nr == 0 || nc == 0 || nr != nc) + gripe_square_matrix_required ("sqrtm"); + else { - maybe_resize (iv.max (), new_nc-1); - if (error_state) - return; + EIG m_eig (m); + ComplexColumnVector lambda (m_eig.eigenvalues ()); + ComplexMatrix Q (m_eig.eigenvectors ()); + + for (int i = 0; i < nr; i++) + { + Complex elt = lambda.elem (i); + if (imag (elt) == 0.0 && real (elt) > 0.0) + lambda.elem (i) = sqrt (real (elt)); + else + lambda.elem (i) = sqrt (elt); + } + + ComplexDiagMatrix D (lambda); + ComplexMatrix result = Q * D * Q.inverse (); + + retval[0] = tree_constant (result); } - else if (rhs_nr == 0 && rhs_nc == 0) - { - if (iv.max () >= rows ()) - { - ::error ("A(matrix,:) = []: row index out of range"); - return; - } - } + } + break; + case tree_constant_rep::scalar_constant: + { + double d = tmp.double_value (); + if (d > 0.0) + retval[0] = tree_constant (sqrt (d)); else { - ::error ("A(matrix,:) = X: the number of rows in X must match the"); - ::error ("number of elements in matrix, and the number of columns"); - ::error ("in X must match the number of columns in A"); - return; + Complex dtmp (d); + retval[0] = tree_constant (sqrt (dtmp)); } + } + break; + case tree_constant_rep::complex_scalar_constant: + { + Complex c = tmp.complex_value (); + retval[0] = tree_constant (log (c)); + } + break; + default: + break; + } + return retval; +} - do_matrix_assignment (rhs, iv, magic_colon); - } +tree_constant * +column_max (const tree_constant *args, int nargin, int nargout) +{ + tree_constant *retval = NULL_TREE_CONST; + + tree_constant arg1; + tree_constant arg2; + tree_constant_rep::constant_type arg1_type = + tree_constant_rep::unknown_constant; + tree_constant_rep::constant_type arg2_type = + tree_constant_rep::unknown_constant; + + switch (nargin) + { + case 3: + arg2 = args[2].make_numeric (); + arg2_type = arg2.const_type (); +// Fall through... + case 2: + arg1 = args[1].make_numeric (); + arg1_type = arg1.const_type (); break; default: panic_impossible (); break; } -} -/* MA3 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - Range& ri, tree_constant& j_arg) -{ - tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type jtype = tmp_j.const_type (); - - int rhs_nr = rhs.rows (); - int rhs_nc = rhs.columns (); - - switch (jtype) + if (nargin == 2 && nargout == 1) { - case complex_scalar_constant: - case scalar_constant: - { - int j = tree_to_mat_idx (tmp_j.double_value ()); - if (index_check (j, "column") < 0) - return; - if (! indexed_assign_conforms (ri.nelem (), 1, rhs_nr, rhs_nc)) + retval = new tree_constant [2]; + switch (arg1_type) + { + case tree_constant_rep::scalar_constant: + retval[0] = tree_constant (arg1.double_value ()); + break; + case tree_constant_rep::complex_scalar_constant: + retval[0] = tree_constant (arg1.complex_value ()); + break; + case tree_constant_rep::matrix_constant: + { + Matrix m = arg1.matrix_value (); + if (m.rows () == 1) + retval[0] = tree_constant (m.row_max ()); + else + retval[0] = tree_constant (m.column_max (), 0); + } + break; + case tree_constant_rep::complex_matrix_constant: + { + ComplexMatrix m = arg1.complex_matrix_value (); + if (m.rows () == 1) + retval[0] = tree_constant (m.row_max ()); + else + retval[0] = tree_constant (m.column_max (), 0); + } + break; + default: + panic_impossible (); + break; + } + } + else if (nargin == 2 && nargout == 2) + { + retval = new tree_constant [2]; + switch (arg1_type) + { + case tree_constant_rep::scalar_constant: { - ::error ("A(range,int) = X: X must be a column vector with the"); - ::error ("same number of elements as range"); - return; - } - maybe_resize (tree_to_mat_idx (ri.max ()), j); - if (error_state) - return; - - do_matrix_assignment (rhs, ri, j); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mj = tmp_j.matrix_value (); - idx_vector jv (mj, user_pref.do_fortran_indexing, "column", - columns ()); - if (! jv) - return; - - if (! indexed_assign_conforms (ri.nelem (), jv.capacity (), - rhs_nr, rhs_nc)) - { - ::error ("A(range,matrix) = X: the number of rows in X must match"); - ::error ("the number of elements in range and the number of"); - ::error ("columns in X must match the number of elements in matrix"); - return; + retval[0] = tree_constant (arg1.double_value ()); + retval[1] = tree_constant (1); } - maybe_resize (tree_to_mat_idx (ri.max ()), jv.max ()); - if (error_state) - return; - - do_matrix_assignment (rhs, ri, jv); - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range rj = tmp_j.range_value (); - if (! indexed_assign_conforms (ri.nelem (), rj.nelem (), - rhs_nr, rhs_nc)) + break; + case tree_constant_rep::complex_scalar_constant: { - ::error ("A(r_range,c_range) = X: the number of rows in X must"); - ::error ("match the number of elements in r_range and the number"); - ::error ("of columns in X must match the number of elements in"); - ::error ("c_range"); - return; + retval[0] = tree_constant (arg1.complex_value ()); + retval[1] = tree_constant (1); } - - int nc = columns (); - if (nc == 2 && is_zero_one (rj) && rhs_nc == 1) - { - do_matrix_assignment (rhs, ri, 1); - } - else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1) - { - do_matrix_assignment (rhs, ri, 0); - } - else + break; + case tree_constant_rep::matrix_constant: { - if (index_check (rj, "column") < 0) - return; - - maybe_resize (tree_to_mat_idx (ri.max ()), - tree_to_mat_idx (rj.max ())); - - if (error_state) - return; - - do_matrix_assignment (rhs, ri, rj); - } - } - break; - case magic_colon: - { - int nc = columns (); - int new_nc = nc; - if (nc == 0) - new_nc = rhs_nc; - - if (indexed_assign_conforms (ri.nelem (), new_nc, rhs_nr, rhs_nc)) - { - maybe_resize (tree_to_mat_idx (ri.max ()), new_nc-1); - if (error_state) - return; - } - else if (rhs_nr == 0 && rhs_nc == 0) - { - int b = tree_to_mat_idx (ri.min ()); - int l = tree_to_mat_idx (ri.max ()); - if (b < 0 || l >= rows ()) + Matrix m = arg1.matrix_value (); + if (m.rows () == 1) { - ::error ("A(range,:) = []: row index out of range"); - return; + retval[0] = tree_constant (m.row_max ()); + retval[1] = tree_constant (m.row_max_loc ()); + } + else + { + retval[0] = tree_constant (m.column_max (), 0); + retval[1] = tree_constant (m.column_max_loc (), 0); } } - else + break; + case tree_constant_rep::complex_matrix_constant: { - ::error ("A(range,:) = X: the number of rows in X must match the"); - ::error ("number of elements in range, and the number of columns"); - ::error ("in X must match the number of columns in A"); - return; - } - - do_matrix_assignment (rhs, ri, magic_colon); - } - break; - default: - panic_impossible (); - break; - } -} - -/* MA4 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant_rep::constant_type i, - tree_constant& j_arg) -{ - tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type jtype = tmp_j.const_type (); - - int rhs_nr = rhs.rows (); - int rhs_nc = rhs.columns (); - - switch (jtype) - { - case complex_scalar_constant: - case scalar_constant: - { - int j = tree_to_mat_idx (tmp_j.double_value ()); - if (index_check (j, "column") < 0) - return; - int nr = rows (); - int nc = columns (); - if (nr == 0 && nc == 0 && rhs_nc == 1) - { - if (rhs.is_complex_type ()) + ComplexMatrix m = arg1.complex_matrix_value (); + if (m.rows () == 1) { - complex_matrix = new ComplexMatrix (); - type_tag = complex_matrix_constant; + retval[0] = tree_constant (m.row_max ()); + retval[1] = tree_constant (m.row_max_loc ()); } else { - matrix = new Matrix (); - type_tag = matrix_constant; - } - maybe_resize (rhs_nr-1, j); - if (error_state) - return; - } - else if (indexed_assign_conforms (nr, 1, rhs_nr, rhs_nc)) - { - maybe_resize (nr-1, j); - if (error_state) - return; - } - else if (rhs_nr == 0 && rhs_nc == 0) - { - if (j < 0 || j >= nc) - { - ::error ("A(:,int) = []: column index out of range"); - return; - } - } - else - { - ::error ("A(:,int) = X: X must be a column vector with the same"); - ::error ("number of rows as A"); - return; - } - - do_matrix_assignment (rhs, magic_colon, j); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mj = tmp_j.matrix_value (); - idx_vector jv (mj, user_pref.do_fortran_indexing, "column", - columns ()); - if (! jv) - return; - - int nr = rows (); - int new_nr = nr; - if (nr == 0) - new_nr = rhs_nr; - - if (indexed_assign_conforms (new_nr, jv.capacity (), - rhs_nr, rhs_nc)) - { - maybe_resize (new_nr-1, jv.max ()); - if (error_state) - return; - } - else if (rhs_nr == 0 && rhs_nc == 0) - { - if (jv.max () >= columns ()) - { - ::error ("A(:,matrix) = []: column index out of range"); - return; + retval[0] = tree_constant (m.column_max (), 0); + retval[1] = tree_constant (m.column_max_loc (), 0); } } - else - { - ::error ("A(:,matrix) = X: the number of rows in X must match the"); - ::error ("number of rows in A, and the number of columns in X must"); - ::error ("match the number of elements in matrix"); - return; - } - - do_matrix_assignment (rhs, magic_colon, jv); - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range rj = tmp_j.range_value (); - int nr = rows (); - int new_nr = nr; - if (nr == 0) - new_nr = rhs_nr; - - if (indexed_assign_conforms (new_nr, rj.nelem (), rhs_nr, rhs_nc)) - { - int nc = columns (); - if (nc == 2 && is_zero_one (rj) && rhs_nc == 1) + break; + default: + panic_impossible (); + break; + } + } + else if (nargin == 3) + { + if (arg1.rows () == arg2.rows () + && arg1.columns () == arg2.columns ()) + { + retval = new tree_constant [2]; + switch (arg1_type) + { + case tree_constant_rep::scalar_constant: { - do_matrix_assignment (rhs, magic_colon, 1); + double result; + double a_elem = arg1.double_value (); + double b_elem = arg2.double_value (); + result = MAX (a_elem, b_elem); + retval[0] = tree_constant (result); } - else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1) + break; + case tree_constant_rep::complex_scalar_constant: { - do_matrix_assignment (rhs, magic_colon, 0); + Complex result; + Complex a_elem = arg1.complex_value (); + Complex b_elem = arg2.complex_value (); + if (abs (a_elem) > abs (b_elem)) + result = a_elem; + else + result = b_elem; + retval[0] = tree_constant (result); + } + break; + case tree_constant_rep::matrix_constant: + { + Matrix result; + result = max (arg1.matrix_value (), arg2.matrix_value ()); + retval[0] = tree_constant (result); } - else - { - if (index_check (rj, "column") < 0) - return; - maybe_resize (new_nr-1, tree_to_mat_idx (rj.max ())); - if (error_state) - return; - } - } - else if (rhs_nr == 0 && rhs_nc == 0) - { - int b = tree_to_mat_idx (rj.min ()); - int l = tree_to_mat_idx (rj.max ()); - if (b < 0 || l >= columns ()) + break; + case tree_constant_rep::complex_matrix_constant: { - ::error ("A(:,range) = []: column index out of range"); - return; + ComplexMatrix result; + result = max (arg1.complex_matrix_value (), + arg2.complex_matrix_value ()); + retval[0] = tree_constant (result); } - } - else - { - ::error ("A(:,range) = X: the number of rows in X must match the"); - ::error ("number of rows in A, and the number of columns in X"); - ::error ("must match the number of elements in range"); - return; - } + break; + default: + panic_impossible (); + break; + } + } + else + error ("max: nonconformant matrices"); + } + else + panic_impossible (); + + return retval; +} - do_matrix_assignment (rhs, magic_colon, rj); - } - break; - case magic_colon: -// a(:,:) = foo is equivalent to a = foo. - do_matrix_assignment (rhs, magic_colon, magic_colon); +tree_constant * +column_min (const tree_constant *args, int nargin, int nargout) +{ + tree_constant *retval = NULL_TREE_CONST; + + tree_constant arg1; + tree_constant arg2; + tree_constant_rep::constant_type arg1_type = + tree_constant_rep::unknown_constant; + tree_constant_rep::constant_type arg2_type = + tree_constant_rep::unknown_constant; + + switch (nargin) + { + case 3: + arg2 = args[2].make_numeric (); + arg2_type = arg2.const_type (); +// Fall through... + case 2: + arg1 = args[1].make_numeric (); + arg1_type = arg1.const_type (); break; default: panic_impossible (); break; } -} -/* - * Functions that actually handle assignment to a matrix using two - * index values. - * - * idx2 - * +---+---+----+----+ - * idx1 | i | v | r | c | - * ---------+---+---+----+----+ - * integer | 1 | 5 | 9 | 13 | - * ---------+---+---+----+----+ - * vector | 2 | 6 | 10 | 14 | - * ---------+---+---+----+----+ - * range | 3 | 7 | 11 | 15 | - * ---------+---+---+----+----+ - * colon | 4 | 8 | 12 | 16 | - * ---------+---+---+----+----+ - */ - -/* 1 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, int j) -{ - REP_ELEM_ASSIGN (i, j, rhs.double_value (), rhs.complex_value (), - rhs.is_real_type ()); -} - -/* 2 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, - idx_vector& jv) -{ - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - for (int j = 0; j < jv.capacity (); j++) - REP_ELEM_ASSIGN (i, jv.elem (j), rhs_m.elem (0, j), - rhs_cm.elem (0, j), rhs.is_real_type ()); -} - -/* 3 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, Range& rj) -{ - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - double b = rj.base (); - double increment = rj.inc (); - - for (int j = 0; j < rj.nelem (); j++) - { - double tmp = b + j * increment; - int col = tree_to_mat_idx (tmp); - REP_ELEM_ASSIGN (i, col, rhs_m.elem (0, j), rhs_cm.elem (0, j), - rhs.is_real_type ()); - } -} - -/* 4 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, - tree_constant_rep::constant_type mcj) -{ - assert (mcj == magic_colon); - - int nc = columns (); - - if (rhs.is_zero_by_zero ()) - { - delete_row (i); - } - else if (rhs.is_matrix_type ()) - { - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - for (int j = 0; j < nc; j++) - REP_ELEM_ASSIGN (i, j, rhs_m.elem (0, j), rhs_cm.elem (0, j), - rhs.is_real_type ()); - } - else if (rhs.is_scalar_type () && nc == 1) - { - REP_ELEM_ASSIGN (i, 0, rhs.double_value (), - rhs.complex_value (), rhs.is_real_type ()); - } - else - panic_impossible (); -} - -/* 5 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - idx_vector& iv, int j) -{ - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - for (int i = 0; i < iv.capacity (); i++) + if (nargin == 2 && nargout == 1) { - int row = iv.elem (i); - REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, 0), - rhs_cm.elem (i, 0), rhs.is_real_type ()); - } -} - -/* 6 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - idx_vector& iv, idx_vector& jv) -{ - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - for (int i = 0; i < iv.capacity (); i++) - { - int row = iv.elem (i); - for (int j = 0; j < jv.capacity (); j++) - { - int col = jv.elem (j); - REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j), - rhs_cm.elem (i, j), rhs.is_real_type ()); - } - } -} - -/* 7 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - idx_vector& iv, Range& rj) -{ - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - double b = rj.base (); - double increment = rj.inc (); - - for (int i = 0; i < iv.capacity (); i++) - { - int row = iv.elem (i); - for (int j = 0; j < rj.nelem (); j++) + retval = new tree_constant [2]; + switch (arg1_type) { - double tmp = b + j * increment; - int col = tree_to_mat_idx (tmp); - REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j), - rhs_cm.elem (i, j), rhs.is_real_type ()); - } - } -} - -/* 8 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, idx_vector& iv, - tree_constant_rep::constant_type mcj) -{ - assert (mcj == magic_colon); - - if (rhs.is_zero_by_zero ()) - { - delete_rows (iv); - } - else - { - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - int nc = columns (); - - for (int j = 0; j < nc; j++) - { - for (int i = 0; i < iv.capacity (); i++) - { - int row = iv.elem (i); - REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, j), - rhs_cm.elem (i, j), rhs.is_real_type ()); - } - } - } -} - -/* 9 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, int j) -{ - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - double b = ri.base (); - double increment = ri.inc (); - - for (int i = 0; i < ri.nelem (); i++) - { - double tmp = b + i * increment; - int row = tree_to_mat_idx (tmp); - REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, 0), - rhs_cm.elem (i, 0), rhs.is_real_type ()); - } -} - -/* 10 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, - idx_vector& jv) -{ - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - double b = ri.base (); - double increment = ri.inc (); - - for (int j = 0; j < jv.capacity (); j++) - { - int col = jv.elem (j); - for (int i = 0; i < ri.nelem (); i++) - { - double tmp = b + i * increment; - int row = tree_to_mat_idx (tmp); - REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j), - rhs_m.elem (i, j), rhs.is_real_type ()); + case tree_constant_rep::scalar_constant: + retval[0] = tree_constant (arg1.double_value ()); + break; + case tree_constant_rep::complex_scalar_constant: + retval[0] = tree_constant (arg1.complex_value ()); + break; + case tree_constant_rep::matrix_constant: + { + Matrix m = arg1.matrix_value (); + if (m.rows () == 1) + retval[0] = tree_constant (m.row_min ()); + else + retval[0] = tree_constant (m.column_min (), 0); + } + break; + case tree_constant_rep::complex_matrix_constant: + { + ComplexMatrix m = arg1.complex_matrix_value (); + if (m.rows () == 1) + retval[0] = tree_constant (m.row_min ()); + else + retval[0] = tree_constant (m.column_min (), 0); + } + break; + default: + panic_impossible (); + break; } } -} - -/* 11 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, - Range& rj) -{ - double ib = ri.base (); - double iinc = ri.inc (); - double jb = rj.base (); - double jinc = rj.inc (); - - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - for (int i = 0; i < ri.nelem (); i++) + else if (nargin == 2 && nargout == 2) { - double itmp = ib + i * iinc; - int row = tree_to_mat_idx (itmp); - for (int j = 0; j < rj.nelem (); j++) - { - double jtmp = jb + j * jinc; - int col = tree_to_mat_idx (jtmp); - REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j), - rhs_cm.elem (i, j), rhs.is_real_type ()); - } - } -} - -/* 12 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, - tree_constant_rep::constant_type mcj) -{ - assert (mcj == magic_colon); - - if (rhs.is_zero_by_zero ()) - { - delete_rows (ri); - } - else - { - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - double ib = ri.base (); - double iinc = ri.inc (); - - int nc = columns (); - - for (int i = 0; i < ri.nelem (); i++) - { - double itmp = ib + i * iinc; - int row = tree_to_mat_idx (itmp); - for (int j = 0; j < nc; j++) - REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, j), - rhs_cm.elem (i, j), rhs.is_real_type ()); - } + retval = new tree_constant [2]; + switch (arg1_type) + { + case tree_constant_rep::scalar_constant: + { + retval[0] = tree_constant (arg1.double_value ()); + retval[1] = tree_constant (1); + } + break; + case tree_constant_rep::complex_scalar_constant: + { + retval[0] = tree_constant (arg1.complex_value ()); + retval[1] = tree_constant (1); + } + break; + case tree_constant_rep::matrix_constant: + { + Matrix m = arg1.matrix_value (); + if (m.rows () == 1) + { + retval[0] = tree_constant (m.row_min ()); + retval[1] = tree_constant (m.row_min_loc ()); + } + else + { + retval[0] = tree_constant (m.column_min (), 0); + retval[1] = tree_constant (m.column_min_loc (), 0); + } + } + break; + case tree_constant_rep::complex_matrix_constant: + { + ComplexMatrix m = arg1.complex_matrix_value (); + if (m.rows () == 1) + { + retval[0] = tree_constant (m.row_min ()); + retval[1] = tree_constant (m.row_min_loc ()); + } + else + { + retval[0] = tree_constant (m.column_min (), 0); + retval[1] = tree_constant (m.column_min_loc (), 0); + } + } + break; + default: + panic_impossible (); + break; + } } -} - -/* 13 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant_rep::constant_type mci, - int j) -{ - assert (mci == magic_colon); - - int nr = rows (); - - if (rhs.is_zero_by_zero ()) - { - delete_column (j); - } - else if (rhs.is_matrix_type ()) - { - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - for (int i = 0; i < nr; i++) - REP_ELEM_ASSIGN (i, j, rhs_m.elem (i, 0), - rhs_cm.elem (i, 0), rhs.is_real_type ()); - } - else if (rhs.is_scalar_type () && nr == 1) + else if (nargin == 3) { - REP_ELEM_ASSIGN (0, j, rhs.double_value (), - rhs.complex_value (), rhs.is_real_type ()); - } - else - panic_impossible (); -} - -/* 14 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant_rep::constant_type mci, - idx_vector& jv) -{ - assert (mci == magic_colon); - - if (rhs.is_zero_by_zero ()) - { - delete_columns (jv); - } - else - { - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - int nr = rows (); - - for (int i = 0; i < nr; i++) + if (arg1.rows () == arg2.rows () + && arg1.columns () == arg2.columns ()) { - for (int j = 0; j < jv.capacity (); j++) - { - int col = jv.elem (j); - REP_ELEM_ASSIGN (i, col, rhs_m.elem (i, j), - rhs_cm.elem (i, j), rhs.is_real_type ()); + retval = new tree_constant [2]; + switch (arg1_type) + { + case tree_constant_rep::scalar_constant: + { + double result; + double a_elem = arg1.double_value (); + double b_elem = arg2.double_value (); + result = MIN (a_elem, b_elem); + retval[0] = tree_constant (result); + } + break; + case tree_constant_rep::complex_scalar_constant: + { + Complex result; + Complex a_elem = arg1.complex_value (); + Complex b_elem = arg2.complex_value (); + if (abs (a_elem) < abs (b_elem)) + result = a_elem; + else + result = b_elem; + retval[0] = tree_constant (result); + } + break; + case tree_constant_rep::matrix_constant: + { + Matrix result; + result = min (arg1.matrix_value (), arg2.matrix_value ()); + retval[0] = tree_constant (result); + } + break; + case tree_constant_rep::complex_matrix_constant: + { + ComplexMatrix result; + result = min (arg1.complex_matrix_value (), + arg2.complex_matrix_value ()); + retval[0] = tree_constant (result); + } + break; + default: + panic_impossible (); + break; } } - } -} - -/* 15 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant_rep::constant_type mci, - Range& rj) -{ - assert (mci == magic_colon); - - if (rhs.is_zero_by_zero ()) - { - delete_columns (rj); - } - else - { - REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); - - int nr = rows (); - - double jb = rj.base (); - double jinc = rj.inc (); - - for (int j = 0; j < rj.nelem (); j++) - { - double jtmp = jb + j * jinc; - int col = tree_to_mat_idx (jtmp); - for (int i = 0; i < nr; i++) - { - REP_ELEM_ASSIGN (i, col, rhs_m.elem (i, j), - rhs_cm.elem (i, j), rhs.is_real_type ()); - } - } - } -} - -/* 16 */ -void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant_rep::constant_type mci, - tree_constant_rep::constant_type mcj) -{ - assert (mci == magic_colon && mcj == magic_colon); - - switch (type_tag) - { - case scalar_constant: - break; - case matrix_constant: - delete matrix; - break; - case complex_scalar_constant: - delete complex_scalar; - break; - case complex_matrix_constant: - delete complex_matrix; - break; - case string_constant: - delete [] string; - break; - case range_constant: - delete range; - break; - case magic_colon: - default: - panic_impossible (); - break; - } - - type_tag = rhs.const_type (); - - switch (type_tag) - { - case scalar_constant: - scalar = rhs.double_value (); - break; - case matrix_constant: - matrix = new Matrix (rhs.matrix_value ()); - break; - case string_constant: - string = strsave (rhs.string_value ()); - break; - case complex_matrix_constant: - complex_matrix = new ComplexMatrix (rhs.complex_matrix_value ()); - break; - case complex_scalar_constant: - complex_scalar = new Complex (rhs.complex_value ()); - break; - case range_constant: - range = new Range (rhs.range_value ()); - break; - case magic_colon: - default: - panic_impossible (); - break; - } -} - -/* - * Functions for deleting rows or columns of a matrix. These are used - * to handle statements like - * - * M (i, j) = [] - */ -void -tree_constant_rep::delete_row (int idx) -{ - if (type_tag == matrix_constant) - { - int nr = matrix->rows (); - int nc = matrix->columns (); - Matrix *new_matrix = new Matrix (nr-1, nc); - int ii = 0; - for (int i = 0; i < nr; i++) - { - if (i != idx) - { - for (int j = 0; j < nc; j++) - new_matrix->elem (ii, j) = matrix->elem (i, j); - ii++; - } - } - delete matrix; - matrix = new_matrix; - } - else if (type_tag == complex_matrix_constant) - { - int nr = complex_matrix->rows (); - int nc = complex_matrix->columns (); - ComplexMatrix *new_matrix = new ComplexMatrix (nr-1, nc); - int ii = 0; - for (int i = 0; i < nr; i++) - { - if (i != idx) - { - for (int j = 0; j < nc; j++) - new_matrix->elem (ii, j) = complex_matrix->elem (i, j); - ii++; - } - } - delete complex_matrix; - complex_matrix = new_matrix; + else + error ("min: nonconformant matrices"); } else panic_impossible (); -} - -void -tree_constant_rep::delete_rows (idx_vector& iv) -{ - iv.sort_uniq (); - int num_to_delete = iv.length (); - - int nr = rows (); - int nc = columns (); - -// If deleting all rows of a column vector, make result 0x0. - if (nc == 1 && num_to_delete == nr) - nc = 0; - - if (type_tag == matrix_constant) - { - Matrix *new_matrix = new Matrix (nr-num_to_delete, nc); - if (nr > num_to_delete) - { - int ii = 0; - int idx = 0; - for (int i = 0; i < nr; i++) - { - if (i == iv.elem (idx)) - idx++; - else - { - for (int j = 0; j < nc; j++) - new_matrix->elem (ii, j) = matrix->elem (i, j); - ii++; - } - } - } - delete matrix; - matrix = new_matrix; - } - else if (type_tag == complex_matrix_constant) - { - ComplexMatrix *new_matrix = new ComplexMatrix (nr-num_to_delete, nc); - if (nr > num_to_delete) - { - int ii = 0; - int idx = 0; - for (int i = 0; i < nr; i++) - { - if (i == iv.elem (idx)) - idx++; - else - { - for (int j = 0; j < nc; j++) - new_matrix->elem (ii, j) = complex_matrix->elem (i, j); - ii++; - } - } - } - delete complex_matrix; - complex_matrix = new_matrix; - } - else - panic_impossible (); -} - -void -tree_constant_rep::delete_rows (Range& ri) -{ - ri.sort (); - int num_to_delete = ri.nelem (); - - int nr = rows (); - int nc = columns (); - -// If deleting all rows of a column vector, make result 0x0. - if (nc == 1 && num_to_delete == nr) - nc = 0; - - double ib = ri.base (); - double iinc = ri.inc (); - - int max_idx = tree_to_mat_idx (ri.max ()); - - if (type_tag == matrix_constant) - { - Matrix *new_matrix = new Matrix (nr-num_to_delete, nc); - if (nr > num_to_delete) - { - int ii = 0; - int idx = 0; - for (int i = 0; i < nr; i++) - { - double itmp = ib + idx * iinc; - int row = tree_to_mat_idx (itmp); - - if (i == row && row <= max_idx) - idx++; - else - { - for (int j = 0; j < nc; j++) - new_matrix->elem (ii, j) = matrix->elem (i, j); - ii++; - } - } - } - delete matrix; - matrix = new_matrix; - } - else if (type_tag == complex_matrix_constant) - { - ComplexMatrix *new_matrix = new ComplexMatrix (nr-num_to_delete, nc); - if (nr > num_to_delete) - { - int ii = 0; - int idx = 0; - for (int i = 0; i < nr; i++) - { - double itmp = ib + idx * iinc; - int row = tree_to_mat_idx (itmp); - - if (i == row && row <= max_idx) - idx++; - else - { - for (int j = 0; j < nc; j++) - new_matrix->elem (ii, j) = complex_matrix->elem (i, j); - ii++; - } - } - } - delete complex_matrix; - complex_matrix = new_matrix; - } - else - panic_impossible (); -} - -void -tree_constant_rep::delete_column (int idx) -{ - if (type_tag == matrix_constant) - { - int nr = matrix->rows (); - int nc = matrix->columns (); - Matrix *new_matrix = new Matrix (nr, nc-1); - int jj = 0; - for (int j = 0; j < nc; j++) - { - if (j != idx) - { - for (int i = 0; i < nr; i++) - new_matrix->elem (i, jj) = matrix->elem (i, j); - jj++; - } - } - delete matrix; - matrix = new_matrix; - } - else if (type_tag == complex_matrix_constant) - { - int nr = complex_matrix->rows (); - int nc = complex_matrix->columns (); - ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-1); - int jj = 0; - for (int j = 0; j < nc; j++) - { - if (j != idx) - { - for (int i = 0; i < nr; i++) - new_matrix->elem (i, jj) = complex_matrix->elem (i, j); - jj++; - } - } - delete complex_matrix; - complex_matrix = new_matrix; - } - else - panic_impossible (); -} - -void -tree_constant_rep::delete_columns (idx_vector& jv) -{ - jv.sort_uniq (); - int num_to_delete = jv.length (); - - int nr = rows (); - int nc = columns (); - -// If deleting all columns of a row vector, make result 0x0. - if (nr == 1 && num_to_delete == nc) - nr = 0; - - if (type_tag == matrix_constant) - { - Matrix *new_matrix = new Matrix (nr, nc-num_to_delete); - if (nc > num_to_delete) - { - int jj = 0; - int idx = 0; - for (int j = 0; j < nc; j++) - { - if (j == jv.elem (idx)) - idx++; - else - { - for (int i = 0; i < nr; i++) - new_matrix->elem (i, jj) = matrix->elem (i, j); - jj++; - } - } - } - delete matrix; - matrix = new_matrix; - } - else if (type_tag == complex_matrix_constant) - { - ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-num_to_delete); - if (nc > num_to_delete) - { - int jj = 0; - int idx = 0; - for (int j = 0; j < nc; j++) - { - if (j == jv.elem (idx)) - idx++; - else - { - for (int i = 0; i < nr; i++) - new_matrix->elem (i, jj) = complex_matrix->elem (i, j); - jj++; - } - } - } - delete complex_matrix; - complex_matrix = new_matrix; - } - else - panic_impossible (); -} - -void -tree_constant_rep::delete_columns (Range& rj) -{ - rj.sort (); - int num_to_delete = rj.nelem (); - - int nr = rows (); - int nc = columns (); - -// If deleting all columns of a row vector, make result 0x0. - if (nr == 1 && num_to_delete == nc) - nr = 0; - - double jb = rj.base (); - double jinc = rj.inc (); - - int max_idx = tree_to_mat_idx (rj.max ()); - - if (type_tag == matrix_constant) - { - Matrix *new_matrix = new Matrix (nr, nc-num_to_delete); - if (nc > num_to_delete) - { - int jj = 0; - int idx = 0; - for (int j = 0; j < nc; j++) - { - double jtmp = jb + idx * jinc; - int col = tree_to_mat_idx (jtmp); - - if (j == col && col <= max_idx) - idx++; - else - { - for (int i = 0; i < nr; i++) - new_matrix->elem (i, jj) = matrix->elem (i, j); - jj++; - } - } - } - delete matrix; - matrix = new_matrix; - } - else if (type_tag == complex_matrix_constant) - { - ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-num_to_delete); - if (nc > num_to_delete) - { - int jj = 0; - int idx = 0; - for (int j = 0; j < nc; j++) - { - double jtmp = jb + idx * jinc; - int col = tree_to_mat_idx (jtmp); - - if (j == col && col <= max_idx) - idx++; - else - { - for (int i = 0; i < nr; i++) - new_matrix->elem (i, jj) = complex_matrix->elem (i, j); - jj++; - } - } - } - delete complex_matrix; - complex_matrix = new_matrix; - } - else - panic_impossible (); -} - - -int -tree_constant_rep::valid_as_scalar_index (void) const -{ - int valid = type_tag == magic_colon - || (type_tag == scalar_constant && NINT (scalar) == 1) - || (type_tag == range_constant - && range->nelem () == 1 && NINT (range->base ()) == 1); - - return valid; -} - -tree_constant -tree_constant_rep::do_scalar_index (const tree_constant *args, - int nargs) const -{ - if (valid_scalar_indices (args, nargs)) - { - if (type_tag == scalar_constant) - return tree_constant (scalar); - else if (type_tag == complex_scalar_constant) - return tree_constant (*complex_scalar); - else - panic_impossible (); - } - else - { - int rows = 0; - int cols = 0; - - switch (nargs) - { - case 3: - { - if (args[2].is_matrix_type ()) - { - Matrix mj = args[2].matrix_value (); - - idx_vector j (mj, user_pref.do_fortran_indexing, ""); - if (! j) - return tree_constant (); - - int len = j.length (); - if (len == j.ones_count ()) - cols = len; - } - else if (args[2].const_type () == magic_colon - || (args[2].is_scalar_type () - && NINT (args[2].double_value ()) == 1)) - { - cols = 1; - } - else - break; - } -// Fall through... - case 2: - { - if (args[1].is_matrix_type ()) - { - Matrix mi = args[1].matrix_value (); - - idx_vector i (mi, user_pref.do_fortran_indexing, ""); - if (! i) - return tree_constant (); - - int len = i.length (); - if (len == i.ones_count ()) - rows = len; - } - else if (args[1].const_type () == magic_colon - || (args[1].is_scalar_type () - && NINT (args[1].double_value ()) == 1)) - { - rows = 1; - } - else if (args[1].is_scalar_type () - && NINT (args[1].double_value ()) == 0) - { - Matrix m (0, 0); - return tree_constant (m); - } - else - break; - - if (cols == 0) - { - if (user_pref.prefer_column_vectors) - cols = 1; - else - { - cols = rows; - rows = 1; - } - } - - if (type_tag == scalar_constant) - { - Matrix m (rows, cols, scalar); - return tree_constant (m); - } - else if (type_tag == complex_scalar_constant) - { - ComplexMatrix cm (rows, cols, *complex_scalar); - return tree_constant (cm); - } - else - panic_impossible (); - } - break; - default: - ::error ("illegal number of arguments for scalar type"); - return tree_constant (); - break; - } - } - - ::error ("index invalid or out of range for scalar type"); - return tree_constant (); -} - -tree_constant -tree_constant_rep::do_matrix_index (const tree_constant *args, - int nargin) const -{ - tree_constant retval; - - switch (nargin) - { - case 2: - if (args == NULL_TREE_CONST) - ::error ("matrix index is null"); - else if (args[1].is_undefined ()) - ::error ("matrix index is a null expression"); - else - retval = do_matrix_index (args[1]); - break; - case 3: - if (args == NULL_TREE_CONST) - ::error ("matrix indices are null"); - else if (args[1].is_undefined ()) - ::error ("first matrix index is a null expression"); - else if (args[2].is_undefined ()) - ::error ("second matrix index is a null expression"); - else - retval = do_matrix_index (args[1], args[2]); - break; - default: - ::error ("too many indices for matrix expression"); - break; - } - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const tree_constant& i_arg) const -{ - tree_constant retval; - - int nr = rows (); - int nc = columns (); - - if (user_pref.do_fortran_indexing) - retval = fortran_style_matrix_index (i_arg); - else if (nr <= 1 || nc <= 1) - retval = do_vector_index (i_arg); - else - ::error ("single index only valid for row or column vector"); return retval; } -tree_constant -tree_constant_rep::fortran_style_matrix_index - (const tree_constant& i_arg) const +static void +mx_sort (Matrix& m, Matrix& idx, int return_idx) { - tree_constant retval; + int nr = m.rows (); + int nc = m.columns (); + idx.resize (nr, nc); + int i, j; + + if (return_idx) + { + for (j = 0; j < nc; j++) + for (i = 0; i < nr; i++) + idx.elem (i, j) = i+1; + } + + for (j = 0; j < nc; j++) + { + for (int gap = nr/2; gap > 0; gap /= 2) + for (i = gap; i < nr; i++) + for (int k = i - gap; + k >= 0 && m.elem (k, j) > m.elem (k+gap, j); + k -= gap) + { + double tmp = m.elem (k, j); + m.elem (k, j) = m.elem (k+gap, j); + m.elem (k+gap, j) = tmp; + + if (return_idx) + { + double tmp = idx.elem (k, j); + idx.elem (k, j) = idx.elem (k+gap, j); + idx.elem (k+gap, j) = tmp; + } + } + } +} - tree_constant tmp_i = i_arg.make_numeric_or_magic (); +static void +mx_sort (RowVector& v, RowVector& idx, int return_idx) +{ + int n = v.capacity (); + idx.resize (n); + int i; + + if (return_idx) + for (i = 0; i < n; i++) + idx.elem (i) = i+1; - tree_constant_rep::constant_type itype = tmp_i.const_type (); + for (int gap = n/2; gap > 0; gap /= 2) + for (i = gap; i < n; i++) + for (int k = i - gap; + k >= 0 && v.elem (k) > v.elem (k+gap); + k -= gap) + { + double tmp = v.elem (k); + v.elem (k) = v.elem (k+gap); + v.elem (k+gap) = tmp; - int nr = rows (); - int nc = columns (); + if (return_idx) + { + double tmp = idx.elem (k); + idx.elem (k) = idx.elem (k+gap); + idx.elem (k+gap) = tmp; + } + } +} + +static void +mx_sort (ComplexMatrix& cm, Matrix& idx, int return_idx) +{ + int nr = cm.rows (); + int nc = cm.columns (); + idx.resize (nr, nc); + int i, j; - switch (itype) + if (return_idx) + { + for (j = 0; j < nc; j++) + for (i = 0; i < nr; i++) + idx.elem (i, j) = i+1; + } + + for (j = 0; j < nc; j++) { - case complex_scalar_constant: - case scalar_constant: + for (int gap = nr/2; gap > 0; gap /= 2) + for (i = gap; i < nr; i++) + for (int k = i - gap; + k >= 0 && abs (cm.elem (k, j)) > abs (cm.elem (k+gap, j)); + k -= gap) + { + Complex ctmp = cm.elem (k, j); + cm.elem (k, j) = cm.elem (k+gap, j); + cm.elem (k+gap, j) = ctmp; + + if (return_idx) + { + double tmp = idx.elem (k, j); + idx.elem (k, j) = idx.elem (k+gap, j); + idx.elem (k+gap, j) = tmp; + } + } + } +} + +static void +mx_sort (ComplexRowVector& cv, RowVector& idx, int return_idx) +{ + int n = cv.capacity (); + idx.resize (n); + int i; + + if (return_idx) + for (i = 0; i < n; i++) + idx.elem (i) = i+1; + + for (int gap = n/2; gap > 0; gap /= 2) + for (i = gap; i < n; i++) + for (int k = i - gap; + k >= 0 && abs (cv.elem (k)) > abs (cv.elem (k+gap)); + k -= gap) + { + Complex tmp = cv.elem (k); + cv.elem (k) = cv.elem (k+gap); + cv.elem (k+gap) = tmp; + + if (return_idx) + { + double tmp = idx.elem (k); + idx.elem (k) = idx.elem (k+gap); + idx.elem (k+gap) = tmp; + } + } +} + +tree_constant * +sort (const tree_constant *args, int nargin, int nargout) +{ +// Assumes that we have been given the correct number of arguments. + + tree_constant *retval = NULL_TREE_CONST; + + int return_idx = nargout > 1; + if (return_idx) + retval = new tree_constant [3]; + else + retval = new tree_constant [2]; + + switch (args[1].const_type ()) + { + case tree_constant_rep::scalar_constant: { - int i = NINT (tmp_i.double_value ()); - int ii = fortran_row (i, nr) - 1; - int jj = fortran_column (i, nr) - 1; - if (index_check (i-1, "") < 0) - return tree_constant (); - if (range_max_check (i-1, nr * nc) < 0) - return tree_constant (); - retval = do_matrix_index (ii, jj); + retval [0] = tree_constant (args[1].double_value ()); + if (return_idx) + retval [1] = tree_constant (1.0); } break; - case complex_matrix_constant: - case matrix_constant: + case tree_constant_rep::complex_scalar_constant: + { + retval [0] = tree_constant (args[1].complex_value ()); + if (return_idx) + retval [1] = tree_constant (1.0); + } + break; + case tree_constant_rep::string_constant: + case tree_constant_rep::range_constant: + case tree_constant_rep::matrix_constant: { - Matrix mi = tmp_i.matrix_value (); - if (mi.rows () == 0 || mi.columns () == 0) + Matrix m = args[1].to_matrix (); + if (m.rows () == 1) { - Matrix mtmp; - retval = tree_constant (mtmp); + int nc = m.columns (); + RowVector v (nc); + for (int i = 0; i < nc; i++) + v.elem (i) = m.elem (0, i); + RowVector idx; + mx_sort (v, idx, return_idx); + + retval [0] = tree_constant (v, 0); + if (return_idx) + retval [1] = tree_constant (idx, 0); } else { -// Yes, we really do want to call this with mi. - retval = fortran_style_matrix_index (mi); +// Sorts m in place, optionally computes index Matrix. + Matrix idx; + mx_sort (m, idx, return_idx); + + retval [0] = tree_constant (m); + if (return_idx) + retval [1] = tree_constant (idx); } } break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - gripe_range_invalid (); - break; - case magic_colon: - retval = do_matrix_index (magic_colon); + case tree_constant_rep::complex_matrix_constant: + { + ComplexMatrix cm = args[1].complex_matrix_value (); + if (cm.rows () == 1) + { + int nc = cm.columns (); + ComplexRowVector cv (nc); + for (int i = 0; i < nc; i++) + cv.elem (i) = cm.elem (0, i); + RowVector idx; + mx_sort (cv, idx, return_idx); + + retval [0] = tree_constant (cv, 0); + if (return_idx) + retval [1] = tree_constant (idx, 0); + } + else + { +// Sorts cm in place, optionally computes index Matrix. + Matrix idx; + mx_sort (cm, idx, return_idx); + + retval [0] = tree_constant (cm); + if (return_idx) + retval [1] = tree_constant (idx); + } + } break; default: panic_impossible (); @@ -5135,1033 +1275,174 @@ return retval; } -tree_constant -tree_constant_rep::fortran_style_matrix_index (const Matrix& mi) const +tree_constant * +feval (const tree_constant *args, int nargin, int nargout) { - assert (is_matrix_type ()); - - tree_constant retval; - - int nr = rows (); - int nc = columns (); - - int len = nr * nc; - - int index_nr = mi.rows (); - int index_nc = mi.columns (); - - if (index_nr >= 1 && index_nc >= 1) - { - const double *cop_out = (const double *) NULL; - const Complex *c_cop_out = (const Complex *) NULL; - int real_type = type_tag == matrix_constant; - if (real_type) - cop_out = matrix->data (); - else - c_cop_out = complex_matrix->data (); - - const double *cop_out_index = mi.data (); - - idx_vector iv (mi, 1, "", len); - if (! iv) - return tree_constant (); - - int result_size = iv.length (); - - if (nc == 1 || (nr != 1 && iv.one_zero_only ())) - { - CRMATRIX (m, cm, result_size, 1); - - for (int i = 0; i < result_size; i++) - { - int idx = iv.elem (i); - CRMATRIX_ASSIGN_ELEM (m, cm, i, 0, cop_out [idx], - c_cop_out [idx], real_type); - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - } - else if (nr == 1) - { - CRMATRIX (m, cm, 1, result_size); +// Assumes that we have been given the correct number of arguments. - for (int i = 0; i < result_size; i++) - { - int idx = iv.elem (i); - CRMATRIX_ASSIGN_ELEM (m, cm, 0, i, cop_out [idx], - c_cop_out [idx], real_type); - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - } - else - { - CRMATRIX (m, cm, index_nr, index_nc); - - for (int j = 0; j < index_nc; j++) - for (int i = 0; i < index_nr; i++) - { - double tmp = *cop_out_index++; - int idx = tree_to_mat_idx (tmp); - CRMATRIX_ASSIGN_ELEM (m, cm, i, j, cop_out [idx], - c_cop_out [idx], real_type); - } + tree_constant *retval = NULL_TREE_CONST; - ASSIGN_CRMATRIX_TO (retval, m, cm); - } - } - else - { - if (index_nr == 0 || index_nc == 0) - ::error ("empty matrix invalid as index"); - else - ::error ("invalid matrix index"); - return tree_constant (); - } - - return retval; -} - -tree_constant -tree_constant_rep::do_vector_index (const tree_constant& i_arg) const -{ - tree_constant retval; - - tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type itype = tmp_i.const_type (); - - int nr = rows (); - int nc = columns (); - - int len = nr > nc ? nr : nc; - - if (nr == 0 || nc == 0) + tree_fvc *fcn = is_valid_function (args[1], "feval", 1); + if (fcn != (tree_fvc *) NULL) { - ::error ("attempt to index empty matrix"); - return retval; - } - - assert ((nr == 1 || nc == 1) && ! user_pref.do_fortran_indexing); - - int swap_indices = (nr == 1); - - switch (itype) - { - case complex_scalar_constant: - case scalar_constant: - { - int i = tree_to_mat_idx (tmp_i.double_value ()); - if (index_check (i, "") < 0) - return tree_constant (); - if (swap_indices) - { - if (range_max_check (i, nc) < 0) - return tree_constant (); - retval = do_matrix_index (0, i); - } - else - { - if (range_max_check (i, nr) < 0) - return tree_constant (); - retval = do_matrix_index (i, 0); - } - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mi = tmp_i.matrix_value (); - if (mi.rows () == 0 || mi.columns () == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else - { - idx_vector iv (mi, user_pref.do_fortran_indexing, "", len); - if (! iv) - return tree_constant (); - - if (swap_indices) - { - if (range_max_check (iv.max (), nc) < 0) - return tree_constant (); - retval = do_matrix_index (0, iv); - } - else - { - if (range_max_check (iv.max (), nr) < 0) - return tree_constant (); - retval = do_matrix_index (iv, 0); - } - } - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range ri = tmp_i.range_value (); - if (len == 2 && is_zero_one (ri)) - { - if (swap_indices) - retval = do_matrix_index (0, 1); - else - retval = do_matrix_index (1, 0); - } - else if (len == 2 && is_one_zero (ri)) - { - retval = do_matrix_index (0, 0); - } - else - { - if (index_check (ri, "") < 0) - return tree_constant (); - if (swap_indices) - { - if (range_max_check (tree_to_mat_idx (ri.max ()), nc) < 0) - return tree_constant (); - retval = do_matrix_index (0, ri); - } - else - { - if (range_max_check (tree_to_mat_idx (ri.max ()), nr) < 0) - return tree_constant (); - retval = do_matrix_index (ri, 0); - } - } - } - break; - case magic_colon: - if (swap_indices) - retval = do_matrix_index (0, magic_colon); - else - retval = do_matrix_index (magic_colon, 0); - break; - default: - panic_impossible (); - break; + args++; + nargin--; + retval = fcn->eval (0, nargout, args, nargin); } return retval; } tree_constant -tree_constant_rep::do_matrix_index (const tree_constant& i_arg, - const tree_constant& j_arg) const +eval_string (const char *string, int print, int ans_assign, + int& parse_status) { - tree_constant retval; - - tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type itype = tmp_i.const_type (); + begin_unwind_frame ("eval_string"); - switch (itype) - { - case complex_scalar_constant: - case scalar_constant: - { - int i = tree_to_mat_idx (tmp_i.double_value ()); - if (index_check (i, "row") < 0) - return tree_constant (); - retval = do_matrix_index (i, j_arg); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mi = tmp_i.matrix_value (); - idx_vector iv (mi, user_pref.do_fortran_indexing, "row", rows ()); - if (! iv) - return tree_constant (); + unwind_protect_int (get_input_from_eval_string); + unwind_protect_ptr (global_command); + unwind_protect_ptr (current_eval_string); + + get_input_from_eval_string = 1; + current_eval_string = string; + + YY_BUFFER_STATE old_buf = current_buffer (); + YY_BUFFER_STATE new_buf = create_buffer ((FILE *) NULL); - if (iv.length () == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else - retval = do_matrix_index (iv, j_arg); - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range ri = tmp_i.range_value (); - int nr = rows (); - if (nr == 2 && is_zero_one (ri)) - { - retval = do_matrix_index (1, j_arg); - } - else if (nr == 2 && is_one_zero (ri)) - { - retval = do_matrix_index (0, j_arg); - } - else - { - if (index_check (ri, "row") < 0) - return tree_constant (); - retval = do_matrix_index (ri, j_arg); - } - } - break; - case magic_colon: - retval = do_matrix_index (magic_colon, j_arg); - break; - default: - panic_impossible (); - break; - } + add_unwind_protect (restore_input_buffer, (void *) old_buf); + add_unwind_protect (delete_input_buffer, (void *) new_buf); + + switch_to_buffer (new_buf); + + unwind_protect_ptr (curr_sym_tab); + + reset_parser (); - return retval; -} + parse_status = yyparse (); -tree_constant -tree_constant_rep::do_matrix_index (int i, const tree_constant& j_arg) const -{ +// Important to reset the idea of where input is coming from before +// trying to eval the command we just parsed -- it might contain the +// name of an function file that still needs to be parsed! + + tree *command = global_command; + + run_unwind_frame ("eval_string"); + tree_constant retval; - tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type jtype = tmp_j.const_type (); - - int nr = rows (); - int nc = columns (); - - switch (jtype) + if (parse_status == 0 && command != NULL_TREE) { - case complex_scalar_constant: - case scalar_constant: - { - int j = tree_to_mat_idx (tmp_j.double_value ()); - if (index_check (j, "column") < 0) - return tree_constant (); - if (range_max_check (i, j, nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (i, j); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mj = tmp_j.matrix_value (); - idx_vector jv (mj, user_pref.do_fortran_indexing, "column", nc); - if (! jv) - return tree_constant (); - - if (jv.length () == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else - { - if (range_max_check (i, jv.max (), nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (i, jv); - } - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range rj = tmp_j.range_value (); - if (nc == 2 && is_zero_one (rj)) - { - retval = do_matrix_index (i, 1); - } - else if (nc == 2 && is_one_zero (rj)) - { - retval = do_matrix_index (i, 0); - } - else - { - if (index_check (rj, "column") < 0) - return tree_constant (); - if (range_max_check (i, tree_to_mat_idx (rj.max ()), nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (i, rj); - } - } - break; - case magic_colon: - if (range_max_check (i, 0, nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (i, magic_colon); - break; - default: - panic_impossible (); - break; - } - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const idx_vector& iv, - const tree_constant& j_arg) const -{ - tree_constant retval; - - tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type jtype = tmp_j.const_type (); - - int nr = rows (); - int nc = columns (); - - switch (jtype) - { - case complex_scalar_constant: - case scalar_constant: - { - int j = tree_to_mat_idx (tmp_j.double_value ()); - if (index_check (j, "column") < 0) - return tree_constant (); - if (range_max_check (iv.max (), j, nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (iv, j); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mj = tmp_j.matrix_value (); - idx_vector jv (mj, user_pref.do_fortran_indexing, "column", nc); - if (! jv) - return tree_constant (); - - if (jv.length () == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else - { - if (range_max_check (iv.max (), jv.max (), nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (iv, jv); - } - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range rj = tmp_j.range_value (); - if (nc == 2 && is_zero_one (rj)) - { - retval = do_matrix_index (iv, 1); - } - else if (nc == 2 && is_one_zero (rj)) - { - retval = do_matrix_index (iv, 0); - } - else - { - if (index_check (rj, "column") < 0) - return tree_constant (); - if (range_max_check (iv.max (), tree_to_mat_idx (rj.max ()), - nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (iv, rj); - } - } - break; - case magic_colon: - if (range_max_check (iv.max (), 0, nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (iv, magic_colon); - break; - default: - panic_impossible (); - break; + retval = command->eval (print); + delete command; } return retval; } tree_constant -tree_constant_rep::do_matrix_index (const Range& ri, - const tree_constant& j_arg) const +eval_string (const tree_constant& arg, int& parse_status) { - tree_constant retval; - - tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type jtype = tmp_j.const_type (); - - int nr = rows (); - int nc = columns (); - - switch (jtype) + if (! arg.is_string_type ()) { - case complex_scalar_constant: - case scalar_constant: - { - int j = tree_to_mat_idx (tmp_j.double_value ()); - if (index_check (j, "column") < 0) - return tree_constant (); - if (range_max_check (tree_to_mat_idx (ri.max ()), j, nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (ri, j); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mj = tmp_j.matrix_value (); - idx_vector jv (mj, user_pref.do_fortran_indexing, "column", nc); - if (! jv) - return tree_constant (); - - if (jv.length () == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else - { - if (range_max_check (tree_to_mat_idx (ri.max ()), - jv.max (), nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (ri, jv); - } - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range rj = tmp_j.range_value (); - if (nc == 2 && is_zero_one (rj)) - { - retval = do_matrix_index (ri, 1); - } - else if (nc == 2 && is_one_zero (rj)) - { - retval = do_matrix_index (ri, 0); - } - else - { - if (index_check (rj, "column") < 0) - return tree_constant (); - if (range_max_check (tree_to_mat_idx (ri.max ()), - tree_to_mat_idx (rj.max ()), nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (ri, rj); - } - } - break; - case magic_colon: - retval = do_matrix_index (ri, magic_colon); - break; - default: - panic_impossible (); - break; + error ("eval: expecting string argument"); + return -1; } - return retval; + char *string = arg.string_value (); + +// Yes Virginia, we always print here... + + return eval_string (string, 1, 1, parse_status); +} + +static int +match_sans_spaces (const char *standard, const char *test) +{ + const char *tp = test; + while (*tp == ' ' || *tp == '\t') + tp++; + + const char *ep = test + strlen (test) - 1; + while (*ep == ' ' || *ep == '\t') + ep--; + + int len = ep - tp + 1; + + return (strncmp (standard, tp, len) == 0); } tree_constant -tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci, - const tree_constant& j_arg) const +get_user_input (const tree_constant *args, int nargin, int nargout, + int debug = 0) { tree_constant retval; - tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); - - tree_constant_rep::constant_type jtype = tmp_j.const_type (); - - int nr = rows (); - int nc = columns (); - - switch (jtype) + int read_as_string = 0; + if (nargin == 3) { - case complex_scalar_constant: - case scalar_constant: - { - int j = tree_to_mat_idx (tmp_j.double_value ()); - if (index_check (j, "column") < 0) - return tree_constant (); - if (range_max_check (0, j, nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (magic_colon, j); - } - break; - case complex_matrix_constant: - case matrix_constant: - { - Matrix mj = tmp_j.matrix_value (); - idx_vector jv (mj, user_pref.do_fortran_indexing, "column", nc); - if (! jv) - return tree_constant (); - - if (jv.length () == 0) - { - Matrix mtmp; - retval = tree_constant (mtmp); - } - else - { - if (range_max_check (0, jv.max (), nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (magic_colon, jv); - } - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - { - Range rj = tmp_j.range_value (); - if (nc == 2 && is_zero_one (rj)) - { - retval = do_matrix_index (magic_colon, 1); - } - else if (nc == 2 && is_one_zero (rj)) - { - retval = do_matrix_index (magic_colon, 0); - } - else - { - if (index_check (rj, "column") < 0) - return tree_constant (); - if (range_max_check (0, tree_to_mat_idx (rj.max ()), nr, nc) < 0) - return tree_constant (); - retval = do_matrix_index (magic_colon, rj); - } - } - break; - case magic_colon: - retval = do_matrix_index (magic_colon, magic_colon); - break; - default: - panic_impossible (); - break; - } - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (int i, int j) const -{ - tree_constant retval; - - if (type_tag == matrix_constant) - retval = tree_constant (matrix->elem (i, j)); - else - retval = tree_constant (complex_matrix->elem (i, j)); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (int i, const idx_vector& jv) const -{ - tree_constant retval; - - int jlen = jv.capacity (); - - CRMATRIX (m, cm, 1, jlen); - - for (int j = 0; j < jlen; j++) - { - int col = jv.elem (j); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, 0, j, i, col); - } - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (int i, const Range& rj) const -{ - tree_constant retval; - - int jlen = rj.nelem (); - - CRMATRIX (m, cm, 1, jlen); - - double b = rj.base (); - double increment = rj.inc (); - for (int j = 0; j < jlen; j++) - { - double tmp = b + j * increment; - int col = tree_to_mat_idx (tmp); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, 0, j, i, col); - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index - (int i, tree_constant_rep::constant_type mcj) const -{ - assert (mcj == magic_colon); - - tree_constant retval; - - int nc = columns (); - - CRMATRIX (m, cm, 1, nc); - - for (int j = 0; j < nc; j++) - { - CRMATRIX_ASSIGN_REP_ELEM (m, cm, 0, j, i, j); - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const idx_vector& iv, int j) const -{ - tree_constant retval; - - int ilen = iv.capacity (); - - CRMATRIX (m, cm, ilen, 1); - - for (int i = 0; i < ilen; i++) - { - int row = iv.elem (i); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, 0, row, j); - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const idx_vector& iv, - const idx_vector& jv) const -{ - tree_constant retval; - - int ilen = iv.capacity (); - int jlen = jv.capacity (); - - CRMATRIX (m, cm, ilen, jlen); - - for (int i = 0; i < ilen; i++) - { - int row = iv.elem (i); - for (int j = 0; j < jlen; j++) + if (args[2].is_string_type () + && strcmp ("s", args[2].string_value ()) == 0) + read_as_string++; + else { - int col = jv.elem (j); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col); + error ("input: unrecognized second argument"); + return retval; } } - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const idx_vector& iv, - const Range& rj) const -{ - tree_constant retval; - - int ilen = iv.capacity (); - int jlen = rj.nelem (); - - CRMATRIX (m, cm, ilen, jlen); - - double b = rj.base (); - double increment = rj.inc (); - - for (int i = 0; i < ilen; i++) - { - int row = iv.elem (i); - for (int j = 0; j < jlen; j++) - { - double tmp = b + j * increment; - int col = tree_to_mat_idx (tmp); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col); - } - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index - (const idx_vector& iv, tree_constant_rep::constant_type mcj) const -{ - assert (mcj == magic_colon); - - tree_constant retval; - - int nc = columns (); - int ilen = iv.capacity (); - - CRMATRIX (m, cm, ilen, nc); - - for (int j = 0; j < nc; j++) - { - for (int i = 0; i < ilen; i++) + char *prompt = "debug> "; + if (nargin > 1) + { + if (args[1].is_string_type ()) + prompt = args[1].string_value (); + else { - int row = iv.elem (i); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, j); - } - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const Range& ri, int j) const -{ - tree_constant retval; - - int ilen = ri.nelem (); - - CRMATRIX (m, cm, ilen, 1); - - double b = ri.base (); - double increment = ri.inc (); - for (int i = 0; i < ilen; i++) - { - double tmp = b + i * increment; - int row = tree_to_mat_idx (tmp); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, 0, row, j); - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const Range& ri, - const idx_vector& jv) const -{ - tree_constant retval; - - int ilen = ri.nelem (); - int jlen = jv.capacity (); - - CRMATRIX (m, cm, ilen, jlen); - - double b = ri.base (); - double increment = ri.inc (); - for (int i = 0; i < ilen; i++) - { - double tmp = b + i * increment; - int row = tree_to_mat_idx (tmp); - for (int j = 0; j < jlen; j++) - { - int col = jv.elem (j); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col); - } - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const Range& ri, const Range& rj) const -{ - tree_constant retval; - - int ilen = ri.nelem (); - int jlen = rj.nelem (); - - CRMATRIX (m, cm, ilen, jlen); - - double ib = ri.base (); - double iinc = ri.inc (); - double jb = rj.base (); - double jinc = rj.inc (); - - for (int i = 0; i < ilen; i++) - { - double itmp = ib + i * iinc; - int row = tree_to_mat_idx (itmp); - for (int j = 0; j < jlen; j++) - { - double jtmp = jb + j * jinc; - int col = tree_to_mat_idx (jtmp); - - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col); + error ("input: unrecognized argument"); + return retval; } } - ASSIGN_CRMATRIX_TO (retval, m, cm); + again: - return retval; -} + flush_output_to_pager (); + + char *input_buf = gnu_readline (prompt); -tree_constant -tree_constant_rep::do_matrix_index - (const Range& ri, tree_constant_rep::constant_type mcj) const -{ - assert (mcj == magic_colon); + if (input_buf != (char *) NULL) + { + if (input_buf) + maybe_save_history (input_buf); - tree_constant retval; - - int nc = columns (); + int len = strlen (input_buf); - int ilen = ri.nelem (); - - CRMATRIX (m, cm, ilen, nc); - - double ib = ri.base (); - double iinc = ri.inc (); + if (len < 1) + { + if (debug) + goto again; + else + return retval; + } - for (int i = 0; i < ilen; i++) - { - double itmp = ib + i * iinc; - int row = tree_to_mat_idx (itmp); - for (int j = 0; j < nc; j++) + if (match_sans_spaces ("exit", input_buf) + || match_sans_spaces ("quit", input_buf) + || match_sans_spaces ("return", input_buf)) + return tree_constant (); + else if (read_as_string) + retval = tree_constant (input_buf); + else { - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, j); + int parse_status; + retval = eval_string (input_buf, 0, 0, parse_status); + if (debug && retval.is_defined ()) + retval.eval (1); } } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci, - int j) const -{ - assert (mci == magic_colon); - - tree_constant retval; - - int nr = rows (); - - CRMATRIX (m, cm, nr, 1); - - for (int i = 0; i < nr; i++) - { - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, 0, i, j); - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci, - const idx_vector& jv) const -{ - assert (mci == magic_colon); - - tree_constant retval; - - int nr = rows (); - int jlen = jv.capacity (); - - CRMATRIX (m, cm, nr, jlen); - - for (int i = 0; i < nr; i++) - { - for (int j = 0; j < jlen; j++) - { - int col = jv.elem (j); - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, i, col); - } - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} + else + error ("input: reading user-input failed!"); -tree_constant -tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci, - const Range& rj) const -{ - assert (mci == magic_colon); - - tree_constant retval; - - int nr = rows (); - int jlen = rj.nelem (); - - CRMATRIX (m, cm, nr, jlen); - - double jb = rj.base (); - double jinc = rj.inc (); - - for (int j = 0; j < jlen; j++) - { - double jtmp = jb + j * jinc; - int col = tree_to_mat_idx (jtmp); - for (int i = 0; i < nr; i++) - { - CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, i, col); - } - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} + if (debug) + goto again; -tree_constant -tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci, - tree_constant_rep::constant_type mcj) const -{ - assert (mci == magic_colon && mcj == magic_colon); - - return tree_constant (*this); -} - -tree_constant -tree_constant_rep::do_matrix_index - (tree_constant_rep::constant_type mci) const -{ - assert (mci == magic_colon); - - tree_constant retval; - int nr = rows (); - int nc = columns (); - int size = nr * nc; - if (size > 0) - { - CRMATRIX (m, cm, size, 1); - int idx = 0; - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - { - CRMATRIX_ASSIGN_REP_ELEM (m, cm, idx, 0, i, j); - idx++; - } - ASSIGN_CRMATRIX_TO (retval, m, cm); - } return retval; }