ivl 679
|
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