GiNaC  1.6.2
operators.cpp
Go to the documentation of this file.
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

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.