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_vector.h>
00010 #include <vcl_stdexcept.h>
00011 #include <vcl_iterator.h>
00012 #include <vcl_string.h>
00013 #include <vcl_iosfwd.h>
00014 
00015 //: Defines a binary mask
00016 class mbl_mask : public vcl_vector<bool>
00017 {
00018  public:
00019   mbl_mask() : vcl_vector<bool>() {}
00020   mbl_mask(unsigned n, bool val = false) : vcl_vector<bool>(n, val) {}
00021 };
00022 
00023 //: Given a collection of indices, produce a collection of masks that isolate each indexed set
00024 //    The input index set does not need to be zero based or continuous
00025 //    The output vector of masks is sorted by corresponding index
00026 //    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)
00027 //    which correspond to the index sets 1,2,4
00028 void mbl_masks_from_index_set(const vcl_vector<unsigned> & indices,
00029                               vcl_vector<mbl_mask> & masks);
00030 
00031 
00032 //: Replace 'true' values in B with values taken from A. size of A must match 'true' count in B
00033 void mbl_mask_on_mask(const mbl_mask & A, mbl_mask & B);
00034 
00035 
00036 //: Merge two input ranges according to a mask ('false' indicates element drawn from range 1, 'true' from range 2)
00037 template <typename ForwardIterator>
00038 void mbl_mask_merge_values(const mbl_mask & mask,
00039                            ForwardIterator first1, ForwardIterator last1,
00040                            ForwardIterator first2, ForwardIterator last2,
00041                            ForwardIterator result)
00042 {
00043   if (vcl_distance(first1, last1) != (int)mask.size() || vcl_distance(first2, last2) != (int)mask.size())
00044     throw vcl_runtime_error("Values and mask lengths differ");
00045 
00046   for (unsigned n = 0 ; first1 != last1 ; ++first1, ++first2, ++n)
00047     *result++ = mask[n] ? *first2 : *first1;
00048 }
00049 
00050 //: Apply a general logical operation between two masks
00051 void mbl_mask_logic(const mbl_mask & A, mbl_mask & B, const vcl_string & operation);
00052 
00053 //: Apply an "AND" (rule 0001) logical operation between two masks
00054 void mbl_mask_logic_and(const mbl_mask & A, mbl_mask & B);
00055 
00056 //: Apply an "OR" (rule 0111) logical operation between two masks
00057 void mbl_mask_logic_or(const mbl_mask & A, mbl_mask & B);
00058 
00059 //: Apply an "XOR" (rule 0110) logical operation between two masks
00060 void mbl_mask_logic_xor(const mbl_mask & A, mbl_mask & B);
00061 
00062 //: Apply a "NOR" (rule 1000) logical operation between two masks
00063 void mbl_mask_logic_nor(const mbl_mask & A, mbl_mask & B);
00064 
00065 //: Apply an "XNOR" (rule 1001) logical operation between two masks
00066 void mbl_mask_logic_xnor(const mbl_mask & A, mbl_mask & B);
00067 
00068 //: Apply an "NAND" (rule 1110) logical operation between two masks
00069 void mbl_mask_logic_nand(const mbl_mask & A, mbl_mask & B);
00070 
00071 //: Apply a mask to a range of values. Result inserted at 'target'
00072 template <typename ForwardIterator, typename OutputIterator>
00073 void mbl_apply_mask(const mbl_mask & mask, ForwardIterator first, ForwardIterator last, OutputIterator target)
00074 {
00075   if (vcl_distance(first, last) != (int)mask.size())
00076     throw vcl_runtime_error("Values and mask lengths differ");
00077 
00078   for (unsigned n = 0; first != last ; ++first, ++n)
00079     if (mask[n]) *target++ = *first;
00080 }
00081 
00082 //: Apply a mask to a vector, returning a new vector
00083 // This can be inefficient. See mbl_apply_mask(mask, src, dst)  for an alternative.
00084 template <typename T>
00085 vcl_vector<T> mbl_apply_mask(const mbl_mask & mask, const vcl_vector<T> & values)
00086 {
00087   vcl_vector<T> retval(values);
00088   mbl_apply_mask(mask, retval);
00089   return retval;
00090 }
00091 
00092 //: Apply a mask to a vector, returning a new vector
00093 // \param mask The mask to apply.
00094 // \param src The source vector.
00095 // \retval dst The destination vector (existing contents will be lost).
00096 template <typename T>
00097 void mbl_apply_mask(const mbl_mask & mask, const vcl_vector<T> & src, vcl_vector<T> & dst)
00098 {
00099   const unsigned n_in = src.size();
00100   if (mask.size() != n_in)
00101     throw vcl_runtime_error("src and mask lengths differ");
00102 
00103   dst.clear();
00104   dst.reserve(n_in); // this is the maximum size we might need
00105   for (unsigned i=0; i<n_in; ++i)
00106   {
00107     if (mask[i])
00108     {
00109       dst.push_back(src[i]);
00110     }
00111   }
00112 }
00113 
00114 //: Apply a mask to a vector in-place
00115 template <typename T>
00116 void mbl_apply_mask(const mbl_mask & mask, vcl_vector<T> & values)
00117 {
00118   const unsigned n_in = values.size();
00119   if (mask.size() != n_in)
00120     throw vcl_runtime_error("Values and mask lengths differ");
00121 
00122   unsigned n_out = 0;
00123   for (unsigned i = 0 ; i < n_in ; ++i)
00124   {
00125     if (mask[i])
00126     {
00127       values[n_out] = values[i];
00128       ++n_out;
00129     }
00130   }
00131   values.resize(n_out);
00132 }
00133 
00134 //: Save to file
00135 void mbl_save_mask(const mbl_mask & mask, vcl_ostream & stream);
00136 
00137 //: Save to file
00138 void mbl_save_mask(const mbl_mask & mask, const char * filename);
00139 
00140 //: Save to file
00141 void mbl_save_mask(const mbl_mask & mask, const vcl_string &filename);
00142 
00143 //: Load from file
00144 void mbl_load_mask(mbl_mask & mask, vcl_istream & stream);
00145 
00146 //: Load from file
00147 void mbl_load_mask(mbl_mask & mask, const char * filename);
00148 
00149 
00150 #endif // mbl_mask_h_