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