00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00028 #ifndef _DBCOMPARE_HPP_
00029 #define _DBCOMPARE_HPP_
00030
00031 #include <vector>
00032 #include <utility>
00033 #include <search_node.h>
00034
00035 namespace coco {
00036
00037 bool eval(const vdbl::rowid& rid, const std::string& colname,
00038 dbc_method tp, vdbl::view* iv, const basic_alltype& cmpval);
00039
00040 template <typename _AT>
00041 void filter_from_view(std::vector<std::pair<vdbl::rowid,_AT> >& riv,
00042 vdbl::view* iv, const std::map<int,std::triple<std::string,
00043 dbc_method, basic_alltype> >& cols,
00044 const std::vector<std::vector<int> >& expr)
00045 {
00046 std::map<int,bool> retr;
00047 std::map<int,bool>::iterator retr_it;
00048 size_t i, j, k;
00049
00050 if(expr.empty()) return;
00051
00052 if(!iv)
00053 {
00054 riv.clear();
00055 return;
00056 }
00057
00058 for(i = 0; i < riv.size(); )
00059 {
00060 bool rmv(true);
00061 retr.clear();
00062
00063 for(j = 0; j < expr.size(); ++j)
00064 {
00065 bool and_res(true);
00066 for(k = 0; k < expr[j].size(); ++k)
00067 {
00068 bool res;
00069 int cmpe(std::abs(expr[j][k]));
00070 bool nege(expr[j][k] < 0);
00071 std::map<int,std::triple<std::string, dbc_method, basic_alltype> >::
00072 const_iterator cols_it;
00073
00074 retr_it = retr.find(cmpe);
00075 if(retr_it != retr.end())
00076 res = retr_it->second;
00077 else
00078 {
00079 cols_it = cols.find(cmpe);
00080 if(cols_it == cols.end())
00081 {
00082 throw api_exception(apiee_other,
00083 std::string("Error in filter_from_view: wrong column index ")+
00084 convert_to_str(cmpe) + " in expression!");
00085 }
00086 else
00087 {
00088 const std::triple<std::string, dbc_method, basic_alltype>&
00089 colsrf(cols_it->second);
00090
00091 res = eval(riv[i].first, colsrf.first, colsrf.second, iv,
00092 colsrf.third);
00093 retr[cmpe] = res;
00094 }
00095 }
00096 res = nege ? !res : res;
00097 if(!res)
00098 {
00099 and_res = false;
00100 break;
00101 }
00102 }
00103 if(and_res)
00104 {
00105 rmv = false;
00106 break;
00107 }
00108 }
00109
00110 if(rmv)
00111 riv.erase(riv.begin()+i);
00112 else
00113 ++i;
00114 }
00115 }
00116
00117 template <typename _TR>
00118 _TR dbccmps_abs(const _TR& x)
00119 {
00120 return x < _TR() ? -x : x;
00121 }
00122
00123 template <typename _TR>
00124 class dbccmps_gt
00125 {
00126 private:
00127 long double abs, rel;
00128 public:
00129 dbccmps_gt(double _rel = 1.0, double _abs = 0.0)
00130 : abs((long double)_abs), rel((long double)_rel) {}
00131 ~dbccmps_gt() {}
00132
00133 bool operator()(const _TR& x, const _TR& y)
00134 { long double relx((long double)(dbccmps_abs(x)+dbccmps_abs(y)));
00135 return x > y+rel*relx+abs; }
00136 };
00137
00138 template <typename _TR>
00139 class dbccmps_absgt
00140 {
00141 private:
00142 long double abs, rel;
00143 public:
00144 dbccmps_absgt(double _rel = 1.0, double _abs = 0.0)
00145 : abs((long double)_abs), rel((long double)_rel) {}
00146 ~dbccmps_absgt() {}
00147
00148 bool operator()(const _TR& x, const _TR& y)
00149 { _TR absx(dbccmps_abs(x)), absy(dbccmps_abs(y));
00150 long double relx((long double)(absx+absy));
00151 return absx > absy+rel*relx+abs; }
00152 };
00153
00154 template <typename _TR>
00155 class dbccmps_lt
00156 {
00157 private:
00158 long double abs, rel;
00159 public:
00160 dbccmps_lt(double _rel = 1.0, double _abs = 0.0)
00161 : abs((long double)_abs), rel((long double)_rel) {}
00162 ~dbccmps_lt() {}
00163
00164 bool operator()(const _TR& x, const _TR& y)
00165 { long double relx((long double)(dbccmps_abs(x)+dbccmps_abs(y)));
00166 return x < y-rel*relx-abs; }
00167 };
00168
00169 template <typename _TR>
00170 class dbccmps_abslt
00171 {
00172 private:
00173 long double abs, rel;
00174 public:
00175 dbccmps_abslt(double _rel = 1.0, double _abs = 0.0)
00176 : abs((long double)_abs), rel((long double)_rel) {}
00177 ~dbccmps_abslt() {}
00178
00179 bool operator()(const _TR& x, const _TR& y)
00180 { _TR absx(dbccmps_abs(x)), absy(dbccmps_abs(y));
00181 long double relx((long double)(absx+absy));
00182 return absx < absy-rel*relx-abs; }
00183 };
00184
00185 template <typename _TR>
00186 class dbccmps_true
00187 {
00188 private:
00189 long double abs, rel;
00190 public:
00191 dbccmps_true(double _rel = 1.0, double _abs = 0.0)
00192 : abs((long double)_abs), rel((long double)_rel) {}
00193 ~dbccmps_true() {}
00194
00195 bool operator()(const _TR& x, const _TR& y)
00196 { long double absx((long double)dbccmps_abs(x));
00197 long double absy((long double)dbccmps_abs(y));
00198 long double zr(rel*(absx+absy)+abs);
00199 return absx > zr && absy <= zr; }
00200 };
00201
00202 template <typename _TR>
00203 class dbccmps_false
00204 {
00205 private:
00206 long double abs, rel;
00207 public:
00208 dbccmps_false(double _rel = 1.0, double _abs = 0.0)
00209 : abs((long double)_abs), rel((long double)_rel) {}
00210 ~dbccmps_false() {}
00211
00212 bool operator()(const _TR& x, const _TR& y)
00213 { long double absx((long double)dbccmps_abs(x));
00214 long double absy((long double)dbccmps_abs(y));
00215 long double zr(rel*(absx+absy)+abs);
00216 return absx <= zr && absy > zr; }
00217 };
00218
00219 template <typename _TR>
00220 struct dbccmp_true
00221 {
00222 dbccmp_true() {}
00223 ~dbccmp_true() {}
00224 bool operator()(const _TR& x, const _TR& y)
00225 { return x != _TR() && y == _TR(); }
00226 };
00227
00228 template <typename _TR>
00229 struct dbccmp_false
00230 {
00231 dbccmp_false() {}
00232 ~dbccmp_false() {}
00233 bool operator()(const _TR& x, const _TR& y)
00234 { return x == _TR() && y != _TR(); }
00235 };
00236
00237 template <typename _TR, typename _AT>
00238 typename std::vector<std::pair<vdbl::rowid,_AT> >::iterator
00239 filter_s(typename std::vector<std::pair<vdbl::rowid,_AT> >& rid,
00240 typename std::vector<std::pair<vdbl::rowid,_AT> >::iterator rid_b,
00241 const std::string& colname, dbc_method tp, vdbl::view* iv,
00242 unsigned int n, _TR, double rel, double abs)
00243 {
00244 if(n == 0)
00245 {
00246 rid.clear();
00247 return rid.end();
00248 }
00249 if(rid.size() <= n)
00250 return rid.end();
00251
00252 typename std::vector<_TR> cmpval;
00253 _TR _help;
00254
00255 for(unsigned int i = rid_b-rid.begin(); i < rid.size();)
00256 {
00257 if(iv->get(rid[i].first, colname, _help))
00258 {
00259 ++i;
00260 cmpval.push_back(_help);
00261 }
00262 else
00263 rid.erase(rid.begin()+i);
00264 }
00265
00266 if(rid.size() <= n)
00267 return rid.end();
00268
00269 std::pair<typename std::vector<_TR>::iterator,
00270 typename std::vector<_TR>::iterator> cmpval_it;
00271
00272 switch(tp)
00273 {
00274 case dbc_sort_max:
00275 std::pair_sort(cmpval.begin(), cmpval.end(), rid.begin(), rid.end(),
00276 dbccmps_gt<_TR>(rel,abs));
00277 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00278 dbccmps_gt<_TR>(rel,abs));
00279 break;
00280 case dbc_sort_absmax:
00281 std::pair_sort(cmpval.begin(), cmpval.end(), rid.begin(), rid.end(),
00282 dbccmps_absgt<_TR>(rel,abs));
00283 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00284 dbccmps_absgt<_TR>(rel,abs));
00285 break;
00286 case dbc_sort_min:
00287 std::pair_sort(cmpval.begin(), cmpval.end(), rid.begin(), rid.end(),
00288 dbccmps_lt<_TR>(rel,abs));
00289 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00290 dbccmps_lt<_TR>(rel,abs));
00291 break;
00292 case dbc_sort_absmin:
00293 std::pair_sort(cmpval.begin(), cmpval.end(), rid.begin(), rid.end(),
00294 dbccmps_abslt<_TR>(rel,abs));
00295 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00296 dbccmps_abslt<_TR>(rel,abs));
00297 break;
00298 case dbc_sort_true:
00299 std::pair_sort(cmpval.begin(), cmpval.end(), rid.begin(), rid.end(),
00300 dbccmps_true<_TR>(rel,abs));
00301 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00302 dbccmps_true<_TR>(rel,abs));
00303 break;
00304 case dbc_sort_false:
00305 std::pair_sort(cmpval.begin(), cmpval.end(), rid.begin(), rid.end(),
00306 dbccmps_false<_TR>(rel,abs));
00307 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00308 dbccmps_false<_TR>(rel,abs));
00309 break;
00310 default:
00311 throw api_exception(apiee_other, "Error in filter_u: tp is wrong!");
00312 break;
00313 }
00314
00315 if(cmpval_it.second != cmpval.end())
00316 {
00317 n = cmpval_it.second - cmpval.begin();
00318 rid.erase(rid.begin()+n, rid.end());
00319 }
00320 n = cmpval_it.first - cmpval.begin();
00321 return rid.begin()+n;
00322 }
00323
00324 template <typename _TR, typename _AT>
00325 typename std::vector<std::pair<vdbl::rowid,_AT> >::iterator
00326 filter_u(typename std::vector<std::pair<vdbl::rowid,_AT> >& rid,
00327 typename std::vector<std::pair<vdbl::rowid,_AT> >::iterator rid_b,
00328 const std::string& colname, dbc_method tp, vdbl::view* iv,
00329 unsigned int n, _TR)
00330 {
00331 if(n == 0)
00332 {
00333 rid.clear();
00334 return rid.end();
00335 }
00336 if(rid.size() <= n)
00337 return rid.end();
00338
00339 typename std::vector<_TR> cmpval;
00340 _TR _help;
00341
00342 for(unsigned int i = rid_b-rid.begin(); i < rid.size();)
00343 {
00344 if(iv->get(rid[i].first, colname, _help))
00345 {
00346 ++i;
00347 cmpval.push_back(_help);
00348 }
00349 else
00350 rid.erase(rid.begin()+i);
00351 }
00352
00353 if(rid.size() <= n)
00354 return rid.end();
00355
00356 std::pair<typename std::vector<_TR>::iterator,
00357 typename std::vector<_TR>::iterator> cmpval_it;
00358
00359 switch(tp)
00360 {
00361 case dbc_sort_max:
00362 case dbc_sort_absmax:
00363 std::pair_sort(cmpval.begin(), cmpval.end(), rid_b, rid.end(),
00364 std::greater<_TR>());
00365 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00366 std::greater<_TR>());
00367 break;
00368 case dbc_sort_min:
00369 case dbc_sort_absmin:
00370 std::pair_sort(cmpval.begin(), cmpval.end(), rid_b, rid.end(),
00371 std::less<_TR>());
00372 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00373 std::less<_TR>());
00374 break;
00375 case dbc_sort_true:
00376 std::pair_sort(cmpval.begin(), cmpval.end(), rid_b, rid.end(),
00377 dbccmp_true<_TR>());
00378 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00379 dbccmp_true<_TR>());
00380 break;
00381 case dbc_sort_false:
00382 std::pair_sort(cmpval.begin(), cmpval.end(), rid_b, rid.end(),
00383 dbccmp_false<_TR>());
00384 cmpval_it = std::equal_range(cmpval.begin(), cmpval.end(), cmpval[n-1],
00385 dbccmp_false<_TR>());
00386 break;
00387 default:
00388 throw api_exception(apiee_other, "Error in filter_u: tp is wrong!");
00389 break;
00390 }
00391
00392 if(cmpval_it.second != cmpval.end())
00393 {
00394 n = cmpval_it.second - cmpval.begin();
00395 rid.erase(rid_b+n, rid.end());
00396 }
00397 n = cmpval_it.first - cmpval.begin();
00398 return rid_b+n;
00399 }
00400
00401 template <typename _AT>
00402 typename std::vector<std::pair<vdbl::rowid,_AT> >::iterator
00403 filter(typename std::vector<std::pair<vdbl::rowid,_AT> >& rid,
00404 typename std::vector<std::pair<vdbl::rowid,_AT> >::iterator rid_b,
00405 const std::string& colname, dbc_method tp, vdbl::view* iv,
00406 unsigned int n, std::pair<double, double> rel_abs)
00407 {
00408 typename std::vector<std::pair<vdbl::rowid,_AT> >::iterator ret;
00409 const char *tyn = iv->get_coltype(colname).name();
00410
00411 if(!strcmp(typeid(double).name(), tyn))
00412 ret = filter_s(rid, rid_b, colname, tp, iv, n, 0.0,
00413 rel_abs.first, rel_abs.second);
00414 else if(!strcmp(typeid(long int).name(), tyn))
00415 ret = filter_s(rid, rid_b, colname, tp, iv, n, 0L,
00416 rel_abs.first, rel_abs.second);
00417 else if(!strcmp(typeid(unsigned long int).name(), tyn))
00418 ret = filter_u(rid, rid_b, colname, tp, iv, n, 0UL);
00419 else if(!strcmp(typeid(search_node_id).name(), tyn))
00420 ret = filter_u(rid, rid_b, colname, tp, iv, n,
00421 search_node_id());
00422 else if(!strcmp(typeid(bool).name(), tyn))
00423 ret = filter_u(rid, rid_b, colname, tp, iv, n, true);
00424 else if(!strcmp(typeid(int).name(), tyn))
00425 ret = filter_s(rid, rid_b, colname, tp, iv, n, 0,
00426 rel_abs.first, rel_abs.second);
00427 else if(!strcmp(typeid(unsigned int).name(), tyn))
00428 ret = filter_u(rid, rid_b, colname, tp, iv, n, 0U);
00429 else if(!strcmp(typeid(std::string).name(), tyn))
00430 ret = filter_u(rid, rid_b, colname, tp, iv, n,
00431 std::string());
00432 else
00433 throw api_exception(apiee_other,
00434 std::string("Error in filter: don't know how to handle type ")+
00435 iv->get_coltype(colname).name() + "!");
00436
00437 return ret;
00438 }
00439
00440 template <typename _AT>
00441 void list_from_view(typename std::vector<std::pair<vdbl::rowid,_AT> >& riv,
00442 vdbl::view* iv, const std::map<int,std::triple<std::string,
00443 dbc_method, basic_alltype > >& cols, const std::vector<int>& sort,
00444 unsigned int n=1)
00445 {
00446 if(sort.empty()) return;
00447
00448 if(!iv)
00449 return;
00450
00451 size_t i;
00452 typename std::vector<std::pair<vdbl::rowid,_AT> >::iterator riv_b(riv.begin());
00453 std::map<int, std::triple<std::string, dbc_method, basic_alltype> >
00454 ::const_iterator cols_it;
00455
00456 for(i = 0; i < sort.size() && riv.size() > n; ++i)
00457 {
00458 cols_it = cols.find(sort[i]);
00459 if(cols_it != cols.end())
00460 {
00461 std::pair<double,double> relabs;
00462 if((*cols_it).second.third.contents_type() == ALLTYPE_EMPTY)
00463 relabs = std::make_pair(0., 0.);
00464 else if((*cols_it).second.third.contents_type() == ALLTYPE_DOUBLE)
00465 relabs = std::make_pair(0., (*cols_it).second.third.nd());
00466 else if((*cols_it).second.third.contents_type() == ALLTYPE_ALLOCED_D)
00467 {
00468 if((*cols_it).second.third.d().size() == 1)
00469 relabs = std::make_pair(0., (*cols_it).second.third.d()[0]);
00470 else if((*cols_it).second.third.d().size() == 2)
00471 relabs = std::make_pair((*cols_it).second.third.d()[1],
00472 (*cols_it).second.third.d()[0]);
00473 else
00474 throw api_exception(apiee_other,
00475 std::string("Error in list_from_view: vals contents vector has ")+
00476 "invalid length for sorting!");
00477 }
00478 else
00479 throw api_exception(apiee_other,
00480 std::string("Error in list_from_view: vals contents vector has ")+
00481 "invalid type for sorting!");
00482 riv_b = filter(riv, riv_b, (*cols_it).second.first, (*cols_it).second.second,
00483 iv, n-(riv_b-riv.begin()), relabs);
00484 }
00485 }
00486 }
00487
00488 }
00489
00490 #endif