ivl 679
ivl/details/set/set_functions.hpp
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>.
00002    A C++ template library extending syntax towards mathematical notation.
00003 
00004    Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr>
00005    Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr>
00006 
00007    ivl is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU Lesser General Public License 
00009    version 3 as published by the Free Software Foundation.
00010 
00011    Alternatively, you can redistribute it and/or modify it under the terms 
00012    of the GNU General Public License version 2 as published by the Free 
00013    Software Foundation.
00014 
00015    ivl is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00018    See the GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License 
00021    and a copy of the GNU Lesser General Public License along 
00022    with ivl. If not, see <http://www.gnu.org/licenses/>. */
00023 
00024 #ifndef IVL_SET_DETAILS_SET_FUNCTIONS_HPP
00025 #define IVL_SET_DETAILS_SET_FUNCTIONS_HPP
00026 
00027 #undef min
00028 
00029 #include "../../../ivl/array.hpp"
00030 
00031 namespace ivl {
00032 
00033 //------------------------------------------------------------------------------------------------
00035 template<class T> inline
00036 size_t intersect(const ivl::array<T>& a, const ivl::array<T>& b)
00037 {
00038         ivl::size_array fa,fb;
00039         ivl::array<ivl::size_array> inda,indb;
00040         ivl::array<T> a_us = unique_count(a,fa,inda);
00041         ivl::array<T> b_us = unique_count(b,fb,indb);
00042         size_t intersections  = intersect_us(a_us,b_us,fa,fb);
00043 
00044 return intersections;
00045 }
00046 
00047 //------------------------------------------------------------------------------------------------
00051 template<class T> inline
00052 size_t intersect(const ivl::array<T>& a, const ivl::array<T>& b, ivl::array<T>& common,
00053                                  ivl::array<ivl::size_array>& ia, ivl::array<ivl::size_array>& ib)
00054 {
00055         ivl::size_array fa,fb;
00056         ivl::array<ivl::size_array> inda,indb;
00057         ivl::array<T> a_us = unique_count(a,fa,inda);
00058         ivl::array<T> b_us = unique_count(b,fb,indb);
00059 
00060         ivl::size_array iia,iib;
00061         size_t intersections  = intersect_us(a_us,b_us,fa,fb, common, iia, iib);
00062 
00063         ia.resize(iia.size());
00064         ib.resize(iib.size());
00065 
00066         for(size_t i=0;i<ia.size();i++) //find index to the initial non-unique arrays
00067         {
00068                 ia[i] = inda[iia[i]];
00069                 ib[i] = indb[iib[i]];
00070         }
00071 
00072 return intersections;
00073 }
00074 
00075 //------------------------------------------------------------------------------------------------
00079 template<class T> inline
00080 size_t intersect_s(const ivl::array<T>& a, const ivl::array<T>& b, ivl::array<T>& common,
00081                                  ivl::array<ivl::size_array>& ia, ivl::array<ivl::size_array>& ib)
00082 {
00083         ivl::size_array fa,fb;
00084         ivl::array<ivl::size_array> inda,indb;
00085         ivl::array<T> a_us = unique_count_s(a,fa,inda);
00086         ivl::array<T> b_us = unique_count_s(b,fb,indb);
00087 
00088         ivl::size_array iia,iib;
00089         size_t intersections  = intersect_us(a_us,b_us,fa,fb, common, iia, iib);
00090 
00091         ia.resize(iia.size());
00092         ib.resize(iib.size());
00093 
00094         for(size_t i=0;i<ia.size();i++) //find index to the initial non-unique arrays
00095         {
00096                 ia[i] = inda[iia[i]];
00097                 ib[i] = indb[iib[i]];
00098         }
00099 
00100 return intersections;
00101 }
00102 
00103 //------------------------------------------------------------------------------------------------
00106 template<class T> inline
00107 size_t intersect_us(const ivl::array<T>& a,      const ivl::array<T>& b)
00108 {
00109         size_t i,j;
00110         i=j=0;
00111 
00112         size_t c = 0;
00113         while(i<a.size() && j<b.size())
00114         {
00115                 int t = ivl::compare( a[i] , b[j] );
00116                 if( t == 0 ) //add a correspondce
00117                 {
00118                         i++;
00119                         j++;
00120                         c++;
00121                 }
00122                 else if( t == 1) //increase the index of b, because the current element of a is higher than the current element of b
00123                         j++;
00124                 else
00125                         i++; //increase the index of a
00126         }
00127 
00128 return c;
00129 }
00130 
00131 
00132 //------------------------------------------------------------------------------------------------
00135 template<class T> inline
00136 size_t intersect_us(const ivl::array<T>& a,      const ivl::array<T>& b,
00137                                         const ivl::size_array& fa, const ivl::size_array& fb)
00138 {
00139         size_t i,j;
00140         i=j=0;
00141 
00142         if( ( fa.size() != a.size() ) || ( fb.size() != b.size() ) )
00143         {
00144                 std::cout << "Input array and the corresponding frequency array should have the same dimension" << std::endl;
00145                 return 0;
00146         }
00147         size_t c = 0;
00148         while(i<a.size() && j<b.size())
00149         {
00150                 int t = ivl::compare( a[i] , b[j] );
00151                 if( t == 0 ) //add a correspondce
00152                 {
00153                         c += std::min( fa[i], fb[j] );
00154                         i++;
00155                         j++;
00156                         //c++;
00157                 }
00158                 else if( t == 1) //increase the index of b, because the current element of a is higher than the current element of b
00159                         j++;
00160                 else
00161                         i++; //increase the index of a
00162         }
00163 
00164 return c;
00165 }
00166 
00167 
00168 
00169 
00170 //------------------------------------------------------------------------------------------------
00175 template<class T> inline
00176 size_t intersect_us(const ivl::array<T>& a, const ivl::array<T>& b,
00177                                         ivl::array<T>& common, ivl::size_array& ia, ivl::size_array &ib)
00178 {
00180         size_t size_a = a.size();
00181         size_t size_b = b.size();
00182 
00183         size_t i,j;
00184         i=j=0;
00185 
00186         std::vector<size_t> iav,ibv;
00187 
00188         while(i<size_a && j<size_b)
00189         {
00190                 int t = ivl::compare( a[i] , b[j] );
00191                 if( t == 0 ) //add a correspondce
00192                 {
00193                         iav.push_back(i);
00194                         ibv.push_back(j);
00195                         i++;
00196                         j++;
00197                 }
00198                 else if( t == 1) //increase the index of b, because the current element of a is higher than the current element of b
00199                         j++;
00200                 else
00201                         i++; //increase the index of a
00202         }
00203 
00204         size_t n_c = iav.size();
00205         common.resize(n_c);
00206         ia.resize(n_c);
00207         ib.resize(n_c);
00208 
00209         for(size_t k=0;k<n_c;k++)
00210         {
00211                 ia[k] = iav[k];
00212                 ib[k] = ibv[k];
00213                 common[k] = a[ia[k]];
00214         }
00215 
00216         return ia.size();
00217 }
00218 
00219 
00220 //------------------------------------------------------------------------------------------------
00225 template<class T> inline
00226 size_t intersect_us(const ivl::array<T>& a, const ivl::array<T>& b,
00227                                         const ivl::size_array& fa, const ivl::size_array& fb,
00228                                         ivl::array<T>& common, ivl::size_array& ia, ivl::size_array &ib)
00229 {
00230         intersect_us(a,b,common,ia,ib);
00231         size_t in =0;
00232         for(size_t i =0;i<ia.size();i++)
00233                 in+= std::min( fa[ia[i]], fb[ib[i]] );
00234 
00235 return in;
00236 }
00237 
00238 
00239 //------------------------------------------------------------------------------------------------
00243 template<class T> inline
00244 ivl::array<T> unique_count(const ivl::array<T>& a, ivl::size_array& f, ivl::array<ivl::size_array>& index)
00245 {
00246         ivl::size_array ind;
00247         ivl::array<T> s_a(a);
00248         radixsort(s_a,ind); //sort the array
00249 
00250         ivl::array<ivl::size_array> ind_temp;
00251         ivl::array<T> un_a =  unique_count_core(s_a,f,ind_temp); //unique_count to the sorted array
00252 
00253         index.resize(ind_temp.size());  //find index from the final unique array to the initial non_unique and non_sorted array
00254         for(size_t i =0;i<ind_temp.size();i++)
00255         {
00256                 index[i].resize(ind_temp[i].size());
00257                 for(size_t j=0;j<ind_temp[i].size();j++)
00258                         index[i][j] = ind[ind_temp[i][j]];
00259         }
00260 
00261 return un_a;
00262 }
00263 
00264 //------------------------------------------------------------------------------------------------
00267 template<class T> inline
00268 ivl::array<T> unique_count(const ivl::array<T>& a, ivl::size_array &f)
00269 {
00270         ivl::array<ivl::size_array> ind2;
00271         ivl::size_array ind;
00272         ivl::array<T> s_a(a);
00273         radixsort(s_a,ind); //sort the array
00274 
00275 return unique_count_core(s_a,f,ind2, false); //unique_count to the sorted array
00276 }
00277 
00278 //------------------------------------------------------------------------------------------------
00280 template<class T> inline
00281 ivl::array<T> unique(const ivl::array<T>& a)
00282 {
00283         ivl::size_array f;
00284         ivl::array<ivl::size_array> ind;
00285         ivl::array<T> s_a(a);
00286         radixsort(s_a); //sort the array
00287 
00288 return unique_count_core(s_a,f,ind, false); //unique_count to the sorted array
00289 }
00290 
00291 //------------------------------------------------------------------------------------------------
00295 template<class T> inline
00296 ivl::array<T> unique_count_s(const ivl::array<T>& a, ivl::size_array& f, ivl::array<ivl::size_array>& index)
00297 {
00298         ivl::array<T> b = unique_count_core(a,f,index, true);
00299         return b;
00300 }
00301 
00302 //------------------------------------------------------------------------------------------------
00305 template<class T> inline
00306 ivl::array<T> unique_count_s(const ivl::array<T>& a, ivl::size_array& f)
00307 {
00308         ivl::size_array index;
00309         ivl::array<T> b = unique_count_core(a,f,index, false);
00310         return b;
00311 }
00312 
00313 //------------------------------------------------------------------------------------------------
00315 template<class T> inline
00316 ivl::array<T> unique_s(const ivl::array<T>& a)
00317 {
00318         ivl::size_array f, index;
00319         ivl::array<T> b = unique_count_core(a,f,index, false);
00320         return b;
00321 }
00322 
00323 //------------------------------------------------------------------------------------------------
00328 template<class T> inline
00329 ivl::array<T> unique_count_core(const ivl::array<T>& s_a, ivl::size_array& f, ivl::array<ivl::size_array>& index, bool option = true)
00330 {
00331         ivl::array<T> unique_a(0);
00332         if(s_a.size()==0)
00333                 return unique_a;
00334         //create a mask to mark where there is a d-dimensional indice appearing for the first time, in order to keep only unique indices
00335         ivl::size_array mask(s_a.size(),(size_t)0);
00336         mask[0]=1;
00337         // fill in the mask for the unique indices, mask also includes the occurences
00338         size_t last = 0;
00339         for(size_t i=1; i<s_a.size(); i++)
00340                 if( ivl::compare( s_a[i] , s_a[i-1]) == 1) // if a new element is found
00341                 {
00342                         mask[i]=1;  // then mark it and add 1
00343                         last = i; // and keep its index
00344                 }
00345                 else
00346                         mask[last]++; // if its not a new value then add one at its last occurence
00347 
00348         ivl::size_array unique = find(mask > size_t(0)); //index of unique elements
00349         unique_a =s_a[unique]; //get unique elements
00350 
00351         f = mask[unique]; //get frequencies for unique elements
00352 
00353         //keep index for the new array (how to go back to the non unique array
00354         if(option)
00355         {
00356                 index.resize(unique_a.size());
00357                 size_t k=0;
00358                 size_t m=0;
00359                 for(size_t i=0;i<index.size();i++)
00360                 {
00361                         index[i].resize(mask[unique[m]]);
00362                         for(size_t j=0;j<index[i].size();j++)
00363                         {
00364                                 index[i][j] = k++;
00365                         }
00366                         m++;
00367                 }
00368         }
00369         else
00370                 index.resize(0);
00371 
00372         return unique_a;
00373 }
00374 
00375 } /* namespace ivl */
00376 
00377 #endif // IVL_SET_DETAILS_SET_FUNCTIONS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations