|
GiNaC
1.6.2
|
00001 00005 /* 00006 * GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #include "relational.h" 00024 #include "operators.h" 00025 #include "numeric.h" 00026 #include "archive.h" 00027 #include "utils.h" 00028 #include "hash_seed.h" 00029 00030 #include <iostream> 00031 #include <stdexcept> 00032 00033 namespace GiNaC { 00034 00035 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(relational, basic, 00036 print_func<print_context>(&relational::do_print). 00037 print_func<print_tree>(&relational::do_print_tree). 00038 print_func<print_python_repr>(&relational::do_print_python_repr)) 00039 00040 00041 // default constructor 00043 00044 relational::relational() { } 00045 00047 // other constructors 00049 00050 // public 00051 00052 relational::relational(const ex & lhs, const ex & rhs, operators oper) : 00053 lh(lhs), rh(rhs), o(oper) { } 00054 00056 // archiving 00058 00059 void relational::read_archive(const archive_node& n, lst& sym_lst) 00060 { 00061 inherited::read_archive(n, sym_lst); 00062 unsigned int opi; 00063 if (!(n.find_unsigned("op", opi))) 00064 throw (std::runtime_error("unknown relational operator in archive")); 00065 o = (operators)opi; 00066 n.find_ex("lh", lh, sym_lst); 00067 n.find_ex("rh", rh, sym_lst); 00068 } 00069 GINAC_BIND_UNARCHIVER(relational); 00070 00071 void relational::archive(archive_node &n) const 00072 { 00073 inherited::archive(n); 00074 n.add_ex("lh", lh); 00075 n.add_ex("rh", rh); 00076 n.add_unsigned("op", o); 00077 } 00078 00080 // functions overriding virtual functions from base classes 00082 00083 // public 00084 00085 static void print_operator(const print_context & c, relational::operators o) 00086 { 00087 switch (o) { 00088 case relational::equal: 00089 c.s << "=="; 00090 break; 00091 case relational::not_equal: 00092 c.s << "!="; 00093 break; 00094 case relational::less: 00095 c.s << "<"; 00096 break; 00097 case relational::less_or_equal: 00098 c.s << "<="; 00099 break; 00100 case relational::greater: 00101 c.s << ">"; 00102 break; 00103 case relational::greater_or_equal: 00104 c.s << ">="; 00105 break; 00106 default: 00107 c.s << "(INVALID RELATIONAL OPERATOR)"; 00108 break; 00109 } 00110 } 00111 00112 void relational::do_print(const print_context & c, unsigned level) const 00113 { 00114 if (precedence() <= level) 00115 c.s << "("; 00116 lh.print(c, precedence()); 00117 print_operator(c, o); 00118 rh.print(c, precedence()); 00119 if (precedence() <= level) 00120 c.s << ")"; 00121 } 00122 00123 void relational::do_print_python_repr(const print_python_repr & c, unsigned level) const 00124 { 00125 c.s << class_name() << '('; 00126 lh.print(c); 00127 c.s << ','; 00128 rh.print(c); 00129 c.s << ",'"; 00130 print_operator(c, o); 00131 c.s << "')"; 00132 } 00133 00134 bool relational::info(unsigned inf) const 00135 { 00136 switch (inf) { 00137 case info_flags::relation: 00138 return 1; 00139 case info_flags::relation_equal: 00140 return o==equal; 00141 case info_flags::relation_not_equal: 00142 return o==not_equal; 00143 case info_flags::relation_less: 00144 return o==less; 00145 case info_flags::relation_less_or_equal: 00146 return o==less_or_equal; 00147 case info_flags::relation_greater: 00148 return o==greater; 00149 case info_flags::relation_greater_or_equal: 00150 return o==greater_or_equal; 00151 } 00152 return 0; 00153 } 00154 00155 size_t relational::nops() const 00156 { 00157 return 2; 00158 } 00159 00160 ex relational::op(size_t i) const 00161 { 00162 GINAC_ASSERT(i<2); 00163 00164 return i==0 ? lh : rh; 00165 } 00166 00167 ex relational::map(map_function & f) const 00168 { 00169 const ex &mapped_lh = f(lh); 00170 const ex &mapped_rh = f(rh); 00171 00172 if (!are_ex_trivially_equal(lh, mapped_lh) 00173 || !are_ex_trivially_equal(rh, mapped_rh)) 00174 return (new relational(mapped_lh, mapped_rh, o))->setflag(status_flags::dynallocated); 00175 else 00176 return *this; 00177 } 00178 00179 ex relational::eval(int level) const 00180 { 00181 if (level==1) 00182 return this->hold(); 00183 00184 if (level == -max_recursion_level) 00185 throw(std::runtime_error("max recursion level reached")); 00186 00187 return (new relational(lh.eval(level-1),rh.eval(level-1),o))->setflag(status_flags::dynallocated | status_flags::evaluated); 00188 } 00189 00190 ex relational::subs(const exmap & m, unsigned options) const 00191 { 00192 const ex & subsed_lh = lh.subs(m, options); 00193 const ex & subsed_rh = rh.subs(m, options); 00194 00195 if (!are_ex_trivially_equal(lh, subsed_lh) || !are_ex_trivially_equal(rh, subsed_rh)) 00196 return relational(subsed_lh, subsed_rh, o).subs_one_level(m, options); 00197 else 00198 return subs_one_level(m, options); 00199 } 00200 00201 ex relational::eval_ncmul(const exvector & v) const 00202 { 00203 return lh.eval_ncmul(v); 00204 } 00205 00206 // protected 00207 00208 int relational::compare_same_type(const basic & other) const 00209 { 00210 GINAC_ASSERT(is_exactly_a<relational>(other)); 00211 const relational &oth = static_cast<const relational &>(other); 00212 if (o==oth.o && lh.is_equal(oth.lh) && rh.is_equal(oth.rh)) 00213 return 0; 00214 switch (o) { 00215 case equal: 00216 case not_equal: 00217 if (oth.o!=o) 00218 return (o < oth.o) ? -1 : 1; 00219 break; 00220 case less: 00221 if (oth.o!=greater) 00222 return (o < oth.o) ? -1 : 1; 00223 break; 00224 case less_or_equal: 00225 if (oth.o!=greater_or_equal) 00226 return (o < oth.o) ? -1 : 1; 00227 break; 00228 case greater: 00229 if (oth.o!=less) 00230 return (o < oth.o) ? -1 : 1; 00231 break; 00232 case greater_or_equal: 00233 if (oth.o!=less_or_equal) 00234 return (o < oth.o) ? -1 : 1; 00235 break; 00236 } 00237 const int lcmpval = lh.compare(oth.rh); 00238 return (lcmpval!=0) ? lcmpval : rh.compare(oth.lh); 00239 } 00240 00241 bool relational::match_same_type(const basic & other) const 00242 { 00243 GINAC_ASSERT(is_exactly_a<relational>(other)); 00244 const relational &oth = static_cast<const relational &>(other); 00245 00246 return o == oth.o; 00247 } 00248 00249 unsigned relational::return_type() const 00250 { 00251 GINAC_ASSERT(lh.return_type()==rh.return_type()); 00252 return lh.return_type(); 00253 } 00254 00255 return_type_t relational::return_type_tinfo() const 00256 { 00257 GINAC_ASSERT(lh.return_type_tinfo()==rh.return_type_tinfo()); 00258 return lh.return_type_tinfo(); 00259 } 00260 00261 unsigned relational::calchash() const 00262 { 00263 unsigned v = make_hash_seed(typeid(*this)); 00264 unsigned lhash = lh.gethash(); 00265 unsigned rhash = rh.gethash(); 00266 00267 v = rotate_left(v); 00268 switch(o) { 00269 case equal: 00270 case not_equal: 00271 if (lhash>rhash) { 00272 v ^= lhash; 00273 lhash = rhash; 00274 } else { 00275 v ^= rhash; 00276 } 00277 break; 00278 case less: 00279 case less_or_equal: 00280 v ^= rhash; 00281 break; 00282 case greater: 00283 case greater_or_equal: 00284 v ^= lhash; 00285 lhash = rhash; 00286 break; 00287 } 00288 v = rotate_left(v); 00289 v ^= lhash; 00290 00291 // store calculated hash value only if object is already evaluated 00292 if (flags & status_flags::evaluated) { 00293 setflag(status_flags::hash_calculated); 00294 hashvalue = v; 00295 } 00296 00297 return v; 00298 } 00299 00301 // new virtual functions which can be overridden by derived classes 00303 00305 ex relational::lhs() const 00306 { 00307 return lh; 00308 } 00309 00311 ex relational::rhs() const 00312 { 00313 return rh; 00314 } 00315 00317 // non-virtual functions in this class 00319 00320 relational::safe_bool relational::make_safe_bool(bool cond) const 00321 { 00322 return cond? &safe_bool_helper::nonnull : 0; 00323 } 00324 00330 relational::operator relational::safe_bool() const 00331 { 00332 const ex df = lh-rh; 00333 if (!is_exactly_a<numeric>(df)) 00334 // cannot decide on non-numerical results 00335 return o==not_equal ? make_safe_bool(true) : make_safe_bool(false); 00336 00337 switch (o) { 00338 case equal: 00339 return make_safe_bool(ex_to<numeric>(df).is_zero()); 00340 case not_equal: 00341 return make_safe_bool(!ex_to<numeric>(df).is_zero()); 00342 case less: 00343 return make_safe_bool(ex_to<numeric>(df)<(*_num0_p)); 00344 case less_or_equal: 00345 return make_safe_bool(ex_to<numeric>(df)<=(*_num0_p)); 00346 case greater: 00347 return make_safe_bool(ex_to<numeric>(df)>(*_num0_p)); 00348 case greater_or_equal: 00349 return make_safe_bool(ex_to<numeric>(df)>=(*_num0_p)); 00350 default: 00351 throw(std::logic_error("invalid relational operator")); 00352 } 00353 } 00354 00355 } // namespace GiNaC