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