Mercurial > hg > octave-lyh
comparison liboctave/idx-vector.h @ 9879:034677ab6865
smarter treatment of mask indexing
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Fri, 27 Nov 2009 14:42:07 +0100 |
parents | 6dafc60dde31 |
children | cddd5c3d5f04 |
comparison
equal
deleted
inserted
replaced
9878:ead4f9c82a9a | 9879:034677ab6865 |
---|---|
57 { | 57 { |
58 class_invalid = -1, | 58 class_invalid = -1, |
59 class_colon = 0, | 59 class_colon = 0, |
60 class_range, | 60 class_range, |
61 class_scalar, | 61 class_scalar, |
62 class_vector | 62 class_vector, |
63 class_mask | |
63 }; | 64 }; |
64 | 65 |
65 private: | 66 private: |
66 | 67 |
67 class OCTAVE_API idx_base_rep | 68 class OCTAVE_API idx_base_rep |
277 template <class T> | 278 template <class T> |
278 idx_vector_rep (const Array<T>&); | 279 idx_vector_rep (const Array<T>&); |
279 | 280 |
280 idx_vector_rep (bool); | 281 idx_vector_rep (bool); |
281 | 282 |
282 idx_vector_rep (const Array<bool>&); | 283 idx_vector_rep (const Array<bool>&, octave_idx_type = -1); |
283 | 284 |
284 idx_vector_rep (const Sparse<bool>&); | 285 idx_vector_rep (const Sparse<bool>&); |
285 | 286 |
286 ~idx_vector_rep (void); | 287 ~idx_vector_rep (void); |
287 | 288 |
326 Array<octave_idx_type> *aowner; | 327 Array<octave_idx_type> *aowner; |
327 | 328 |
328 dim_vector orig_dims; | 329 dim_vector orig_dims; |
329 }; | 330 }; |
330 | 331 |
332 // The logical mask index. | |
333 class OCTAVE_API idx_mask_rep : public idx_base_rep | |
334 { | |
335 public: | |
336 // Direct constructor. | |
337 idx_mask_rep (bool *_data, octave_idx_type _len, | |
338 octave_idx_type _ext, const dim_vector& od, direct) | |
339 : data (_data), len (_len), ext (_ext), aowner (0), orig_dims (od) { } | |
340 | |
341 idx_mask_rep (void) | |
342 : data (0), len (0), aowner (0) | |
343 { } | |
344 | |
345 idx_mask_rep (bool); | |
346 | |
347 idx_mask_rep (const Array<bool>&, octave_idx_type = -1); | |
348 | |
349 ~idx_mask_rep (void); | |
350 | |
351 octave_idx_type xelem (octave_idx_type i) const; | |
352 | |
353 octave_idx_type checkelem (octave_idx_type i) const; | |
354 | |
355 octave_idx_type length (octave_idx_type) const | |
356 { return len; } | |
357 | |
358 octave_idx_type extent (octave_idx_type n) const | |
359 { return std::max (n, ext); } | |
360 | |
361 idx_class_type idx_class (void) const { return class_mask; } | |
362 | |
363 idx_base_rep *sort_uniq_clone (bool = false) | |
364 { count++; return this; } | |
365 | |
366 dim_vector orig_dimensions (void) const | |
367 { return orig_dims; } | |
368 | |
369 bool is_colon_equiv (octave_idx_type n) const | |
370 { return count == n && ext == n; } | |
371 | |
372 const bool *get_data (void) const { return data; } | |
373 | |
374 std::ostream& print (std::ostream& os) const; | |
375 | |
376 private: | |
377 | |
378 DECLARE_OCTAVE_ALLOCATOR | |
379 | |
380 // No copying! | |
381 idx_mask_rep (const idx_mask_rep& idx); | |
382 | |
383 const bool *data; | |
384 octave_idx_type len, ext; | |
385 | |
386 // FIXME: I'm not sure if this is a good design. Maybe it would be better to | |
387 // employ some sort of generalized iteration scheme. | |
388 mutable octave_idx_type lsti, lste; | |
389 | |
390 // This is a trick to allow user-given mask arrays to be used as indices | |
391 // without copying. If the following pointer is nonzero, we do not own the data, | |
392 // but rather have an Array<bool> object that provides us the data. | |
393 // Note that we need a pointer because we deferred the Array<T> declaration and | |
394 // we do not want it yet to be defined. | |
395 | |
396 Array<bool> *aowner; | |
397 | |
398 dim_vector orig_dims; | |
399 }; | |
331 | 400 |
332 idx_vector (idx_base_rep *r) : rep (r) { } | 401 idx_vector (idx_base_rep *r) : rep (r) { } |
333 | 402 |
334 // The shared empty vector representation (for fast default constructor) | 403 // The shared empty vector representation (for fast default constructor) |
335 static idx_vector_rep *nil_rep (void) | 404 static idx_vector_rep *nil_rep (void) |
398 idx_vector (double x) : rep (new idx_scalar_rep (x)) { chkerr (); } | 467 idx_vector (double x) : rep (new idx_scalar_rep (x)) { chkerr (); } |
399 | 468 |
400 idx_vector (float x) : rep (new idx_scalar_rep (x)) { chkerr (); } | 469 idx_vector (float x) : rep (new idx_scalar_rep (x)) { chkerr (); } |
401 | 470 |
402 // A scalar bool does not necessarily map to scalar index. | 471 // A scalar bool does not necessarily map to scalar index. |
403 idx_vector (bool x) : rep (new idx_vector_rep (x)) { chkerr (); } | 472 idx_vector (bool x) : rep (new idx_mask_rep (x)) { chkerr (); } |
404 | 473 |
405 template <class T> | 474 template <class T> |
406 idx_vector (const Array<octave_int<T> >& nda) : rep (new idx_vector_rep (nda)) | 475 idx_vector (const Array<octave_int<T> >& nda) : rep (new idx_vector_rep (nda)) |
407 { chkerr (); } | 476 { chkerr (); } |
408 | 477 |
410 { chkerr (); } | 479 { chkerr (); } |
411 | 480 |
412 idx_vector (const Array<float>& nda) : rep (new idx_vector_rep (nda)) | 481 idx_vector (const Array<float>& nda) : rep (new idx_vector_rep (nda)) |
413 { chkerr (); } | 482 { chkerr (); } |
414 | 483 |
415 idx_vector (const Array<bool>& nda) : rep (new idx_vector_rep (nda)) | 484 idx_vector (const Array<bool>& nda); |
416 { chkerr (); } | |
417 | 485 |
418 idx_vector (const Range& r) | 486 idx_vector (const Range& r) |
419 : rep (new idx_range_rep (r)) | 487 : rep (new idx_range_rep (r)) |
420 { chkerr (); } | 488 { chkerr (); } |
421 | 489 |
550 const octave_idx_type *data = r->get_data (); | 618 const octave_idx_type *data = r->get_data (); |
551 for (octave_idx_type i = 0; i < len; i++) | 619 for (octave_idx_type i = 0; i < len; i++) |
552 dest[i] = src[data[i]]; | 620 dest[i] = src[data[i]]; |
553 } | 621 } |
554 break; | 622 break; |
623 case class_mask: | |
624 { | |
625 idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep); | |
626 const bool *data = r->get_data (); | |
627 octave_idx_type ext = r->extent (0); | |
628 for (octave_idx_type i = 0; i < ext; i++) | |
629 if (data[i]) *dest++ = src[i]; | |
630 } | |
631 break; | |
555 default: | 632 default: |
556 assert (false); | 633 assert (false); |
557 break; | 634 break; |
558 } | 635 } |
559 | 636 |
606 const octave_idx_type *data = r->get_data (); | 683 const octave_idx_type *data = r->get_data (); |
607 for (octave_idx_type i = 0; i < len; i++) | 684 for (octave_idx_type i = 0; i < len; i++) |
608 dest[data[i]] = src[i]; | 685 dest[data[i]] = src[i]; |
609 } | 686 } |
610 break; | 687 break; |
688 case class_mask: | |
689 { | |
690 idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep); | |
691 const bool *data = r->get_data (); | |
692 octave_idx_type ext = r->extent (0); | |
693 for (octave_idx_type i = 0; i < ext; i++) | |
694 if (data[i]) dest[i] = *src++; | |
695 } | |
696 break; | |
611 default: | 697 default: |
612 assert (false); | 698 assert (false); |
613 break; | 699 break; |
614 } | 700 } |
615 | 701 |
662 const octave_idx_type *data = r->get_data (); | 748 const octave_idx_type *data = r->get_data (); |
663 for (octave_idx_type i = 0; i < len; i++) | 749 for (octave_idx_type i = 0; i < len; i++) |
664 dest[data[i]] = val; | 750 dest[data[i]] = val; |
665 } | 751 } |
666 break; | 752 break; |
753 case class_mask: | |
754 { | |
755 idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep); | |
756 const bool *data = r->get_data (); | |
757 octave_idx_type ext = r->extent (0); | |
758 for (octave_idx_type i = 0; i < ext; i++) | |
759 if (data[i]) dest[i] = val; | |
760 } | |
761 break; | |
667 default: | 762 default: |
668 assert (false); | 763 assert (false); |
669 break; | 764 break; |
670 } | 765 } |
671 | 766 |
712 case class_vector: | 807 case class_vector: |
713 { | 808 { |
714 idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep); | 809 idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep); |
715 const octave_idx_type *data = r->get_data (); | 810 const octave_idx_type *data = r->get_data (); |
716 for (octave_idx_type i = 0; i < len; i++) body (data[i]); | 811 for (octave_idx_type i = 0; i < len; i++) body (data[i]); |
812 } | |
813 break; | |
814 case class_mask: | |
815 { | |
816 idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep); | |
817 const bool *data = r->get_data (); | |
818 octave_idx_type ext = r->extent (0); | |
819 for (octave_idx_type i = 0, j = 0; i < ext; i++) | |
820 if (data[i]) body (j++); | |
717 } | 821 } |
718 break; | 822 break; |
719 default: | 823 default: |
720 assert (false); | 824 assert (false); |
721 break; | 825 break; |
774 octave_idx_type i; | 878 octave_idx_type i; |
775 for (i = 0; i < len && body (data[i]); i++) ; | 879 for (i = 0; i < len && body (data[i]); i++) ; |
776 ret = i; | 880 ret = i; |
777 } | 881 } |
778 break; | 882 break; |
883 case class_mask: | |
884 { | |
885 idx_mask_rep * r = dynamic_cast<idx_mask_rep *> (rep); | |
886 const bool *data = r->get_data (); | |
887 octave_idx_type ext = r->extent (0), j = 0; | |
888 for (octave_idx_type i = 0; i < ext; i++) | |
889 if (data[i] && body (j++)) | |
890 break; | |
891 ret = j; | |
892 } | |
893 break; | |
779 default: | 894 default: |
780 assert (false); | 895 assert (false); |
781 break; | 896 break; |
782 } | 897 } |
783 | 898 |
807 bool is_permutation (octave_idx_type n) const; | 922 bool is_permutation (octave_idx_type n) const; |
808 | 923 |
809 // Copies all the indices to a given array. Not allowed for colons. | 924 // Copies all the indices to a given array. Not allowed for colons. |
810 void copy_data (octave_idx_type *data) const; | 925 void copy_data (octave_idx_type *data) const; |
811 | 926 |
927 // If the index is a mask, convert it to index vector. | |
928 idx_vector unmask (void) const; | |
929 | |
812 // Unconverts the index to a scalar, Range or double array. | 930 // Unconverts the index to a scalar, Range or double array. |
931 // Note that the index class can be changed, if it's a mask index. | |
813 void unconvert (idx_class_type& iclass, | 932 void unconvert (idx_class_type& iclass, |
814 double& scalar, Range& range, Array<double>& array) const; | 933 double& scalar, Range& range, Array<double>& array); |
815 | 934 |
816 // FIXME -- these are here for compatibility. They should be removed | 935 // FIXME -- these are here for compatibility. They should be removed |
817 // when no longer in use. | 936 // when no longer in use. |
818 | 937 |
819 octave_idx_type elem (octave_idx_type n) const | 938 octave_idx_type elem (octave_idx_type n) const |