# HG changeset patch # User jwe # Date 813482692 0 # Node ID 27a03373de4150e889934daeafba168ce4152fd0 # Parent 1adb4798e5c1bb30841210e901cdd6e9f551569d [project @ 1995-10-12 07:22:26 by jwe] diff --git a/liboctave/Array-C.cc b/liboctave/Array-C.cc --- a/liboctave/Array-C.cc +++ b/liboctave/Array-C.cc @@ -33,6 +33,12 @@ template class Array2; template class DiagArray; +template void assign (Array&, const Array&); +template void assign (Array&, const Array&); + +template void assign (Array2&, const Array2&); +template void assign (Array2&, const Array2&); + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/Array-d.cc b/liboctave/Array-d.cc --- a/liboctave/Array-d.cc +++ b/liboctave/Array-d.cc @@ -31,6 +31,10 @@ template class Array2; template class DiagArray; +template void assign (Array&, const Array&); + +template void assign (Array2&, const Array2&); + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/Array.cc b/liboctave/Array.cc --- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -31,8 +31,17 @@ #include +#include + #include "Array.h" +#if defined (HEAVYWEIGHT_INDEXING) +#include "idx-vector.h" +#include "Array-idx.h" +#endif + +#include "lo-error.h" + // The real representation of all arrays. template @@ -40,6 +49,12 @@ { len = n; data = new T [len]; + +#ifdef HEAVYWEIGHT_INDEXING + idx = 0; + max_indices = 0; + idx_count = 0; +#endif } template @@ -47,16 +62,30 @@ { len = a.len; count = a.count; + data = new T [len]; for (int i = 0; i < len; i++) data[i] = a.data[i]; + +#ifdef HEAVYWEIGHT_INDEXING + max_indices = a.max_indices; + idx_count = a.idx_count; + if (a.idx) + { + idx_vector *idx = new idx_vector [max_indices]; + for (int i = 0; i < max_indices; i++) + idx[i] = a.idx[i]; + } + else + idx = 0; +#endif } template ArrayRep::~ArrayRep (void) { delete [] data; - data = (T *) 0; + delete [] idx; } template @@ -97,7 +126,6 @@ rep = a.rep; rep->count++; } - return *this; } @@ -148,8 +176,7 @@ { if (n < 0) { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); + (*current_liboctave_error_handler) ("can't resize to negative dimension"); return; } @@ -163,6 +190,8 @@ rep = new ArrayRep (n); rep->count = 1; + SET_MAX_INDICES (1); + if (old_data && old_len > 0) { int min_len = old_len < n ? old_len : n; @@ -181,8 +210,7 @@ { if (n < 0) { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); + (*current_liboctave_error_handler) ("can't resize to negative dimension"); return; } @@ -196,6 +224,8 @@ rep = new ArrayRep (n); rep->count = 1; + SET_MAX_INDICES (1); + int min_len = old_len < n ? old_len : n; if (old_data && old_len > 0) @@ -280,8 +310,7 @@ { if (r < 0 || c < 0) { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); + (*current_liboctave_error_handler) ("can't resize to negative dimension"); return; } @@ -290,6 +319,7 @@ ArrayRep *old_rep = rep; const T *old_data = data (); + int old_d1 = dim1 (); int old_d2 = dim2 (); int old_len = length (); @@ -297,6 +327,8 @@ rep = new ArrayRep (r*c); rep->count = 1; + SET_MAX_INDICES (2); + d1 = r; d2 = c; @@ -320,8 +352,7 @@ { if (r < 0 || c < 0) { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); + (*current_liboctave_error_handler) ("can't resize to negative dimension"); return; } @@ -337,6 +368,8 @@ rep = new ArrayRep (r*c); rep->count = 1; + SET_MAX_INDICES (2); + d1 = r; d2 = c; @@ -513,8 +546,7 @@ { if (r < 0 || c < 0) { - (*current_liboctave_error_handler) - ("can't resize to negative dimensions"); + (*current_liboctave_error_handler) ("can't resize to negative dimensions"); return; } @@ -530,6 +562,8 @@ rep = new ArrayRep (new_len); rep->count = 1; + SET_MAX_INDICES (2); + nr = r; nc = c; @@ -551,8 +585,7 @@ { if (r < 0 || c < 0) { - (*current_liboctave_error_handler) - ("can't resize to negative dimensions"); + (*current_liboctave_error_handler) ("can't resize to negative dimensions"); return; } @@ -568,6 +601,8 @@ rep = new ArrayRep (new_len); rep->count = 1; + SET_MAX_INDICES (2); + nr = r; nc = c; diff --git a/liboctave/Array.h b/liboctave/Array.h --- a/liboctave/Array.h +++ b/liboctave/Array.h @@ -28,10 +28,14 @@ #pragma interface #endif +#define HEAVYWEIGHT_INDEXING 1 + #include #include "lo-error.h" +class idx_vector; + // Classes we declare. template class ArrayRep; @@ -40,6 +44,12 @@ template class Array3; template class DiagArray; +#ifdef HEAVYWEIGHT_INDEXING +#define SET_MAX_INDICES(n) set_max_indices (n) +#else +#define SET_MAX_INDICES(n) +#endif + // The real representation of all arrays. template @@ -54,24 +64,42 @@ private: + T *data; int count; int len; - T *data; + +#ifdef HEAVYWEIGHT_INDEXING + idx_vector *idx; + int max_indices; + int idx_count; +#endif protected: ArrayRep (T *d, int l) { + data = d; len = l; - data = d; + +#ifdef HEAVYWEIGHT_INDEXING + idx = 0; + max_indices = 0; + idx_count = 0; +#endif } public: ArrayRep (void) { + data = 0; len = 0; - data = 0; + +#ifdef HEAVYWEIGHT_INDEXING + idx = 0; + max_indices = 0; + idx_count = 0; +#endif } ArrayRep (int n); @@ -86,7 +114,17 @@ T elem (int n) const; - void resize (int n); +#ifdef HEAVYWEIGHT_INDEXING + void set_max_indices (int mi) { max_indices = mi; } + + void clear_index (void); + + void set_index (const idx_vector& i); + + int index_count (void) const { return idx_count; } + + idx_vector *get_idx (void) const { return idx; } +#endif }; // One dimensional array class. Handles the reference counting for @@ -103,20 +141,23 @@ { rep = new ArrayRep (d, l); rep->count = 1; + set_max_indices (1); } public: Array (void) { - rep = new ArrayRep; + rep = new ArrayRep (); rep->count = 1; + set_max_indices (1); } Array (int n) { rep = new ArrayRep (n); rep->count = 1; + set_max_indices (1); } Array (int n, const T& val); @@ -166,8 +207,27 @@ const T *data (void) const { return rep->data; } T *fortran_vec (void); + +#ifdef HEAVYWEIGHT_INDEXING + void set_max_indices (int mi) { rep->set_max_indices (mi); } + + void clear_index (void) { rep->clear_index (); } + + void set_index (const idx_vector& i) { rep->set_index (i); } + + int index_count (void) const { return rep->index_count (); } + + idx_vector *get_idx (void) const { return rep->get_idx (); } + + void maybe_delete_elements (idx_vector& i); + + Array value (void); +#endif }; +template +int assign (Array& lhs, const Array& rhs); + // Two dimensional array class. template @@ -175,45 +235,63 @@ { protected: - int d1; - int d2; - Array2 (T *d, int n, int m) : Array (d, n*m) { d1 = n; d2 = m; + set_max_indices (2); } public: + // These really need to be protected (and they will be in the + // future, so don't depend on them being here!), but they can't be + // until template friends work correctly in g++. + + int d1; + int d2; + Array2 (void) : Array () { d1 = 0; d2 = 0; + set_max_indices (2); } Array2 (int n, int m) : Array (n*m) { d1 = n; d2 = m; + set_max_indices (2); } Array2 (int n, int m, const T& val) : Array (n*m, val) { d1 = n; d2 = m; + set_max_indices (2); } Array2 (const Array2& a) : Array (a) { d1 = a.d1; d2 = a.d2; + set_max_indices (2); } - Array2 (const DiagArray& a) : Array (a.rows () * a.cols (), T (0)) + Array2 (const Array& a, int n, int m) : Array (a) + { + d1 = n; + d2 = m; + set_max_indices (2); + } + + Array2 (const DiagArray& a) : Array (a.rows () * a.cols (), T (0)) { for (int i = 0; i < a.length (); i++) elem (i, i) = a.elem (i, i); + + set_max_indices (2); } ~Array2 (void) { } @@ -251,8 +329,17 @@ void resize (int n, int m); void resize (int n, int m, const T& val); + +#ifdef HEAVYWEIGHT_INDEXING + void maybe_delete_elements (idx_vector& i, idx_vector& j); + + Array2 value (void); +#endif }; +template +int assign (Array2& lhs, const Array2& rhs); + // Three dimensional array class. template @@ -266,6 +353,7 @@ { d2 = m; d3 = k; + set_max_indices (3); } public: @@ -274,24 +362,28 @@ { d2 = 0; d3 = 0; + set_max_indices (3); } Array3 (int n, int m, int k) : Array2 (n, m*k) { d2 = m; d3 = k; + set_max_indices (3); } Array3 (int n, int m, int k, const T& val) : Array2 (n, m*k, val) { d2 = m; d3 = k; + set_max_indices (3); } Array3 (const Array3& a) : Array2 (a) { d2 = a.d2; d3 = a.d3; + set_max_indices (3); } ~Array3 (void) { } @@ -325,8 +417,17 @@ void resize (int n, int m, int k); void resize (int n, int m, int k, const T& val); + +#ifdef HEAVYWEIGHT_INDEXING + void maybe_delete_elements (idx_vector& i, idx_vector& j, idx_vector& k); + + Array3 value (void); +#endif }; +template +int assign (Array3& lhs, const Array3& rhs); + // A two-dimensional array with diagonal elements only. // // Idea and example code for Proxy class and functions from: @@ -344,8 +445,8 @@ class DiagArray : public Array { private: - inline T get (int i) { return Array::elem (i); } - inline void set (const T& val, int i) { Array::elem (i) = val; } + T get (int i) { return Array::elem (i); } + void set (const T& val, int i) { Array::elem (i) = val; } #if 0 #if ! (defined (_AIX) && defined (__GNUG__) && __GNUC__ > 1 && __GNUC_MINOR__ < 6) @@ -353,33 +454,32 @@ { public: - inline Proxy (DiagArray *ref, int r, int c) + Proxy (DiagArray *ref, int r, int c) : i (r), j (c), object (ref) { } - inline const Proxy& operator = (const T& val) const - { - if (i == j) - { - if (object) - object->set (val, i); - } - else - (*current_liboctave_error_handler) - ("assignment to off-diagonal element attempted for diagonal array"); + const Proxy& operator = (const T& val) const + { + if (i == j) + { + if (object) + object->set (val, i); + } + else + (*current_liboctave_error_handler) ("invalid assignment to off-diagonal in diagonal array"); - return *this; - } + return *this; + } - inline operator T () const - { - if (object && i == j) - return object->get (i); - else - { - static T foo (0); - return foo; - } - } + operator T () const + { + if (object && i == j) + return object->get (i); + else + { + static T foo (0); + return foo; + } + } private: @@ -387,7 +487,7 @@ // taking the address of a Proxy. Maybe it should be implemented // by means of a companion function in the DiagArray class. - inline T *operator& () const { assert (0); return (T *) 0; } + T *operator& () const { assert (0); return (T *) 0; } int i; int j; @@ -409,6 +509,7 @@ { nr = r; nc = c; + set_max_indices (2); } public: @@ -417,57 +518,64 @@ { nr = 0; nc = 0; + set_max_indices (2); } DiagArray (int n) : Array (n) -{ - nr = n; - nc = n; -} + { + nr = n; + nc = n; + set_max_indices (2); + } DiagArray (int n, const T& val) : Array (n, val) -{ - nr = n; - nc = n; -} + { + nr = n; + nc = n; + set_max_indices (2); + } DiagArray (int r, int c) : Array (r < c ? r : c) -{ - nr = r; - nc = c; -} + { + nr = r; + nc = c; + set_max_indices (2); + } DiagArray (int r, int c, const T& val) : Array (r < c ? r : c, val) -{ - nr = r; - nc = c; -} + { + nr = r; + nc = c; + set_max_indices (2); + } DiagArray (const Array& a) : Array (a) -{ - nr = nc = a.length (); -} + { + nr = nc = a.length (); + set_max_indices (2); + } DiagArray (const DiagArray& a) : Array (a) -{ - nr = a.nr; - nc = a.nc; -} + { + nr = a.nr; + nc = a.nc; + set_max_indices (2); + } ~DiagArray (void) { } DiagArray& operator = (const DiagArray& a) -{ - if (this != &a) { - Array::operator = (a); - nr = a.nr; - nc = a.nc; + if (this != &a) + { + Array::operator = (a); + nr = a.nr; + nc = a.nc; + } + + return *this; } - return *this; -} - int dim1 (void) const { return nr; } int dim2 (void) const { return nc; } @@ -476,31 +584,31 @@ int columns (void) const { return nc; } #if 0 - inline Proxy elem (int r, int c) - { - return Proxy (this, r, c); - } + Proxy elem (int r, int c) + { + return Proxy (this, r, c); + } - inline Proxy checkelem (int r, int c) - { - if (r < 0 || c < 0 || r >= nr || c >= nc) - { - (*current_liboctave_error_handler) ("range error"); - return Proxy (0, r, c); - } - else - return Proxy (this, r, c); - } + Proxy checkelem (int r, int c) + { + if (r < 0 || c < 0 || r >= nr || c >= nc) + { + (*current_liboctave_error_handler) ("range error"); + return Proxy (0, r, c); + } + else + return Proxy (this, r, c); + } - inline Proxy operator () (int r, int c) - { - if (r < 0 || c < 0 || r >= nr || c >= nc) - { - (*current_liboctave_error_handler) ("range error"); - return Proxy (0, r, c); - } - else - return Proxy (this, r, c); + Proxy operator () (int r, int c) + { + if (r < 0 || c < 0 || r >= nr || c >= nc) + { + (*current_liboctave_error_handler) ("range error"); + return Proxy (0, r, c); + } + else + return Proxy (this, r, c); } #else T& elem (int r, int c); @@ -518,6 +626,8 @@ void resize (int n, int m); void resize (int n, int m, const T& val); + + void maybe_delete_elements (idx_vector& i, idx_vector& j); }; #endif diff --git a/liboctave/Makefile.in b/liboctave/Makefile.in --- a/liboctave/Makefile.in +++ b/liboctave/Makefile.in @@ -18,10 +18,10 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ -MATRIX_INC = Array.h MArray.h Matrix.h mx-base.h mx-defs.h mx-ext.h \ - CColVector.h CDiagMatrix.h CMatrix.h CRowVector.h \ - CmplxAEPBAL.h CmplxCHOL.h CmplxDET.h CmplxHESS.h CmplxLU.h \ - CmplxQR.h CmplxQRP.h CmplxSCHUR.h CmplxSVD.h EIG.h \ +MATRIX_INC = Array.h Array-idx.h MArray.h Matrix.h mx-base.h \ + mx-defs.h mx-ext.h CColVector.h CDiagMatrix.h CMatrix.h \ + CRowVector.h CmplxAEPBAL.h CmplxCHOL.h CmplxDET.h CmplxHESS.h \ + CmplxLU.h CmplxQR.h CmplxQRP.h CmplxSCHUR.h CmplxSVD.h EIG.h \ dColVector.h dDiagMatrix.h dMatrix.h dRowVector.h dbleAEPBAL.h \ dbleCHOL.h dbleDET.h dbleGEPBAL.h dbleHESS.h dbleLU.h dbleQR.h \ dbleQRP.h dbleSCHUR.h dbleSVD.h @@ -37,7 +37,8 @@ TI_SRC = Array-C.cc Array-i.cc Array-d.cc MArray-C.cc MArray-d.cc -MATRIX_SRC = CColVector.cc CDiagMatrix.cc CMatrix.cc CRowVector.cc \ +MATRIX_SRC = Array-ext.cc CColVector.cc CDiagMatrix.cc CMatrix.cc \ + CRowVector.cc \ CmplxAEPBAL.cc CmplxCHOL.cc CmplxDET.cc CmplxHESS.cc CmplxLU.cc \ CmplxQR.cc CmplxQRP.cc CmplxSCHUR.cc CmplxSVD.cc EIG.cc \ dColVector.cc dDiagMatrix.cc dMatrix.cc dRowVector.cc \ diff --git a/liboctave/idx-vector.cc b/liboctave/idx-vector.cc --- a/liboctave/idx-vector.cc +++ b/liboctave/idx-vector.cc @@ -34,17 +34,26 @@ #include #include "Range.h" +#include "dColVector.h" #include "dMatrix.h" -#include "error.h" #include "idx-vector.h" -#include "user-prefs.h" -#include "utils.h" +#include "lo-error.h" -idx_vector::idx_vector (const idx_vector& a) +#define IDX_VEC_REP idx_vector::idx_vector_rep + +IDX_VEC_REP::idx_vector_rep (const IDX_VEC_REP& a) { data = 0; initialized = a.initialized; + frozen = a.frozen; + colon_equiv_checked = a.colon_equiv_checked; + colon_equiv = a.colon_equiv; + + colon = a.colon; + + orig_nr = a.orig_nr; + orig_nc = a.orig_nc; len = a.len; if (len > 0) @@ -71,65 +80,93 @@ return ((int) (x - 0.5) - 1); } -idx_vector::idx_vector (const Matrix& m, int do_ftn_idx, - const char *rc, int z_len) +IDX_VEC_REP::idx_vector_rep (const ColumnVector& v) { data = 0; initialized = 0; - - int nr = m.rows (); - int nc = m.columns (); + frozen = 0; + colon_equiv_checked = 0; + colon_equiv = 0; + colon = 0; - if (nr == 0 || nc == 0) + int len = v.length (); + + orig_nr = len; + orig_nc = 1; + + if (len == 0) { - len = 0; num_zeros = 0; num_ones = 0; one_zero = 0; + max_val = 0; + min_val = 0; initialized = 1; return; } - else if (nr > 1 && nc > 1 && do_ftn_idx) + else { - const double *cop_out = m.data (); - len = nr * nc; data = new int [len]; for (int i = 0; i < len; i++) - data[i] = tree_to_mat_idx (*cop_out++); + data[i] = tree_to_mat_idx (v.elem (i)); } - else if (nr == 1 && nc > 0) + + init_state (); +} + +IDX_VEC_REP::idx_vector_rep (const Matrix& m) +{ + data = 0; + initialized = 0; + frozen = 0; + colon_equiv_checked = 0; + colon_equiv = 0; + colon = 0; + + orig_nr = m.rows (); + orig_nc = m.columns (); + + len = orig_nr * orig_nc; + + if (len == 0) { - len = nc; - data = new int [len]; - for (int i = 0; i < len; i++) - data[i] = tree_to_mat_idx (m.elem (0, i)); - } - else if (nc == 1 && nr > 0) - { - len = nr; - data = new int [len]; - for (int i = 0; i < len; i++) - data[i] = tree_to_mat_idx (m.elem (i, 0)); + num_zeros = 0; + num_ones = 0; + one_zero = 0; + max_val = 0; + min_val = 0; + initialized = 1; + return; } else { - ::error ("invalid matrix used as index"); - return; + int k = 0; + data = new int [len]; + for (int j = 0; j < orig_nc; j++) + for (int i = 0; i < orig_nr; i++) + data[k++] = tree_to_mat_idx (m.elem (i, j)); } - init_state (rc, z_len); + init_state (); } -idx_vector::idx_vector (const Range& r) +IDX_VEC_REP::idx_vector_rep (const Range& r) { data = 0; initialized = 0; + frozen = 0; + colon_equiv_checked = 0; + colon_equiv = 0; + colon = 0; len = r.nelem (); + orig_nr = 1; + orig_nc = len; + if (len < 0) { - ::error ("invalid range used as index"); + (*current_liboctave_error_handler) ("invalid range used as index"); return; } else if (len == 0) @@ -137,6 +174,8 @@ num_zeros = 0; num_ones = 0; one_zero = 0; + max_val = 0; + min_val = 0; initialized = 1; return; } @@ -155,12 +194,38 @@ init_state (); } -idx_vector& -idx_vector::operator = (const idx_vector& a) +IDX_VEC_REP::idx_vector_rep (char c) +{ + assert (c == ':'); + + colon = 1; + len = 0; + num_zeros = 0; + num_ones = 0; + one_zero = 0; + initialized = 0; + frozen = 0; + colon_equiv_checked = 0; + colon_equiv = 0; + data = 0; + + init_state (); +} + +IDX_VEC_REP& +IDX_VEC_REP::operator = (const IDX_VEC_REP& a) { if (this != &a) { initialized = a.initialized; + frozen = a.frozen; + colon_equiv_checked = a.colon_equiv_checked; + colon_equiv = a.colon_equiv; + + colon = a.colon; + + orig_nr = a.orig_nr; + orig_nc = a.orig_nc; delete [] data; len = a.len; @@ -179,90 +244,33 @@ } void -idx_vector::init_state (const char *rc, int z_len) +IDX_VEC_REP::init_state (void) { - one_zero = 1; num_zeros = 0; num_ones = 0; - min_val = max_val = data[0]; - - int i = 0; - do - { - if (data[i] == -1) - num_zeros++; - else if (data[i] == 0) - num_ones++; - - if (one_zero && data[i] != -1 && data[i] != 0) - one_zero = 0; - - if (data[i] > max_val) - max_val = data[i]; - - if (data[i] < min_val) - min_val = data[i]; - } - while (++i < len); - - if (one_zero && z_len == len) - { - if (num_ones != len || user_pref.prefer_zero_one_indexing) - convert_one_zero_to_idx (); - } - else if (min_val < 0) + if (colon) { - ::error ("%s index %d out of range", rc, min_val+1); - initialized = 0; - return; - } -#if 0 - // Checking max index against size won't work right here unless we - // also look at resize on range error, and we have to do that later - // on anyway. - - else if (max_val >= z_len) - { - ::error ("%s index %d out of range", rc, max_val+1); - initialized = 0; - return; - } -#endif - - initialized = 1; -} - -void -idx_vector::convert_one_zero_to_idx (void) -{ - if (num_ones == 0) - { - len = 0; - max_val = 0; - min_val = 0; - delete [] data; - data = 0; + one_zero = 0; + min_val = max_val = 0; } else { - assert (num_ones + num_zeros == len); - - int *new_data = new int [num_ones]; - int count = 0; - for (int i = 0; i < len; i++) - if (data[i] == 0) - new_data[count++] = i; - - delete [] data; - len = num_ones; - data = new_data; + one_zero = 1; min_val = max_val = data[0]; int i = 0; do { + if (data[i] == -1) + num_zeros++; + else if (data[i] == 0) + num_ones++; + + if (one_zero && data[i] != -1 && data[i] != 0) + one_zero = 0; + if (data[i] > max_val) max_val = data[i]; @@ -271,14 +279,60 @@ } while (++i < len); } + + initialized = 1; +} + +void +IDX_VEC_REP::maybe_convert_one_zero_to_idx (int z_len, int prefer_zero_one) +{ + if (one_zero && z_len == len + && (num_ones != len || prefer_zero_one)) + { + if (num_ones == 0) + { + len = 0; + max_val = 0; + min_val = 0; + delete [] data; + data = 0; + } + else + { + assert (num_ones + num_zeros == len); + + int *new_data = new int [num_ones]; + int count = 0; + for (int i = 0; i < len; i++) + if (data[i] == 0) + new_data[count++] = i; + + delete [] data; + len = num_ones; + data = new_data; + + min_val = max_val = data[0]; + + int i = 0; + do + { + if (data[i] > max_val) + max_val = data[i]; + + if (data[i] < min_val) + min_val = data[i]; + } + while (++i < len); + } + } } int -idx_vector::checkelem (int n) const +IDX_VEC_REP::checkelem (int n) const { if (n < 0 || n >= len) { - ::error ("idx-vector: index out of range"); + (*current_liboctave_error_handler) ("idx-vector: index out of range"); return 0; } @@ -291,52 +345,147 @@ return (*i - *j); } -void -idx_vector::sort (void) +static inline void +sort_data (int *d, int len) +{ + qsort ((void *) d, len, sizeof (int), + (int (*)(const void*, const void*)) intcmp); +} + +static inline int +make_uniq (int *d, int len) +{ + int k = 0; + for (int i = 1; i < len; i++) + { + if (d[i] != d[k]) + { + k++; + d[k] = d[i]; + } + } + return k+1; +} + +static inline int * +copy_data (const int *d, int len) { - qsort ((void *) data, len, sizeof (int), - (int (*)(const void*, const void*)) intcmp); + int *new_data = new int [len]; + + for (int i = 0; i < len; i++) + new_data[i] = d[i]; + + return new_data; +} + +int +IDX_VEC_REP::is_colon_equiv (int n, int sort) +{ + if (! colon_equiv_checked) + { + if (colon) + { + colon_equiv = 1; + } + else if (len > 0) + { + int *tmp_data = copy_data (data, len); + + if (sort) + sort_data (tmp_data, len); + + int tmp_len = make_uniq (tmp_data, len); + + colon_equiv = ((tmp_len == 0 && n == 0) + || (tmp_len == n + && tmp_data[0] == 0 + && tmp_data[tmp_len-1] == tmp_len - 1)); + + delete [] tmp_data; + } + else + colon_equiv = 0; + + colon_equiv_checked = 1; + } + + return colon_equiv; } void -idx_vector::sort_uniq (void) -{ - if (len > 0) - { - sort (); - - int *new_data = new int [len]; - new_data[0] = data[0]; - int k = 0; - for (int i = 1; i < len; i++) - { - if (data[i] != new_data[k]) - { - k++; - new_data[k] = data[i]; - } - } - delete [] data; - len = k+1; - data = new_data; - } -} - -void -idx_vector::shorten (int n) +IDX_VEC_REP::shorten (int n) { if (n > 0 && n <= len) len = n; else - panic_impossible (); + (*current_liboctave_error_handler) + ("idx_vector::shorten: internal error!"); } ostream& -operator << (ostream& os, const idx_vector& a) +IDX_VEC_REP::print (ostream& os) const +{ + for (int i = 0; i < len; i++) + os << data[i] << "\n"; + return os; +} + +int +IDX_VEC_REP::freeze (int z_len, const char *tag, + int prefer_zero_one, int resize_ok) { - for (int i = 0; i < a.len; i++) - os << a.data[i] << "\n"; - return os; + if (frozen) + { + assert (frozen_at_z_len == z_len); + return frozen_len; + } + + frozen_len = -1; + + if (colon) + frozen_len = z_len; + else + { + if (len == 0) + frozen_len = 0; + else + { + maybe_convert_one_zero_to_idx (z_len, prefer_zero_one); + + int max_val = max (); + int min_val = min (); + + if (min_val < 0) + { + if (tag) + (*current_liboctave_error_handler) + ("invalid %s index = %d", tag, min_val+1); + else + (*current_liboctave_error_handler) + ("invalid index = %d", min_val+1); + + initialized = 0; + } + else if (! resize_ok && max_val >= z_len) + { + if (tag) + (*current_liboctave_error_handler) + ("invalid %s index = %d", tag, max_val+1); + else + (*current_liboctave_error_handler) + ("invalid index = %d", max_val+1); + + initialized = 0; + } + else + frozen_len = length (z_len); + } + } + + frozen = 1; + frozen_at_z_len = z_len; + + return frozen_len; } /* diff --git a/liboctave/idx-vector.h b/liboctave/idx-vector.h --- a/liboctave/idx-vector.h +++ b/liboctave/idx-vector.h @@ -29,78 +29,207 @@ #endif class ostream; +class ColumnVector; class Matrix; class Range; class idx_vector { +private: + + struct + idx_vector_rep + { + idx_vector_rep::idx_vector_rep (void) + { + colon = 0; + len = 0; + num_zeros = 0; + num_ones = 0; + one_zero = 0; + orig_nr = 0; + orig_nc = 0; + initialized = 0; + frozen = 0; + colon_equiv_checked = 0; + colon_equiv = 0; + data = 0; + } + + idx_vector_rep (const ColumnVector& v); + + idx_vector_rep (const Matrix& m); + + idx_vector_rep (const Range& r); + + idx_vector_rep (char c); + + idx_vector_rep (const idx_vector_rep& a); + + idx_vector_rep::~idx_vector_rep (void) { delete [] data; } + + idx_vector_rep& operator = (const idx_vector_rep& a); + + int ok (void) { return initialized; } + + int capacity (void) const { return len; } + int length (int colon_len) const { return colon ? colon_len : len; } + + int elem (int n) const { return colon ? n : data[n]; } + + int checkelem (int n) const; + int operator () (int n) const { return checkelem (n); } + + int max (void) const { return max_val; } + int min (void) const { return min_val; } + + int one_zero_only (void) const { return one_zero; } + int zeros_count (void) const { return num_zeros; } + int ones_count (void) const { return num_ones; } + + int is_colon (void) const { return colon; } + int is_colon_equiv (int n, int sort); + + int orig_rows (void) const { return orig_nr; } + int orig_columns (void) const { return orig_nc; } + + // other stuff + + void shorten (int n); // Unsafe. Avoid at all cost. + + int freeze (int z_len, const char *tag, int prefer_zero_one, + int resize_ok); + + // i/o + + ostream& print (ostream& os) const; + + int *data; + int len; + int num_zeros; + int num_ones; + int max_val; + int min_val; + int orig_nr; + int orig_nc; + int count; + int frozen_at_z_len; + int frozen_len; + unsigned int colon : 1; + unsigned int one_zero : 1; + unsigned int initialized : 1; + unsigned int frozen : 1; + unsigned int colon_equiv_checked : 1; + unsigned int colon_equiv : 1; + + void init_state (void); + + void maybe_convert_one_zero_to_idx (int z_len, int prefer_zero_one); + }; + public: idx_vector::idx_vector (void) { - len = 0; - num_zeros = 0; - num_ones = 0; - one_zero = 0; - initialized = 0; - data = 0; + rep = new idx_vector_rep (); + rep->count = 1; + } + + idx_vector (const ColumnVector& v) + { + rep = new idx_vector_rep (v); + rep->count = 1; + } + + idx_vector (const Matrix& m) + { + rep = new idx_vector_rep (m); + rep->count = 1; + } + + idx_vector (const Range& r) + { + rep = new idx_vector_rep (r); + rep->count = 1; + } + + idx_vector (char c) + { + rep = new idx_vector_rep (c); + rep->count = 1; + } + + idx_vector (const idx_vector& a) + { + rep = a.rep; + rep->count++; } - idx_vector (const idx_vector& a); - - idx_vector (const Matrix& m, int do_ftn_idx, - const char *rc = 0, int z_len = 0); - - idx_vector (const Range& r); + idx_vector::~idx_vector (void) + { + if (--rep->count <= 0) + delete rep; + } - idx_vector::~idx_vector (void) { delete [] data; } - - idx_vector& operator = (const idx_vector& a); + idx_vector& operator = (const idx_vector& a) + { + if (this != &a) + { + if (--rep->count <= 0) + delete rep; - idx_vector::operator void * () const - { - return initialized ? (void *) 1 : (void *) 0; + rep = a.rep; + rep->count++; + } + return *this; } - int idx_vector::capacity (void) const { return len; } - int idx_vector::length (void) const { return len; } + idx_vector::operator void * () const { return (void *) rep->ok (); } + + int idx_vector::capacity (void) const { return rep->capacity (); } + int idx_vector::length (int cl) const { return rep->length (cl); } - int idx_vector::elem (int n) const { return data[n]; } - int idx_vector::checkelem (int n) const; - int idx_vector::operator () (int n) const { return checkelem (n); } + int idx_vector::elem (int n) const { return rep->elem (n); } + int idx_vector::checkelem (int n) const { return rep->checkelem (n); } + int idx_vector::operator () (int n) const { return rep->operator () (n); } - int idx_vector::max (void) const { return max_val; } - int idx_vector::min (void) const { return min_val; } + int idx_vector::max (void) const { return rep->max (); } + int idx_vector::min (void) const { return rep->min (); } - int idx_vector::one_zero_only (void) const { return one_zero; } - int idx_vector::zeros_count (void) const { return num_zeros; } - int idx_vector::ones_count (void) const { return num_ones; } + int idx_vector::one_zero_only (void) const { return rep->one_zero_only (); } + int idx_vector::zeros_count (void) const { return rep->zeros_count (); } + int idx_vector::ones_count (void) const { return rep->ones_count (); } -// other stuff + int is_colon (void) const { return rep->is_colon (); } + int is_colon_equiv (int n, int sort = 0) const + { return rep->is_colon_equiv (n, sort); } - void sort (void); - void sort_uniq (void); + int orig_rows (void) const { return rep->orig_rows (); } + int orig_columns (void) const { return rep->orig_columns (); } - void shorten (int n); // Unsafe. Avoid at all cost. +// Unsafe. Avoid at all cost. + void shorten (int n) { rep->shorten (n); } // i/o - friend ostream& operator << (ostream& os, const idx_vector& a); + int freeze (int z_len, const char *tag, int prefer_zero_one = 0, + int resize_ok = 0) + { return rep->freeze (z_len, tag, prefer_zero_one, resize_ok); } + + ostream& print (ostream& os) const { return rep->print (os); } + + friend ostream& operator << (ostream& os, const idx_vector& a) + { return a.print (os); } + + void maybe_convert_one_zero_to_idx (int z_len, int prefer_zero_one = 0) + { rep->maybe_convert_one_zero_to_idx (z_len, prefer_zero_one); } private: - int *data; - int len; - int num_zeros; - int num_ones; - int max_val; - int min_val; - unsigned int one_zero : 1; - unsigned int initialized : 1; + idx_vector_rep *rep; - void init_state (const char *rc = 0, int z_len = 0); - void convert_one_zero_to_idx (void); + void init_state (void) { rep->init_state (); } }; #endif