|
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 "operators.h" 00024 #include "numeric.h" 00025 #include "add.h" 00026 #include "mul.h" 00027 #include "power.h" 00028 #include "ncmul.h" 00029 #include "relational.h" 00030 #include "print.h" 00031 #include "utils.h" 00032 00033 #include <iomanip> 00034 #include <iostream> 00035 00036 namespace GiNaC { 00037 00039 static inline const ex exadd(const ex & lh, const ex & rh) 00040 { 00041 return (new add(lh,rh))->setflag(status_flags::dynallocated); 00042 } 00043 00045 static inline const ex exmul(const ex & lh, const ex & rh) 00046 { 00047 // Check if we are constructing a mul object or a ncmul object. Due to 00048 // ncmul::eval()'s rule to pull out commutative elements we need to check 00049 // only one of the elements. 00050 if (rh.return_type()==return_types::commutative || 00051 lh.return_type()==return_types::commutative) { 00052 return (new mul(lh,rh))->setflag(status_flags::dynallocated); 00053 } else { 00054 return (new ncmul(lh,rh))->setflag(status_flags::dynallocated); 00055 } 00056 } 00057 00059 static inline const ex exminus(const ex & lh) 00060 { 00061 return (new mul(lh,_ex_1))->setflag(status_flags::dynallocated); 00062 } 00063 00064 // binary arithmetic operators ex with ex 00065 00066 const ex operator+(const ex & lh, const ex & rh) 00067 { 00068 return exadd(lh, rh); 00069 } 00070 00071 const ex operator-(const ex & lh, const ex & rh) 00072 { 00073 return exadd(lh, exminus(rh)); 00074 } 00075 00076 const ex operator*(const ex & lh, const ex & rh) 00077 { 00078 return exmul(lh, rh); 00079 } 00080 00081 const ex operator/(const ex & lh, const ex & rh) 00082 { 00083 return exmul(lh, power(rh,_ex_1)); 00084 } 00085 00086 00087 // binary arithmetic operators numeric with numeric 00088 00089 const numeric operator+(const numeric & lh, const numeric & rh) 00090 { 00091 return lh.add(rh); 00092 } 00093 00094 const numeric operator-(const numeric & lh, const numeric & rh) 00095 { 00096 return lh.sub(rh); 00097 } 00098 00099 const numeric operator*(const numeric & lh, const numeric & rh) 00100 { 00101 return lh.mul(rh); 00102 } 00103 00104 const numeric operator/(const numeric & lh, const numeric & rh) 00105 { 00106 return lh.div(rh); 00107 } 00108 00109 00110 // binary arithmetic assignment operators with ex 00111 00112 ex & operator+=(ex & lh, const ex & rh) 00113 { 00114 return lh = exadd(lh, rh); 00115 } 00116 00117 ex & operator-=(ex & lh, const ex & rh) 00118 { 00119 return lh = exadd(lh, exminus(rh)); 00120 } 00121 00122 ex & operator*=(ex & lh, const ex & rh) 00123 { 00124 return lh = exmul(lh, rh); 00125 } 00126 00127 ex & operator/=(ex & lh, const ex & rh) 00128 { 00129 return lh = exmul(lh, power(rh,_ex_1)); 00130 } 00131 00132 00133 // binary arithmetic assignment operators with numeric 00134 00135 numeric & operator+=(numeric & lh, const numeric & rh) 00136 { 00137 lh = lh.add(rh); 00138 return lh; 00139 } 00140 00141 numeric & operator-=(numeric & lh, const numeric & rh) 00142 { 00143 lh = lh.sub(rh); 00144 return lh; 00145 } 00146 00147 numeric & operator*=(numeric & lh, const numeric & rh) 00148 { 00149 lh = lh.mul(rh); 00150 return lh; 00151 } 00152 00153 numeric & operator/=(numeric & lh, const numeric & rh) 00154 { 00155 lh = lh.div(rh); 00156 return lh; 00157 } 00158 00159 00160 // unary operators 00161 00162 const ex operator+(const ex & lh) 00163 { 00164 return lh; 00165 } 00166 00167 const ex operator-(const ex & lh) 00168 { 00169 return exminus(lh); 00170 } 00171 00172 const numeric operator+(const numeric & lh) 00173 { 00174 return lh; 00175 } 00176 00177 const numeric operator-(const numeric & lh) 00178 { 00179 return _num_1_p->mul(lh); 00180 } 00181 00182 00183 // increment / decrement operators 00184 00186 ex & operator++(ex & rh) 00187 { 00188 return rh = exadd(rh, _ex1); 00189 } 00190 00192 ex & operator--(ex & rh) 00193 { 00194 return rh = exadd(rh, _ex_1); 00195 } 00196 00199 const ex operator++(ex & lh, int) 00200 { 00201 ex tmp(lh); 00202 lh = exadd(lh, _ex1); 00203 return tmp; 00204 } 00205 00208 const ex operator--(ex & lh, int) 00209 { 00210 ex tmp(lh); 00211 lh = exadd(lh, _ex_1); 00212 return tmp; 00213 } 00214 00216 numeric& operator++(numeric & rh) 00217 { 00218 rh = rh.add(*_num1_p); 00219 return rh; 00220 } 00221 00223 numeric& operator--(numeric & rh) 00224 { 00225 rh = rh.add(*_num_1_p); 00226 return rh; 00227 } 00228 00231 const numeric operator++(numeric & lh, int) 00232 { 00233 numeric tmp(lh); 00234 lh = lh.add(*_num1_p); 00235 return tmp; 00236 } 00237 00240 const numeric operator--(numeric & lh, int) 00241 { 00242 numeric tmp(lh); 00243 lh = lh.add(*_num_1_p); 00244 return tmp; 00245 } 00246 00247 // binary relational operators ex with ex 00248 00249 const relational operator==(const ex & lh, const ex & rh) 00250 { 00251 return relational(lh,rh,relational::equal); 00252 } 00253 00254 const relational operator!=(const ex & lh, const ex & rh) 00255 { 00256 return relational(lh,rh,relational::not_equal); 00257 } 00258 00259 const relational operator<(const ex & lh, const ex & rh) 00260 { 00261 return relational(lh,rh,relational::less); 00262 } 00263 00264 const relational operator<=(const ex & lh, const ex & rh) 00265 { 00266 return relational(lh,rh,relational::less_or_equal); 00267 } 00268 00269 const relational operator>(const ex & lh, const ex & rh) 00270 { 00271 return relational(lh,rh,relational::greater); 00272 } 00273 00274 const relational operator>=(const ex & lh, const ex & rh) 00275 { 00276 return relational(lh,rh,relational::greater_or_equal); 00277 } 00278 00279 // input/output stream operators and manipulators 00280 00281 static int my_ios_index() 00282 { 00283 static int i = std::ios_base::xalloc(); 00284 return i; 00285 } 00286 00287 // Stream format gets copied or destroyed 00288 static void my_ios_callback(std::ios_base::event ev, std::ios_base & s, int i) 00289 { 00290 print_context *p = static_cast<print_context *>(s.pword(i)); 00291 if (ev == std::ios_base::erase_event) { 00292 delete p; 00293 s.pword(i) = 0; 00294 } else if (ev == std::ios_base::copyfmt_event && p != 0) 00295 s.pword(i) = p->duplicate(); 00296 } 00297 00298 enum { 00299 callback_registered = 1 00300 }; 00301 00302 // Get print_context associated with stream, may return 0 if no context has 00303 // been associated yet 00304 static inline print_context *get_print_context(std::ios_base & s) 00305 { 00306 return static_cast<print_context *>(s.pword(my_ios_index())); 00307 } 00308 00309 // Set print_context associated with stream, retain options 00310 static void set_print_context(std::ios_base & s, const print_context & c) 00311 { 00312 int i = my_ios_index(); 00313 long flags = s.iword(i); 00314 if (!(flags & callback_registered)) { 00315 s.register_callback(my_ios_callback, i); 00316 s.iword(i) = flags | callback_registered; 00317 } 00318 print_context *p = static_cast<print_context *>(s.pword(i)); 00319 unsigned options = p ? p->options : c.options; 00320 delete p; 00321 p = c.duplicate(); 00322 p->options = options; 00323 s.pword(i) = p; 00324 } 00325 00326 // Get options for print_context associated with stream 00327 static inline unsigned get_print_options(std::ios_base & s) 00328 { 00329 print_context *p = get_print_context(s); 00330 return p ? p->options : 0; 00331 } 00332 00333 // Set options for print_context associated with stream 00334 static void set_print_options(std::ostream & s, unsigned options) 00335 { 00336 print_context *p = get_print_context(s); 00337 if (p == 0) 00338 set_print_context(s, print_dflt(s, options)); 00339 else 00340 p->options = options; 00341 } 00342 00343 std::ostream & operator<<(std::ostream & os, const ex & e) 00344 { 00345 print_context *p = get_print_context(os); 00346 if (p == 0) 00347 e.print(print_dflt(os)); 00348 else 00349 e.print(*p); 00350 return os; 00351 } 00352 00353 std::ostream & operator<<(std::ostream & os, const exvector & e) 00354 { 00355 print_context *p = get_print_context(os); 00356 exvector::const_iterator i = e.begin(); 00357 exvector::const_iterator vend = e.end(); 00358 00359 if (i==vend) { 00360 os << "[]"; 00361 return os; 00362 } 00363 00364 os << "["; 00365 while (true) { 00366 if (p == 0) 00367 i -> print(print_dflt(os)); 00368 else 00369 i -> print(*p); 00370 ++i; 00371 if (i==vend) 00372 break; 00373 os << ","; 00374 } 00375 os << "]"; 00376 00377 return os; 00378 } 00379 00380 std::ostream & operator<<(std::ostream & os, const exset & e) 00381 { 00382 print_context *p = get_print_context(os); 00383 exset::const_iterator i = e.begin(); 00384 exset::const_iterator send = e.end(); 00385 00386 if (i==send) { 00387 os << "<>"; 00388 return os; 00389 } 00390 00391 os << "<"; 00392 while (true) { 00393 if (p == 0) 00394 i->print(print_dflt(os)); 00395 else 00396 i->print(*p); 00397 ++i; 00398 if (i == send) 00399 break; 00400 os << ","; 00401 } 00402 os << ">"; 00403 00404 return os; 00405 } 00406 00407 std::ostream & operator<<(std::ostream & os, const exmap & e) 00408 { 00409 print_context *p = get_print_context(os); 00410 exmap::const_iterator i = e.begin(); 00411 exmap::const_iterator mend = e.end(); 00412 00413 if (i==mend) { 00414 os << "{}"; 00415 return os; 00416 } 00417 00418 os << "{"; 00419 while (true) { 00420 if (p == 0) 00421 i->first.print(print_dflt(os)); 00422 else 00423 i->first.print(*p); 00424 os << "=="; 00425 if (p == 0) 00426 i->second.print(print_dflt(os)); 00427 else 00428 i->second.print(*p); 00429 ++i; 00430 if( i==mend ) 00431 break; 00432 os << ","; 00433 } 00434 os << "}"; 00435 00436 return os; 00437 } 00438 00439 std::istream & operator>>(std::istream & is, ex & e) 00440 { 00441 throw (std::logic_error("expression input from streams not implemented")); 00442 } 00443 00444 std::ostream & dflt(std::ostream & os) 00445 { 00446 set_print_context(os, print_dflt(os)); 00447 set_print_options(os, 0); 00448 return os; 00449 } 00450 00451 std::ostream & latex(std::ostream & os) 00452 { 00453 set_print_context(os, print_latex(os)); 00454 return os; 00455 } 00456 00457 std::ostream & python(std::ostream & os) 00458 { 00459 set_print_context(os, print_python(os)); 00460 return os; 00461 } 00462 00463 std::ostream & python_repr(std::ostream & os) 00464 { 00465 set_print_context(os, print_python_repr(os)); 00466 return os; 00467 } 00468 00469 std::ostream & tree(std::ostream & os) 00470 { 00471 set_print_context(os, print_tree(os)); 00472 return os; 00473 } 00474 00475 std::ostream & csrc(std::ostream & os) 00476 { 00477 set_print_context(os, print_csrc_double(os)); 00478 return os; 00479 } 00480 00481 std::ostream & csrc_float(std::ostream & os) 00482 { 00483 set_print_context(os, print_csrc_float(os)); 00484 return os; 00485 } 00486 00487 std::ostream & csrc_double(std::ostream & os) 00488 { 00489 set_print_context(os, print_csrc_double(os)); 00490 return os; 00491 } 00492 00493 std::ostream & csrc_cl_N(std::ostream & os) 00494 { 00495 set_print_context(os, print_csrc_cl_N(os)); 00496 return os; 00497 } 00498 00499 std::ostream & index_dimensions(std::ostream & os) 00500 { 00501 set_print_options(os, get_print_options(os) | print_options::print_index_dimensions); 00502 return os; 00503 } 00504 00505 std::ostream & no_index_dimensions(std::ostream & os) 00506 { 00507 set_print_options(os, get_print_options(os) & ~print_options::print_index_dimensions); 00508 return os; 00509 } 00510 00511 } // namespace GiNaC