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