# HG changeset patch # User jwe # Date 777330444 0 # Node ID 9aef0a53eee750bb10ad9ea875fe16b62cd31cbf # Parent 985a9c61f1377dc68c06d9c8fee983b90cd90898 [project @ 1994-08-19 21:06:30 by jwe] diff -r 985a9c61f137 -r 9aef0a53eee7 src/tc-rep.cc --- a/src/tc-rep.cc Fri Aug 19 20:44:28 1994 +0000 +++ b/src/tc-rep.cc Fri Aug 19 21:07:24 1994 +0000 @@ -40,6 +40,7 @@ #include "arith-ops.h" #include "variables.h" +#include "sysdep.h" #include "error.h" #include "gripes.h" #include "user-prefs.h" @@ -53,6 +54,8 @@ // How about a few macros? +#define TC_REP tree_constant::tree_constant_rep + #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif @@ -87,13 +90,13 @@ int nc = 0; \ Matrix m; \ ComplexMatrix cm; \ - if ((tc).const_type () == tree_constant_rep::complex_matrix_constant) \ + if ((tc).const_type () == TC_REP::complex_matrix_constant) \ { \ cm = (tc).complex_matrix_value (); \ nr = (cm).rows (); \ nc = (cm).columns (); \ } \ - else if ((tc).const_type () == tree_constant_rep::matrix_constant) \ + else if ((tc).const_type () == TC_REP::matrix_constant) \ { \ m = (tc).matrix_value (); \ nr = (m).rows (); \ @@ -110,7 +113,7 @@ #define REP_ELEM_ASSIGN(i,j,rval,cval,real_type) \ do \ { \ - if (type_tag == tree_constant_rep::matrix_constant) \ + if (type_tag == TC_REP::matrix_constant) \ { \ if (real_type) \ matrix->elem ((i), (j)) = (rval); \ @@ -137,7 +140,7 @@ #define CRMATRIX(m,cm,nr,nc) \ Matrix m; \ ComplexMatrix cm; \ - if (type_tag == tree_constant_rep::matrix_constant) \ + if (type_tag == TC_REP::matrix_constant) \ (m).resize ((nr), (nc)); \ else if (type_tag == complex_matrix_constant) \ (cm).resize ((nr), (nc)); \ @@ -243,20 +246,20 @@ // The real representation of constants. -tree_constant_rep::tree_constant_rep (void) +TC_REP::tree_constant_rep (void) { type_tag = unknown_constant; orig_text = 0; } -tree_constant_rep::tree_constant_rep (double d) +TC_REP::tree_constant_rep (double d) { scalar = d; type_tag = scalar_constant; orig_text = 0; } -tree_constant_rep::tree_constant_rep (const Matrix& m) +TC_REP::tree_constant_rep (const Matrix& m) { if (m.rows () == 1 && m.columns () == 1) { @@ -271,7 +274,7 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const DiagMatrix& d) +TC_REP::tree_constant_rep (const DiagMatrix& d) { if (d.rows () == 1 && d.columns () == 1) { @@ -286,8 +289,7 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const RowVector& v, int - prefer_column_vector) +TC_REP::tree_constant_rep (const RowVector& v, int prefer_column_vector) { int len = v.capacity (); if (len == 1) @@ -321,8 +323,7 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const ColumnVector& v, - int prefer_column_vector) +TC_REP::tree_constant_rep (const ColumnVector& v, int prefer_column_vector) { int len = v.capacity (); if (len == 1) @@ -356,14 +357,14 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const Complex& c) +TC_REP::tree_constant_rep (const Complex& c) { complex_scalar = new Complex (c); type_tag = complex_scalar_constant; orig_text = 0; } -tree_constant_rep::tree_constant_rep (const ComplexMatrix& m) +TC_REP::tree_constant_rep (const ComplexMatrix& m) { if (m.rows () == 1 && m.columns () == 1) { @@ -378,7 +379,7 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const ComplexDiagMatrix& d) +TC_REP::tree_constant_rep (const ComplexDiagMatrix& d) { if (d.rows () == 1 && d.columns () == 1) { @@ -393,8 +394,8 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const ComplexRowVector& v, - int prefer_column_vector) +TC_REP::tree_constant_rep (const ComplexRowVector& v, + int prefer_column_vector) { int len = v.capacity (); if (len == 1) @@ -428,8 +429,8 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const ComplexColumnVector& v, - int prefer_column_vector) +TC_REP::tree_constant_rep (const ComplexColumnVector& v, int + prefer_column_vector) { int len = v.capacity (); if (len == 1) @@ -463,14 +464,14 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const char *s) +TC_REP::tree_constant_rep (const char *s) { string = strsave (s); type_tag = string_constant; orig_text = 0; } -tree_constant_rep::tree_constant_rep (double b, double l, double i) +TC_REP::tree_constant_rep (double b, double l, double i) { range = new Range (b, l, i); int nel = range->nelem (); @@ -504,7 +505,7 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (const Range& r) +TC_REP::tree_constant_rep (const Range& r) { if (r.nelem () > 1) { @@ -527,14 +528,14 @@ orig_text = 0; } -tree_constant_rep::tree_constant_rep (tree_constant_rep::constant_type t) +TC_REP::tree_constant_rep (TC_REP::constant_type t) { assert (t == magic_colon); type_tag = magic_colon; orig_text = 0; } -tree_constant_rep::tree_constant_rep (const tree_constant_rep& t) +TC_REP::tree_constant_rep (const tree_constant_rep& t) { type_tag = t.type_tag; @@ -542,26 +543,34 @@ { 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; @@ -570,31 +579,35 @@ orig_text = strsave (t.orig_text); } -tree_constant_rep::~tree_constant_rep (void) +TC_REP::~tree_constant_rep (void) { switch (type_tag) { case unknown_constant: - break; case scalar_constant: - break; + case magic_colon: + 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; @@ -605,905 +618,54 @@ #if defined (MDEBUG) void * -tree_constant_rep::operator new (size_t size) +TC_REP::operator new (size_t size) { tree_constant_rep *p = ::new tree_constant_rep; - cerr << "tree_constant_rep::new(): " << p << "\n"; + cerr << "TC_REP::new(): " << p << "\n"; return p; } void -tree_constant_rep::operator delete (void *p, size_t size) +TC_REP::operator delete (void *p, size_t size) { - cerr << "tree_constant_rep::delete(): " << p << "\n"; + cerr << "TC_REP::delete(): " << p << "\n"; ::delete p; } #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) -{ - 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; -} - -void -tree_constant_rep::stash_original_text (char *s) -{ - orig_text = strsave (s); -} - -tree_constant_rep::constant_type -tree_constant_rep::force_numeric (int force_str_conv) -{ - 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) 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) +int +TC_REP::rows (void) const { - 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_expression::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_expression::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::maybe_mutate (void) -{ - 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; - } -} - -void -tree_constant_rep::print (void) -{ - if (error_state) - return; - - int nr = rows (); - int nc = columns (); - - 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); - } -} - -static char * -undo_string_escapes (char c) -{ - static char retval[2]; - retval[1] = '\0'; - - if (! c) - return 0; - - switch (c) - { - case '\a': - return "\\a"; - case '\b': // backspace - return "\\b"; - case '\f': // formfeed - return "\\f"; - case '\n': // newline - return "\\n"; - case '\r': // carriage return - return "\\r"; - case '\t': // horizontal tab - return "\\t"; - case '\v': // vertical tab - return "\\v"; - case '\\': // backslash - return "\\\\"; - case '"': // double quote - return "\\\""; - default: - retval[0] = c; - return retval; - } -} - -void -tree_constant_rep::print_code (ostream& os) -{ - int nr = rows (); - int nc = columns (); + int retval = -1; switch (type_tag) { case scalar_constant: - if (orig_text) - os << orig_text; - else - os << scalar; - break; - case matrix_constant: - if (nr == 0 || nc == 0) - os << "[]"; - else - panic_impossible (); - break; case complex_scalar_constant: - { - double re = complex_scalar->real (); - double im = complex_scalar->imag (); - -// We don't collapse Re +/- Im into a complex number yet, so if we get -// here, we had better have a pure imaginary number that's positive... - - assert (re == 0.0 && im > 0.0); - - if (orig_text) - os << orig_text; - else - os << im; - -#if 0 - int sign_printed = 0; - - if (re != 0.0) - { - os << re; - - if (im > 0.0) - { - os << " + "; - sign_printed = 1; - } - else if (im < 0.0) - { - os << " - "; - sign_printed = 1; - } - } - - if (im != 0.0) - os << (sign_printed ? (im < 0.0 ? -im : im) : im); -#endif - } - break; - case complex_matrix_constant: - if (nr == 0 || nc == 0) - os << "[]"; - else - panic_impossible (); - break; + retval = 1; + break; + case string_constant: - { - os << "\""; - char *s, *t = string; - while (s = undo_string_escapes (*t++)) - os << s; - os << "\""; - } - break; case range_constant: - panic_impossible (); - break; + retval = (columns () > 0); + break; + + case matrix_constant: + retval = matrix->rows (); + break; + + case complex_matrix_constant: + retval = complex_matrix->rows (); + break; + case magic_colon: - os << ":"; - break; - default: - panic_impossible (); - break; - } -} - -tree_constant -tree_constant_rep::do_index (const Octave_object& args) -{ - tree_constant retval; - - if (error_state) - return retval; - - if (rows () == 0 || columns () == 0) - { - ::error ("attempt to index empty matrix"); - return retval; - } - - switch (type_tag) - { - case complex_scalar_constant: - case scalar_constant: - retval = do_scalar_index (args); - break; - case complex_matrix_constant: - case matrix_constant: - retval = do_matrix_index (args); - break; - case string_constant: - gripe_string_invalid (); -// retval = do_string_index (args); - 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); - retval = do_index (args); - break; + ::error ("invalid use of colon operator"); + break; + + case unknown_constant: + retval = 0; + break; + default: panic_impossible (); break; @@ -1512,195 +674,52 @@ return retval; } -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 +TC_REP::columns (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); - break; + case matrix_constant: - retval = matrix->rows (); - break; + retval = matrix->columns (); + break; + case complex_matrix_constant: - retval = complex_matrix->rows (); - break; + 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; -} - -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 +TC_REP::all (void) const { if (type_tag == string_constant || type_tag == range_constant) { @@ -1709,6 +728,7 @@ } tree_constant retval; + switch (type_tag) { case scalar_constant: @@ -1717,24 +737,28 @@ 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: @@ -1742,11 +766,12 @@ panic_impossible (); break; } + return retval; } tree_constant -tree_constant_rep::any (void) const +TC_REP::any (void) const { if (type_tag == string_constant || type_tag == range_constant) { @@ -1755,6 +780,7 @@ } tree_constant retval; + switch (type_tag) { case scalar_constant: @@ -1763,24 +789,87 @@ 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; +} + +int +TC_REP::valid_as_scalar_index (void) const +{ + return (type_tag == magic_colon + || (type_tag == scalar_constant && NINT (scalar) == 1) + || (type_tag == range_constant + && range->nelem () == 1 && NINT (range->base ()) == 1)); +} + +int +TC_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: @@ -1788,21 +877,414 @@ panic_impossible (); break; } + + return retval; +} + +static void +warn_implicit_conversion (const char *from, const char *to) +{ + warning ("implicit conversion from %s to %s", from, to); +} + +double +TC_REP::double_value (int force_string_conversion) const +{ + double retval = octave_NaN; + + switch (type_tag) + { + case scalar_constant: + retval = scalar; + break; + + case matrix_constant: + { + if (user_pref.do_fortran_indexing && rows () > 0 && columns () > 0) + retval = matrix->elem (0, 0); + else + gripe_invalid_conversion ("real matrix", "real scalar"); + + retval = octave_NaN; + } + break; + + case complex_matrix_constant: + case complex_scalar_constant: + { + int flag = user_pref.ok_to_lose_imaginary_part; + + if (flag < 0) + warn_implicit_conversion ("complex scalar", "real scalar"); + + if (flag) + { + if (type_tag == complex_scalar_constant) + retval = ::real (*complex_scalar); + else if (type_tag == complex_matrix_constant) + { + if (user_pref.do_fortran_indexing + && rows () > 0 && columns () > 0) + retval = ::real (complex_matrix->elem (0, 0)); + else + gripe_invalid_conversion ("complex matrix", "real scalar"); + } + else + panic_impossible (); + } + else + gripe_invalid_conversion ("complex scalar", "real scalar"); + } + break; + + case string_constant: + { + int flag = force_string_conversion; + if (! flag) + flag = user_pref.implicit_str_to_num_ok; + + if (flag < 0) + warn_implicit_conversion ("string", "real scalar"); + + int len = strlen (string); + if (flag && (len == 1 || (len > 1 && user_pref.do_fortran_indexing))) + retval = toascii ((int) string[0]); + else + gripe_invalid_conversion ("string", "real scalar"); + } + break; + + case range_constant: + { + int nel = range->nelem (); + if (nel == 1 || (nel > 1 && user_pref.do_fortran_indexing)) + retval = range->base (); + else + gripe_invalid_conversion ("range", "real scalar"); + } + break; + + default: + gripe_invalid_conversion (type_as_string (), "real scalar"); + break; + } + + return retval; +} + +Matrix +TC_REP::matrix_value (int force_string_conversion) const +{ + Matrix retval; + + switch (type_tag) + { + case scalar_constant: + retval = Matrix (1, 1, scalar); + break; + + case matrix_constant: + retval = *matrix; + break; + + case complex_scalar_constant: + case complex_matrix_constant: + { + int flag = user_pref.ok_to_lose_imaginary_part; + if (flag < 0) + warn_implicit_conversion ("complex matrix", "real matrix"); + + if (flag) + { + if (type_tag == complex_scalar_constant) + retval = Matrix (1, 1, ::real (*complex_scalar)); + else if (type_tag == complex_matrix_constant) + retval = ::real (*complex_matrix); + else + panic_impossible (); + } + else + gripe_invalid_conversion ("complex matrix", "real matrix"); + } + break; + + case string_constant: + { + int flag = force_string_conversion; + if (! flag) + flag = user_pref.implicit_str_to_num_ok; + + if (flag < 0) + warn_implicit_conversion ("string", "real matrix"); + + if (flag) + { + int len = strlen (string); + + retval.resize (1, len); + + if (len > 1) + { + for (int i = 0; i < len; i++) + retval.elem (0, i) = toascii ((int) string[i]); + } + else if (len == 1) + retval.elem (0, 0) = toascii ((int) string[0]); + else + panic_impossible (); + } + else + gripe_invalid_conversion ("string", "real matrix"); + } + break; + + case range_constant: + retval = range->matrix_value (); + break; + + default: + gripe_invalid_conversion (type_as_string (), "real matrix"); + break; + } + + return retval; +} + +Complex +TC_REP::complex_value (int force_string_conversion) const +{ + Complex retval; + + switch (type_tag) + { + case complex_scalar_constant: + retval = *complex_scalar; + break; + + case scalar_constant: + retval = scalar; + break; + + case complex_matrix_constant: + case matrix_constant: + { + if (user_pref.do_fortran_indexing && rows () > 0 && columns () > 0) + { + if (type_tag == complex_matrix_constant) + retval = complex_matrix->elem (0, 0); + else + retval = matrix->elem (0, 0); + } + else + gripe_invalid_conversion ("real matrix", "real scalar"); + + retval = octave_NaN; + } + break; + + case string_constant: + { + int flag = force_string_conversion; + if (! flag) + flag = user_pref.implicit_str_to_num_ok; + + if (flag < 0) + warn_implicit_conversion ("string", "complex scalar"); + + int len = strlen (string); + if (flag && (len == 1 || (len > 1 && user_pref.do_fortran_indexing))) + retval = toascii ((int) string[0]); + else + gripe_invalid_conversion ("string", "complex scalar"); + } + break; + + case range_constant: + { + int nel = range->nelem (); + if (nel == 1 || (nel > 1 && user_pref.do_fortran_indexing)) + retval = range->base (); + else + gripe_invalid_conversion ("range", "complex scalar"); + } + break; + + default: + gripe_invalid_conversion (type_as_string (), "complex scalar"); + break; + } + + return retval; +} + +ComplexMatrix +TC_REP::complex_matrix_value (int force_string_conversion) const +{ + ComplexMatrix retval; + + switch (type_tag) + { + case scalar_constant: + retval = ComplexMatrix (1, 1, Complex (scalar)); + break; + + case complex_scalar_constant: + retval = ComplexMatrix (1, 1, *complex_scalar); + break; + + case matrix_constant: + retval = ComplexMatrix (*matrix); + break; + + case complex_matrix_constant: + retval = *complex_matrix; + break; + + case string_constant: + { + int flag = force_string_conversion; + if (! flag) + flag = user_pref.implicit_str_to_num_ok; + + if (flag < 0) + warn_implicit_conversion ("string", "complex matrix"); + + if (flag) + { + int len = strlen (string); + + retval.resize (1, len); + + if (len > 1) + { + for (int i = 0; i < len; i++) + retval.elem (0, i) = toascii ((int) string[i]); + } + else if (len == 1) + retval.elem (0, 0) = toascii ((int) string[0]); + else + panic_impossible (); + } + else + gripe_invalid_conversion ("string", "real matrix"); + } + break; + + case range_constant: + retval = range->matrix_value (); + break; + + default: + gripe_invalid_conversion (type_as_string (), "complex matrix"); + break; + } + + return retval; +} + +char * +TC_REP::string_value (void) const +{ + assert (type_tag == string_constant); + return string; +} + +Range +TC_REP::range_value (void) const +{ + assert (type_tag == range_constant); + return *range; +} + +// This could be made more efficient by doing all the work here rather +// than relying on matrix_value() to do any possible type conversions. + +ColumnVector +TC_REP::vector_value (int force_string_conversion, + int force_vector_conversion) const +{ + ColumnVector retval; + + Matrix m = matrix_value (force_string_conversion); + + if (error_state) + return retval; + + 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); + } + else if (nr > 0 && nc > 0 + && (user_pref.do_fortran_indexing || force_vector_conversion)) + { + retval.resize (nr * nc); + int k = 0; + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + retval.elem (k++) = m.elem (i, j); + } + else + gripe_invalid_conversion ("real matrix", "real vector"); + + return retval; +} + +// This could be made more efficient by doing all the work here rather +// than relying on complex_matrix_value() to do any possible type +// conversions. + +ComplexColumnVector +TC_REP::complex_vector_value (int force_string_conversion, + int force_vector_conversion) const +{ + ComplexColumnVector retval; + + ComplexMatrix m = complex_matrix_value (force_string_conversion); + + if (error_state) + return retval; + + 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); + } + else if (nr > 0 && nc > 0 + && (user_pref.do_fortran_indexing || force_vector_conversion)) + { + retval.resize (nr * nc); + int k = 0; + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + retval.elem (k++) = m.elem (i, j); + } + else + gripe_invalid_conversion ("complex matrix", "complex vector"); + 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) +TC_REP::convert_to_str (void) { tree_constant retval; @@ -1820,10 +1302,11 @@ retval = tree_constant (s); } break; + case complex_matrix_constant: case matrix_constant: { - ColumnVector v = to_vector (); + ColumnVector v = vector_value (); int len = v.length (); if (len == 0) ::error ("can only convert vectors and scalars to strings"); @@ -1843,6 +1326,7 @@ } } break; + case range_constant: { Range r = range_value (); @@ -1862,19 +1346,22 @@ delete [] s; } break; + case string_constant: retval = string; break; + case magic_colon: default: panic_impossible (); break; } + return retval; } void -tree_constant_rep::convert_to_row_or_column_vector (void) +TC_REP::convert_to_row_or_column_vector (void) { assert (type_tag == matrix_constant || type_tag == complex_matrix_constant); @@ -1932,619 +1419,1677 @@ } } -int -tree_constant_rep::is_true (void) const +void +TC_REP::force_numeric (int force_str_conv) { - 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: + break; + + case string_constant: { - Matrix m = (complex_matrix->all ()) . all (); - retval = (m.rows () == 1 - && m.columns () == 1 - && m.elem (0, 0) != 0.0); + 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 string_constant: + 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 retval; } tree_constant -tree_constant_rep::cumprod (void) const +TC_REP::make_numeric (int force_str_conv) 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; + retval = tree_constant (*matrix); + 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; + 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; +} + +void +TC_REP::bump_value (tree_expression::type etype) +{ + switch (etype) + { + case tree_expression::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_expression::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 +TC_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 +TC_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 +TC_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 +TC_REP::maybe_resize (int i, force_orient f_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); + } +} + +void +TC_REP::stash_original_text (char *s) +{ + orig_text = strsave (s); +} + +// Indexing functions. + +tree_constant +TC_REP::do_index (const Octave_object& args) +{ + tree_constant retval; + + if (error_state) + return retval; + + if (rows () == 0 || columns () == 0) + { + ::error ("attempt to index empty matrix"); + return retval; + } + + switch (type_tag) + { + case complex_scalar_constant: + case scalar_constant: + retval = do_scalar_index (args); + break; + + case complex_matrix_constant: + case matrix_constant: + retval = do_matrix_index (args); + break; + + case string_constant: + gripe_string_invalid (); +// retval = do_string_index (args); + 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); + retval = do_index (args); + break; + + default: + panic_impossible (); + break; + } + return retval; } tree_constant -tree_constant_rep::cumsum (void) const +TC_REP::do_scalar_index (const Octave_object& args) const { - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.cumsum (); - } - tree_constant retval; - switch (type_tag) - { + + if (valid_scalar_indices (args)) + { + if (type_tag == scalar_constant) + retval = scalar; + else if (type_tag == complex_scalar_constant) + retval = *complex_scalar; + else + panic_impossible (); + + return retval; + } + else + { + int rows = 0; + int cols = 0; + + int nargin = args.length (); + + switch (nargin) + { + 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 retval; + + 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 retval; + + 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) + { + return Matrix (); + } + else + break; + + if (cols == 0) + { + if (user_pref.prefer_column_vectors) + cols = 1; + else + { + cols = rows; + rows = 1; + } + } + + if (type_tag == scalar_constant) + { + return Matrix (rows, cols, scalar); + } + else if (type_tag == complex_scalar_constant) + { + return ComplexMatrix (rows, cols, *complex_scalar); + } + else + panic_impossible (); + } + break; + + default: + ::error ("invalid 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 +TC_REP::do_matrix_index (const Octave_object& args) const +{ + tree_constant retval; + + int nargin = args.length (); + + switch (nargin) + { + case 2: + if (args.length () <= 0) + ::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.length () <= 0) + ::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 +TC_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 +TC_REP::do_matrix_index (const tree_constant& i_arg, + const tree_constant& j_arg) const +{ + tree_constant retval; + + tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); + + TC_REP::constant_type itype = tmp_i.const_type (); + + switch (itype) + { + case complex_scalar_constant: case scalar_constant: - retval = tree_constant (scalar); - break; + { + 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 m = matrix->cumsum (); - retval = tree_constant (m); + Matrix mi = tmp_i.matrix_value (); + idx_vector iv (mi, user_pref.do_fortran_indexing, "row", rows ()); + if (! iv) + return tree_constant (); + + if (iv.length () == 0) + { + Matrix mtmp; + retval = tree_constant (mtmp); + } + else + retval = do_matrix_index (iv, j_arg); } break; - case complex_scalar_constant: - retval = tree_constant (*complex_scalar); - break; - case complex_matrix_constant: + + case string_constant: + gripe_string_invalid (); + break; + + case range_constant: { - ComplexMatrix m = complex_matrix->cumsum (); - retval = tree_constant (m); + 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 string_constant: - case range_constant: + case magic_colon: + retval = do_matrix_index (magic_colon, j_arg); + break; + default: panic_impossible (); break; } + + return retval; +} + +tree_constant +TC_REP::do_matrix_index (TC_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; } tree_constant -tree_constant_rep::prod (void) const +TC_REP::fortran_style_matrix_index (const tree_constant& i_arg) const { - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.prod (); - } - tree_constant retval; - switch (type_tag) - { + + tree_constant tmp_i = i_arg.make_numeric_or_magic (); + + TC_REP::constant_type itype = tmp_i.const_type (); + + int nr = rows (); + int nc = columns (); + + switch (itype) + { + case complex_scalar_constant: case scalar_constant: - retval = tree_constant (scalar); - break; + { + 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); + } + break; + + case complex_matrix_constant: case matrix_constant: { - Matrix m = matrix->prod (); - retval = tree_constant (m); + Matrix mi = tmp_i.matrix_value (); + if (mi.rows () == 0 || mi.columns () == 0) + { + Matrix mtmp; + retval = tree_constant (mtmp); + } + else + { +// Yes, we really do want to call this with mi. + retval = fortran_style_matrix_index (mi); + } } 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: + gripe_string_invalid (); + break; + case range_constant: + gripe_range_invalid (); + break; + case magic_colon: + retval = do_matrix_index (magic_colon); + break; + 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 +TC_REP::fortran_style_matrix_index (const Matrix& mi) 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); + assert (is_matrix_type ()); 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); + 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 = 0; + const Complex *c_cop_out = 0; + 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); + + 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); + } + + ASSIGN_CRMATRIX_TO (retval, m, cm); + } } 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); + 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::diag (void) const +TC_REP::do_vector_index (const tree_constant& i_arg) const { - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.diag (); - } - tree_constant retval; - switch (type_tag) - { + + tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); + + TC_REP::constant_type itype = tmp_i.const_type (); + + int nr = rows (); + int nc = columns (); + + int len = MAX (nr, nc); + + assert ((nr == 1 || nc == 1) && ! user_pref.do_fortran_indexing); + + int swap_indices = (nr == 1); + + switch (itype) + { + case complex_scalar_constant: case scalar_constant: - retval = tree_constant (scalar); - break; + { + 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: { - int nr = rows (); - int nc = columns (); - if (nr == 0 || nc == 0) + 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; + } + + return retval; +} + +tree_constant +TC_REP::do_matrix_index (int i, const tree_constant& j_arg) const +{ + tree_constant retval; + + tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); + + TC_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 (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 (nr == 1 || nc == 1) - retval = make_diag (matrix_value (), 0); else { - ColumnVector v = matrix->diag (); - if (v.capacity () > 0) - retval = tree_constant (v); + 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 +TC_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 (); + + TC_REP::constant_type jtype = tmp_j.const_type (); + + int nr = rows (); + int nc = columns (); + + switch (jtype) + { case complex_scalar_constant: - retval = tree_constant (*complex_scalar); - break; + 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: { - int nr = rows (); - int nc = columns (); - if (nr == 0 || nc == 0) + 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 (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); + 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 string_constant: - case range_constant: + 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; } + + return retval; +} + +tree_constant +TC_REP::do_matrix_index (const Range& ri, + const tree_constant& j_arg) const +{ + tree_constant retval; + + tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); + + TC_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 (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; + } + return retval; } tree_constant -tree_constant_rep::diag (const tree_constant& a) const +TC_REP::do_matrix_index (TC_REP::constant_type mci, + const tree_constant& j_arg) 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; + + tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); + + TC_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 (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 +TC_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 +TC_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 +TC_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 +TC_REP::do_matrix_index (int i, TC_REP::constant_type mcj) const +{ + assert (mcj == magic_colon); 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 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 +TC_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 +TC_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++) { - 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); - } + int col = jv.elem (j); + CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col); } - break; - case complex_matrix_constant: - if (a_type == scalar_constant) + } + + ASSIGN_CRMATRIX_TO (retval, m, cm); + + return retval; +} + +tree_constant +TC_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++) { - 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); - } + double tmp = b + j * increment; + int col = tree_to_mat_idx (tmp); + CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col); } - else - ::error ("diag: invalid second argument"); - - break; - case string_constant: - case range_constant: - case magic_colon: - default: - panic_impossible (); - break; - } + } + + ASSIGN_CRMATRIX_TO (retval, m, cm); + return retval; } tree_constant -tree_constant_rep::mapper (Mapper_fcn& m_fcn, int print) const +TC_REP::do_matrix_index (const idx_vector& iv, + TC_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++) + { + 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 +TC_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 +TC_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 +TC_REP::do_matrix_index (const Range& ri, const Range& rj) const { tree_constant retval; - if (type_tag == string_constant || type_tag == range_constant) - { - tree_constant tmp = make_numeric (); - return tmp.mapper (m_fcn, print); - } + 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); + } + } + + ASSIGN_CRMATRIX_TO (retval, m, cm); + + return retval; +} + +tree_constant +TC_REP::do_matrix_index (const Range& ri, TC_REP::constant_type mcj) const +{ + assert (mcj == magic_colon); + + tree_constant retval; + + int nc = columns (); + + int ilen = ri.nelem (); + + CRMATRIX (m, cm, ilen, nc); + + double ib = ri.base (); + double iinc = ri.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 < nc; j++) + { + CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, j); + } + } + + ASSIGN_CRMATRIX_TO (retval, m, cm); + + return retval; +} + +tree_constant +TC_REP::do_matrix_index (TC_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 +TC_REP::do_matrix_index (TC_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; +} + +tree_constant +TC_REP::do_matrix_index (TC_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; +} + +tree_constant +TC_REP::do_matrix_index (TC_REP::constant_type mci, + TC_REP::constant_type mcj) const +{ + tree_constant retval; + + assert (mci == magic_colon && mcj == magic_colon); switch (type_tag) { + case complex_scalar_constant: + retval = *complex_scalar; + break; + 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) - { - Complex c = m_fcn.c_c_mapper (Complex (scalar)); - retval = tree_constant (c); - } - else - panic_impossible (); - } - else - { - if (m_fcn.d_d_mapper) - { - 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) - { - ComplexMatrix cm = map (m_fcn.c_c_mapper, - ComplexMatrix (*matrix)); - retval = tree_constant (cm); - } - else - panic_impossible (); - } - else - { - if (m_fcn.d_d_mapper) - { - 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) - { - double d; - d = m_fcn.d_c_mapper (*complex_scalar); - retval = tree_constant (d); - } - else if (m_fcn.c_c_mapper) - { - Complex c; - c = m_fcn.c_c_mapper (*complex_scalar); - retval = tree_constant (c); - } - else - panic_impossible (); + retval = scalar; break; case complex_matrix_constant: - if (m_fcn.d_c_mapper) - { - Matrix m; - m = map (m_fcn.d_c_mapper, *complex_matrix); - retval = tree_constant (m); - } - else if (m_fcn.c_c_mapper) - { - ComplexMatrix cm; - cm = map (m_fcn.c_c_mapper, *complex_matrix); - retval = tree_constant (cm); - } - else - panic_impossible (); - break; + + retval = *complex_matrix; + break; + + case matrix_constant: + retval = *matrix; + break; + + case range_constant: + retval = *range; + break; + case string_constant: - case range_constant: + retval = string; + break; + case magic_colon: default: panic_impossible (); break; } + return retval; } @@ -2553,7 +3098,7 @@ // hand off to other functions to do the real work. void -tree_constant_rep::assign (const tree_constant& rhs, const Octave_object& args) +TC_REP::assign (const tree_constant& rhs, const Octave_object& args) { tree_constant rhs_tmp = rhs.make_numeric (); @@ -2572,13 +3117,16 @@ case unknown_constant: do_scalar_assignment (rhs_tmp, args); break; + case complex_matrix_constant: case matrix_constant: do_matrix_assignment (rhs_tmp, args); break; + case string_constant: ::error ("invalid assignment to string type"); break; + case range_constant: case magic_colon: default: @@ -2591,8 +3139,8 @@ // this can convert the left-hand side to a matrix. void -tree_constant_rep::do_scalar_assignment (const tree_constant& rhs, - const Octave_object& args) +TC_REP::do_scalar_assignment (const tree_constant& rhs, + const Octave_object& args) { assert (type_tag == unknown_constant || type_tag == scalar_constant @@ -2651,7 +3199,7 @@ } else if (user_pref.resize_on_range_error) { - tree_constant_rep::constant_type old_type_tag = type_tag; + TC_REP::constant_type old_type_tag = type_tag; if (type_tag == complex_scalar_constant) { @@ -2667,7 +3215,8 @@ } // If there is an error, the call to do_matrix_assignment should not -// destroy the current value. tree_constant_rep::eval(int) will take +// destroy the current value. +// TC_REP::eval(int) will take // care of converting single element matrices back to scalars. do_matrix_assignment (rhs, args); @@ -2697,8 +3246,8 @@ // matrix to an expression with empty indices to do nothing. void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - const Octave_object& args) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + const Octave_object& args) { assert (type_tag == unknown_constant || type_tag == matrix_constant @@ -2739,6 +3288,7 @@ else do_matrix_assignment (rhs, args(1)); break; + case 3: if (args.length () <= 0) ::error ("matrix indices are null"); @@ -2760,6 +3310,7 @@ else do_matrix_assignment (rhs, args(1), args(2)); break; + default: ::error ("too many indices for matrix expression"); break; @@ -2769,8 +3320,8 @@ // Matrix assignments indexed by a single value. void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - const tree_constant& i_arg) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg) { int nr = rows (); int nc = columns (); @@ -2814,12 +3365,12 @@ // multi-dimensional matrices. void -tree_constant_rep::fortran_style_matrix_assignment (const tree_constant& rhs, - const tree_constant& i_arg) +TC_REP::fortran_style_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg) { tree_constant tmp_i = i_arg.make_numeric_or_magic (); - tree_constant_rep::constant_type itype = tmp_i.const_type (); + TC_REP::constant_type itype = tmp_i.const_type (); int nr = rows (); int nc = columns (); @@ -2879,6 +3430,7 @@ do_matrix_assignment (rhs, ii, jj); } break; + case complex_matrix_constant: case matrix_constant: { @@ -2954,12 +3506,15 @@ 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(:,:) = []. if (rhs_nr == 0 && rhs_nc == 0) @@ -2967,6 +3522,7 @@ else fortran_style_matrix_assignment (rhs, magic_colon); break; + default: panic_impossible (); break; @@ -2976,8 +3532,8 @@ // Fortran-style assignment for vector index. void -tree_constant_rep::fortran_style_matrix_assignment (const tree_constant& rhs, - idx_vector& i) +TC_REP::fortran_style_matrix_assignment (const tree_constant& rhs, + idx_vector& i) { assert (rhs.is_matrix_type ()); @@ -3020,10 +3576,10 @@ // Fortran-style assignment for colon index. void -tree_constant_rep::fortran_style_matrix_assignment - (const tree_constant& rhs, tree_constant_rep::constant_type mci) +TC_REP::fortran_style_matrix_assignment (const tree_constant& rhs, + TC_REP::constant_type mci) { - assert (rhs.is_matrix_type () && mci == tree_constant_rep::magic_colon); + assert (rhs.is_matrix_type () && mci == TC_REP::magic_colon); int nr = rows (); int nc = columns (); @@ -3069,8 +3625,8 @@ // assignment to a matrix indexed by two colons. void -tree_constant_rep::vector_assignment (const tree_constant& rhs, - const tree_constant& i_arg) +TC_REP::vector_assignment (const tree_constant& rhs, + const tree_constant& i_arg) { int nr = rows (); int nc = columns (); @@ -3080,7 +3636,7 @@ tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); - tree_constant_rep::constant_type itype = tmp_i.const_type (); + TC_REP::constant_type itype = tmp_i.const_type (); switch (itype) { @@ -3093,6 +3649,7 @@ do_vector_assign (rhs, i); } break; + case complex_matrix_constant: case matrix_constant: { @@ -3105,9 +3662,11 @@ do_vector_assign (rhs, iv); } break; + case string_constant: gripe_string_invalid (); break; + case range_constant: { Range ri = tmp_i.range_value (); @@ -3128,6 +3687,7 @@ } } break; + case magic_colon: { int rhs_nr = rhs.rows (); @@ -3150,8 +3710,7 @@ // 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) +TC_REP::check_vector_assign (int rhs_nr, int rhs_nc, int ilen, const char *rm) { int nr = rows (); int nc = columns (); @@ -3187,7 +3746,7 @@ // Assignment to a vector with an integer index. void -tree_constant_rep::do_vector_assign (const tree_constant& rhs, int i) +TC_REP::do_vector_assign (const tree_constant& rhs, int i) { int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); @@ -3244,8 +3803,7 @@ // Assignment to a vector with a vector index. void -tree_constant_rep::do_vector_assign (const tree_constant& rhs, - idx_vector& iv) +TC_REP::do_vector_assign (const tree_constant& rhs, idx_vector& iv) { if (rhs.is_zero_by_zero ()) { @@ -3349,8 +3907,7 @@ // Assignment to a vector with a range index. void -tree_constant_rep::do_vector_assign (const tree_constant& rhs, - Range& ri) +TC_REP::do_vector_assign (const tree_constant& rhs, Range& ri) { if (rhs.is_zero_by_zero ()) { @@ -3458,13 +4015,13 @@ // assignment. void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - const tree_constant& i_arg, - const tree_constant& j_arg) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg, + const tree_constant& j_arg) { tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); - tree_constant_rep::constant_type itype = tmp_i.const_type (); + TC_REP::constant_type itype = tmp_i.const_type (); switch (itype) { @@ -3477,6 +4034,7 @@ do_matrix_assignment (rhs, i, j_arg); } break; + case complex_matrix_constant: case matrix_constant: { @@ -3488,9 +4046,11 @@ do_matrix_assignment (rhs, iv, j_arg); } break; + case string_constant: gripe_string_invalid (); break; + case range_constant: { Range ri = tmp_i.range_value (); @@ -3511,9 +4071,11 @@ } } break; + case magic_colon: do_matrix_assignment (rhs, magic_colon, j_arg); break; + default: panic_impossible (); break; @@ -3522,12 +4084,12 @@ /* MA1 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, int i, - const tree_constant& j_arg) +TC_REP::do_matrix_assignment (const tree_constant& rhs, int i, + const 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 (); + TC_REP::constant_type jtype = tmp_j.const_type (); int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); @@ -3552,6 +4114,7 @@ do_matrix_assignment (rhs, i, j); } break; + case complex_matrix_constant: case matrix_constant: { @@ -3574,9 +4137,11 @@ do_matrix_assignment (rhs, i, jv); } break; + case string_constant: gripe_string_invalid (); break; + case range_constant: { Range rj = tmp_j.range_value (); @@ -3608,6 +4173,7 @@ } } break; + case magic_colon: { int nc = columns (); @@ -3660,13 +4226,12 @@ /* MA2 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - idx_vector& iv, - const tree_constant& j_arg) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, const 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 (); + TC_REP::constant_type jtype = tmp_j.const_type (); int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); @@ -3692,6 +4257,7 @@ do_matrix_assignment (rhs, iv, j); } break; + case complex_matrix_constant: case matrix_constant: { @@ -3716,9 +4282,11 @@ do_matrix_assignment (rhs, iv, jv); } break; + case string_constant: gripe_string_invalid (); break; + case range_constant: { Range rj = tmp_j.range_value (); @@ -3752,6 +4320,7 @@ } } break; + case magic_colon: { int nc = columns (); @@ -3793,13 +4362,12 @@ /* MA3 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - Range& ri, - const tree_constant& j_arg) +TC_REP::do_matrix_assignment (const tree_constant& rhs, Range& ri, + const 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 (); + TC_REP::constant_type jtype = tmp_j.const_type (); int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); @@ -3825,6 +4393,7 @@ do_matrix_assignment (rhs, ri, j); } break; + case complex_matrix_constant: case matrix_constant: { @@ -3849,9 +4418,11 @@ do_matrix_assignment (rhs, ri, jv); } break; + case string_constant: gripe_string_invalid (); break; + case range_constant: { Range rj = tmp_j.range_value (); @@ -3889,6 +4460,7 @@ } } break; + case magic_colon: { int nc = columns (); @@ -3931,13 +4503,13 @@ /* MA4 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - tree_constant_rep::constant_type i, - const tree_constant& j_arg) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + TC_REP::constant_type i, + const 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 (); + TC_REP::constant_type jtype = tmp_j.const_type (); int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); @@ -3992,6 +4564,7 @@ do_matrix_assignment (rhs, magic_colon, j); } break; + case complex_matrix_constant: case matrix_constant: { @@ -4032,9 +4605,11 @@ do_matrix_assignment (rhs, magic_colon, jv); } break; + case string_constant: gripe_string_invalid (); break; + case range_constant: { Range rj = tmp_j.range_value (); @@ -4084,10 +4659,12 @@ 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); break; + default: panic_impossible (); break; @@ -4112,8 +4689,7 @@ /* 1 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - int i, int j) +TC_REP::do_matrix_assignment (const tree_constant& rhs, int i, int j) { REP_ELEM_ASSIGN (i, j, rhs.double_value (), rhs.complex_value (), rhs.is_real_type ()); @@ -4121,8 +4697,7 @@ /* 2 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, int i, - idx_vector& jv) +TC_REP::do_matrix_assignment (const tree_constant& rhs, int i, idx_vector& jv) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4133,8 +4708,7 @@ /* 3 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - int i, Range& rj) +TC_REP::do_matrix_assignment (const tree_constant& rhs, int i, Range& rj) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4152,8 +4726,8 @@ /* 4 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, int i, - tree_constant_rep::constant_type mcj) +TC_REP::do_matrix_assignment (const tree_constant& rhs, int i, + TC_REP::constant_type mcj) { assert (mcj == magic_colon); @@ -4182,8 +4756,8 @@ /* 5 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - idx_vector& iv, int j) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, int j) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4197,9 +4771,8 @@ /* 6 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - idx_vector& iv, - idx_vector& jv) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, idx_vector& jv) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4217,9 +4790,8 @@ /* 7 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - idx_vector& iv, - Range& rj) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, Range& rj) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4241,9 +4813,8 @@ /* 8 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - idx_vector& iv, - tree_constant_rep::constant_type mcj) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, TC_REP::constant_type mcj) { assert (mcj == magic_colon); @@ -4271,8 +4842,7 @@ /* 9 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - Range& ri, int j) +TC_REP::do_matrix_assignment (const tree_constant& rhs, Range& ri, int j) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4290,9 +4860,8 @@ /* 10 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - Range& ri, - idx_vector& jv) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + Range& ri, idx_vector& jv) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4314,9 +4883,8 @@ /* 11 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - Range& ri, - Range& rj) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + Range& ri, Range& rj) { double ib = ri.base (); double iinc = ri.inc (); @@ -4341,9 +4909,8 @@ /* 12 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - Range& ri, - tree_constant_rep::constant_type mcj) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + Range& ri, TC_REP::constant_type mcj) { assert (mcj == magic_colon); @@ -4373,9 +4940,8 @@ /* 13 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - tree_constant_rep::constant_type mci, - int j) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + TC_REP::constant_type mci, int j) { assert (mci == magic_colon); @@ -4404,9 +4970,8 @@ /* 14 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - tree_constant_rep::constant_type mci, - idx_vector& jv) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + TC_REP::constant_type mci, idx_vector& jv) { assert (mci == magic_colon); @@ -4434,9 +4999,8 @@ /* 15 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - tree_constant_rep::constant_type mci, - Range& rj) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + TC_REP::constant_type mci, Range& rj) { assert (mci == magic_colon); @@ -4468,9 +5032,9 @@ /* 16 */ void -tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, - tree_constant_rep::constant_type mci, - tree_constant_rep::constant_type mcj) +TC_REP::do_matrix_assignment (const tree_constant& rhs, + TC_REP::constant_type mci, + TC_REP::constant_type mcj) { assert (mci == magic_colon && mcj == magic_colon); @@ -4478,21 +5042,27 @@ { 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 (); @@ -4506,21 +5076,27 @@ 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 (); @@ -4534,7 +5110,7 @@ // M (i, j) = [] void -tree_constant_rep::delete_row (int idx) +TC_REP::delete_row (int idx) { if (type_tag == matrix_constant) { @@ -4577,7 +5153,7 @@ } void -tree_constant_rep::delete_rows (idx_vector& iv) +TC_REP::delete_rows (idx_vector& iv) { iv.sort_uniq (); int num_to_delete = iv.length (); @@ -4638,7 +5214,7 @@ } void -tree_constant_rep::delete_rows (Range& ri) +TC_REP::delete_rows (Range& ri) { ri.sort (); int num_to_delete = ri.nelem (); @@ -4710,7 +5286,7 @@ } void -tree_constant_rep::delete_column (int idx) +TC_REP::delete_column (int idx) { if (type_tag == matrix_constant) { @@ -4753,7 +5329,7 @@ } void -tree_constant_rep::delete_columns (idx_vector& jv) +TC_REP::delete_columns (idx_vector& jv) { jv.sort_uniq (); int num_to_delete = jv.length (); @@ -4814,7 +5390,7 @@ } void -tree_constant_rep::delete_columns (Range& rj) +TC_REP::delete_columns (Range& rj) { rj.sort (); int num_to_delete = rj.nelem (); @@ -4885,1260 +5461,537 @@ panic_impossible (); } -// Indexing functions. - -int -tree_constant_rep::valid_as_scalar_index (void) const -{ - return (type_tag == magic_colon - || (type_tag == scalar_constant && NINT (scalar) == 1) - || (type_tag == range_constant - && range->nelem () == 1 && NINT (range->base ()) == 1)); -} - -tree_constant -tree_constant_rep::do_scalar_index (const Octave_object& args) const -{ - tree_constant retval; - - if (valid_scalar_indices (args)) - { - if (type_tag == scalar_constant) - retval = scalar; - else if (type_tag == complex_scalar_constant) - retval = *complex_scalar; - else - panic_impossible (); - - return retval; - } - else - { - int rows = 0; - int cols = 0; - - int nargin = args.length (); - - switch (nargin) - { - 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 retval; - - 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 retval; - - 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) - { - return Matrix (); - } - else - break; - - if (cols == 0) - { - if (user_pref.prefer_column_vectors) - cols = 1; - else - { - cols = rows; - rows = 1; - } - } - - if (type_tag == scalar_constant) - { - return Matrix (rows, cols, scalar); - } - else if (type_tag == complex_scalar_constant) - { - return ComplexMatrix (rows, cols, *complex_scalar); - } - else - panic_impossible (); - } - break; - default: - ::error ("invalid 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 Octave_object& args) const -{ - tree_constant retval; - - int nargin = args.length (); - - switch (nargin) - { - case 2: - if (args.length () <= 0) - ::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.length () <= 0) - ::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 -{ - tree_constant retval; - - 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 (); - - switch (itype) - { - case complex_scalar_constant: - case 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); - } - 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 - { -// Yes, we really do want to call this with mi. - retval = fortran_style_matrix_index (mi); - } - } - break; - case string_constant: - gripe_string_invalid (); - break; - case range_constant: - gripe_range_invalid (); - break; - case magic_colon: - retval = do_matrix_index (magic_colon); - break; - default: - panic_impossible (); - break; - } - - return retval; -} - -tree_constant -tree_constant_rep::fortran_style_matrix_index (const Matrix& mi) const -{ - 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 = 0; - const Complex *c_cop_out = 0; - 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); - - 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); - } - - 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 = MAX (nr, nc); - - 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; - } - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const tree_constant& i_arg, - const tree_constant& j_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 (); - - 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 (); - - 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; - } - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (int i, 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 (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 +void +TC_REP::maybe_mutate (void) { - 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; - } - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (const Range& ri, - 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 (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; - } - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci, - 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 (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++) - { - 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 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++) - { - 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); - } - } - - ASSIGN_CRMATRIX_TO (retval, m, cm); - - return retval; -} - -tree_constant -tree_constant_rep::do_matrix_index - (const Range& ri, tree_constant_rep::constant_type mcj) const -{ - assert (mcj == magic_colon); - - tree_constant retval; - - int nc = columns (); - - int ilen = ri.nelem (); - - CRMATRIX (m, cm, ilen, nc); - - double ib = ri.base (); - double iinc = ri.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 < nc; j++) - { - 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 (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; -} - -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; -} - -tree_constant -tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci, - tree_constant_rep::constant_type mcj) const -{ - tree_constant retval; - - assert (mci == magic_colon && mcj == magic_colon); + if (error_state) + return; switch (type_tag) { case complex_scalar_constant: - retval = *complex_scalar; - break; + 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: - retval = scalar; - break; + 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: - retval = *complex_matrix; - break; + 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; + } +} + +void +TC_REP::print (void) +{ + if (error_state) + return; + + if (print) + { + ostrstream output_buf; + + switch (type_tag) + { + case scalar_constant: + octave_print_internal (output_buf, scalar); + break; + + case matrix_constant: + octave_print_internal (output_buf, *matrix); + break; + + case complex_scalar_constant: + octave_print_internal (output_buf, *complex_scalar); + break; + + case complex_matrix_constant: + 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); + } +} + +static char * +undo_string_escapes (char c) +{ + static char retval[2]; + retval[1] = '\0'; + + if (! c) + return 0; + + switch (c) + { + case '\a': + return "\\a"; + + case '\b': // backspace + return "\\b"; + + case '\f': // formfeed + return "\\f"; + + case '\n': // newline + return "\\n"; + + case '\r': // carriage return + return "\\r"; + + case '\t': // horizontal tab + return "\\t"; + + case '\v': // vertical tab + return "\\v"; + + case '\\': // backslash + return "\\\\"; + + case '"': // double quote + return "\\\""; + + default: + retval[0] = c; + return retval; + } +} + +void +TC_REP::print_code (ostream& os) +{ + switch (type_tag) + { + case scalar_constant: + if (orig_text) + os << orig_text; + else + octave_print_internal (os, scalar, 1); + break; + + case matrix_constant: + octave_print_internal (os, *matrix, 1); + break; + + case complex_scalar_constant: + { + double re = complex_scalar->real (); + double im = complex_scalar->imag (); + +// If we have the original text and a pure imaginary, just print the +// original text, because this must be a constant that was parsed as +// part of a function. + + if (orig_text && re == 0.0 && im > 0.0) + os << orig_text; + else + octave_print_internal (os, *complex_scalar, 1); + } + break; + + case complex_matrix_constant: + octave_print_internal (os, *complex_matrix, 1); + break; + + case string_constant: + { + os << "\""; + char *s, *t = string; + while (s = undo_string_escapes (*t++)) + os << s; + os << "\""; + } + break; + + case range_constant: + octave_print_internal (os, *range, 1); + break; + + case magic_colon: + os << ":"; + break; + + default: + panic_impossible (); + break; + } +} + +char * +TC_REP::type_as_string (void) const +{ + switch (type_tag) + { + case scalar_constant: + return "real scalar"; + case matrix_constant: - retval = *matrix; - break; + return "real matrix"; + + case complex_scalar_constant: + return "complex scalar"; + + case complex_matrix_constant: + return "complex matrix"; + + case string_constant: + return "string"; + case range_constant: - retval = *range; - break; + return "range"; + + default: + return ""; + } +} + +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 (); + + TC_REP::constant_type a_type = tmp_a.const_type (); + TC_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 TC_REP::scalar_constant: + + d1 = tmp_a.double_value (); + + switch (b_type) + { + case TC_REP::scalar_constant: + d2 = tmp_b.double_value (); + ans = do_binary_op (d1, d2, t); + break; + + case TC_REP::matrix_constant: + m2 = tmp_b.matrix_value (); + ans = do_binary_op (d1, m2, t); + break; + + case TC_REP::complex_scalar_constant: + c2 = tmp_b.complex_value (); + ans = do_binary_op (d1, c2, t); + break; + + case TC_REP::complex_matrix_constant: + cm2 = tmp_b.complex_matrix_value (); + ans = do_binary_op (d1, cm2, t); + break; + + case TC_REP::magic_colon: + default: + panic_impossible (); + break; + } + break; + + case TC_REP::matrix_constant: + + m1 = tmp_a.matrix_value (); + + switch (b_type) + { + case TC_REP::scalar_constant: + d2 = tmp_b.double_value (); + ans = do_binary_op (m1, d2, t); + break; + + case TC_REP::matrix_constant: + m2 = tmp_b.matrix_value (); + ans = do_binary_op (m1, m2, t); + break; + + case TC_REP::complex_scalar_constant: + c2 = tmp_b.complex_value (); + ans = do_binary_op (m1, c2, t); + break; + + case TC_REP::complex_matrix_constant: + cm2 = tmp_b.complex_matrix_value (); + ans = do_binary_op (m1, cm2, t); + break; + + case TC_REP::magic_colon: + default: + panic_impossible (); + break; + } + break; + + case TC_REP::complex_scalar_constant: + + c1 = tmp_a.complex_value (); + + switch (b_type) + { + case TC_REP::scalar_constant: + d2 = tmp_b.double_value (); + ans = do_binary_op (c1, d2, t); + break; + + case TC_REP::matrix_constant: + m2 = tmp_b.matrix_value (); + ans = do_binary_op (c1, m2, t); + break; + + case TC_REP::complex_scalar_constant: + c2 = tmp_b.complex_value (); + ans = do_binary_op (c1, c2, t); + break; + + case TC_REP::complex_matrix_constant: + cm2 = tmp_b.complex_matrix_value (); + ans = do_binary_op (c1, cm2, t); + break; + + case TC_REP::magic_colon: + default: + panic_impossible (); + break; + } + break; + + case TC_REP::complex_matrix_constant: + + cm1 = tmp_a.complex_matrix_value (); + + switch (b_type) + { + case TC_REP::scalar_constant: + d2 = tmp_b.double_value (); + ans = do_binary_op (cm1, d2, t); + break; + + case TC_REP::matrix_constant: + m2 = tmp_b.matrix_value (); + ans = do_binary_op (cm1, m2, t); + break; + + case TC_REP::complex_scalar_constant: + c2 = tmp_b.complex_value (); + ans = do_binary_op (cm1, c2, t); + break; + + case TC_REP::complex_matrix_constant: + cm2 = tmp_b.complex_matrix_value (); + ans = do_binary_op (cm1, cm2, t); + break; + + case TC_REP::magic_colon: + default: + panic_impossible (); + break; + } + break; + + case TC_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 TC_REP::scalar_constant: + ans = do_unary_op (tmp_a.double_value (), t); + break; + + case TC_REP::matrix_constant: + { + Matrix m = tmp_a.matrix_value (); + ans = do_unary_op (m, t); + } + break; + + case TC_REP::complex_scalar_constant: + ans = do_unary_op (tmp_a.complex_value (), t); + break; + + case TC_REP::complex_matrix_constant: + { + ComplexMatrix m = tmp_a.complex_matrix_value (); + ans = do_unary_op (m, t); + } + break; + + case TC_REP::magic_colon: + default: + panic_impossible (); + break; + } + + return ans; +} + +tree_constant +TC_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: - retval = string; - break; + case range_constant: case magic_colon: default: panic_impossible (); @@ -6149,27 +6002,577 @@ } tree_constant -tree_constant_rep::do_matrix_index - (tree_constant_rep::constant_type mci) const +TC_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 +TC_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 +TC_REP::sum (void) const { - assert (mci == magic_colon); + 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 +TC_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 +TC_REP::diag (void) const +{ + if (type_tag == string_constant || type_tag == range_constant) + { + tree_constant tmp = make_numeric (); + return tmp.diag (); + } 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++) + + 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 { - CRMATRIX_ASSIGN_REP_ELEM (m, cm, idx, 0, i, j); - idx++; + ComplexColumnVector v = complex_matrix->diag (); + if (v.capacity () > 0) + retval = tree_constant (v); } - ASSIGN_CRMATRIX_TO (retval, m, cm); - } + } + break; + + case string_constant: + case range_constant: + case magic_colon: + default: + panic_impossible (); + break; + } + + return retval; +} + +tree_constant +TC_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 (); + + TC_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; +} + +// XXX FIXME XXX -- this can probably be rewritten efficiently as a +// nonmember function... + +tree_constant +TC_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) + { + Complex c = m_fcn.c_c_mapper (Complex (scalar)); + retval = tree_constant (c); + } + else + ::error ("%s: unable to handle real arguments", m_fcn.name); + } + else + { + if (m_fcn.d_d_mapper) + { + double d = m_fcn.d_d_mapper (scalar); + retval = tree_constant (d); + } + else + ::error ("%s: unable to handle real arguments", m_fcn.name); + } + 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) + { + ComplexMatrix cm = map (m_fcn.c_c_mapper, + ComplexMatrix (*matrix)); + retval = tree_constant (cm); + } + else + ::error ("%s: unable to handle real arguments", m_fcn.name); + } + else + { + if (m_fcn.d_d_mapper) + { + Matrix m = map (m_fcn.d_d_mapper, *matrix); + retval = tree_constant (m); + } + else + ::error ("%s: unable to handle real arguments", m_fcn.name); + } + break; + + case complex_scalar_constant: + if (m_fcn.d_c_mapper) + { + double d; + d = m_fcn.d_c_mapper (*complex_scalar); + retval = tree_constant (d); + } + else if (m_fcn.c_c_mapper) + { + Complex c; + c = m_fcn.c_c_mapper (*complex_scalar); + retval = tree_constant (c); + } + else + ::error ("%s: unable to handle complex arguments", m_fcn.name); + break; + + case complex_matrix_constant: + if (m_fcn.d_c_mapper) + { + Matrix m; + m = map (m_fcn.d_c_mapper, *complex_matrix); + retval = tree_constant (m); + } + else if (m_fcn.c_c_mapper) + { + ComplexMatrix cm; + cm = map (m_fcn.c_c_mapper, *complex_matrix); + retval = tree_constant (cm); + } + else + ::error ("%s: unable to handle complex arguments", m_fcn.name); + break; + + case string_constant: + case range_constant: + case magic_colon: + default: + panic_impossible (); + break; + } + return retval; }