00001
00002
00003
00004
00005
00006
00007 #ifndef IBIS_EXPR_H
00008 #define IBIS_EXPR_H
00012 #include "util.h"
00013 #include "array_t.h"
00014
00015 namespace ibis {
00016 class qRange;
00017 class qContinuousRange;
00018 class qDiscreteRange;
00019 class qString;
00020 class qMultiString;
00021 class compRange;
00022 class rangeJoin;
00023 class qAnyAny;
00024 class qLike;
00025 }
00026
00031 class ibis::qExpr {
00032 public:
00035 enum TYPE {
00036 LOGICAL_UNDEFINED, LOGICAL_NOT, LOGICAL_AND, LOGICAL_OR, LOGICAL_XOR,
00037 LOGICAL_MINUS, RANGE, DRANGE, STRING, MSTRING, COMPRANGE, MATHTERM,
00038 JOIN, TOPK, ANYANY, LIKE
00039 };
00041 enum COMPARE {
00042 OP_UNDEFINED, OP_LT, OP_GT, OP_LE, OP_GE, OP_EQ
00043 };
00044
00046 qExpr() : type(LOGICAL_UNDEFINED), left(0), right(0) {}
00047
00049 explicit qExpr(TYPE op) : type(op), left(0), right(0) {}
00051 qExpr(TYPE op, qExpr* qe1, qExpr* qe2) : type(op), left(qe1),
00052 right(qe2) {}
00054 qExpr(const qExpr& qe) : type(qe.type),
00055 left(qe.left ? qe.left->dup() : 0),
00056 right(qe.right ? qe.right->dup() : 0) {}
00058 virtual ~qExpr() {delete right; delete left;}
00059
00061 void setLeft(qExpr *expr) {delete left; left=expr;}
00063 void setRight(qExpr *expr) {delete right; right=expr;}
00065 qExpr*& getLeft() {return left;}
00067 qExpr*& getRight() {return right;}
00068
00070 TYPE getType() const {return type;}
00072 const qExpr* getLeft() const {return left;}
00074 const qExpr* getRight() const {return right;}
00075
00077 bool hasJoin() const;
00078
00080 virtual uint32_t nItems() const {
00081 return 1 + (left != 0 ? left->nItems() : 0) +
00082 (right != 0 ? right->nItems() : 0);}
00083
00085 virtual void print(std::ostream&) const;
00087 virtual void printFull(std::ostream& out) const;
00088
00090 struct weight {
00091 virtual double operator()(const qExpr* ex) const = 0;
00092 virtual ~weight() {};
00093 };
00094 double reorder(const weight&);
00095
00096 virtual qExpr* dup() const {
00097 qExpr* res = new qExpr(type);
00098 if (left)
00099 res->left = left->dup();
00100 if (right)
00101 res->right = right->dup();
00102 return res;
00103 }
00104
00105 bool isTerminal() const {return (left==0 && right==0);}
00106 bool directEval() const
00107 {return (type==RANGE || type==STRING || type==COMPRANGE ||
00108 type==DRANGE || type==MSTRING || type==ANYANY ||
00109 (type==LOGICAL_NOT && left && left->directEval()));}
00110
00113 virtual bool isSimple() const {
00114 if (left) {
00115 if (right) return left->isSimple() && right->isSimple();
00116 else return left->isSimple();
00117 }
00118 else if (right) {
00119 return right->isSimple();
00120 }
00121 else {
00122 return true;
00123 }
00124 }
00125
00129 int separateSimple(ibis::qExpr *&simple, ibis::qExpr *&tail) const;
00130
00132 void extractJoins(std::vector<const rangeJoin*>& terms) const;
00134 qRange* findRange(const char* vname);
00135
00137 static void simplify(ibis::qExpr*&);
00138
00139 qExpr& operator=(const qExpr& rhs) {
00140 delete left; delete right;
00141 type = rhs.type;
00142 left = (rhs.left != 0 ? rhs.left->dup() : 0);
00143 right = (rhs.right != 0 ? rhs.right->dup() : 0);
00144 return *this;
00145 }
00146
00147 private:
00148 TYPE type;
00149 qExpr* left;
00150 qExpr* right;
00151
00152
00153 void adjust();
00154 };
00155
00160 class ibis::qRange : public ibis::qExpr {
00161 public:
00163 virtual const char* colName() const = 0;
00166 virtual bool inRange(double val) const = 0;
00167
00169 virtual void restrictRange(double left, double right) = 0;
00171 virtual const double& leftBound() const = 0;
00173 virtual const double& rightBound() const = 0;
00175 virtual bool empty() const = 0;
00176
00177 virtual ~qRange() {};
00178
00179 protected:
00180
00181 qRange() : qExpr() {};
00182 qRange(TYPE t) : qExpr(t) {};
00183
00184 private:
00185 qRange(const qRange&) {};
00186 qRange& operator=(const qRange&);
00187 };
00188
00204 class ibis::qContinuousRange : public ibis::qRange {
00205 public:
00207 qContinuousRange()
00208 : qRange(ibis::qExpr::RANGE), name(0), lower(0), upper(0),
00209 left_op(OP_UNDEFINED), right_op(OP_UNDEFINED) {};
00211 qContinuousRange(const char* lstr, COMPARE lop, const char* prop,
00212 COMPARE rop, const char* rstr);
00214 qContinuousRange(const char* col, COMPARE op, uint32_t val) :
00215 qRange(ibis::qExpr::RANGE), name(ibis::util::strnewdup(col)),
00216 lower(DBL_MAX), upper(val), left_op(OP_UNDEFINED), right_op(op) {};
00218 qContinuousRange(const qContinuousRange& rhs) :
00219 qRange(ibis::qExpr::RANGE), name(ibis::util::strnewdup(rhs.name)),
00220 lower(rhs.lower), upper(rhs.upper), left_op(rhs.left_op),
00221 right_op(rhs.right_op) {};
00223 qContinuousRange(double lv, COMPARE lop, const char* prop,
00224 COMPARE rop, double rv)
00225 : qRange(ibis::qExpr::RANGE), name(ibis::util::strnewdup(prop)),
00226 lower(lv), upper(rv), left_op(lop), right_op(rop) {};
00228 qContinuousRange(const char* prop, COMPARE op, double val)
00229 : qRange(ibis::qExpr::RANGE), name(ibis::util::strnewdup(prop)),
00230 lower(-DBL_MAX), upper(val), left_op(OP_UNDEFINED), right_op(op) {
00231
00232 if (right_op == ibis::qExpr::OP_GT) {
00233 right_op = ibis::qExpr::OP_UNDEFINED;
00234 left_op = ibis::qExpr::OP_LT;
00235 lower = upper;
00236 upper = DBL_MAX;
00237 }
00238 else if (right_op == ibis::qExpr::OP_GE) {
00239 right_op = ibis::qExpr::OP_UNDEFINED;
00240 left_op = ibis::qExpr::OP_LE;
00241 lower = upper;
00242 upper = DBL_MAX;
00243 }
00244 };
00245
00246 virtual ~qContinuousRange() {delete [] name;}
00247
00248
00249 virtual const char *colName() const {return name;}
00250 COMPARE leftOperator() const {return left_op;}
00251 COMPARE rightOperator() const {return right_op;}
00252 virtual const double& leftBound() const {
00253 return (lower);}
00254 virtual const double& rightBound() const {
00255 return (upper);}
00256
00257
00258 double& leftBound() {return lower;}
00259 double& rightBound() {return upper;}
00260 COMPARE& leftOperator() {return left_op;}
00261 COMPARE& rightOperator() {return right_op;}
00262
00263
00264 void foldBoundaries();
00265
00266 void foldUnsignedBoundaries();
00267
00268
00269 virtual qContinuousRange* dup() const {return new qContinuousRange(*this);}
00270 virtual bool inRange(double val) const;
00271 virtual void restrictRange(double left, double right);
00272 virtual bool empty() const;
00273
00274 virtual void print(std::ostream&) const;
00275 virtual void printFull(std::ostream& out) const {print(out);}
00277 inline bool operator<(const qContinuousRange& y) const;
00278
00279 private:
00280 char* name;
00281 double lower, upper;
00282 COMPARE left_op, right_op;
00283
00284 qContinuousRange& operator=(const qContinuousRange&);
00285 friend void ibis::qExpr::simplify(ibis::qExpr*&);
00286 };
00287
00290 class ibis::qDiscreteRange : public ibis::qRange {
00291 public:
00293 qDiscreteRange() : qRange(DRANGE) {};
00294 qDiscreteRange(const char *col, const char *nums);
00295 qDiscreteRange(const char *col, const std::vector<uint32_t>& val);
00296 qDiscreteRange(const char *col, const std::vector<double>& val);
00297 qDiscreteRange(const char *col, ibis::array_t<uint32_t>& val);
00298 qDiscreteRange(const char *col, ibis::array_t<double>& val);
00299
00301 qDiscreteRange(const qDiscreteRange& dr)
00302 : qRange(DRANGE), name(dr.name), values(dr.values) {}
00303 virtual ~qDiscreteRange() {};
00304
00305
00306 virtual const char* colName() const {return name.c_str();}
00307 const ibis::array_t<double>& getValues() const {return values;}
00308 ibis::array_t<double>& getValues() {return values;}
00309
00311 virtual qDiscreteRange* dup() const {return new qDiscreteRange(*this);}
00312 virtual bool inRange(double val) const;
00313 virtual void restrictRange(double left, double right);
00314 virtual bool empty() const {return values.empty();}
00315 virtual const double& leftBound() const {return values.front();}
00316 virtual const double& rightBound() const {return values.back();}
00317 virtual uint32_t nItems() const {return values.size();}
00318
00320 ibis::qExpr* convert() const;
00321
00322 virtual void print(std::ostream&) const;
00323 virtual void printFull(std::ostream& out) const {print(out);}
00324
00325 private:
00326 std::string name;
00327 ibis::array_t<double> values;
00328
00329 qDiscreteRange& operator=(const qDiscreteRange&);
00330 };
00331
00342 class ibis::qString : public ibis::qExpr {
00343 public:
00344
00345 qString() : qExpr(STRING), lstr(0), rstr(0) {};
00346 qString(const char* ls, const char* rs);
00347 virtual ~qString() {delete [] rstr; delete [] lstr;}
00348
00349 const char* leftString() const {return lstr;}
00350 const char* rightString() const {return rstr;}
00351
00352 virtual qString* dup() const {return new qString(*this);}
00353 virtual void print(std::ostream&) const;
00354 virtual void printFull(std::ostream& out) const {print(out);}
00355
00356 private:
00357 char* lstr;
00358 char* rstr;
00359
00360 qString(const qString& rhs) : qExpr(STRING),
00361 lstr(ibis::util::strnewdup(rhs.lstr)),
00362 rstr(ibis::util::strnewdup(rhs.rstr)) {}
00363 qString& operator=(const qString&);
00364 };
00365
00367 class ibis::qLike : public ibis::qExpr {
00368 public:
00370 qLike() : qExpr(LIKE), lstr(0), rpat(0) {};
00371 qLike(const char* ls, const char* rs);
00373 virtual ~qLike() {delete [] rpat; delete [] lstr;}
00374
00376 const char* colName() const {return lstr;}
00378 const char* pattern() const {return rpat;}
00379
00380 virtual qLike* dup() const {return new qLike(*this);}
00381 virtual void print(std::ostream&) const;
00382 virtual void printFull(std::ostream& out) const {print(out);}
00383
00384 private:
00386 char* lstr;
00388 char* rpat;
00389
00391 qLike(const qLike& rhs) : qExpr(LIKE),
00392 lstr(ibis::util::strnewdup(rhs.lstr)),
00393 rpat(ibis::util::strnewdup(rhs.rpat)) {}
00394 qLike& operator=(const qLike&);
00395 };
00396
00400 class ibis::qMultiString : public ibis::qExpr {
00401 public:
00402 qMultiString() : qExpr(MSTRING) {};
00403 qMultiString(const char *col, const char *sval);
00404 virtual ~qMultiString() {};
00405
00407 virtual qMultiString* dup() const {return new qMultiString(*this);}
00408 virtual void print(std::ostream& out) const;
00409 virtual void printFull(std::ostream& out) const {print(out);}
00410
00412 const char* colName() const {return name.c_str();}
00414 const std::vector<std::string>& valueList() const {return values;}
00416 ibis::qExpr* convert() const;
00417
00418 private:
00419 std::string name;
00420 std::vector<std::string> values;
00421 };
00422
00423 namespace ibis {
00425 namespace math {
00427 enum TERM_TYPE {UNDEFINED, VARIABLE, NUMBER, STRING, OPERATOR,
00428 STDFUNCTION1, STDFUNCTION2,
00429 CUSTOMFUNCTION1, CUSTOMFUNCTION2};
00432 enum OPERADOR {UNKNOWN=0, BITOR, BITAND,
00433 PLUS, MINUS, MULTIPLY, DIVIDE, REMAINDER, NEGATE, POWER};
00435 enum STDFUN1 {ACOS=0, ASIN, ATAN, CEIL, COS, COSH, EXP, FABS, FLOOR,
00436 FREXP, LOG10, LOG, MODF, SIN, SINH, SQRT, TAN, TANH};
00437 enum STDFUN2 {ATAN2=0, FMOD, LDEXP, POW};
00438
00440 extern const char* operator_name[];
00442 extern const char* stdfun1_name[];
00444 extern const char* stdfun2_name[];
00458 extern bool preserveInputExpressions;
00459
00461 class term : public ibis::qExpr {
00462 public:
00463 virtual ~term() {};
00464
00465 virtual TERM_TYPE termType() const = 0;
00466
00468 virtual double eval() const = 0;
00470 virtual term* dup() const = 0;
00472 virtual void print(std::ostream& out) const = 0;
00476 virtual term* reduce() {return this;};
00477
00478 protected:
00479 term() : qExpr(MATHTERM) {};
00480 };
00481
00483 class barrel {
00484 public:
00485
00486 barrel() {};
00487 barrel(const term* const t) {recordVariable(t);}
00488 virtual ~barrel() {};
00489
00490
00491 uint32_t size() const {return varmap.size();}
00492 const char* name(uint32_t i) const {return namelist[i];}
00493 const double& value(uint32_t i) const {return varvalues[i];}
00494 double& value(uint32_t i) {return varvalues[i];}
00495
00497 void recordVariable(const term* const t);
00501 inline uint32_t recordVariable(const char* name);
00503 bool equivalent(const barrel& rhs) const;
00504
00505 protected:
00506
00507
00508 typedef std::map< const char*, uint32_t, ibis::lessi > termMap;
00509
00510
00511
00512 friend class variable;
00513 double getValue(uint32_t i) const {return varvalues[i];}
00515 double getValue(const char* nm) const {
00516 termMap::const_iterator it = varmap.find(nm);
00517 if (it != varmap.end()) {
00518 uint32_t i = (*it).second;
00519 return varvalues[i];
00520 }
00521 else {
00522 return DBL_MAX;
00523 }
00524 }
00525
00528 termMap varmap;
00529 std::vector< double > varvalues;
00530 std::vector< const char* > namelist;
00531 };
00532
00534 class variable : public term {
00535 public:
00536
00537
00538
00539 variable(const char* var)
00540 : name(ibis::util::strnewdup(var)), myBar(0), varind(0) {}
00541 variable(const variable& v)
00542 : name(ibis::util::strnewdup(v.name)), myBar(v.myBar),
00543 varind(v.varind) {}
00544 virtual ~variable() {delete [] name;}
00545
00546 virtual TERM_TYPE termType() const {return VARIABLE;}
00547 virtual variable* dup() const {return new variable(*this);}
00548 virtual double eval() const {return myBar->getValue(varind);}
00549
00550 virtual uint32_t nItems() const {return 1U;}
00551 virtual void print(std::ostream& out) const {out << name;}
00552 const char* variableName() const {return name;}
00553
00554 void recordVariable(barrel& bar) const {
00555 varind = bar.recordVariable(name);
00556 myBar = &bar;
00557 }
00558
00559 private:
00560 char* name;
00561 mutable barrel* myBar;
00562 mutable uint32_t varind;
00563
00564 variable& operator=(const variable&);
00565 };
00566
00568 class number : public term {
00569 public:
00570 number(const char* num) : val(atof(num)) {};
00571 number(double v) : val(v) {};
00572 virtual ~number() {};
00573
00574 virtual TERM_TYPE termType() const {return NUMBER;}
00575 virtual number* dup() const {return new number(val);}
00576 virtual double eval() const {return val;}
00577
00578 virtual uint32_t nItems() const {return 1U;}
00579 virtual void print(std::ostream& out) const {out << val;}
00580
00581
00582 void negate() {val = -val;}
00583
00584 void invert() {val = 1.0/val;}
00585
00586 private:
00587 double val;
00588 friend class bediener;
00589 friend void ibis::qExpr::simplify(ibis::qExpr*&);
00590 };
00591
00593 class literal : public term {
00594 public:
00595 literal(const char* s) : str(ibis::util::strnewdup(s)) {};
00596 virtual ~literal() {delete [] str;}
00597
00598 virtual TERM_TYPE termType() const {return ibis::math::STRING;}
00599 virtual literal* dup() const {return new literal(str);}
00600 virtual double eval() const {return 0.0;}
00601
00602 virtual uint32_t nItems() const {return 1U;}
00603 virtual void print(std::ostream& out) const {out << str;}
00604 operator char* () const {return str;}
00605
00606 private:
00607 char* str;
00608
00609 literal(const literal&);
00610 literal& operator=(const literal&);
00611 };
00612
00614 class bediener : public term {
00615 public:
00616 bediener(ibis::math::OPERADOR op) : operador(op) {};
00617 virtual ~bediener() {};
00618
00619 virtual TERM_TYPE termType() const {return OPERATOR;}
00620 virtual bediener* dup() const {
00621 bediener *tmp = new bediener(operador);
00622 tmp->setRight(getRight()->dup());
00623 tmp->setLeft(getLeft()->dup());
00624 return tmp;
00625 }
00626 virtual double eval() const;
00627 virtual void print(std::ostream& out) const;
00628 virtual term* reduce();
00629
00630 private:
00631 ibis::math::OPERADOR operador;
00632
00633 void reorder();
00634
00635
00636 void linearize(const ibis::math::OPERADOR op,
00637 std::vector<ibis::math::term*>& terms);
00638
00639
00640 void convertConstants();
00641 friend void ibis::qExpr::simplify(ibis::qExpr*&);
00642 };
00643
00645 class stdFunction1 : public term {
00646 public:
00647 stdFunction1(const char* name);
00648 stdFunction1(const STDFUN1 ft) : ftype(ft) {}
00649 virtual ~stdFunction1() {}
00650
00651 virtual stdFunction1* dup() const {
00652 stdFunction1 *tmp = new stdFunction1(ftype);
00653 tmp->setLeft(getLeft()->dup());
00654 return tmp;
00655 }
00656 virtual TERM_TYPE termType() const {return STDFUNCTION1;}
00657 virtual double eval() const;
00658 virtual void print(std::ostream& out) const;
00659 virtual term* reduce();
00660
00661 private:
00662 STDFUN1 ftype;
00663 };
00664
00666 class stdFunction2 : public term {
00667 public:
00668 stdFunction2(const char* name);
00669 stdFunction2(const STDFUN2 ft) : ftype(ft) {}
00670 virtual ~stdFunction2() {}
00671
00672 virtual stdFunction2* dup() const {
00673 stdFunction2 *tmp = new stdFunction2(ftype);
00674 tmp->setRight(getRight()->dup());
00675 tmp->setLeft(getLeft()->dup());
00676 return tmp;
00677 }
00678 virtual TERM_TYPE termType() const {return STDFUNCTION2;}
00679 virtual double eval() const;
00680 virtual void print(std::ostream& out) const;
00681 virtual term* reduce();
00682
00683 private:
00684 STDFUN2 ftype;
00685 };
00686 }
00687 }
00688
00691 class ibis::compRange : public ibis::qExpr {
00692 public:
00693
00694
00695 compRange() : qExpr(ibis::qExpr::COMPRANGE), expr3(0),
00696 op12(ibis::qExpr::OP_UNDEFINED),
00697 op23(ibis::qExpr::OP_UNDEFINED) {;}
00698 compRange(ibis::math::term* me1, COMPARE lop,
00699 ibis::math::term* me2)
00700 : qExpr(ibis::qExpr::COMPRANGE, me1, me2), expr3(0),
00701 op12(lop), op23(ibis::qExpr::OP_UNDEFINED) {;}
00702 compRange(ibis::math::term* me1, ibis::qExpr::COMPARE lop,
00703 ibis::math::term* me2, ibis::qExpr::COMPARE rop,
00704 ibis::math::term* me3)
00705 : qExpr(ibis::qExpr::COMPRANGE, me1, me2), expr3(me3),
00706 op12(lop), op23(rop) {;}
00707
00708 compRange(const compRange& rhs) :
00709 ibis::qExpr(rhs), expr3(rhs.expr3 ? rhs.expr3->dup() : 0),
00710 op12(rhs.op12), op23(rhs.op23) {};
00711 virtual ~compRange() {delete expr3;}
00712
00713
00714 ibis::qExpr::COMPARE leftOperator() const {return op12;}
00715 ibis::qExpr::COMPARE rightOperator() const {return op23;}
00716 ibis::math::term* getTerm3() {return expr3;}
00717 const ibis::math::term* getTerm3() const {return expr3;}
00718 void setTerm3(ibis::math::term* t) {delete expr3; expr3 = t;}
00719
00721 virtual qExpr* dup() const {return new compRange(*this);}
00723 inline bool inRange() const;
00724
00725 virtual uint32_t nItems() const {
00726 return ibis::qExpr::nItems() +
00727 (expr3 != 0 ? expr3->nItems() : 0);}
00729 virtual void print(std::ostream&) const;
00730 virtual void printFull(std::ostream& out) const {print(out);}
00731
00732 virtual bool isSimple() const {return isSimpleRange();}
00734 inline bool isSimpleRange() const;
00735
00737 bool maybeStringCompare() const;
00738
00739
00740 ibis::qContinuousRange* simpleRange() const;
00741
00742 private:
00743 ibis::math::term *expr3;
00744 ibis::qExpr::COMPARE op12;
00745 ibis::qExpr::COMPARE op23;
00746 };
00747
00752 class ibis::rangeJoin : public ibis::qExpr {
00753 public:
00754 rangeJoin(const char* n1, const char *n2)
00755 : ibis::qExpr(ibis::qExpr::JOIN), name1(n1), name2(n2), expr(0) {};
00756 rangeJoin(const char* n1, const char *n2, ibis::math::term *x) :
00757 ibis::qExpr(ibis::qExpr::JOIN), name1(n1), name2(n2), expr(x) {};
00758 virtual ~rangeJoin() {delete expr;};
00759
00760 virtual void print(std::ostream& out) const;
00761 virtual void printFull(std::ostream& out) const {print(out);}
00762 virtual rangeJoin* dup() const
00763 {return new rangeJoin(name1.c_str(), name2.c_str(), expr->dup());};
00764
00765 const char* getName1() const {return name1.c_str();}
00766 const char* getName2() const {return name2.c_str();}
00767 ibis::math::term* getRange() {return expr;}
00768 const ibis::math::term* getRange() const {return expr;}
00769 void setRange(ibis::math::term *t) {delete expr; expr = t;}
00770
00771 virtual uint32_t nItems() const {
00772 return ibis::qExpr::nItems() +
00773 (expr != 0 ? expr->nItems() : 0);}
00774
00775 private:
00776 std::string name1;
00777 std::string name2;
00778 ibis::math::term *expr;
00779
00780 rangeJoin(const rangeJoin&);
00781 rangeJoin& operator=(const rangeJoin&);
00782 };
00783
00795 class ibis::qAnyAny : public ibis::qExpr {
00796 public:
00797 qAnyAny() : qExpr(ANYANY) {};
00798 qAnyAny(const char *pre, const double dbl);
00799 qAnyAny(const char *pre, const char *val);
00800 ~qAnyAny() {};
00801
00802 const char* getPrefix() const {return prefix.c_str();}
00803 const ibis::array_t<double>& getValues() const {return values;}
00804
00805
00806 virtual qExpr* dup() const {return new qAnyAny(*this);}
00807
00808 virtual void print(std::ostream& out) const;
00809 virtual void printFull(std::ostream& out) const {print(out);}
00810
00811 private:
00812 std::string prefix;
00813 ibis::array_t<double> values;
00814 };
00815
00816 inline void ibis::qContinuousRange::foldBoundaries() {
00817 switch (left_op) {
00818 case ibis::qExpr::OP_LT:
00819 lower = floor(lower);
00820 break;
00821 case ibis::qExpr::OP_LE:
00822 lower = ceil(lower);
00823 break;
00824 case ibis::qExpr::OP_GT:
00825 lower = ceil(lower);
00826 break;
00827 case ibis::qExpr::OP_GE:
00828 lower = floor(lower);
00829 break;
00830 case ibis::qExpr::OP_EQ:
00831 if (lower != floor(lower))
00832 left_op = ibis::qExpr::OP_UNDEFINED;
00833 break;
00834 default:
00835 break;
00836 }
00837 switch (right_op) {
00838 case ibis::qExpr::OP_LT:
00839 upper = ceil(upper);
00840 break;
00841 case ibis::qExpr::OP_LE:
00842 upper = floor(upper);
00843 break;
00844 case ibis::qExpr::OP_GT:
00845 upper = floor(upper);
00846 break;
00847 case ibis::qExpr::OP_GE:
00848 upper = ceil(upper);
00849 break;
00850 case ibis::qExpr::OP_EQ:
00851 if (upper != floor(upper))
00852 right_op = ibis::qExpr::OP_UNDEFINED;
00853 break;
00854 default:
00855 break;
00856 }
00857 }
00858
00859 inline void ibis::qContinuousRange::foldUnsignedBoundaries() {
00860 switch (left_op) {
00861 case ibis::qExpr::OP_LT:
00862 if (lower >= 0.0) {
00863 lower = floor(lower);
00864 }
00865 else {
00866 left_op = ibis::qExpr::OP_LE;
00867 lower = 0.0;
00868 }
00869 break;
00870 case ibis::qExpr::OP_LE:
00871 if (lower >= 0.0)
00872 lower = ceil(lower);
00873 else
00874 lower = 0.0;
00875 break;
00876 case ibis::qExpr::OP_GT:
00877 lower = ceil(lower);
00878 break;
00879 case ibis::qExpr::OP_GE:
00880 lower = floor(lower);
00881 break;
00882 case ibis::qExpr::OP_EQ:
00883 if (lower != floor(lower) || lower < 0.0)
00884 left_op = ibis::qExpr::OP_UNDEFINED;
00885 break;
00886 default:
00887 break;
00888 }
00889 switch (right_op) {
00890 case ibis::qExpr::OP_LT:
00891 upper = ceil(upper);
00892 break;
00893 case ibis::qExpr::OP_LE:
00894 upper = floor(upper);
00895 break;
00896 case ibis::qExpr::OP_GT:
00897 if (upper > 0.0) {
00898 upper = floor(upper);
00899 }
00900 else {
00901 right_op = ibis::qExpr::OP_GE;
00902 upper = 0.0;
00903 }
00904 break;
00905 case ibis::qExpr::OP_GE:
00906 if (upper >= 0.0)
00907 upper = ceil(upper);
00908 else
00909 upper = 0.0;
00910 break;
00911 case ibis::qExpr::OP_EQ:
00912 if (upper != floor(upper) || upper < 0.0)
00913 right_op = ibis::qExpr::OP_UNDEFINED;
00914 break;
00915 default:
00916 break;
00917 }
00918 }
00919
00921 inline bool ibis::qContinuousRange::operator<
00922 (const ibis::qContinuousRange& y) const {
00923 int cmp = strcmp(colName(), y.colName());
00924 if (cmp < 0)
00925 return true;
00926 else if (cmp > 0)
00927 return false;
00928 else if (left_op < y.left_op)
00929 return true;
00930 else if (left_op > y.left_op)
00931 return false;
00932 else if (right_op < y.right_op)
00933 return true;
00934 else if (right_op > y.right_op)
00935 return false;
00936 else if (lower < y.lower)
00937 return true;
00938 else if (lower > y.lower)
00939 return false;
00940 else if (upper < y.upper)
00941 return true;
00942 else
00943 return false;
00944 }
00945
00946 inline bool ibis::compRange::isSimpleRange() const {
00947 bool res = false;
00948 if (expr3 == 0 && getLeft() != 0)
00949 res = ((static_cast<const ibis::math::term*>(getLeft())->
00950 termType()==ibis::math::VARIABLE &&
00951 static_cast<const ibis::math::term*>(getRight())->
00952 termType()==ibis::math::NUMBER) ||
00953 (static_cast<const ibis::math::term*>(getLeft())->
00954 termType()==ibis::math::NUMBER &&
00955 static_cast<const ibis::math::term*>(getRight())->
00956 termType()==ibis::math::VARIABLE));
00957 else if (expr3 != 0 && expr3->termType()==ibis::math::NUMBER)
00958 res = (getLeft() == 0 &&
00959 static_cast<const ibis::math::term*>(getRight())->termType()
00960 == ibis::math::VARIABLE) ||
00961 (static_cast<const ibis::math::term*>(getLeft())->
00962 termType()==ibis::math::NUMBER &&
00963 static_cast<const ibis::math::term*>(getRight())->
00964 termType()==ibis::math::VARIABLE);
00965 return res;
00966 }
00967
00968 inline bool ibis::compRange::maybeStringCompare() const {
00969 return (expr3 == 0 && op12==OP_EQ && getLeft() != 0 && getRight() != 0 &&
00970 (static_cast<const ibis::math::term*>(getLeft())->termType()
00971 ==ibis::math::VARIABLE ||
00972 static_cast<const ibis::math::term*>(getLeft())->termType()
00973 ==ibis::math::STRING) &&
00974 (static_cast<const ibis::math::term*>(getRight())->termType()
00975 ==ibis::math::VARIABLE ||
00976 static_cast<const ibis::math::term*>(getRight())->termType()
00977 ==ibis::math::STRING));
00978 }
00979
00982 inline bool ibis::compRange::inRange() const {
00983 if (getRight() == 0) return false;
00984
00985 const double tm2 =
00986 static_cast<const ibis::math::term*>(getRight())->eval();
00987 if (op12 == OP_UNDEFINED && op23 == OP_UNDEFINED)
00988 return (tm2 != 0.0);
00989
00990 bool res = true;
00991 if (getLeft() != 0 && op12 != OP_UNDEFINED) {
00992 const double tm1 =
00993 static_cast<const ibis::math::term*>(getLeft())->eval();
00994 switch (op12) {
00995 case OP_LT: res = (tm1 < tm2); break;
00996 case OP_LE: res = (tm1 <= tm2); break;
00997 case OP_GT: res = (tm1 > tm2); break;
00998 case OP_GE: res = (tm1 >= tm2); break;
00999 case OP_EQ: res = (tm1 == tm2); break;
01000 default: break;
01001 }
01002 }
01003 if (expr3 != 0 && op23 != OP_UNDEFINED && res == true) {
01004 const double tm3 = expr3->eval();
01005 switch (op23) {
01006 case OP_LT: res = (tm2 < tm3); break;
01007 case OP_LE: res = (tm2 <= tm3); break;
01008 case OP_GT: res = (tm2 > tm3); break;
01009 case OP_GE: res = (tm2 >= tm3); break;
01010 case OP_EQ: res = (tm2 == tm3); break;
01011 default: break;
01012 }
01013 }
01014 return res;
01015 }
01016
01021 inline bool ibis::qDiscreteRange::inRange(double val) const {
01022 if (values.empty()) return false;
01023 if (val < values[0] || val > values.back()) return false;
01024
01025 uint32_t i = 0, j = values.size();
01026 if (j < 32) {
01027
01028
01029 for (i = 0; i < j; ++ i)
01030 if (values[i] == val) return true;
01031 return false;
01032 }
01033 else {
01034 uint32_t m = (i + j) / 2;
01035 while (i < m) {
01036 if (values[m] == val) return true;
01037 if (values[m] < val)
01038 i = m;
01039 else
01040 j = m;
01041 m = (i + j) / 2;
01042 }
01043 return (values[m] == val);
01044 }
01045 }
01046
01049 inline uint32_t ibis::math::barrel::recordVariable(const char* name) {
01050 uint32_t ind = varmap.size();
01051 termMap::const_iterator it = varmap.find(name);
01052 if (it == varmap.end()) {
01053 varmap[name] = ind;
01054 namelist.push_back(name);
01055 varvalues.push_back(0.0);
01056 }
01057 else {
01058 ind = (*it).second;
01059 }
01060 return ind;
01061 }
01062
01063 namespace std {
01064 inline ostream& operator<<(ostream&, const ibis::qExpr&);
01065 inline ostream& operator<<(ostream&, const ibis::qExpr::COMPARE&);
01066 }
01067
01069 inline std::ostream& std::operator<<(std::ostream& out, const ibis::qExpr& pn) {
01070 pn.print(out);
01071 return out;
01072 }
01073
01075 inline std::ostream& std::operator<<(std::ostream& out,
01076 const ibis::qExpr::COMPARE& op) {
01077 switch (op) {
01078 default:
01079 case ibis::qExpr::OP_UNDEFINED:
01080 out << "??"; break;
01081 case ibis::qExpr::OP_LT:
01082 out << "<"; break;
01083 case ibis::qExpr::OP_LE:
01084 out << "<="; break;
01085 case ibis::qExpr::OP_GT:
01086 out << ">"; break;
01087 case ibis::qExpr::OP_GE:
01088 out << ">="; break;
01089 case ibis::qExpr::OP_EQ:
01090 out << "=="; break;
01091 }
01092 return out;
01093 }
01094 #endif // IBIS_EXPR_H