|
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 "ex.h" 00024 #include "add.h" 00025 #include "mul.h" 00026 #include "ncmul.h" 00027 #include "numeric.h" 00028 #include "matrix.h" 00029 #include "power.h" 00030 #include "lst.h" 00031 #include "relational.h" 00032 #include "utils.h" 00033 00034 #include <iostream> 00035 #include <stdexcept> 00036 00037 namespace GiNaC { 00038 00040 // other constructors 00042 00043 // none (all inlined) 00044 00046 // non-virtual functions in this class 00048 00049 // public 00050 00056 void ex::print(const print_context & c, unsigned level) const 00057 { 00058 bp->print(c, level); 00059 } 00060 00062 void ex::dbgprint() const 00063 { 00064 bp->dbgprint(); 00065 } 00066 00068 void ex::dbgprinttree() const 00069 { 00070 bp->dbgprinttree(); 00071 } 00072 00073 ex ex::expand(unsigned options) const 00074 { 00075 if (options == 0 && (bp->flags & status_flags::expanded)) // The "expanded" flag only covers the standard options; someone might want to re-expand with different options 00076 return *this; 00077 else 00078 return bp->expand(options); 00079 } 00080 00086 ex ex::diff(const symbol & s, unsigned nth) const 00087 { 00088 if (!nth) 00089 return *this; 00090 else 00091 return bp->diff(s, nth); 00092 } 00093 00095 bool ex::match(const ex & pattern) const 00096 { 00097 exmap repl_lst; 00098 return bp->match(pattern, repl_lst); 00099 } 00100 00105 bool ex::find(const ex & pattern, exset& found) const 00106 { 00107 if (match(pattern)) { 00108 found.insert(*this); 00109 return true; 00110 } 00111 bool any_found = false; 00112 for (size_t i=0; i<nops(); i++) 00113 if (op(i).find(pattern, found)) 00114 any_found = true; 00115 return any_found; 00116 } 00117 00120 ex ex::subs(const lst & ls, const lst & lr, unsigned options) const 00121 { 00122 GINAC_ASSERT(ls.nops() == lr.nops()); 00123 00124 // Convert the lists to a map 00125 exmap m; 00126 for (lst::const_iterator its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) { 00127 m.insert(std::make_pair(*its, *itr)); 00128 00129 // Search for products and powers in the expressions to be substituted 00130 // (for an optimization in expairseq::subs()) 00131 if (is_exactly_a<mul>(*its) || is_exactly_a<power>(*its)) 00132 options |= subs_options::pattern_is_product; 00133 } 00134 if (!(options & subs_options::pattern_is_product)) 00135 options |= subs_options::pattern_is_not_product; 00136 00137 return bp->subs(m, options); 00138 } 00139 00144 ex ex::subs(const ex & e, unsigned options) const 00145 { 00146 if (e.info(info_flags::relation_equal)) { 00147 00148 // Argument is a relation: convert it to a map 00149 exmap m; 00150 const ex & s = e.op(0); 00151 m.insert(std::make_pair(s, e.op(1))); 00152 00153 if (is_exactly_a<mul>(s) || is_exactly_a<power>(s)) 00154 options |= subs_options::pattern_is_product; 00155 else 00156 options |= subs_options::pattern_is_not_product; 00157 00158 return bp->subs(m, options); 00159 00160 } else if (e.info(info_flags::list)) { 00161 00162 // Argument is a list: convert it to a map 00163 exmap m; 00164 GINAC_ASSERT(is_a<lst>(e)); 00165 for (lst::const_iterator it = ex_to<lst>(e).begin(); it != ex_to<lst>(e).end(); ++it) { 00166 ex r = *it; 00167 if (!r.info(info_flags::relation_equal)) 00168 throw(std::invalid_argument("basic::subs(ex): argument must be a list of equations")); 00169 const ex & s = r.op(0); 00170 m.insert(std::make_pair(s, r.op(1))); 00171 00172 // Search for products and powers in the expressions to be substituted 00173 // (for an optimization in expairseq::subs()) 00174 if (is_exactly_a<mul>(s) || is_exactly_a<power>(s)) 00175 options |= subs_options::pattern_is_product; 00176 } 00177 if (!(options & subs_options::pattern_is_product)) 00178 options |= subs_options::pattern_is_not_product; 00179 00180 return bp->subs(m, options); 00181 00182 } else 00183 throw(std::invalid_argument("ex::subs(ex): argument must be a relation_equal or a list")); 00184 } 00185 00187 void ex::traverse_preorder(visitor & v) const 00188 { 00189 accept(v); 00190 00191 size_t n = nops(); 00192 for (size_t i = 0; i < n; ++i) 00193 op(i).traverse_preorder(v); 00194 } 00195 00197 void ex::traverse_postorder(visitor & v) const 00198 { 00199 size_t n = nops(); 00200 for (size_t i = 0; i < n; ++i) 00201 op(i).traverse_postorder(v); 00202 00203 accept(v); 00204 } 00205 00207 ex & ex::let_op(size_t i) 00208 { 00209 makewriteable(); 00210 return bp->let_op(i); 00211 } 00212 00213 ex & ex::operator[](const ex & index) 00214 { 00215 makewriteable(); 00216 return (*bp)[index]; 00217 } 00218 00219 ex & ex::operator[](size_t i) 00220 { 00221 makewriteable(); 00222 return (*bp)[i]; 00223 } 00224 00226 ex ex::lhs() const 00227 { 00228 if (!is_a<relational>(*this)) 00229 throw std::runtime_error("ex::lhs(): not a relation"); 00230 return bp->op(0); 00231 } 00232 00234 ex ex::rhs() const 00235 { 00236 if (!is_a<relational>(*this)) 00237 throw std::runtime_error("ex::rhs(): not a relation"); 00238 return bp->op(1); 00239 } 00240 00242 bool ex::is_polynomial(const ex & vars) const 00243 { 00244 if (is_a<lst>(vars)) { 00245 const lst & varlst = ex_to<lst>(vars); 00246 for (lst::const_iterator i=varlst.begin(); i!=varlst.end(); ++i) 00247 if (!bp->is_polynomial(*i)) 00248 return false; 00249 return true; 00250 } 00251 else 00252 return bp->is_polynomial(vars); 00253 } 00254 00256 bool ex::is_zero_matrix() const 00257 { 00258 if (is_zero()) 00259 return true; 00260 else { 00261 ex e = evalm(); 00262 return is_a<matrix>(e) && ex_to<matrix>(e).is_zero_matrix(); 00263 } 00264 } 00265 00266 // private 00267 00270 void ex::makewriteable() 00271 { 00272 GINAC_ASSERT(bp->flags & status_flags::dynallocated); 00273 bp.makewritable(); 00274 GINAC_ASSERT(bp->get_refcount() == 1); 00275 } 00276 00279 void ex::share(const ex & other) const 00280 { 00281 if ((bp->flags | other.bp->flags) & status_flags::not_shareable) 00282 return; 00283 00284 if (bp->get_refcount() <= other.bp->get_refcount()) 00285 bp = other.bp; 00286 else 00287 other.bp = bp; 00288 } 00289 00293 ptr<basic> ex::construct_from_basic(const basic & other) 00294 { 00295 if (!(other.flags & status_flags::evaluated)) { 00296 00297 // The object is not yet evaluated, so call eval() to evaluate 00298 // the top level. This will return either 00299 // a) the original object with status_flags::evaluated set (when the 00300 // eval() implementation calls hold()) 00301 // or 00302 // b) a different expression. 00303 // 00304 // eval() returns an ex, not a basic&, so this will go through 00305 // construct_from_basic() a second time. In case a) we end up in 00306 // the "else" branch below. In case b) we end up here again and 00307 // apply eval() once more. The recursion stops when eval() calls 00308 // hold() or returns an object that already has its "evaluated" 00309 // flag set, such as a symbol or a numeric. 00310 const ex & tmpex = other.eval(1); 00311 00312 // Eventually, the eval() recursion goes through the "else" branch 00313 // below, which assures that the object pointed to by tmpex.bp is 00314 // allocated on the heap (either it was already on the heap or it 00315 // is a heap-allocated duplicate of another object). 00316 GINAC_ASSERT(tmpex.bp->flags & status_flags::dynallocated); 00317 00318 // If the original object is not referenced but heap-allocated, 00319 // it means that eval() hit case b) above. The original object is 00320 // no longer needed (it evaluated into something different), so we 00321 // delete it (because nobody else will). 00322 if ((other.get_refcount() == 0) && (other.flags & status_flags::dynallocated)) 00323 delete &other; // yes, you can apply delete to a const pointer 00324 00325 // We can't return a basic& here because the tmpex is destroyed as 00326 // soon as we leave the function, which would deallocate the 00327 // evaluated object. 00328 return tmpex.bp; 00329 00330 } else { 00331 00332 // The easy case: making an "ex" out of an evaluated object. 00333 if (other.flags & status_flags::dynallocated) { 00334 00335 // The object is already heap-allocated, so we can just make 00336 // another reference to it. 00337 return ptr<basic>(const_cast<basic &>(other)); 00338 00339 } else { 00340 00341 // The object is not heap-allocated, so we create a duplicate 00342 // on the heap. 00343 basic *bp = other.duplicate(); 00344 bp->setflag(status_flags::dynallocated); 00345 GINAC_ASSERT(bp->get_refcount() == 0); 00346 return bp; 00347 } 00348 } 00349 } 00350 00351 basic & ex::construct_from_int(int i) 00352 { 00353 switch (i) { // prefer flyweights over new objects 00354 case -12: 00355 return *const_cast<numeric *>(_num_12_p); 00356 case -11: 00357 return *const_cast<numeric *>(_num_11_p); 00358 case -10: 00359 return *const_cast<numeric *>(_num_10_p); 00360 case -9: 00361 return *const_cast<numeric *>(_num_9_p); 00362 case -8: 00363 return *const_cast<numeric *>(_num_8_p); 00364 case -7: 00365 return *const_cast<numeric *>(_num_7_p); 00366 case -6: 00367 return *const_cast<numeric *>(_num_6_p); 00368 case -5: 00369 return *const_cast<numeric *>(_num_5_p); 00370 case -4: 00371 return *const_cast<numeric *>(_num_4_p); 00372 case -3: 00373 return *const_cast<numeric *>(_num_3_p); 00374 case -2: 00375 return *const_cast<numeric *>(_num_2_p); 00376 case -1: 00377 return *const_cast<numeric *>(_num_1_p); 00378 case 0: 00379 return *const_cast<numeric *>(_num0_p); 00380 case 1: 00381 return *const_cast<numeric *>(_num1_p); 00382 case 2: 00383 return *const_cast<numeric *>(_num2_p); 00384 case 3: 00385 return *const_cast<numeric *>(_num3_p); 00386 case 4: 00387 return *const_cast<numeric *>(_num4_p); 00388 case 5: 00389 return *const_cast<numeric *>(_num5_p); 00390 case 6: 00391 return *const_cast<numeric *>(_num6_p); 00392 case 7: 00393 return *const_cast<numeric *>(_num7_p); 00394 case 8: 00395 return *const_cast<numeric *>(_num8_p); 00396 case 9: 00397 return *const_cast<numeric *>(_num9_p); 00398 case 10: 00399 return *const_cast<numeric *>(_num10_p); 00400 case 11: 00401 return *const_cast<numeric *>(_num11_p); 00402 case 12: 00403 return *const_cast<numeric *>(_num12_p); 00404 default: 00405 basic *bp = new numeric(i); 00406 bp->setflag(status_flags::dynallocated); 00407 GINAC_ASSERT(bp->get_refcount() == 0); 00408 return *bp; 00409 } 00410 } 00411 00412 basic & ex::construct_from_uint(unsigned int i) 00413 { 00414 switch (i) { // prefer flyweights over new objects 00415 case 0: 00416 return *const_cast<numeric *>(_num0_p); 00417 case 1: 00418 return *const_cast<numeric *>(_num1_p); 00419 case 2: 00420 return *const_cast<numeric *>(_num2_p); 00421 case 3: 00422 return *const_cast<numeric *>(_num3_p); 00423 case 4: 00424 return *const_cast<numeric *>(_num4_p); 00425 case 5: 00426 return *const_cast<numeric *>(_num5_p); 00427 case 6: 00428 return *const_cast<numeric *>(_num6_p); 00429 case 7: 00430 return *const_cast<numeric *>(_num7_p); 00431 case 8: 00432 return *const_cast<numeric *>(_num8_p); 00433 case 9: 00434 return *const_cast<numeric *>(_num9_p); 00435 case 10: 00436 return *const_cast<numeric *>(_num10_p); 00437 case 11: 00438 return *const_cast<numeric *>(_num11_p); 00439 case 12: 00440 return *const_cast<numeric *>(_num12_p); 00441 default: 00442 basic *bp = new numeric(i); 00443 bp->setflag(status_flags::dynallocated); 00444 GINAC_ASSERT(bp->get_refcount() == 0); 00445 return *bp; 00446 } 00447 } 00448 00449 basic & ex::construct_from_long(long i) 00450 { 00451 switch (i) { // prefer flyweights over new objects 00452 case -12: 00453 return *const_cast<numeric *>(_num_12_p); 00454 case -11: 00455 return *const_cast<numeric *>(_num_11_p); 00456 case -10: 00457 return *const_cast<numeric *>(_num_10_p); 00458 case -9: 00459 return *const_cast<numeric *>(_num_9_p); 00460 case -8: 00461 return *const_cast<numeric *>(_num_8_p); 00462 case -7: 00463 return *const_cast<numeric *>(_num_7_p); 00464 case -6: 00465 return *const_cast<numeric *>(_num_6_p); 00466 case -5: 00467 return *const_cast<numeric *>(_num_5_p); 00468 case -4: 00469 return *const_cast<numeric *>(_num_4_p); 00470 case -3: 00471 return *const_cast<numeric *>(_num_3_p); 00472 case -2: 00473 return *const_cast<numeric *>(_num_2_p); 00474 case -1: 00475 return *const_cast<numeric *>(_num_1_p); 00476 case 0: 00477 return *const_cast<numeric *>(_num0_p); 00478 case 1: 00479 return *const_cast<numeric *>(_num1_p); 00480 case 2: 00481 return *const_cast<numeric *>(_num2_p); 00482 case 3: 00483 return *const_cast<numeric *>(_num3_p); 00484 case 4: 00485 return *const_cast<numeric *>(_num4_p); 00486 case 5: 00487 return *const_cast<numeric *>(_num5_p); 00488 case 6: 00489 return *const_cast<numeric *>(_num6_p); 00490 case 7: 00491 return *const_cast<numeric *>(_num7_p); 00492 case 8: 00493 return *const_cast<numeric *>(_num8_p); 00494 case 9: 00495 return *const_cast<numeric *>(_num9_p); 00496 case 10: 00497 return *const_cast<numeric *>(_num10_p); 00498 case 11: 00499 return *const_cast<numeric *>(_num11_p); 00500 case 12: 00501 return *const_cast<numeric *>(_num12_p); 00502 default: 00503 basic *bp = new numeric(i); 00504 bp->setflag(status_flags::dynallocated); 00505 GINAC_ASSERT(bp->get_refcount() == 0); 00506 return *bp; 00507 } 00508 } 00509 00510 basic & ex::construct_from_ulong(unsigned long i) 00511 { 00512 switch (i) { // prefer flyweights over new objects 00513 case 0: 00514 return *const_cast<numeric *>(_num0_p); 00515 case 1: 00516 return *const_cast<numeric *>(_num1_p); 00517 case 2: 00518 return *const_cast<numeric *>(_num2_p); 00519 case 3: 00520 return *const_cast<numeric *>(_num3_p); 00521 case 4: 00522 return *const_cast<numeric *>(_num4_p); 00523 case 5: 00524 return *const_cast<numeric *>(_num5_p); 00525 case 6: 00526 return *const_cast<numeric *>(_num6_p); 00527 case 7: 00528 return *const_cast<numeric *>(_num7_p); 00529 case 8: 00530 return *const_cast<numeric *>(_num8_p); 00531 case 9: 00532 return *const_cast<numeric *>(_num9_p); 00533 case 10: 00534 return *const_cast<numeric *>(_num10_p); 00535 case 11: 00536 return *const_cast<numeric *>(_num11_p); 00537 case 12: 00538 return *const_cast<numeric *>(_num12_p); 00539 default: 00540 basic *bp = new numeric(i); 00541 bp->setflag(status_flags::dynallocated); 00542 GINAC_ASSERT(bp->get_refcount() == 0); 00543 return *bp; 00544 } 00545 } 00546 00547 basic & ex::construct_from_double(double d) 00548 { 00549 basic *bp = new numeric(d); 00550 bp->setflag(status_flags::dynallocated); 00551 GINAC_ASSERT(bp->get_refcount() == 0); 00552 return *bp; 00553 } 00554 00556 // static member variables 00558 00559 // none 00560 00562 // functions which are not member functions 00564 00565 // none 00566 00568 // global functions 00570 00571 // none 00572 00573 00574 } // namespace GiNaC