contrib/mul/mbl/mbl_mask.h
Go to the documentation of this file.
00001 // This is mul/mbl/mbl_mask.h
00002 #ifndef mbl_mask_h_
00003 #define mbl_mask_h_
00004 //:
00005 // \file
00006 // \author Barry Skellern
00007 // \brief Class representing a binary mask, and related functions
00008 
00009 #include <vcl_algorithm.h>
00010 #include <vcl_vector.h>
00011 #include <vcl_stdexcept.h>
00012 #include <vcl_iterator.h>
00013 #include <vcl_string.h>
00014 #include <vcl_iosfwd.h>
00015 
00016 //: Defines a binary mask
00017 class mbl_mask : public vcl_vector<bool>
00018 {
00019  public:
00020   mbl_mask() : vcl_vector<bool>() {}
00021   mbl_mask(unsigned n, bool val = false) : vcl_vector<bool>(n, val) {}
00022 };
00023 
00024 //: Given a collection of indices, produce a collection of masks that isolate each indexed set
00025 //    The input index set does not need to be zero based or continuous
00026 //    The output vector of masks is sorted by corresponding index
00027 //    for example: (1,4,2,1,2) will make three masks: (1,0,0,1,0), (0,0,1,0,1) and (0,1,0,0,0)
00028 //    which correspond to the index sets 1,2,4
00029 void mbl_masks_from_index_set(const vcl_vector<unsigned> & indices,
00030                               vcl_vector<mbl_mask> & masks);
00031 
00032 
00033 //: Replace 'true' values in B with values taken from A. size of A must match 'true' count in B
00034 void mbl_mask_on_mask(const mbl_mask & A, mbl_mask & B);
00035 
00036 
00037 //: Merge two input ranges according to a mask ('false' indicates element drawn from range 1, 'true' from range 2)
00038 template <typename ForwardIterator>
00039 void mbl_mask_merge_values(const mbl_mask & mask,
00040                            ForwardIterator first1, ForwardIterator last1,
00041                            ForwardIterator first2, ForwardIterator last2,
00042                            ForwardIterator result)
00043 {
00044   if (vcl_distance(first1, last1) != (int)mask.size() || vcl_distance(first2, last2) != (int)mask.size())
00045     throw vcl_out_of_range("Values and mask lengths differ");
00046 
00047   for (unsigned n = 0 ; first1 != last1 ; ++first1, ++first2, ++n)
00048     *result++ = mask[n] ? *first2 : *first1;
00049 }
00050 
00051 //: Apply a general logical operation between two masks
00052 void mbl_mask_logic(const mbl_mask & A, mbl_mask & B, const vcl_string & operation);
00053 
00054 //: Apply an "AND" (rule 0001) logical operation between two masks
00055 void mbl_mask_logic_and(const mbl_mask & A, mbl_mask & B);
00056 
00057 //: Apply an "OR" (rule 0111) logical operation between two masks
00058 void mbl_mask_logic_or(const mbl_mask & A, mbl_mask & B);
00059 
00060 //: Apply an "XOR" (rule 0110) logical operation between two masks
00061 void mbl_mask_logic_xor(const mbl_mask & A, mbl_mask & B);
00062 
00063 //: Apply a "NOR" (rule 1000) logical operation between two masks
00064 void mbl_mask_logic_nor(const mbl_mask & A, mbl_mask & B);
00065 
00066 //: Apply an "XNOR" (rule 1001) logical operation between two masks
00067 void mbl_mask_logic_xnor(const mbl_mask & A, mbl_mask & B);
00068 
00069 //: Apply an "NAND" (rule 1110) logical operation between two masks
00070 void mbl_mask_logic_nand(const mbl_mask & A, mbl_mask & B);
00071 
00072 //: Apply a mask to a range of values. Result inserted at 'target'
00073 template <typename ForwardIterator, typename OutputIterator>
00074 void mbl_apply_mask(const mbl_mask & mask, ForwardIterator first, ForwardIterator last, OutputIterator target)
00075 {
00076   if (vcl_distance(first, last) != (int)mask.size())
00077     throw vcl_out_of_range("Values and mask lengths differ");
00078 
00079   for (unsigned n = 0; first != last ; ++first, ++n)
00080     if (mask[n]) *target++ = *first;
00081 }
00082 
00083 //: Apply a mask to a vector, returning a new vector
00084 // This can be inefficient. See mbl_apply_mask(mask, src, dst)  for an alternative.
00085 template <typename T>
00086 vcl_vector<T> mbl_apply_mask(const mbl_mask & mask, const vcl_vector<T> & values)
00087 {
00088   vcl_vector<T> retval(values);
00089   mbl_apply_mask(mask, retval);
00090   return retval;
00091 }
00092 
00093 //: Apply a mask to a vector, returning a new vector
00094 // \param mask The mask to apply.
00095 // \param src The source vector.
00096 // \retval dst The destination vector (existing contents will be lost).
00097 template <typename T>
00098 void mbl_apply_mask(const mbl_mask & mask, const vcl_vector<T> & src, vcl_vector<T> & dst)
00099 {
00100   const unsigned n_in = src.size();
00101   if (mask.size() != n_in)
00102     throw vcl_out_of_range("src and mask lengths differ");
00103 
00104   dst.clear();
00105   dst.reserve(n_in); // this is the maximum size we might need
00106   for (unsigned i=0; i<n_in; ++i)
00107   {
00108     if (mask[i])
00109     {
00110       dst.push_back(src[i]);
00111     }
00112   }
00113 }
00114 
00115 //: Use a mask to replace some values in a vector
00116 // \param mask The mask to apply.
00117 // \param src1 The source vector to be updated.
00118 // \param src2 The source vector to be updated with.
00119 // \retval dst The destination vector (existing contents will be lost).
00120 template <typename T>
00121 void mbl_replace_using_mask(const mbl_mask & mask, const vcl_vector<T> & src1, const vcl_vector<T> & src2, vcl_vector<T> & dst)
00122 {
00123   const unsigned n_in = src1.size();
00124   if (mask.size() != n_in)
00125     throw vcl_out_of_range("src1 and mask lengths differ");
00126 
00127   unsigned n_true = vcl_count( mask.begin(), mask.end(), true );
00128   if ( n_true != src2.size() )
00129     throw vcl_out_of_range("src2 and mask are not compatible");
00130 
00131   vcl_vector<T> dst_tmp;
00132   dst_tmp.clear();
00133   dst_tmp.reserve(n_in); // this is the maximum size we might need
00134   unsigned j = 0;
00135   for (unsigned i=0; i<n_in; ++i)
00136   {
00137     if (mask[i])
00138     {
00139       dst_tmp.push_back(src2[j]);
00140       ++j;
00141     }
00142     else
00143       dst_tmp.push_back(src1[i]);
00144   }
00145   dst = dst_tmp;
00146 }
00147 
00148 //: Apply a mask to a vector in-place
00149 template <typename T>
00150 void mbl_apply_mask(const mbl_mask & mask, vcl_vector<T> & values)
00151 {
00152   const unsigned n_in = values.size();
00153   if (mask.size() != n_in)
00154     throw vcl_out_of_range("Values and mask lengths differ");
00155 
00156   unsigned n_out = 0;
00157   for (unsigned i = 0 ; i < n_in ; ++i)
00158   {
00159     if (mask[i])
00160     {
00161       values[n_out] = values[i];
00162       ++n_out;
00163     }
00164   }
00165   values.resize(n_out);
00166 }
00167 
00168 //: Save to file
00169 void mbl_save_mask(const mbl_mask & mask, vcl_ostream & stream);
00170 
00171 //: Save to file
00172 void mbl_save_mask(const mbl_mask & mask, const char * filename);
00173 
00174 //: Save to file
00175 void mbl_save_mask(const mbl_mask & mask, const vcl_string &filename);
00176 
00177 //: Load from file
00178 void mbl_load_mask(mbl_mask & mask, vcl_istream & stream);
00179 
00180 //: Load from file
00181 void mbl_load_mask(mbl_mask & mask, const char * filename);
00182 
00183 //: Load from file
00184 void mbl_load_mask(mbl_mask & mask, const vcl_string &filename);
00185 
00186 //: Convert a mask to a list of indices.
00187 // \param mask Input mask.
00188 // \retval inds List of (zero-based) indices i where mask[i]==true.
00189 void mbl_mask_to_indices(const mbl_mask& mask, vcl_vector<unsigned>& inds);
00190 
00191 //: Convert a list of indices to a mask.
00192 // \param inds List of (zero-based) indices.
00193 // \param n The length of the output mask.
00194 // \retval mask Output mask. mask[i]==true for all i in \a inds
00195 void mbl_indices_to_mask(const vcl_vector<unsigned>& inds,
00196                          const unsigned n,
00197                          mbl_mask& mask);
00198 
00199 
00200 #endif // mbl_mask_h_