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