00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #if !defined (octave_Array_h)
00027 #define octave_Array_h 1
00028
00029 #include <cassert>
00030 #include <cstddef>
00031
00032 #include <algorithm>
00033 #include <iosfwd>
00034
00035 #include "dim-vector.h"
00036 #include "idx-vector.h"
00037 #include "lo-traits.h"
00038 #include "lo-utils.h"
00039 #include "oct-sort.h"
00040 #include "quit.h"
00041 #include "oct-mem.h"
00042 #include "oct-refcount.h"
00043
00044
00045
00046
00047 template <class T>
00048 class
00049 Array
00050 {
00051 protected:
00052
00053
00054
00055
00056
00057 class ArrayRep
00058 {
00059 public:
00060
00061 T *data;
00062 octave_idx_type len;
00063 octave_refcount<int> count;
00064
00065 ArrayRep (T *d, octave_idx_type l)
00066 : data (no_ctor_new<T> (l)), len (l), count (1)
00067 {
00068 copy_or_memcpy (l, d, data);
00069 }
00070
00071 template <class U>
00072 ArrayRep (U *d, octave_idx_type l)
00073 : data (no_ctor_new<T> (l)), len (l), count (1)
00074 {
00075 std::copy (d, d+l, data);
00076 }
00077
00078 ArrayRep (void) : data (0), len (0), count (1) { }
00079
00080 explicit ArrayRep (octave_idx_type n) : data (no_ctor_new<T> (n)), len (n), count (1) { }
00081
00082 explicit ArrayRep (octave_idx_type n, const T& val)
00083 : data (no_ctor_new<T> (n)), len (n), count (1)
00084 {
00085 fill_or_memset (n, val, data);
00086 }
00087
00088 ArrayRep (const ArrayRep& a)
00089 : data (no_ctor_new<T> (a.len)), len (a.len), count (1)
00090 {
00091 copy_or_memcpy (a.len, a.data, data);
00092 }
00093
00094 ~ArrayRep (void) { no_ctor_delete<T> (data); }
00095
00096 octave_idx_type length (void) const { return len; }
00097
00098 private:
00099
00100
00101
00102 ArrayRep& operator = (const ArrayRep& a);
00103 };
00104
00105
00106
00107 public:
00108
00109 void make_unique (void)
00110 {
00111 if (rep->count > 1)
00112 {
00113 ArrayRep *r = new ArrayRep (slice_data, slice_len);
00114
00115 if (--rep->count == 0)
00116 delete rep;
00117
00118 rep = r;
00119 slice_data = rep->data;
00120 }
00121 }
00122
00123 typedef T element_type;
00124
00125 typedef typename ref_param<T>::type crefT;
00126
00127 typedef bool (*compare_fcn_type) (typename ref_param<T>::type,
00128 typename ref_param<T>::type);
00129
00130 protected:
00131
00132 dim_vector dimensions;
00133
00134 typename Array<T>::ArrayRep *rep;
00135
00136
00137
00138
00139
00140
00141
00142
00143 T* slice_data;
00144 octave_idx_type slice_len;
00145
00146
00147 Array (const Array<T>& a, const dim_vector& dv,
00148 octave_idx_type l, octave_idx_type u)
00149 : dimensions (dv), rep(a.rep), slice_data (a.slice_data+l), slice_len (u-l)
00150 {
00151 rep->count++;
00152 dimensions.chop_trailing_singletons ();
00153 }
00154
00155 private:
00156
00157 typename Array<T>::ArrayRep *nil_rep (void) const
00158 {
00159
00160
00161
00162
00163 static typename Array<T>::ArrayRep nr;
00164 return &nr;
00165 }
00166
00167 public:
00168
00169
00170
00171 Array (void)
00172 : dimensions (), rep (nil_rep ()), slice_data (rep->data),
00173 slice_len (rep->len)
00174 {
00175 rep->count++;
00176 }
00177
00178
00179 explicit Array (octave_idx_type n) GCC_ATTR_DEPRECATED
00180 : dimensions (n, 1), rep (new typename Array<T>::ArrayRep (n)),
00181 slice_data (rep->data), slice_len (rep->len)
00182 { }
00183
00184
00185 explicit Array (octave_idx_type n, const T& val) GCC_ATTR_DEPRECATED
00186 : dimensions (n, 1), rep (new typename Array<T>::ArrayRep (n)),
00187 slice_data (rep->data), slice_len (rep->len)
00188 {
00189 fill (val);
00190 }
00191
00192
00193 explicit Array (const dim_vector& dv)
00194 : dimensions (dv),
00195 rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
00196 slice_data (rep->data), slice_len (rep->len)
00197 {
00198 dimensions.chop_trailing_singletons ();
00199 }
00200
00201
00202 explicit Array (const dim_vector& dv, const T& val)
00203 : dimensions (dv),
00204 rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
00205 slice_data (rep->data), slice_len (rep->len)
00206 {
00207 fill (val);
00208 dimensions.chop_trailing_singletons ();
00209 }
00210
00211
00212 Array (const Array<T>& a, const dim_vector& dv);
00213
00214
00215 template <class U>
00216 Array (const Array<U>& a)
00217 : dimensions (a.dims ()),
00218 rep (new typename Array<T>::ArrayRep (a.data (), a.length ())),
00219 slice_data (rep->data), slice_len (rep->len)
00220 { }
00221
00222
00223 Array (const Array<T>& a)
00224 : dimensions (a.dimensions), rep (a.rep), slice_data (a.slice_data),
00225 slice_len (a.slice_len)
00226 {
00227 rep->count++;
00228 }
00229
00230 public:
00231
00232 ~Array (void)
00233 {
00234 if (--rep->count == 0)
00235 delete rep;
00236 }
00237
00238 Array<T>& operator = (const Array<T>& a)
00239 {
00240 if (this != &a)
00241 {
00242 if (--rep->count == 0)
00243 delete rep;
00244
00245 rep = a.rep;
00246 rep->count++;
00247
00248 dimensions = a.dimensions;
00249 slice_data = a.slice_data;
00250 slice_len = a.slice_len;
00251 }
00252
00253 return *this;
00254 }
00255
00256 void fill (const T& val);
00257
00258 void clear (void);
00259 void clear (const dim_vector& dv);
00260
00261 void clear (octave_idx_type r, octave_idx_type c)
00262 { clear (dim_vector (r, c)); }
00263
00264 octave_idx_type capacity (void) const { return slice_len; }
00265 octave_idx_type length (void) const { return capacity (); }
00266 octave_idx_type nelem (void) const { return capacity (); }
00267 octave_idx_type numel (void) const { return nelem (); }
00268
00269 octave_idx_type dim1 (void) const { return dimensions(0); }
00270 octave_idx_type dim2 (void) const { return dimensions(1); }
00271 octave_idx_type dim3 (void) const { return dimensions(2); }
00272
00273
00274 Array<T> as_column (void) const
00275 {
00276 Array<T> retval (*this);
00277 if (dimensions.length () != 2 || dimensions(1) != 1)
00278 retval.dimensions = dim_vector (numel (), 1);
00279
00280 return retval;
00281 }
00282
00283
00284 Array<T> as_row (void) const
00285 {
00286 Array<T> retval (*this);
00287 if (dimensions.length () != 2 || dimensions(0) != 1)
00288 retval.dimensions = dim_vector (1, numel ());
00289
00290 return retval;
00291 }
00292
00293
00294 Array<T> as_matrix (void) const
00295 {
00296 Array<T> retval (*this);
00297 if (dimensions.length () != 2)
00298 retval.dimensions = dimensions.redim (2);
00299
00300 return retval;
00301 }
00302
00303 octave_idx_type rows (void) const { return dim1 (); }
00304 octave_idx_type cols (void) const { return dim2 (); }
00305 octave_idx_type columns (void) const { return dim2 (); }
00306 octave_idx_type pages (void) const { return dim3 (); }
00307
00308 size_t byte_size (void) const { return static_cast<size_t> (numel ()) * sizeof (T); }
00309
00310
00311 const dim_vector& dims (void) const { return dimensions; }
00312
00313 Array<T> squeeze (void) const;
00314
00315 void chop_trailing_singletons (void) GCC_ATTR_DEPRECATED
00316 { dimensions.chop_trailing_singletons (); }
00317
00318 octave_idx_type compute_index (octave_idx_type i, octave_idx_type j) const;
00319 octave_idx_type compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k) const;
00320 octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx) const;
00321
00322 octave_idx_type compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const
00323 { return dimensions.compute_index (ra_idx.data (), ra_idx.length ()); }
00324
00325
00326
00327 T& xelem (octave_idx_type n) { return slice_data [n]; }
00328 crefT xelem (octave_idx_type n) const { return slice_data [n]; }
00329
00330 T& xelem (octave_idx_type i, octave_idx_type j) { return xelem (dim1()*j+i); }
00331 crefT xelem (octave_idx_type i, octave_idx_type j) const { return xelem (dim1()*j+i); }
00332
00333 T& xelem (octave_idx_type i, octave_idx_type j, octave_idx_type k)
00334 { return xelem (i, dim2()*k+j); }
00335 crefT xelem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const
00336 { return xelem (i, dim2()*k+j); }
00337
00338 T& xelem (const Array<octave_idx_type>& ra_idx)
00339 { return xelem (compute_index_unchecked (ra_idx)); }
00340
00341 crefT xelem (const Array<octave_idx_type>& ra_idx) const
00342 { return xelem (compute_index_unchecked (ra_idx)); }
00343
00344
00345
00346
00347
00348 T& checkelem (octave_idx_type n);
00349 T& checkelem (octave_idx_type i, octave_idx_type j);
00350 T& checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k);
00351 T& checkelem (const Array<octave_idx_type>& ra_idx);
00352
00353 T& elem (octave_idx_type n)
00354 {
00355 make_unique ();
00356 return xelem (n);
00357 }
00358
00359 T& elem (octave_idx_type i, octave_idx_type j) { return elem (dim1()*j+i); }
00360
00361 T& elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) { return elem (i, dim2()*k+j); }
00362
00363 T& elem (const Array<octave_idx_type>& ra_idx)
00364 { return Array<T>::elem (compute_index_unchecked (ra_idx)); }
00365
00366 #if defined (BOUNDS_CHECKING)
00367 T& operator () (octave_idx_type n) { return checkelem (n); }
00368 T& operator () (octave_idx_type i, octave_idx_type j) { return checkelem (i, j); }
00369 T& operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) { return checkelem (i, j, k); }
00370 T& operator () (const Array<octave_idx_type>& ra_idx) { return checkelem (ra_idx); }
00371 #else
00372 T& operator () (octave_idx_type n) { return elem (n); }
00373 T& operator () (octave_idx_type i, octave_idx_type j) { return elem (i, j); }
00374 T& operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) { return elem (i, j, k); }
00375 T& operator () (const Array<octave_idx_type>& ra_idx) { return elem (ra_idx); }
00376 #endif
00377
00378 crefT checkelem (octave_idx_type n) const;
00379 crefT checkelem (octave_idx_type i, octave_idx_type j) const;
00380 crefT checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const;
00381 crefT checkelem (const Array<octave_idx_type>& ra_idx) const;
00382
00383 crefT elem (octave_idx_type n) const { return xelem (n); }
00384
00385 crefT elem (octave_idx_type i, octave_idx_type j) const { return xelem (i, j); }
00386
00387 crefT elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { return xelem (i, j, k); }
00388
00389 crefT elem (const Array<octave_idx_type>& ra_idx) const
00390 { return Array<T>::xelem (compute_index_unchecked (ra_idx)); }
00391
00392 #if defined (BOUNDS_CHECKING)
00393 crefT operator () (octave_idx_type n) const { return checkelem (n); }
00394 crefT operator () (octave_idx_type i, octave_idx_type j) const { return checkelem (i, j); }
00395 crefT operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { return checkelem (i, j, k); }
00396 crefT operator () (const Array<octave_idx_type>& ra_idx) const { return checkelem (ra_idx); }
00397 #else
00398 crefT operator () (octave_idx_type n) const { return elem (n); }
00399 crefT operator () (octave_idx_type i, octave_idx_type j) const { return elem (i, j); }
00400 crefT operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { return elem (i, j, k); }
00401 crefT operator () (const Array<octave_idx_type>& ra_idx) const { return elem (ra_idx); }
00402 #endif
00403
00404
00405
00406
00407
00408 Array<T> column (octave_idx_type k) const;
00409
00410 Array<T> page (octave_idx_type k) const;
00411
00412
00413
00414 Array<T> linear_slice (octave_idx_type lo, octave_idx_type up) const;
00415
00416 Array<T> reshape (octave_idx_type nr, octave_idx_type nc) const
00417 { return Array<T> (*this, dim_vector (nr, nc)); }
00418
00419 Array<T> reshape (const dim_vector& new_dims) const
00420 { return Array<T> (*this, new_dims); }
00421
00422 Array<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const;
00423 Array<T> ipermute (const Array<octave_idx_type>& vec) const
00424 { return permute (vec, true); }
00425
00426 bool is_square (void) const { return (dim1 () == dim2 ()); }
00427
00428 bool is_empty (void) const { return numel () == 0; }
00429
00430 bool is_vector (void) const { return dimensions.is_vector (); }
00431
00432 Array<T> transpose (void) const;
00433 Array<T> hermitian (T (*fcn) (const T&) = 0) const;
00434
00435 const T *data (void) const { return slice_data; }
00436
00437 const T *fortran_vec (void) const { return data (); }
00438
00439 T *fortran_vec (void);
00440
00441 bool is_shared (void) { return rep->count > 1; }
00442
00443 int ndims (void) const { return dimensions.length (); }
00444
00445
00446
00447 Array<T> index (const idx_vector& i) const;
00448
00449 Array<T> index (const idx_vector& i, const idx_vector& j) const;
00450
00451 Array<T> index (const Array<idx_vector>& ia) const;
00452
00453 static const T& resize_fill_value ();
00454
00455
00456
00457 void resize1 (octave_idx_type n, const T& rfv = resize_fill_value ());
00458
00459 void resize (octave_idx_type n) GCC_ATTR_DEPRECATED
00460 { resize1 (n); }
00461
00462 void resize (octave_idx_type nr, octave_idx_type nc,
00463 const T& rfv = resize_fill_value ()) GCC_ATTR_DEPRECATED
00464 {
00465 resize2 (nr, nc, rfv);
00466 }
00467
00468 void resize (const dim_vector& dv, const T& rfv = resize_fill_value ());
00469
00470
00471
00472
00473
00474 Array<T> index (const idx_vector& i, bool resize_ok,
00475 const T& rfv = resize_fill_value ()) const;
00476
00477 Array<T> index (const idx_vector& i, const idx_vector& j,
00478 bool resize_ok, const T& rfv = resize_fill_value ()) const;
00479
00480 Array<T> index (const Array<idx_vector>& ia,
00481 bool resize_ok, const T& rfv = resize_fill_value ()) const;
00482
00483
00484
00485 void assign (const idx_vector& i, const Array<T>& rhs,
00486 const T& rfv = resize_fill_value ());
00487
00488 void assign (const idx_vector& i, const idx_vector& j, const Array<T>& rhs,
00489 const T& rfv = resize_fill_value ());
00490
00491 void assign (const Array<idx_vector>& ia, const Array<T>& rhs,
00492 const T& rfv = resize_fill_value ());
00493
00494
00495
00496
00497 void delete_elements (const idx_vector& i);
00498
00499
00500 void delete_elements (int dim, const idx_vector& i);
00501
00502
00503 void delete_elements (const Array<idx_vector>& ia);
00504
00505
00506
00507
00508
00509 Array<T>& insert (const Array<T>& a, const Array<octave_idx_type>& idx);
00510
00511
00512 Array<T>& insert (const Array<T>& a, octave_idx_type r, octave_idx_type c);
00513
00514 void maybe_economize (void)
00515 {
00516 if (rep->count == 1 && slice_len != rep->len)
00517 {
00518 ArrayRep *new_rep = new ArrayRep (slice_data, slice_len);
00519 delete rep;
00520 rep = new_rep;
00521 slice_data = rep->data;
00522 }
00523 }
00524
00525 void print_info (std::ostream& os, const std::string& prefix) const;
00526
00527
00528
00529 void *mex_get_data (void) const { return const_cast<T *> (data ()); }
00530
00531 Array<T> sort (int dim = 0, sortmode mode = ASCENDING) const;
00532 Array<T> sort (Array<octave_idx_type> &sidx, int dim = 0,
00533 sortmode mode = ASCENDING) const;
00534
00535
00536 sortmode is_sorted (sortmode mode = UNSORTED) const;
00537
00538
00539 Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;
00540
00541
00542 sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
00543
00544
00545
00546 octave_idx_type lookup (const T& value, sortmode mode = UNSORTED) const;
00547
00548
00549
00550 Array<octave_idx_type> lookup (const Array<T>& values, sortmode mode = UNSORTED) const;
00551
00552
00553 octave_idx_type nnz (void) const;
00554
00555
00556
00557 Array<octave_idx_type> find (octave_idx_type n = -1, bool backward = false) const;
00558
00559
00560
00561 Array<T> nth_element (const idx_vector& n, int dim = 0) const;
00562
00563 Array<T> diag (octave_idx_type k = 0) const;
00564
00565
00566
00567
00568 static Array<T>
00569 cat (int dim, octave_idx_type n, const Array<T> *array_list);
00570
00571 template <class U, class F>
00572 Array<U>
00573 map (F fcn) const
00574 {
00575 octave_idx_type len = length ();
00576
00577 const T *m = data ();
00578
00579 Array<U> result (dims ());
00580 U *p = result.fortran_vec ();
00581
00582 octave_idx_type i;
00583 for (i = 0; i < len - 3; i += 4)
00584 {
00585 octave_quit ();
00586
00587 p[i] = fcn (m[i]);
00588 p[i+1] = fcn (m[i+1]);
00589 p[i+2] = fcn (m[i+2]);
00590 p[i+3] = fcn (m[i+3]);
00591 }
00592
00593 octave_quit ();
00594
00595 for (; i < len; i++)
00596 p[i] = fcn (m[i]);
00597
00598 return result;
00599 }
00600
00601
00602 template <class U>
00603 Array<U>
00604 map (U (&fcn) (T)) const
00605 { return map<U, U (&) (T)> (fcn); }
00606
00607 template <class U>
00608 Array<U>
00609 map (U (&fcn) (const T&)) const
00610 { return map<U, U (&) (const T&)> (fcn); }
00611
00612
00613 template <class F, bool zero>
00614 bool test (F fcn) const
00615 {
00616 octave_idx_type len = length ();
00617
00618 const T *m = data ();
00619
00620 octave_idx_type i;
00621 for (i = 0; i < len - 3; i += 4)
00622 {
00623 octave_quit ();
00624
00625 if (fcn (m[i]) != zero
00626 || fcn (m[i+1]) != zero
00627 || fcn (m[i+2]) != zero
00628 || fcn (m[i+3]) != zero)
00629 return ! zero;
00630
00631 }
00632
00633 octave_quit ();
00634
00635 for (; i < len; i++)
00636 if (fcn (m[i]) != zero)
00637 return ! zero;
00638
00639 return zero;
00640 }
00641
00642
00643 template <class F>
00644 bool test_any (F fcn) const
00645 { return test<F, false> (fcn); }
00646
00647 template <class F>
00648 bool test_all (F fcn) const
00649 { return test<F, true> (fcn); }
00650
00651
00652 bool test_any (bool (&fcn) (T)) const
00653 { return test<bool (&) (T), false> (fcn); }
00654
00655 bool test_any (bool (&fcn) (const T&)) const
00656 { return test<bool (&) (const T&), false> (fcn); }
00657
00658 bool test_all (bool (&fcn) (T)) const
00659 { return test<bool (&) (T), true> (fcn); }
00660
00661 bool test_all (bool (&fcn) (const T&)) const
00662 { return test<bool (&) (const T&), true> (fcn); }
00663
00664 template <class U> friend class Array;
00665
00666
00667
00668
00669 bool optimize_dimensions (const dim_vector& dv);
00670
00671 private:
00672
00673 void resize2 (octave_idx_type nr, octave_idx_type nc,
00674 const T& rfv = resize_fill_value ());
00675
00676 static void instantiation_guard ();
00677 };
00678
00679
00680
00681
00682
00683
00684
00685 template<class ArrayClass>
00686 class NoAlias : public ArrayClass
00687 {
00688 typedef typename ArrayClass::element_type T;
00689 public:
00690 NoAlias () : ArrayClass () { }
00691
00692
00693 template <class X>
00694 explicit NoAlias (X x) : ArrayClass (x) { }
00695
00696 template <class X, class Y>
00697 explicit NoAlias (X x, Y y) : ArrayClass (x, y) { }
00698
00699 template <class X, class Y, class Z>
00700 explicit NoAlias (X x, Y y, Z z) : ArrayClass (x, y, z) { }
00701
00702 T& operator () (octave_idx_type n)
00703 { return ArrayClass::xelem (n); }
00704 T& operator () (octave_idx_type i, octave_idx_type j)
00705 { return ArrayClass::xelem (i, j); }
00706 T& operator () (octave_idx_type i, octave_idx_type j, octave_idx_type k)
00707 { return ArrayClass::xelem (i, j, k); }
00708 T& operator () (const Array<octave_idx_type>& ra_idx)
00709 { return ArrayClass::xelem (ra_idx); }
00710 };
00711
00712 template <class T>
00713 std::ostream&
00714 operator << (std::ostream& os, const Array<T>& a);
00715
00716 #endif