Mercurial > hg > octave-nkf
diff src/pt-mat.cc @ 1827:effa9400766f
[project @ 1996-02-02 14:07:51 by jwe]
author | jwe |
---|---|
date | Fri, 02 Feb 1996 14:10:10 +0000 |
parents | a02f140ed897 |
children | 003570e69c7b |
line wrap: on
line diff
--- a/src/pt-mat.cc +++ b/src/pt-mat.cc @@ -1,7 +1,7 @@ // pt-mat.cc -*- C++ -*- /* -Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton +Copyright (C) 1996 John W. Eaton This file is part of Octave. @@ -46,96 +46,339 @@ // constant matrices, but it allows us to construct matrices from // other matrices, variables, and functions. -tree_matrix::~tree_matrix (void) -{ - delete element; - delete next; -} +// But first, some internal classes that make our job much easier. -int -tree_matrix::is_matrix_constant (void) const +class +tm_row_const { - const tree_matrix *list = this; +private: + + class + tm_row_const_rep : public SLList<tree_constant> + { + public: + + tm_row_const_rep (void) + : SLList<tree_constant> (), count (1), nr (0), nc (0), + all_str (false), is_cmplx (false), ok (false) { } + + tm_row_const_rep (const tree_matrix_row& mr) + : SLList<tree_constant> (), count (1), nr (0), nc (0), + all_str (false), is_cmplx (false), ok (false) + { init (mr); } + + ~tm_row_const_rep (void) { } + + int count; + + int nr; + int nc; - while (list) + bool all_str; + bool is_cmplx; + + bool ok; + + void init (const tree_matrix_row&); + + private: + + tm_row_const_rep (const tm_row_const_rep&); + + tm_row_const_rep& operator = + (const tm_row_const_rep&); + }; + +public: + + tm_row_const (void) : rep (0) { } + + tm_row_const (const tree_matrix_row& mr) + : rep (new tm_row_const_rep (mr)) { } + + tm_row_const (const tm_row_const& x) : rep (x.rep) { - tree_expression *elem = list->element; + if (rep) + rep->count++; + } + + tm_row_const& operator = (const tm_row_const& x) + { + if (this != &x && rep != x.rep) + { + if (rep && --rep->count == 0) + delete rep; - if (! elem->is_constant ()) - return 0; + rep = x.rep; + + if (rep) + rep->count++; + } - list = list->next; + return *this; + } + + ~tm_row_const (void) + { + if (rep && --rep->count == 0) + delete rep; } - return 1; + int rows (void) { return rep->nr; } + int cols (void) { return rep->nc; } + + bool all_strings (void) const { return rep->all_str; } + bool is_complex (void) const { return rep->is_cmplx; } + + tree_constant& operator () (Pix p) { return rep->operator () (p); } + + const tree_constant& operator () (Pix p) const + { return rep->operator () (p); } + + Pix first (void) const { return rep->first (); } + void next (Pix& p) const { rep->next (p); } + + operator void* () const + { + return (rep && rep->ok) ? (void *) -1 : (void *) 0; + } + +private: + + tm_row_const_rep *rep; +}; + +void +tm_row_const::tm_row_const_rep::init (const tree_matrix_row& mr) +{ + all_str = true; + + int empties_ok = user_pref.empty_list_elements_ok; + + bool first_elem = true; + + for (Pix p = mr.first (); p != 0; mr.next (p)) + { + tree_expression *elt = mr (p); + + tree_constant tmp = elt->eval (false); + + if (error_state || tmp.is_undefined ()) + break; + else + { + int this_elt_nr = tmp.rows (); + int this_elt_nc = tmp.columns (); + + if (this_elt_nr == 0 || this_elt_nc == 0) + { + if (empties_ok < 0) + warning ("empty matrix found in matrix list"); + else if (empties_ok == 0) + { + ::error ("empty matrix found in matrix list"); + break; + } + } + else + { + if (first_elem) + { + first_elem = false; + + nr = this_elt_nr; + } + else if (this_elt_nr != nr) + { + ::error ("number of rows must match"); + break; + } + + nc += this_elt_nc; + + append (tmp); + } + + if (all_str && ! tmp.is_string ()) + all_str = false; + + if (! is_cmplx && tmp.is_complex_type ()) + is_cmplx = true; + } + } + + ok = ! error_state; } -tree_matrix * -tree_matrix::chain (tree_expression *t, tree_matrix::dir d) +template class SLNode<tm_row_const>; +template class SLList<tm_row_const>; + +class +tm_const : public SLList<tm_row_const> +{ +public: + + tm_const (const tree_matrix& tm) + : SLList<tm_row_const> (), nr (0), nc (0), all_str (false), + is_cmplx (false), ok (false) + { init (tm); } + + ~tm_const (void) { } + + int rows (void) const { return nr; } + int cols (void) const { return nc; } + + bool all_strings (void) const { return all_str; } + bool is_complex (void) const { return is_cmplx; } + + operator void* () const { return ok ? (void *) -1 : (void *) 0; } + +private: + + int nr; + int nc; + + bool all_str; + bool is_cmplx; + + bool ok; + + tm_const (void); + + tm_const (const tm_const&); + + tm_const& operator = (const tm_const&); + + void init (const tree_matrix& tm); +}; + +void +tm_const::init (const tree_matrix& tm) { - tree_matrix *tmp = new tree_matrix (t, d); - tmp->next = this; - return tmp; + all_str = true; + + int empties_ok = user_pref.empty_list_elements_ok; + + bool first_elem = true; + + // Just eval and figure out if what we have is complex or all + // strings. We can't check columns until we know that this is a + // numeric matrix -- collections of strings can have elements of + // different lengths. + + for (Pix p = tm.first (); p != 0; tm.next (p)) + { + tree_matrix_row *elt = tm (p); + + tm_row_const tmp (*elt); + + if (tmp) + { + if (all_str && ! tmp.all_strings ()) + all_str = false; + + if (! is_cmplx && tmp.is_complex ()) + is_cmplx = true; + + append (tmp); + } + else + break; + } + + if (! error_state) + { + for (Pix p = first (); p != 0; next (p)) + { + tm_row_const elt = this->operator () (p); + + int this_elt_nr = elt.rows (); + int this_elt_nc = elt.cols (); + + if (this_elt_nr == 0 || this_elt_nc == 0) + { + if (empties_ok < 0) + warning ("empty matrix found in matrix list"); + else if (empties_ok == 0) + { + ::error ("empty matrix found in matrix list"); + break; + } + } + else + { + if (first_elem) + { + first_elem = false; + + nc = this_elt_nc; + } + else if (all_str) + { + if (this_elt_nc > nc) + nc = this_elt_nc; + } + else if (this_elt_nc != nc) + { + ::error ("number of columns must match"); + break; + } + + nr += this_elt_nr; + } + } + } + + ok = ! error_state; } -tree_matrix * -tree_matrix::reverse (void) +bool +tree_matrix_row::is_matrix_constant (void) const { - tree_matrix *list = this; - tree_matrix *next; - tree_matrix *prev = 0; + for (Pix p = first (); p != 0; next (p)) + { + tree_expression *elt = this->operator () (p); - while (list) - { - next = list->next; - list->next = prev; - prev = list; - list = next; + if (! elt->is_constant ()) + return false; } - return prev; -} -int -tree_matrix::length (void) -{ - tree_matrix *list = this; - int len = 0; - while (list) - { - len++; - list = list->next; - } - return len; + return true; } tree_return_list * -tree_matrix::to_return_list (void) +tree_matrix_row::to_return_list (void) { tree_return_list *retval = 0; - tree_matrix *list; + bool first_elem = true; - for (list = this; list; list = list->next) + for (Pix p = first (); p != 0; next (p)) { - tree_expression *elem = list->element; + tree_expression *elt = this->operator () (p); - int is_id = elem->is_identifier (); + bool is_id = elt->is_identifier (); - int is_idx_expr = elem->is_index_expression (); + bool is_idx_expr = elt->is_index_expression (); if (is_id || is_idx_expr) { tree_index_expression *idx_expr; + if (is_id) { - tree_identifier *id = (tree_identifier *) elem; + tree_identifier *id = (tree_identifier *) elt; idx_expr = new tree_index_expression (id); } else - idx_expr = (tree_index_expression *) elem; + idx_expr = (tree_index_expression *) elt; - if (list == this) - retval = new tree_return_list (idx_expr); + if (first_elem) + { + first_elem = false; + + retval = new tree_return_list (idx_expr); + } else retval->append (idx_expr); } @@ -150,320 +393,143 @@ return retval; } -// Just about as ugly as it gets. - -struct const_matrix_list +void +tree_matrix_row::print_code (ostream& os) { - tree_matrix::dir direction; - tree_constant elem; - int nr; - int nc; -}; + Pix p = first (); + + while (p) + { + tree_expression *elt = this->operator () (p); + + next (p); + + if (elt) + { + elt->print_code (os); + + if (p) + os << ", "; + } + } +} +bool +tree_matrix::is_matrix_constant (void) const +{ + for (Pix p = first (); p != 0; next (p)) + { + tree_matrix_row *elt = this->operator () (p); + + if (! elt->is_matrix_constant ()) + return false; + } + + return true; +} + +// Just about as ugly as it gets. // Less ugly than before, anyway. +// Looking better all the time. tree_constant -tree_matrix::eval (int /* print */) +tree_matrix::eval (bool /* print */) { tree_constant retval; - if (error_state) - return retval; + tm_const tmp (*this); - // Just count the elements without looking at them. - - int total_len = length (); + if (tmp) + { + int nr = tmp.rows (); + int nc = tmp.cols (); - // Easier to deal with this later instead of a tree_matrix - // structure. - - const_matrix_list *list = new const_matrix_list [total_len]; + Matrix m; + ComplexMatrix cm; + charMatrix chm; - // Stats we want to keep track of. + // Now, extract the values from the individual elements and + // insert them in the result matrix. - int all_strings = 1; - - int found_complex = 0; + bool all_strings = tmp.all_strings (); + bool found_complex = tmp.is_complex (); - int row_total = 0; - int col_total = 0; + if (all_strings) + chm.resize (nr, nc, 0); + else if (found_complex) + cm.resize (nr, nc, 0.0); + else + m.resize (nr, nc, 0.0); - int row_height = 0; - - int cols_this_row = 0; - - int first_row = 1; + int put_row = 0; - int empties_ok = user_pref.empty_list_elements_ok; - - tree_matrix *ptr = this; + for (Pix p = tmp.first (); p != 0; tmp.next (p)) + { + int put_col = 0; - // Stuff for the result matrix or string. Declared here so that we - // don't get warnings from gcc about the goto crossing the - // initialization of these values. + tm_row_const row = tmp (p); - int put_row = 0; - int put_col = 0; + for (Pix q = row.first (); q != 0; row.next (q)) + { + tree_constant elt = row (q); - int prev_nr = 0; - int prev_nc = 0; - - Matrix m; - ComplexMatrix cm; - charMatrix chm; - - // Eliminate empties and gather stats. + if (found_complex) + { + if (elt.is_real_scalar ()) + cm (put_row, put_col) = elt.double_value (); + else if (elt.is_real_matrix () || elt.is_range ()) + cm.insert (elt.matrix_value (), put_row, put_col); + else if (elt.is_complex_scalar ()) + cm (put_row, put_col) = elt.complex_value (); + else + { + ComplexMatrix cm_elt = elt.complex_matrix_value (); - int found_new_row_in_empties = 0; - - int len = 0; - for (int i = 0; i < total_len; i++) - { - tree_expression *elem = ptr->element; - if (! elem) - { - retval = tree_constant (Matrix ()); - goto done; - } + if (error_state) + goto done; - tree_constant tmp = elem->eval (0); - if (error_state || tmp.is_undefined ()) - { - retval = tree_constant (); - goto done; - } + cm.insert (cm_elt, put_row, put_col); + } + } + else + { + if (elt.is_real_scalar ()) + m (put_row, put_col) = elt.double_value (); + else if (elt.is_string () && all_strings) + { + charMatrix chm_elt = elt.all_strings (); - int nr = tmp.rows (); - int nc = tmp.columns (); + if (error_state) + goto done; - dir direct = ptr->direction; + chm.insert (chm_elt, put_row, put_col); + } + else + { + Matrix m_elt = elt.matrix_value (); + + if (error_state) + goto done; - if (nr == 0 || nc == 0) - { - if (empties_ok < 0) - warning ("empty matrix found in matrix list"); - else if (empties_ok == 0) - { - ::error ("empty matrix found in matrix list"); - retval = tree_constant (); - goto done; + m.insert (m_elt, put_row, put_col); + } + } + + if (all_strings && chm.rows () > 0 && chm.cols () > 0) + retval = tree_constant (chm, true); + else if (found_complex) + retval = cm; + else + retval = m; + + put_col += elt.columns (); } - if (direct == md_down) - found_new_row_in_empties = 1; - - goto next; - } - - if (found_new_row_in_empties) - { - found_new_row_in_empties = 0; - list[len].direction = md_down; - } - else - list[len].direction = direct; - - list[len].elem = tmp; - list[len].nr = nr; - list[len].nc = nc; - - if (all_strings && ! tmp.is_string ()) - all_strings = 0; - - if (! found_complex && tmp.is_complex_type ()) - found_complex = 1; - - len++; - - next: - - ptr = ptr->next; - } - - // if (all_strings) - // cerr << "all strings\n"; - - // Compute size of result matrix, and check to see that the dimensions - // of all the elements will match up properly. - - for (int i = 0; i < len; i++) - { - dir direct = list[i].direction; - - int nr = list[i].nr; - int nc = list[i].nc; - - if (i == 0) - { - row_total = nr; - col_total = nc; - - row_height = nr; - cols_this_row = nc; - } - else - { - switch (direct) - { - case md_right: - { - if (nr != row_height) - { - ::error ("number of rows must match"); - goto done; - } - else - { - cols_this_row += nc; - - if (first_row) - col_total = cols_this_row; - else if (all_strings && cols_this_row > col_total) - col_total = cols_this_row; - } - } - break; - - case md_down: - { - if (cols_this_row != col_total && ! all_strings) - { - ::error ("number of columns must match"); - goto done; - } - first_row = 0; - row_total += nr; - row_height = nr; - cols_this_row = nc; - } - break; - - default: - panic_impossible (); - break; - } + put_row += row.rows (); } } - // Don't forget to check to see if the last element will fit. - - if (all_strings && cols_this_row > col_total) - { - col_total = cols_this_row; - } - else if (cols_this_row != col_total) - { - ::error ("number of columns must match"); - goto done; - } - - // Now, extract the values from the individual elements and insert - // them in the result matrix. - - if (all_strings) - chm.resize (row_total, col_total, 0); - else if (found_complex) - cm.resize (row_total, col_total, 0.0); - else - m.resize (row_total, col_total, 0.0); - - for (int i = 0; i < len; i++) - { - tree_constant tmp = list[i].elem; - - int nr = list[i].nr; - int nc = list[i].nc; - - if (nr == 0 || nc == 0) - continue; - - if (i == 0) - { - put_row = 0; - put_col = 0; - } - else - { - switch (list[i].direction) - { - case md_right: - put_col += prev_nc; - break; - - case md_down: - put_row += prev_nr; - put_col = 0; - break; - - default: - panic_impossible (); - break; - } - } - - if (found_complex) - { - if (tmp.is_real_scalar ()) - { - cm (put_row, put_col) = tmp.double_value (); - } - else if (tmp.is_real_matrix () || tmp.is_range ()) - { - cm.insert (tmp.matrix_value (), put_row, put_col); - } - else if (tmp.is_complex_scalar ()) - { - cm (put_row, put_col) = tmp.complex_value (); - } - else - { - ComplexMatrix cm_tmp = tmp.complex_matrix_value (); - - if (error_state) - goto done; - - cm.insert (cm_tmp, put_row, put_col); - } - } - else - { - if (tmp.is_real_scalar ()) - { - m (put_row, put_col) = tmp.double_value (); - } - else if (tmp.is_string () && all_strings) - { - charMatrix chm_tmp = tmp.all_strings (); - - if (error_state) - goto done; - - chm.insert (chm_tmp, put_row, put_col); - } - else - { - Matrix m_tmp = tmp.matrix_value (); - - if (error_state) - goto done; - - m.insert (m_tmp, put_row, put_col); - } - } - - prev_nr = nr; - prev_nc = nc; - } - - if (all_strings && chm.rows () > 0 && chm.cols () > 0) - retval = tree_constant (chm, 1); - else if (found_complex) - retval = cm; - else - retval = m; - - done: - delete [] list; +done: return retval; } @@ -478,29 +544,20 @@ os << "["; - tree_matrix *list = this; + Pix p = first (); - while (list) + while (p) { - list->element->print_code (os); + tree_matrix_row *elt = this->operator () (p); - list = list->next; + next (p); - if (list) + if (elt) { - switch (list->direction) - { - case md_right: - os << ", "; - break; + elt->print_code (os); - case md_down: - os << "; "; - break; - - default: - break; - } + if (p) + os << "; "; } }