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_idx_vector_h)
00027 #define octave_idx_vector_h 1
00028
00029 #include <cassert>
00030
00031 #include <algorithm>
00032 #include <iosfwd>
00033
00034 #include "dim-vector.h"
00035 #include "oct-inttypes.h"
00036 #include "oct-alloc.h"
00037
00038 template<class T> class Array;
00039 template<class T> class Sparse;
00040 class Range;
00041
00042
00043
00044
00045
00046
00047
00048
00049 class
00050 OCTAVE_API
00051 idx_vector
00052 {
00053 public:
00054
00055 enum idx_class_type
00056 {
00057 class_invalid = -1,
00058 class_colon = 0,
00059 class_range,
00060 class_scalar,
00061 class_vector
00062 };
00063
00064 private:
00065
00066 class OCTAVE_API idx_base_rep
00067 {
00068 public:
00069 idx_base_rep (void) : count (1), err (false) { }
00070
00071 virtual ~idx_base_rep (void) { }
00072
00073
00074 virtual octave_idx_type xelem (octave_idx_type i) const = 0;
00075
00076
00077 virtual octave_idx_type checkelem (octave_idx_type i) const = 0;
00078
00079
00080 virtual octave_idx_type length (octave_idx_type n) const = 0;
00081
00082
00083 virtual octave_idx_type extent (octave_idx_type n) const = 0;
00084
00085
00086 virtual idx_class_type idx_class (void) const { return class_invalid; }
00087
00088
00089 virtual idx_base_rep *sort_uniq_clone (bool uniq = false) = 0;
00090
00091
00092 virtual bool is_colon_equiv (octave_idx_type) const
00093 { return false; }
00094
00095
00096 virtual dim_vector orig_dimensions (void) const
00097 { return dim_vector (); }
00098
00099
00100 virtual std::ostream& print (std::ostream& os) const = 0;
00101
00102 int count;
00103
00104 bool err;
00105
00106 private:
00107
00108
00109 idx_base_rep (const idx_base_rep&);
00110 };
00111
00112
00113 class OCTAVE_API idx_colon_rep : public idx_base_rep
00114 {
00115 public:
00116 idx_colon_rep (void) { }
00117
00118 idx_colon_rep (char c);
00119
00120 octave_idx_type xelem (octave_idx_type i) const
00121 { return i; }
00122
00123 octave_idx_type checkelem (octave_idx_type i) const;
00124
00125 octave_idx_type length (octave_idx_type n) const
00126 { return n; }
00127
00128 octave_idx_type extent (octave_idx_type n) const
00129 { return n; }
00130
00131 idx_class_type idx_class (void) const { return class_colon; }
00132
00133 idx_base_rep *sort_uniq_clone (bool = false)
00134 { count++; return this; }
00135
00136 bool is_colon_equiv (octave_idx_type) const
00137 { return true; }
00138
00139 std::ostream& print (std::ostream& os) const;
00140
00141 private:
00142
00143 DECLARE_OCTAVE_ALLOCATOR
00144
00145
00146 idx_colon_rep (const idx_colon_rep& idx);
00147 };
00148
00149
00150 enum direct { DIRECT };
00151
00152
00153 class OCTAVE_API idx_range_rep : public idx_base_rep
00154 {
00155 public:
00156 idx_range_rep (octave_idx_type _start, octave_idx_type _len,
00157 octave_idx_type _step, direct)
00158 : idx_base_rep (), start(_start), len(_len), step(_step) { }
00159
00160 idx_range_rep (void)
00161 : start(0), len(0), step(1) { }
00162
00163
00164 idx_range_rep (octave_idx_type _start, octave_idx_type _limit,
00165 octave_idx_type _step);
00166
00167 idx_range_rep (const Range&);
00168
00169 octave_idx_type xelem (octave_idx_type i) const
00170 { return start + i * step; }
00171
00172 octave_idx_type checkelem (octave_idx_type i) const;
00173
00174 octave_idx_type length (octave_idx_type) const
00175 { return len; }
00176
00177 octave_idx_type extent (octave_idx_type n) const
00178 { return len ? std::max (n, (start + 1 + (step < 0 ? 0 : step * (len - 1)))) : n; }
00179
00180 idx_class_type idx_class (void) const { return class_range; }
00181
00182 idx_base_rep *sort_uniq_clone (bool uniq = false);
00183
00184 bool is_colon_equiv (octave_idx_type n) const
00185 { return start == 0 && step == 1 && len == n; }
00186
00187 dim_vector orig_dimensions (void) const
00188 { return dim_vector (1, len); }
00189
00190 octave_idx_type get_start (void) const { return start; }
00191
00192 octave_idx_type get_step (void) const { return step; }
00193
00194 std::ostream& print (std::ostream& os) const;
00195
00196 private:
00197
00198 DECLARE_OCTAVE_ALLOCATOR
00199
00200
00201 idx_range_rep (const idx_range_rep& idx);
00202
00203 octave_idx_type start, len, step;
00204
00205 };
00206
00207
00208 class OCTAVE_API idx_scalar_rep : public idx_base_rep
00209 {
00210 public:
00211 idx_scalar_rep (octave_idx_type i, direct)
00212 : data (i) { }
00213
00214 idx_scalar_rep (void)
00215 : data (0) { }
00216
00217
00218 idx_scalar_rep (octave_idx_type i);
00219
00220 template <class T>
00221 idx_scalar_rep (T x);
00222
00223 octave_idx_type xelem (octave_idx_type) const
00224 { return data; }
00225
00226 octave_idx_type checkelem (octave_idx_type i) const;
00227
00228 octave_idx_type length (octave_idx_type) const
00229 { return 1; }
00230
00231 octave_idx_type extent (octave_idx_type n) const
00232 { return std::max (n, data + 1); }
00233
00234 idx_class_type idx_class (void) const { return class_scalar; }
00235
00236 idx_base_rep *sort_uniq_clone (bool = false)
00237 { count++; return this; }
00238
00239 bool is_colon_equiv (octave_idx_type n) const
00240 { return n == 1 && data == 0; }
00241
00242 dim_vector orig_dimensions (void) const
00243 { return dim_vector (1, 1); }
00244
00245 octave_idx_type get_data (void) const { return data; }
00246
00247 std::ostream& print (std::ostream& os) const;
00248
00249 private:
00250
00251 DECLARE_OCTAVE_ALLOCATOR
00252
00253
00254 idx_scalar_rep (const idx_scalar_rep& idx);
00255
00256 octave_idx_type data;
00257
00258 };
00259
00260
00261 class OCTAVE_API idx_vector_rep : public idx_base_rep
00262 {
00263 public:
00264
00265 idx_vector_rep (octave_idx_type *_data, octave_idx_type _len,
00266 octave_idx_type _ext, const dim_vector& od, direct)
00267 : data (_data), len (_len), ext (_ext), aowner (0), orig_dims (od) { }
00268
00269 idx_vector_rep (void)
00270 : data (0), len (0), aowner (0)
00271 { }
00272
00273
00274 idx_vector_rep (const Array<octave_idx_type>& inda);
00275
00276 template <class T>
00277 idx_vector_rep (const Array<T>&);
00278
00279 idx_vector_rep (bool);
00280
00281 idx_vector_rep (const Array<bool>&);
00282
00283 idx_vector_rep (const Sparse<bool>&);
00284
00285 ~idx_vector_rep (void);
00286
00287 octave_idx_type xelem (octave_idx_type i) const
00288 { return data[i]; }
00289
00290 octave_idx_type checkelem (octave_idx_type i) const;
00291
00292 octave_idx_type length (octave_idx_type) const
00293 { return len; }
00294
00295 octave_idx_type extent (octave_idx_type n) const
00296 { return std::max (n, ext); }
00297
00298 idx_class_type idx_class (void) const { return class_vector; }
00299
00300 idx_base_rep *sort_uniq_clone (bool uniq = false);
00301
00302 dim_vector orig_dimensions (void) const
00303 { return orig_dims; }
00304
00305 const octave_idx_type *get_data (void) const { return data; }
00306
00307 std::ostream& print (std::ostream& os) const;
00308
00309 private:
00310
00311 DECLARE_OCTAVE_ALLOCATOR
00312
00313
00314 idx_vector_rep (const idx_vector_rep& idx);
00315
00316 const octave_idx_type *data;
00317 octave_idx_type len, ext;
00318
00319
00320
00321
00322
00323
00324
00325 Array<octave_idx_type> *aowner;
00326
00327 dim_vector orig_dims;
00328 };
00329
00330
00331 idx_vector (idx_base_rep *r) : rep (r) { }
00332
00333
00334 static idx_vector_rep *nil_rep (void)
00335 {
00336 static idx_vector_rep ivr;
00337 return &ivr;
00338 }
00339
00340
00341 static idx_vector_rep *err_rep (void)
00342 {
00343 static idx_vector_rep ivr;
00344 ivr.err = true;
00345 return &ivr;
00346 }
00347
00348
00349
00350 void chkerr (void)
00351 {
00352 if (rep->err)
00353 {
00354 if (--rep->count == 0)
00355 delete rep;
00356 rep = err_rep ();
00357 rep->count++;
00358 }
00359 }
00360
00361 public:
00362
00363
00364 idx_vector (void) : rep (nil_rep ()) { rep->count++; }
00365
00366
00367 idx_vector (octave_idx_type i) : rep (new idx_scalar_rep (i))
00368 { chkerr (); }
00369
00370 idx_vector (octave_idx_type start, octave_idx_type limit,
00371 octave_idx_type step = 1)
00372 : rep (new idx_range_rep (start, limit, step))
00373 { chkerr (); }
00374
00375 static idx_vector
00376 make_range (octave_idx_type start, octave_idx_type step,
00377 octave_idx_type len)
00378 {
00379 return idx_vector (new idx_range_rep (start, len, step, DIRECT));
00380 }
00381
00382 idx_vector (const Array<octave_idx_type>& inda)
00383 : rep (new idx_vector_rep (inda))
00384 { chkerr (); }
00385
00386
00387 static const idx_vector colon;
00388
00389
00390 idx_vector (char c) : rep (new idx_colon_rep (c)) { chkerr (); }
00391
00392
00393
00394 template <class T>
00395 idx_vector (octave_int<T> x) : rep (new idx_scalar_rep (x)) { chkerr (); }
00396
00397 idx_vector (double x) : rep (new idx_scalar_rep (x)) { chkerr (); }
00398
00399 idx_vector (float x) : rep (new idx_scalar_rep (x)) { chkerr (); }
00400
00401
00402 idx_vector (bool x) : rep (new idx_vector_rep (x)) { chkerr (); }
00403
00404 template <class T>
00405 idx_vector (const Array<octave_int<T> >& nda) : rep (new idx_vector_rep (nda))
00406 { chkerr (); }
00407
00408 idx_vector (const Array<double>& nda) : rep (new idx_vector_rep (nda))
00409 { chkerr (); }
00410
00411 idx_vector (const Array<float>& nda) : rep (new idx_vector_rep (nda))
00412 { chkerr (); }
00413
00414 idx_vector (const Array<bool>& nda) : rep (new idx_vector_rep (nda))
00415 { chkerr (); }
00416
00417 idx_vector (const Range& r)
00418 : rep (new idx_range_rep (r))
00419 { chkerr (); }
00420
00421 idx_vector (const Sparse<bool>& nda) : rep (new idx_vector_rep (nda))
00422 { chkerr (); }
00423
00424 idx_vector (const idx_vector& a) : rep (a.rep) { rep->count++; }
00425
00426 ~idx_vector (void)
00427 {
00428 if (--rep->count == 0)
00429 delete rep;
00430 }
00431
00432 idx_vector& operator = (const idx_vector& a)
00433 {
00434 if (this != &a)
00435 {
00436 if (--rep->count == 0)
00437 delete rep;
00438
00439 rep = a.rep;
00440 rep->count++;
00441 }
00442 return *this;
00443 }
00444
00445 idx_class_type idx_class (void) const { return rep->idx_class (); }
00446
00447 octave_idx_type length (octave_idx_type n = 0) const
00448 { return rep->length (n); }
00449
00450 octave_idx_type extent (octave_idx_type n) const
00451 { return rep->extent (n); }
00452
00453 octave_idx_type xelem (octave_idx_type n) const
00454 { return rep->xelem (n); }
00455
00456 octave_idx_type checkelem (octave_idx_type n) const
00457 { return rep->checkelem (n); }
00458
00459 octave_idx_type operator () (octave_idx_type n) const
00460 {
00461 #if defined (BOUNDS_CHECKING)
00462 return rep->checkelem (n);
00463 #else
00464 return rep->xelem (n);
00465 #endif
00466 }
00467
00468 operator bool (void) const
00469 { return ! rep->err; }
00470
00471 bool is_colon (void) const
00472 { return rep->idx_class () == class_colon; }
00473
00474 bool is_scalar (void) const
00475 { return rep->idx_class () == class_scalar; }
00476
00477 bool is_range (void) const
00478 { return rep->idx_class () == class_range; }
00479
00480 bool is_colon_equiv (octave_idx_type n) const
00481 { return rep->is_colon_equiv (n); }
00482
00483 idx_vector sorted (bool uniq = false) const
00484 { return idx_vector (rep->sort_uniq_clone (uniq)); }
00485
00486 dim_vector orig_dimensions (void) const { return rep->orig_dimensions (); }
00487
00488 octave_idx_type orig_rows (void) const
00489 { return orig_dimensions () (0); }
00490
00491 octave_idx_type orig_columns (void) const
00492 { return orig_dimensions () (1); }
00493
00494 int orig_empty (void) const
00495 { return (! is_colon () && orig_dimensions().any_zero ()); }
00496
00497
00498
00499 std::ostream& print (std::ostream& os) const { return rep->print (os); }
00500
00501 friend std::ostream& operator << (std::ostream& os, const idx_vector& a)
00502 { return a.print (os); }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 template <class T>
00513 octave_idx_type
00514 index (const T *src, octave_idx_type n, T *dest) const
00515 {
00516 octave_idx_type len = rep->length (n);
00517 switch (rep->idx_class ())
00518 {
00519 case class_colon:
00520 std::copy (src, src + len, dest);
00521 break;
00522 case class_range:
00523 {
00524 idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
00525 octave_idx_type start = r->get_start (), step = r->get_step ();
00526 const T *ssrc = src + start;
00527 if (step == 1)
00528 std::copy (ssrc, ssrc + len, dest);
00529 else if (step == -1)
00530 std::reverse_copy (ssrc - len + 1, ssrc + 1, dest);
00531 else if (step == 0)
00532 std::fill_n (dest, len, *ssrc);
00533 else
00534 {
00535 for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
00536 dest[i] = ssrc[j];
00537 }
00538 }
00539 break;
00540 case class_scalar:
00541 {
00542 idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
00543 dest[0] = src[r->get_data ()];
00544 }
00545 break;
00546 case class_vector:
00547 {
00548 idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
00549 const octave_idx_type *data = r->get_data ();
00550 for (octave_idx_type i = 0; i < len; i++)
00551 dest[i] = src[data[i]];
00552 }
00553 break;
00554 default:
00555 assert (false);
00556 break;
00557 }
00558
00559 return len;
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 template <class T>
00571 octave_idx_type
00572 assign (const T *src, octave_idx_type n, T *dest) const
00573 {
00574 octave_idx_type len = rep->length (n);
00575 switch (rep->idx_class ())
00576 {
00577 case class_colon:
00578 std::copy (src, src + len, dest);
00579 break;
00580 case class_range:
00581 {
00582 idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
00583 octave_idx_type start = r->get_start (), step = r->get_step ();
00584 T *sdest = dest + start;
00585 if (step == 1)
00586 std::copy (src, src + len, sdest);
00587 else if (step == -1)
00588 std::reverse_copy (src, src + len, sdest - len + 1);
00589 else
00590 {
00591 for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
00592 sdest[j] = src[i];
00593 }
00594 }
00595 break;
00596 case class_scalar:
00597 {
00598 idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
00599 dest[r->get_data ()] = src[0];
00600 }
00601 break;
00602 case class_vector:
00603 {
00604 idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
00605 const octave_idx_type *data = r->get_data ();
00606 for (octave_idx_type i = 0; i < len; i++)
00607 dest[data[i]] = src[i];
00608 }
00609 break;
00610 default:
00611 assert (false);
00612 break;
00613 }
00614
00615 return len;
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 template <class T>
00627 octave_idx_type
00628 fill (const T& val, octave_idx_type n, T *dest) const
00629 {
00630 octave_idx_type len = rep->length (n);
00631 switch (rep->idx_class ())
00632 {
00633 case class_colon:
00634 std::fill (dest, dest + len, val);
00635 break;
00636 case class_range:
00637 {
00638 idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
00639 octave_idx_type start = r->get_start (), step = r->get_step ();
00640 T *sdest = dest + start;
00641 if (step == 1)
00642 std::fill (sdest, sdest + len, val);
00643 else if (step == -1)
00644 std::fill (sdest - len + 1, sdest + 1, val);
00645 else
00646 {
00647 for (octave_idx_type i = 0, j = 0; i < len; i++, j += step)
00648 sdest[j] = val;
00649 }
00650 }
00651 break;
00652 case class_scalar:
00653 {
00654 idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
00655 dest[r->get_data ()] = val;
00656 }
00657 break;
00658 case class_vector:
00659 {
00660 idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
00661 const octave_idx_type *data = r->get_data ();
00662 for (octave_idx_type i = 0; i < len; i++)
00663 dest[data[i]] = val;
00664 }
00665 break;
00666 default:
00667 assert (false);
00668 break;
00669 }
00670
00671 return len;
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682 template <class Functor>
00683 void
00684 loop (octave_idx_type n, Functor body) const
00685 {
00686 octave_idx_type len = rep->length (n);
00687 switch (rep->idx_class ())
00688 {
00689 case class_colon:
00690 for (octave_idx_type i = 0; i < len; i++) body (i);
00691 break;
00692 case class_range:
00693 {
00694 idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
00695 octave_idx_type start = r->get_start (), step = r->get_step ();
00696 octave_idx_type i, j;
00697 if (step == 1)
00698 for (i = start, j = start + len; i < j; i++) body (i);
00699 else if (step == -1)
00700 for (i = start, j = start - len; i > j; i--) body (i);
00701 else
00702 for (i = 0, j = start; i < len; i++, j += step) body (j);
00703 }
00704 break;
00705 case class_scalar:
00706 {
00707 idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
00708 body (r->get_data ());
00709 }
00710 break;
00711 case class_vector:
00712 {
00713 idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
00714 const octave_idx_type *data = r->get_data ();
00715 for (octave_idx_type i = 0; i < len; i++) body (data[i]);
00716 }
00717 break;
00718 default:
00719 assert (false);
00720 break;
00721 }
00722
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 template <class Functor>
00736 octave_idx_type
00737 bloop (octave_idx_type n, Functor body) const
00738 {
00739 octave_idx_type len = rep->length (n), ret;
00740 switch (rep->idx_class ())
00741 {
00742 case class_colon:
00743 {
00744 octave_idx_type i;
00745 for (i = 0; i < len && body (i); i++) ;
00746 ret = i;
00747 }
00748 break;
00749 case class_range:
00750 {
00751 idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
00752 octave_idx_type start = r->get_start (), step = r->get_step ();
00753 octave_idx_type i, j;
00754 if (step == 1)
00755 for (i = start, j = start + len; i < j && body (i); i++) ;
00756 else if (step == -1)
00757 for (i = start, j = start - len; i > j && body (i); i--) ;
00758 else
00759 for (i = 0, j = start; i < len && body (j); i++, j += step) ;
00760 ret = i;
00761 }
00762 break;
00763 case class_scalar:
00764 {
00765 idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
00766 ret = body (r->get_data ()) ? 1 : 0;
00767 }
00768 break;
00769 case class_vector:
00770 {
00771 idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
00772 const octave_idx_type *data = r->get_data ();
00773 octave_idx_type i;
00774 for (i = 0; i < len && body (data[i]); i++) ;
00775 ret = i;
00776 }
00777 break;
00778 default:
00779 assert (false);
00780 break;
00781 }
00782
00783 return ret;
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793 bool maybe_reduce (octave_idx_type n, const idx_vector& j,
00794 octave_idx_type nj);
00795
00796 bool is_cont_range (octave_idx_type n,
00797 octave_idx_type& l, octave_idx_type& u) const;
00798
00799
00800
00801 octave_idx_type increment (void) const;
00802
00803 idx_vector
00804 complement (octave_idx_type n) const;
00805
00806 bool is_permutation (octave_idx_type n) const;
00807
00808
00809 void copy_data (octave_idx_type *data) const;
00810
00811
00812 void unconvert (idx_class_type& iclass,
00813 double& scalar, Range& range, Array<double>& array) const;
00814
00815
00816
00817
00818 octave_idx_type elem (octave_idx_type n) const
00819 { return (*this) (n); }
00820
00821 bool is_colon_equiv (octave_idx_type n, int) const
00822 { return is_colon_equiv (n); }
00823
00824 octave_idx_type
00825 freeze (octave_idx_type z_len, const char *tag, bool resize_ok = false);
00826
00827 void sort (bool uniq = false)
00828 { *this = sorted (uniq); }
00829
00830 octave_idx_type ones_count (void) const;
00831
00832 octave_idx_type max (void) const { return extent (1) - 1; }
00833
00834 private:
00835
00836 idx_base_rep *rep;
00837
00838 };
00839
00840 #endif
00841
00842
00843
00844
00845
00846