SyFi  0.3
ginac_tools.cpp
Go to the documentation of this file.
00001 // Copyright (C) 2006-2009 Kent-Andre Mardal and Simula Research Laboratory
00002 //
00003 // This file is part of SyFi.
00004 //
00005 // SyFi is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // SyFi is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with SyFi. If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #include "ginac_tools.h"
00019 #include "symbol_factory.h"
00020 
00021 #include <ginac/ginac.h>
00022 
00023 #include <iostream>
00024 #include <sstream>
00025 #include <fstream>
00026 #include <stdexcept>
00027 
00028 using namespace std;
00029 using namespace GiNaC;
00030 
00031 namespace SyFi
00032 {
00033 
00034         GiNaC::lst cross(GiNaC::lst& v1, GiNaC::lst& v2)
00035         {
00036                 GiNaC::lst ret;
00037                 if ( v1.nops() != v2.nops() )
00038                 {
00039                         cout <<"incompatible vectors "<<endl;
00040                         cout <<"v1.nops() "<<v1.nops();
00041                         cout <<"  v2.nops() "<<v2.nops()<<endl; ;
00042                         return GiNaC::lst();
00043                 }
00044                 ret.append(  v1.op(1)*v2.op(2) - v1.op(2)*v2.op(1));
00045                 ret.append(- v1.op(0)*v2.op(2) + v1.op(2)*v2.op(0));
00046                 ret.append(  v1.op(0)*v2.op(1) - v1.op(1)*v2.op(0));
00047                 return ret;
00048         }
00049 
00050         GiNaC::ex inner(GiNaC::ex a, GiNaC::ex b, bool transposed)
00051         {
00052                 if (GiNaC::is_a<GiNaC::matrix>(a) && GiNaC::is_a<GiNaC::matrix>(b))
00053                 {
00054                         GiNaC::matrix ma = GiNaC::ex_to<GiNaC::matrix>(a);
00055                         GiNaC::matrix mb = GiNaC::ex_to<GiNaC::matrix>(b);
00056                         if ( !transposed )
00057                         {
00058                                 if (ma.cols() != mb.cols() || ma.rows() != mb.rows() )
00059                                 {
00060                                         cout <<"Incompatible matrices "<<endl;
00061                                         cout <<"a.cols() "<<ma.cols()<<endl;
00062                                         cout <<"a.rows() "<<ma.rows()<<endl;
00063                                         cout <<"b.cols() "<<mb.cols()<<endl;
00064                                         cout <<"b.rows() "<<mb.rows()<<endl;
00065                                         cout <<"a="<<a<<endl;
00066                                         cout <<"b="<<b<<endl;
00067                                         throw std::runtime_error("Incompatible matrices.");
00068                                 }
00069 
00070                                 GiNaC::ex ret;
00071                                 for (unsigned int i=0; i<ma.rows(); i++)
00072                                 {
00073                                         for (unsigned int j=0; j<ma.cols(); j++)
00074                                         {
00075                                                 ret += ma(i,j)*mb(i,j);
00076                                         }
00077                                 }
00078                                 return ret;
00079                         }
00080                         else
00081                         {
00082                                 if (ma.cols() != mb.rows() || ma.rows() != mb.cols() )
00083                                 {
00084                                         cout <<"Incompatible matrices "<<endl;
00085                                         cout <<"a.cols() "<<ma.cols()<<endl;
00086                                         cout <<"a.rows() "<<ma.rows()<<endl;
00087                                         cout <<"b.cols() "<<mb.cols()<<endl;
00088                                         cout <<"b.rows() "<<mb.rows()<<endl;
00089                                         cout <<"a="<<a<<endl;
00090                                         cout <<"b="<<b<<endl;
00091                                         throw std::runtime_error("Incompatible matrices.");
00092                                 }
00093 
00094                                 GiNaC::ex ret;
00095                                 for (unsigned int i=0; i<ma.rows(); i++)
00096                                 {
00097                                         for (unsigned int j=0; j<ma.cols(); j++)
00098                                         {
00099                                                 ret += ma(i,j)*mb(j,i);
00100                                         }
00101                                 }
00102                                 return ret;
00103                         }
00104                 }
00105                 else if (GiNaC::is_a<GiNaC::lst>(a)
00106                         && GiNaC::is_a<GiNaC::lst>(b))
00107                 {
00108                         return inner(GiNaC::ex_to<GiNaC::lst>(a), GiNaC::ex_to<GiNaC::lst>(b));
00109                 }
00110                 else
00111                 {
00112                         return a*b;
00113                 }
00114         }
00115 
00116         GiNaC::ex inner(GiNaC::lst v1, GiNaC::lst v2)
00117         {
00118                 GiNaC::ex ret;
00119 
00120                 if ( v1.nops() != v2.nops() )
00121                 {
00122                         cout <<"incompatible vectors "<<endl;
00123                         cout <<"v1.nops() "<<v1.nops();
00124                         cout <<"  v2.nops() "<<v2.nops()<<endl; ;
00125                         return 0;
00126                 }
00127                 for (unsigned i = 0; i <= v1.nops()-1 ; ++i)
00128                 {
00129                         if ( GiNaC::is_a<GiNaC::lst>(v1.op(i)) &&
00130                                 GiNaC::is_a<GiNaC::lst>(v2.op(i)) )
00131                         {
00132                                 ret += inner(GiNaC::ex_to<GiNaC::lst>(v1.op(i)),
00133                                         GiNaC::ex_to<GiNaC::lst>(v2.op(i)));
00134                         }
00135                         else
00136                         {
00137                                 ret += v1.op(i)*v2.op(i);
00138                         }
00139                 }
00140                 return ret;
00141         }
00142 
00143         GiNaC::ex inner(GiNaC::exvector& v1, GiNaC::exvector& v2)
00144         {
00145                 GiNaC::ex ret;
00146                 for (unsigned int i=0; i< v1.size(); i++)
00147                 {
00148                         ret += v1[i]*v2[i];
00149                 }
00150                 return ret;
00151         }
00152 
00153         GiNaC::lst matvec(GiNaC::matrix& M, GiNaC::lst& x)
00154         {
00155                 GiNaC::lst ret;
00156                 int nr = M.rows();
00157                 int nc = M.cols();
00158                 for (int i = 0; i < nr; i++)
00159                 {
00160                         GiNaC::ex tmp;
00161                         for (int j = 0; j < nc; j++)
00162                         {
00163                                 tmp = tmp +  M(i,j)*(x.op(j));
00164                         }
00165                         ret.append(tmp);
00166                 }
00167                 return ret;
00168         }
00169 
00170         GiNaC::ex matvec(GiNaC::ex A, GiNaC::ex x)
00171         {
00172                 ex sol;
00173 
00174                 if (GiNaC::is_a<GiNaC::matrix>(A) && GiNaC::is_a<GiNaC::matrix>(x))
00175                 {
00176                         GiNaC::matrix AA = GiNaC::ex_to<GiNaC::matrix>(A);
00177                         GiNaC::matrix xx = GiNaC::ex_to<GiNaC::matrix>(x);
00178                         sol = AA.mul(xx);
00179                 }
00180                 else
00181                 {
00182                         throw std::runtime_error("Invalid argument types, need matrices");
00183                 }
00184                 return sol;
00185         }
00186 
00187         GiNaC::lst ex2equations(GiNaC::ex rel)
00188         {
00189                 GiNaC::ex lhs = rel.lhs();
00190                 GiNaC::ex rhs = rel.rhs();
00191 
00192                 GiNaC::ex l;
00193                 GiNaC::ex r;
00194 
00195                 GiNaC::lst eqs;
00196 
00197                 for (int i=lhs.ldegree(x); i<=lhs.degree(x); ++i)
00198                 {
00199                         for (int j=lhs.ldegree(y); j<=lhs.degree(y); ++j)
00200                         {
00201                                 for (int k=lhs.ldegree(z); k<=lhs.degree(z); ++k)
00202                                 {
00203                                         l = lhs.coeff(x,i).coeff(y, j).coeff(z,k);
00204                                         r = rhs.coeff(x,i).coeff(y, j).coeff(z,k);
00205                                         //      if (! (l == 0 && r == 0 ) )  eqs.append(l == r); OLD VERSION
00206                                         if ( (l != 0 && (r == 0 || r == 1) ) )  eqs.append(l == r);
00207                                 }
00208                         }
00209                 }
00210                 eqs.sort();
00211                 return eqs;
00212         }
00213 
00214         GiNaC::lst collapse(GiNaC::lst l)
00215         {
00216                 GiNaC::lst lc;
00217                 GiNaC::lst::const_iterator iter1, iter2;
00218 
00219                 for (iter1 = l.begin(); iter1 != l.end(); ++iter1)
00220                 {
00221                         if (GiNaC::is_a<GiNaC::lst>(*iter1))
00222                         {
00223                                 for (iter2 = GiNaC::ex_to<GiNaC::lst>(*iter1).begin(); iter2 != GiNaC::ex_to<GiNaC::lst>(*iter1).end(); ++iter2)
00224                                 {
00225                                         lc.append(*iter2);
00226                                 }
00227                         }
00228                         else
00229                         {
00230                                 lc.append(*iter1);
00231                         }
00232                 }
00233                 lc.sort();
00234                 lc.unique();
00235                 return lc;
00236         }
00237 
00238         GiNaC::matrix equations2matrix(const GiNaC::ex &eqns, const GiNaC::ex &symbols)
00239         {
00240 
00241                 GiNaC::matrix sys(eqns.nops(),symbols.nops());
00242                 GiNaC::matrix rhs(eqns.nops(),1);
00243                 GiNaC::matrix vars(symbols.nops(),1);
00244 
00245                 for (size_t r=0; r<eqns.nops(); r++)
00246                 {
00247                                                                  // lhs-rhs==0
00248                         const GiNaC::ex eq = eqns.op(r).op(0)-eqns.op(r).op(1);
00249                         GiNaC::ex linpart = eq;
00250                         for (size_t c=0; c<symbols.nops(); c++)
00251                         {
00252                                 const GiNaC::ex co = eq.coeff(GiNaC::ex_to<GiNaC::symbol>(symbols.op(c)),1);
00253                                 linpart -= co*symbols.op(c);
00254                                 sys(r,c) = co;
00255                         }
00256                         linpart = linpart.expand();
00257                         rhs(r,0) = -linpart;
00258                 }
00259                 return sys;
00260         }
00261 
00262         void matrix_from_equations(const GiNaC::ex &eqns, const GiNaC::ex &symbols, GiNaC::matrix& A, GiNaC::matrix& b)
00263         {
00264                 // build matrix from equation system
00265                 GiNaC::matrix sys(eqns.nops(),symbols.nops());
00266                 GiNaC::matrix rhs(eqns.nops(),1);
00267                 GiNaC::matrix vars(symbols.nops(),1);
00268 
00269                 for (size_t r=0; r<eqns.nops(); r++)
00270                 {
00271                                                                  // lhs-rhs==0
00272                         const GiNaC::ex eq = eqns.op(r).op(0)-eqns.op(r).op(1);
00273                         GiNaC::ex linpart = eq;
00274                         for (size_t c=0; c<symbols.nops(); c++)
00275                         {
00276                                 const GiNaC::ex co = eq.coeff(GiNaC::ex_to<GiNaC::symbol>(symbols.op(c)),1);
00277                                 linpart -= co*symbols.op(c);
00278                                 sys(r,c) = co;
00279                         }
00280                         linpart = linpart.expand();
00281                         rhs(r,0) = -linpart;
00282                 }
00283                 A = sys;
00284                 b = rhs;
00285         }
00286 
00287         GiNaC::ex lst_to_matrix2(const GiNaC::lst& l)
00288         {
00289                 GiNaC::lst::const_iterator itr, itc;
00290 
00291                 // Find number of rows and columns
00292                 size_t rows = l.nops(), cols = 0;
00293                 for (itr = l.begin(); itr != l.end(); ++itr)
00294                 {
00295                         if (!GiNaC::is_a<GiNaC::lst>(*itr))
00296                                 //              throw (std::invalid_argument("lst_to_matrix: argument must be a list of lists"));
00297                                 cols = 1;
00298                         if (itr->nops() > cols)
00299                                 cols = itr->nops();
00300                 }
00301                 // Allocate and fill matrix
00302                 GiNaC::matrix &M = *new GiNaC::matrix(rows, cols);
00303                 M.setflag(GiNaC::status_flags::dynallocated);
00304 
00305                 unsigned i;
00306                 for (itr = l.begin(), i = 0; itr != l.end(); ++itr, ++i)
00307                 {
00308                         unsigned j;
00309                         if (cols == 1)
00310                         {
00311                                 M(i, 0) = *itr;
00312                         }
00313                         else
00314                         {
00315                                 for (itc = GiNaC::ex_to<GiNaC::lst>(*itr).begin(), j = 0; itc != GiNaC::ex_to<GiNaC::lst>(*itr).end(); ++itc, ++j)
00316                                         M(i, j) = *itc;
00317                         }
00318                 }
00319                 return M;
00320         }
00321 
00322         GiNaC::lst matrix_to_lst2(const GiNaC::ex& m)
00323         {
00324                 if (GiNaC::is_a<GiNaC::matrix>(m))
00325                 {
00326                         GiNaC::matrix A = GiNaC::ex_to<GiNaC::matrix>(m);
00327                         int cols = A.cols();
00328                         int rows = A.rows();
00329 
00330                         GiNaC::lst ret;
00331                         if ( cols == 1 )
00332                         {
00333                                 for (unsigned int i=0; i<=A.rows()-1; i++)
00334                                 {
00335                                         ret.append(A(i,0));
00336                                 }
00337                         }
00338                         else if ( rows == 1 )
00339                         {
00340                                 for (unsigned int i=0; i<=A.cols()-1; i++)
00341                                 {
00342                                         ret.append(A(0,i));
00343                                 }
00344                         }
00345                         else
00346                         {
00347                                 for (unsigned int i=0; i<=A.rows()-1; i++)
00348                                 {
00349                                         GiNaC::lst rl;
00350                                         for (unsigned int j=0; j<=A.cols()-1; j++)
00351                                         {
00352                                                 rl.append(A(i,j));
00353                                         }
00354                                         ret.append(rl);
00355                                 }
00356                         }
00357                         return ret;
00358                 }
00359                 else
00360                 {
00361                         return GiNaC::lst();
00362                 }
00363         }
00364 
00365         GiNaC::lst lst_equals(GiNaC::ex a, GiNaC::ex b)
00366         {
00367                 GiNaC::lst ret;
00368                 if ( (GiNaC::is_a<GiNaC::lst>(a)) && (GiNaC::is_a<GiNaC::lst>(b)) /*&& (a.nops() == b.nops())*/ ) {
00369                 for (unsigned int i=0; i<= a.nops()-1; i++)
00370                 {
00371                         ret.append(b.op(i) == a.op(i));
00372                 }
00373         }
00374         else if ( !(GiNaC::is_a<GiNaC::lst>(a)) && !(GiNaC::is_a<GiNaC::lst>(b)))
00375         {
00376                 ret.append(b == a);
00377         }
00378         else if ( !(GiNaC::is_a<GiNaC::lst>(a)) && (GiNaC::is_a<GiNaC::lst>(b)))
00379         {
00380                 ret.append(b.op(0) == a);
00381         }
00382         else
00383         {
00384                 throw(std::invalid_argument("Make sure that the lists a and b are comparable."));
00385         }
00386         return ret;
00387 }
00388 
00389 
00390 int find(GiNaC::ex e, GiNaC::lst list)
00391 {
00392         for (unsigned int i=0; i< list.nops(); i++)
00393         {
00394                 if ( e == list.op(i) ) return i;
00395         }
00396         return -1;
00397 }
00398 
00399 
00400 void visitor_subst_pow(GiNaC::ex e, GiNaC::exmap& map, ex_int_map& intmap, string a)
00401 {
00402         static int i=0;
00403         if (map.find(e) != map.end())
00404         {
00405                 intmap[e] = intmap[e]+1;
00406                 return;
00407         }
00408         if (GiNaC::is_exactly_a<GiNaC::power>(e))
00409         {
00410                 std::ostringstream s;
00411                 s <<a<<i++;
00412                 map[e] = GiNaC::symbol(s.str());
00413                 intmap[e] = 0;
00414                 for (unsigned int i=0; i< e.nops(); i++)
00415                 {
00416                         GiNaC::ex e2 = e.op(i);
00417                         //       cout <<"power e "<<e2<<endl;
00418                         visitor_subst_pow(e2,map,intmap, a);
00419                 }
00420         }
00421         else if (GiNaC::is_a<GiNaC::function>(e))
00422         {
00423                 std::ostringstream s;
00424                 s <<a<<i++;
00425                 map[e] = GiNaC::symbol(s.str());
00426                 intmap[e] = 0;
00427                 for (unsigned int i=0; i< e.nops(); i++)
00428                 {
00429                         GiNaC::ex e2 = e.op(i);
00430                         //       cout <<"function e "<<e2<<endl;
00431                         visitor_subst_pow(e2,map,intmap, a);
00432                 }
00433         }
00434         else if (GiNaC::is_a<GiNaC::mul>(e))
00435         {
00436                 if (e.nops() > 4 && e.nops() < 10 )
00437                 {
00438                         std::ostringstream s;
00439                         s <<a<<i++;
00440                         map[e] = GiNaC::symbol(s.str());
00441                         intmap[e] = 0;
00442                 }
00443 
00444                 for (unsigned int i=0; i< e.nops(); i++)
00445                 {
00446                         GiNaC::ex e2 = e.op(i);
00447                         visitor_subst_pow(e2,map,intmap, a);
00448                 }
00449         }
00450         else if (GiNaC::is_a<GiNaC::add>(e))
00451         {
00452                 for (unsigned int i=0; i< e.nops(); i++)
00453                 {
00454                         GiNaC::ex e2 = e.op(i);
00455                         visitor_subst_pow(e2,map,intmap,a);
00456                 }
00457         }
00458 }
00459 
00460 
00461 void check_visitor(GiNaC::ex e, GiNaC::lst& exlist)
00462 {
00463         if (find(e, exlist) >= 0) return;
00464 
00465         //  cout <<"ex e "<<e<<endl;
00466         if (GiNaC::is_a<GiNaC::numeric>(e))
00467         {
00468         }
00469         else if (GiNaC::is_a<GiNaC::add>(e) )
00470         {
00471                 //    cout <<"e "<<e <<endl;
00472                 //    cout <<"e.nops() "<<e.nops() <<endl;
00473                 if (e.nops() > 4 && e.nops() < 10 ) exlist.append(e);
00474                 for (unsigned int i=0; i< e.nops(); i++)
00475                 {
00476                         GiNaC::ex e2 = e.op(i);
00477                         //       cout <<"add e "<<e2<<endl;
00478                         //       exlist.append(e2);
00479                         check_visitor(e2,exlist);
00480                 }
00481         }
00482         else if (GiNaC::is_a<GiNaC::mul>(e))
00483         {
00484                 for (unsigned int i=0; i< e.nops(); i++)
00485                 {
00486                         GiNaC::ex e2 = e.op(i);
00487                         //       cout <<"mul e "<<e2<<endl;
00488                         exlist.append(e2);
00489                         check_visitor(e2,exlist);
00490                 }
00491         }
00492         else if (GiNaC::is_a<GiNaC::lst>(e))
00493         {
00494                 for (unsigned int i=0; i< e.nops(); i++)
00495                 {
00496                         GiNaC::ex e2 = e.op(i);
00497                         //       cout <<"GiNaC::lst e "<<e2<<endl;
00498                         //       exlist.append(e2);
00499                         check_visitor(e2,exlist);
00500                 }
00501         }
00502         else if (GiNaC::is_exactly_a<GiNaC::power>(e))
00503         {
00504                 exlist.append(e);
00505                 for (unsigned int i=0; i< e.nops(); i++)
00506                 {
00507                         GiNaC::ex e2 = e.op(i);
00508                         //       cout <<"power e "<<e2<<endl;
00509                         check_visitor(e2,exlist);
00510                 }
00511         }
00512         else if (GiNaC::is_a<GiNaC::function>(e))
00513         {
00514                 exlist.append(e);
00515                 for (unsigned int i=0; i< e.nops(); i++)
00516                 {
00517                         GiNaC::ex e2 = e.op(i);
00518                         //       cout <<"function e "<<e2<<endl;
00519                         check_visitor(e2,exlist);
00520                 }
00521         }
00522 
00523         else
00524         {
00525                 //       exlist.append(e);
00526                 //    cout <<"atom e "<<e<<endl;
00527         }
00528 
00529         exlist.sort();
00530         exlist.unique();
00531 }
00532 
00533 
00534 GiNaC::ex homogenous_pol(unsigned int order, unsigned int nsd, const string a)
00535 {
00536         using SyFi::x;
00537         using SyFi::y;
00538         using SyFi::z;
00539 
00540         if ( nsd == 1)
00541         {
00542                 GiNaC::symbol a0(istr(a,0));
00543                 return GiNaC::lst(a0*pow(x,order), a0, pow(x,order));
00544         }
00545         else if ( nsd == 2 )
00546         {
00547                 GiNaC::ex variables = get_symbolic_matrix(1,order+1, a);
00548                 GiNaC::lst basis;
00549                 GiNaC::ex ret;
00550                 for (unsigned int i=0; i<= order; i++)
00551                 {
00552                         basis.append(pow(x,i)*pow(y,order-i));
00553                         ret += variables.op(i)*basis.op(i);
00554                 }
00555                 return GiNaC::lst(ret, matrix_to_lst2(variables), basis);
00556         }
00557         else if ( nsd == 3 )
00558         {
00559                 GiNaC::lst basis;
00560                 for (unsigned int i=0; i<= order; i++)
00561                 {
00562                         for (unsigned int j=0; j<= order; j++)
00563                         {
00564                                 for (unsigned int k=0; k<= order; k++)
00565                                 {
00566                                         if ( i + j + k == order )
00567                                         {
00568                                                 basis.append(pow(x,i)*pow(y,j)*pow(z,k));
00569                                         }
00570                                 }
00571                         }
00572                 }
00573                 GiNaC::ex variables = get_symbolic_matrix(1,basis.nops(), a);
00574                 GiNaC::ex ret;
00575                 for (unsigned int i=0; i<basis.nops(); i++)
00576                 {
00577                         ret += variables.op(i)*basis.op(i);
00578                 }
00579                 return GiNaC::lst(ret, matrix_to_lst2(variables), basis);
00580         }
00581         throw std::runtime_error("Homogenous polynomials only implemented in 1D, 2D and 3D");
00582 }
00583 
00584 
00585 GiNaC::lst homogenous_polv(unsigned int no_fields, unsigned int order, unsigned int nsd, const string a)
00586 {
00587         GiNaC::lst ret1;                         // contains the polynom
00588         GiNaC::lst ret2;                         // contains the coefficients
00589         GiNaC::lst ret3;                         // constains the basis functions
00590         GiNaC::lst basis_tmp;
00591         for (unsigned int i=0; i< no_fields; i++)
00592         {
00593                 GiNaC::lst basis;
00594                 std::ostringstream s;
00595                 s <<a<<""<<i<<"_";
00596                 GiNaC::ex polspace = homogenous_pol(order, nsd, s.str());
00597                 ret1.append(polspace.op(0));
00598                 ret2.append(polspace.op(1));
00599                 basis_tmp = GiNaC::ex_to<GiNaC::lst>(polspace.op(2));
00600                 for (GiNaC::lst::const_iterator basis_iterator = basis_tmp.begin();
00601                         basis_iterator != basis_tmp.end(); ++basis_iterator)
00602                 {
00603                         GiNaC::lst tmp_lst;
00604                         for (unsigned int d=1; d<=no_fields; d++) tmp_lst.append(0);
00605                         tmp_lst.let_op(i) = (*basis_iterator);
00606                         ret3.append(tmp_lst);
00607                 }
00608         }
00609         return GiNaC::lst(ret1,ret2,ret3);
00610 }
00611 
00612 
00613 GiNaC::ex pol(unsigned int order, unsigned int nsd, const string a)
00614 {
00615         using SyFi::x;
00616         using SyFi::y;
00617         using SyFi::z;
00618 
00619         GiNaC::ex ret;                           // ex to return
00620         int dof;                                         // degrees of freedom
00621         GiNaC::ex A;                             // ex holding the coefficients a_0 .. a_dof
00622         GiNaC::lst basis;
00623 
00624         if (nsd == 1)
00625         {
00626                 /* 1D:
00627                  * P^n = a_0 + a_1*x + .... + a_n*x^n
00628                  * dof : n+1
00629                  */
00630                 dof = order+1;
00631                 A = get_symbolic_matrix(1,dof, a);
00632                 int o=0;
00633                 for (GiNaC::const_iterator i = A.begin(); i != A.end(); ++i)
00634                 {
00635                         ret += (*i)*pow(x,o);
00636                         basis.append(pow(x,o));
00637                         o++;
00638                 }
00639         }
00640         else if ( nsd == 2)
00641         {
00642 
00643                 /* 2D: structure of coefficients (a_i)
00644                  * [ a_0      a_1 x     a_3 x^2     a_6 x^3
00645                  * [ a_2 y    a_4 xy    a_7 x^2y
00646                  * [ a_5 y^2  a_8 xy^2
00647                  * [ a_9 y^3
00648                  */
00649                 dof = (order+1)*(order+2)/2;
00650                 A = get_symbolic_matrix(1, dof , a);
00651 
00652                 size_t i=0;
00653                 for (unsigned int o = 0; o <= order; o++)
00654                 {
00655                         for (unsigned int d = 0; d <= o; d++)
00656                         {
00657                                 ret += A.op(i)*pow(y,d)*pow(x,o-d);
00658                                 basis.append(pow(y,d)*pow(x,o-d));
00659                                 i++;
00660                         }
00661                 }
00662         }
00663         else if (nsd == 3)
00664         {
00665 
00666                 /* Similar structure as in 2D, but
00667                  * structured as a tetraheder, i.e.,
00668                  *   a_o + a_1 x + a_2 y + a_3 z
00669                  * + a_4 x^2 + a_5 xy +
00670                  */
00671                 dof = 0;
00672                 for (unsigned int j=0; j<= order; j++)
00673                 {
00674                         dof += (j+1)*(j+2)/2;
00675                 }
00676                 A = get_symbolic_matrix(1, dof , a);
00677 
00678                 size_t i=0;
00679                 for (unsigned int o = 0; o <= order; o++)
00680                 {
00681                         for (unsigned int d = 0; d <= o; d++)
00682                         {
00683                                 for (unsigned int f = 0; f <= o; f++)
00684                                 {
00685                                         if ( int(o)-int(d)-int(f) >= 0)
00686                                         {
00687                                                 ret += A.op(i)*pow(y,f)*pow(z,d)*pow(x,o-d-f);
00688                                                 basis.append(pow(y,f)*pow(z,d)*pow(x,o-d-f));
00689                                                 i++;
00690                                         }
00691                                 }
00692                         }
00693                 }
00694         }
00695         return GiNaC::lst(ret,matrix_to_lst2(A), basis);
00696 }
00697 
00698 
00699 GiNaC::lst polv(unsigned int no_fields, unsigned int order, unsigned int nsd, const string a)
00700 {
00701         GiNaC::lst ret1;                         // contains the polynom
00702         GiNaC::lst ret2;                         // contains the coefficients
00703         GiNaC::lst ret3;                         // constains the basis functions
00704         GiNaC::lst basis_tmp;
00705         for (unsigned int i=0; i< no_fields; i++)
00706         {
00707                 GiNaC::lst basis;
00708                 std::ostringstream s;
00709                 s <<a<<""<<i<<"_";
00710                 GiNaC::ex polspace = pol(order, nsd, s.str());
00711                 ret1.append(polspace.op(0));
00712                 ret2.append(polspace.op(1));
00713                 basis_tmp = GiNaC::ex_to<GiNaC::lst>(polspace.op(2));
00714                 for (GiNaC::lst::const_iterator basis_iterator = basis_tmp.begin();
00715                         basis_iterator != basis_tmp.end(); ++basis_iterator)
00716                 {
00717                         GiNaC::lst tmp_lst;
00718                         for (unsigned int d=1; d<=no_fields; d++) tmp_lst.append(0);
00719                         tmp_lst.let_op(i) = (*basis_iterator);
00720                         ret3.append(tmp_lst);
00721                 }
00722         }
00723         return GiNaC::lst(ret1,ret2,ret3);
00724 
00725         /* Old Code:
00726            GiNaC::lst ret;
00727            for (int i=1; i<= nsd; i++) {
00728            std::ostringstream s;
00729            s <<a<<"^"<<i<<"_";
00730            GiNaC::ex p = pol(order, nsd, s.str());
00731         ret.append(p);
00732         }
00733         return ret;
00734         */
00735 }
00736 
00737 
00738 GiNaC::ex polb(unsigned int order, unsigned int nsd, const string a)
00739 {
00740         using SyFi::x;
00741         using SyFi::y;
00742         using SyFi::z;
00743 
00744         GiNaC::ex ret;                           // ex to return
00745         int dof;                                         // degrees of freedom
00746         GiNaC::ex A;                             // ex holding the coefficients a_0 .. a_dof
00747         GiNaC::lst basis;
00748 
00749         if (nsd == 1)
00750         {
00751                 /* 1D:
00752                  * P^n = a_0 + a_1*x + .... + a_n*x^n
00753                  * dof : n+1
00754                  */
00755                 dof = order+1;
00756                 A = get_symbolic_matrix(1,dof, a);
00757                 int o=0;
00758                 for (GiNaC::const_iterator i = A.begin(); i != A.end(); ++i)
00759                 {
00760                         ret += (*i)*pow(x,o);
00761                         basis.append(pow(x,o));
00762                         o++;
00763                 }
00764         }
00765         else if ( nsd == 2)
00766         {
00767 
00768                 /* 2D: structure of coefficients (a_i)
00769                  * [ a_0      a_1 x     a_3 x^2     a_6 x^3
00770                  * [ a_2 y    a_4 xy    a_7 x^2y
00771                  * [ a_5 y^2  a_8 xy^2
00772                  * [ a_9 y^3
00773                  */
00774 
00775                 dof = (order+1)*(order+1);
00776                 A = get_symbolic_matrix(1, dof , a);
00777 
00778                 size_t i=0;
00779                 for (unsigned int o = 0; o <= order; o++)
00780                 {
00781                         for (unsigned int d = 0; d <= order; d++)
00782                         {
00783                                 ret += A.op(i)*pow(y,d)*pow(x,o);
00784                                 basis.append(pow(y,d)*pow(x,o));
00785                                 i++;
00786                         }
00787                 }
00788         }
00789         else if (nsd == 3)
00790         {
00791 
00792                 /* Similar structure as in 2D, but
00793                  * structured as a tetraheder, i.e.,
00794                  *   a_o + a_1 x + a_2 y + a_3 z
00795                  * + a_4 x^2 + a_5 xy +
00796                  */
00797                 dof = (order+1)*(order+1)*(order+1);
00798                 A = get_symbolic_matrix(1, dof , a);
00799 
00800                 size_t i=0;
00801                 for (unsigned int o = 0; o <= order; o++)
00802                 {
00803                         for (unsigned int d = 0; d <= order; d++)
00804                         {
00805                                 for (unsigned int f = 0; f <= order; f++)
00806                                 {
00807                                         ret += A.op(i)*pow(y,f)*pow(z,d)*pow(x,o);
00808                                         basis.append(pow(y,f)*pow(z,d)*pow(x,o));
00809                                         i++;
00810                                 }
00811                         }
00812                 }
00813         }
00814 
00815         return GiNaC::lst(ret,matrix_to_lst2(A), basis);
00816 }
00817 
00818 
00819 GiNaC::lst coeffs(GiNaC::lst pols)
00820 {
00821         GiNaC::lst cc;
00822         GiNaC::lst tmp;
00823         for (unsigned int i=0; i<= pols.nops()-1; i++)
00824         {
00825                 tmp = coeffs(pols.op(i));
00826                 cc = collapse(GiNaC::lst(cc, tmp));
00827         }
00828         return cc;
00829 }
00830 
00831 
00832 GiNaC::lst coeffs(GiNaC::ex pol)
00833 {
00834         using SyFi::x;
00835         using SyFi::y;
00836         using SyFi::z;
00837 
00838         GiNaC::lst cc;
00839         GiNaC::ex c, b;
00840         for (int i=pol.ldegree(x); i<=pol.degree(x); ++i)
00841         {
00842                 for (int j=pol.ldegree(y); j<=pol.degree(y); ++j)
00843                 {
00844                         for (int k=pol.ldegree(z); k<=pol.degree(z); ++k)
00845                         {
00846                                 c = pol.coeff(x,i).coeff(y, j).coeff(z,k);
00847                                 if ( c != 0 ) cc.append(c);
00848                         }
00849                 }
00850         }
00851         return cc;
00852 }
00853 
00854 
00855 GiNaC::exvector coeff(GiNaC::ex pol)
00856 {
00857         using SyFi::x;
00858         using SyFi::y;
00859         using SyFi::z;
00860 
00861         GiNaC::exvector cc;
00862         GiNaC::ex c, b;
00863         for (int i=pol.ldegree(x); i<=pol.degree(x); ++i)
00864         {
00865                 for (int j=pol.ldegree(y); j<=pol.degree(y); ++j)
00866                 {
00867                         for (int k=pol.ldegree(z); k<=pol.degree(z); ++k)
00868                         {
00869                                 c = pol.coeff(x,i).coeff(y, j).coeff(z,k);
00870                                 if ( c != 0 ) cc.insert(cc.begin(),c);
00871                         }
00872                 }
00873         }
00874         return cc;
00875 }
00876 
00877 
00878 GiNaC::exmap pol2basisandcoeff(GiNaC::ex e, GiNaC::ex s)
00879 {
00880         if (GiNaC::is_a<GiNaC::symbol>(s))
00881         {
00882                 GiNaC::symbol ss = GiNaC::ex_to<GiNaC::symbol>(s);
00883                 e = expand(e);
00884                 GiNaC::ex c;
00885                 GiNaC::ex b;
00886                 GiNaC::exmap map;
00887                 for (int i=e.ldegree(ss); i<=e.degree(ss); ++i)
00888                 {
00889                         c = e.coeff(ss,i);
00890                         b = pow(ss,i);
00891                         map[b] = c;
00892                 }
00893                 return map;
00894         }
00895         else
00896         {
00897                 throw(std::invalid_argument("The second argument must be a symbol."));
00898         }
00899 }
00900 
00901 
00902 GiNaC::exmap pol2basisandcoeff(GiNaC::ex e)
00903 {
00904         using SyFi::x;
00905         using SyFi::y;
00906         using SyFi::z;
00907 
00908         e = expand(e);
00909         GiNaC::ex c;
00910         GiNaC::ex b;
00911         GiNaC::exmap map;
00912         for (int i=e.ldegree(x); i<=e.degree(x); ++i)
00913         {
00914                 for (int j=e.ldegree(y); j<=e.degree(y); ++j)
00915                 {
00916                         for (int k=e.ldegree(z); k<=e.degree(z); ++k)
00917                         {
00918                                 c = e.coeff(x,i).coeff(y, j).coeff(z,k);
00919                                 b = pow(x,i)*pow(y,j)*pow(z,k);
00920                                 map[b] = c;
00921                         }
00922                 }
00923         }
00924         return map;
00925 }
00926 
00927 
00928 GiNaC::ex legendre1D(const GiNaC::symbol x, unsigned int n)
00929 {
00930         GiNaC::ex P;
00931         // Rodrigue's formula for Legendre polynomial of 1D
00932         // The interval [-1, 1]
00933         P=1/(pow(2,n)*GiNaC::factorial(n))*GiNaC::diff(GiNaC::pow((x*x-1),n),x,n);
00934         // -----------------
00935         // The interval [0,1]
00936         //  GiNaC::ex xx = 2*x - 1;
00937         // P=1/(pow(2,2*n)*GiNaC::factorial(n))*GiNaC::diff(GiNaC::pow((xx*xx-1),n),x,n);
00938         return P;
00939 }
00940 
00941 
00942 GiNaC::ex legendre(unsigned int order, unsigned int nsd, const string s)
00943 {
00944         using SyFi::x;
00945         using SyFi::y;
00946         using SyFi::z;
00947 
00948         // The Legendre polynomials to be used in FiniteElement
00949         GiNaC::ex leg;
00950         GiNaC::ex A;
00951         GiNaC::lst basis;
00952         int dof;
00953 
00954         GiNaC::ex b;
00955 
00956         // 1D
00957         if(nsd == 1)
00958         {
00959                 dof = order+1;
00960                 A = get_symbolic_matrix(1,dof,s);
00961                 int o=0;
00962                 for(GiNaC::const_iterator i = A.begin(); i!=A.end(); ++i)
00963                 {
00964                         b= legendre1D(x,o);
00965                         leg+= (*i)*b;
00966                         basis.append(b);
00967                         o++;
00968                 }
00969         }
00970         // 2D
00971         /*
00972         else if(nsd == 2){  // NB: Only for tensor products on TRIANGLES (not boxes)
00973                 / * 2D: structure of coefficients (a_i)
00974                  * [ a_0           a_1 P_1(x)           a_3 P_2(x)        a_6 P_3(x)
00975                  * [ a_2 P_1(y)    a_4 P_1(x)*P_1(y)    a_7 P_2(x)*P_1(y)
00976                  * [ a_5 P_2(y)    a_8 P_1(x)*P_2(y)
00977         * [ a_9 P_3(y)
00978         * /
00979         dof = (order+1)*(order+2)/2;
00980         A = get_symbolic_matrix(1,dof,s);
00981         size_t i=0;
00982         for (int o = 0; o <= order; o++) {
00983         for (int d = 0; d <= o; d++) {
00984         b = legendre1D(y,d)*legendre1D(x,o-d);
00985         leg += A.op(i)*b;
00986         basis.append(b);
00987         i++;
00988 
00989         }
00990         }
00991         }
00992         */
00993         else if(nsd == 2)                        // NB: Only for tensor products on rectangles
00994         {
00995                 dof = (order+1)*(order+1);
00996                 A = get_symbolic_matrix(1,dof,s);
00997                 size_t i=0;
00998                 for (unsigned int o = 0; o <= order; o++)
00999                 {
01000                         for (unsigned int d = 0; d <= order; d++)
01001                         {
01002                                 b = legendre1D(y,d)*legendre1D(x,o);
01003                                 leg += A.op(i)*b;
01004                                 basis.append(b);
01005                                 i++;
01006 
01007                         }
01008                 }
01009         }
01010 
01011         /* tetrahedron
01012         else if(nsd==3){
01013                 dof = 0;
01014                 for (int j=0; j<= order; j++) {
01015                         dof += (j+1)*(j+2)/2;
01016                 }
01017         A = get_symbolic_matrix(1, dof , s);
01018 
01019         size_t i=0;
01020         for (int o = 0; o <= order; o++) {
01021         for (int d = 0; d <= o; d++) {
01022         for (int f = 0; f <= o; f++) {
01023         if ( o-d-f >= 0) {
01024         b = legendre1D(y,f)*legendre1D(z,d)*legendre1D(x,o-d-f);
01025         leg += A.op(i)*b;
01026         basis.append(b);
01027         i++;
01028         }
01029         }
01030         }
01031         }
01032         }
01033         */
01034 
01035         else if(nsd==3)
01036         {
01037                 dof = (order+1)*(order+1)*(order+1);
01038                 A = get_symbolic_matrix(1, dof , s);
01039 
01040                 size_t i=0;
01041                 for (unsigned int o = 0; o <= order; o++)
01042                 {
01043                         for (unsigned int d = 0; d <= order; d++)
01044                         {
01045                                 for (unsigned int f = 0; f <= order; f++)
01046                                 {
01047                                         b = legendre1D(y,f)*legendre1D(z,d)*legendre1D(x,o);
01048                                         leg += A.op(i)*b;
01049                                         basis.append(b);
01050                                         i++;
01051                                 }
01052                         }
01053                 }
01054         }
01055         return GiNaC::lst(leg,matrix_to_lst2(A), basis);
01056 }
01057 
01058 
01059 GiNaC::lst legendrev(unsigned int no_fields, unsigned int order, unsigned int nsd, const string a)
01060 {
01061         GiNaC::lst ret1;                         // contains the polynom
01062         GiNaC::lst ret2;                         // contains the coefficients
01063         GiNaC::lst ret3;                         // constains the basis functions
01064         GiNaC::lst basis_tmp;
01065         for (unsigned int i=1; i<= no_fields; i++)
01066         {
01067                 GiNaC::lst basis;
01068                 std::ostringstream s;
01069                 s <<a<<""<<i<<"_";
01070                 GiNaC::ex polspace = legendre(order, nsd, s.str());
01071                 ret1.append(polspace.op(0));
01072                 ret2.append(polspace.op(1));
01073                 basis_tmp = GiNaC::ex_to<GiNaC::lst>(polspace.op(2));
01074                 for (GiNaC::lst::const_iterator basis_iterator = basis_tmp.begin();
01075                         basis_iterator != basis_tmp.end(); ++basis_iterator)
01076                 {
01077                         GiNaC::lst tmp_lst;
01078                         for (unsigned int d=1; d<=no_fields; d++) tmp_lst.append(0);
01079                         tmp_lst.let_op(i-1) = (*basis_iterator);
01080                         ret3.append(tmp_lst);
01081                 }
01082         }
01083         return GiNaC::lst(ret1,ret2,ret3);
01084 }
01085 
01086 
01087 bool compare(const ex & e, const string & s)
01088 {
01089         ostringstream ss;
01090         ss << e;
01091         return ss.str() == s;
01092 }
01093 
01094 
01095 void EQUAL_OR_DIE(const ex & e, const string & s)
01096 {
01097         if (!compare(e, s))
01098         {
01099                 ostringstream os;
01100                 os << "ERROR: expression e: " <<e<<" is not equal to "<<s<<endl;
01101                 throw runtime_error(os.str());
01102         }
01103 }
01104 
01105 
01106 // =========== expression inspection utilities
01107 
01108 class SymbolMapBuilderVisitor:
01109 public visitor,
01110         public symbol::visitor
01111 {
01112         public:
01113                 SymbolMapBuilderVisitor(GiNaC::exmap & em): symbolmap(em) {}
01114 
01115                 GiNaC::exmap & symbolmap;
01116 
01117                 void visit(const symbol & s)
01118                 {
01119                         GiNaC::exmap::iterator it = symbolmap.find(s);
01120                         if(it != symbolmap.end())
01121                         {
01122                                 it->second++;
01123                         }
01124                         else
01125                         {
01126                                 //GiNaC::exmap::value_type p(ex(s), ex(s));
01127                                 //symbolmap.insert(p);
01128                                 symbolmap[ex(s)] = ex(s);
01129                         }
01130                 }
01131 };
01132 
01133 class SymbolCounterVisitor:
01134 public visitor,
01135         public symbol::visitor,
01136         public basic::visitor
01137 {
01138         public:
01139                 exhashmap<int> symbolcount;
01140 
01141                 void visit(const basic & s)
01142                 {
01143                         std::cout << "visiting basic " << std::endl;
01144                 }
01145 
01146                 void visit(const symbol & s)
01147                 {
01148                         ex e = s;
01149                         std::cout << "visiting symbol " << e << std::endl;
01150                         exhashmap<int>::iterator it = symbolcount.find(s);
01151                         if(it != symbolcount.end())
01152                         {
01153                                 std::cout << "found symbol " << e << std::endl;
01154                                 it->second++;
01155                         }
01156                         else
01157                         {
01158                                 std::cout << "adding symbol " << e << std::endl;
01159                                 pair<ex,int> p;
01160                                 p.first = ex(s);
01161                                 p.second = 1;
01162                                 symbolcount.insert(p);
01163                         }
01164                 }
01165 };
01166 
01167 exhashmap<int> count_symbols(const ex & e)
01168 {
01169         SymbolCounterVisitor v;
01170         e.traverse(v);
01171         return v.symbolcount;
01172 }
01173 
01174 
01175 /*
01176 GiNaC::exvector get_symbols3(const GiNaC::ex & e)
01177 {
01178         // Implemented directly to avoid copying map:
01179         SymbolCounterVisitor v;
01180         e.traverse(v);
01181 exhashmap<int> & sc = v.symbolcount;
01182 
01183 int i = 0;
01184 GiNaC::exvector l(sc.size());
01185 for(exhashmap<int>::iterator it=sc.begin(); it!=sc.end(); it++)
01186 {
01187 //l.push_back(it->first);
01188 l[i] = it->first;
01189 i++;
01190 }
01191 return l;
01192 }
01193 
01194 std::list<GiNaC::ex> get_symbols2(const ex & e)
01195 {
01196 // Implemented directly to avoid copying map:
01197 SymbolCounterVisitor v;
01198 e.traverse(v);
01199 exhashmap<int> & sc = v.symbolcount;
01200 
01201 list<ex> l;
01202 for(exhashmap<int>::iterator it=sc.begin(); it!=sc.end(); it++)
01203 {
01204 l.push_back(it->first);
01205 }
01206 return l;
01207 }
01208 
01209 void get_symbols(const ex & e, GiNaC::exmap & em)
01210 {
01211 SymbolMapBuilderVisitor v(em);
01212 e.traverse(v);
01213 }
01214 */
01215 ex extract_symbols(const ex & e)
01216 {
01217         // Implemented directly to avoid copying map:
01218         SymbolCounterVisitor v;
01219         e.traverse(v);
01220         exhashmap<int> & sc = v.symbolcount;
01221 
01222         lst l;
01223         for(exhashmap<int>::iterator it=sc.begin(); it!=sc.end(); it++)
01224         {
01225                 l.append(it->first);
01226                 std::cout << (it->first) << std::endl;
01227         }
01228         ex ret = l;
01229         return ret;
01230 }
01231 
01232 
01233 // Collect all symbols of an expression
01234 void collect_symbols(const GiNaC::ex & e, exset & v)
01235 {
01236         if (GiNaC::is_a<GiNaC::symbol>(e))
01237         {
01238                 v.insert(e);
01239         }
01240         else
01241         {
01242                 for (size_t i=0; i<e.nops(); i++)
01243                 {
01244                         collect_symbols(e.op(i), v);
01245                 }
01246         }
01247 }
01248 
01249 
01250 GiNaC::exvector collect_symbols(const GiNaC::ex & e)
01251 {
01252         exset s;
01253         collect_symbols(e, s);
01254         GiNaC::exvector v(s.size());
01255         for(exset::iterator i=s.begin(); i!= s.end(); i++)
01256         {
01257                 v.push_back(*i);
01258         }
01259         return v;
01260 }
01261 
01262 
01263 bool compare_archives(const string & first, const string & second, std::ostream & os)
01264 {
01265         bool ret = true;
01266 
01267         // read both archives
01268         archive a1, a2;
01269         ifstream if1(first.c_str()), if2(second.c_str());
01270         if1 >> a1;
01271         if2 >> a2;
01272 
01273         // compare size
01274         int n = a1.num_expressions();
01275         int n2 = a2.num_expressions();
01276         if(n != n2)
01277         {
01278                 os << "Archives " << first << " and " << second
01279                         << " has a different number of expressions, " << n << " and " << n2 << "." << endl;
01280                 os << "Comparing common expressions." << endl;
01281                 ret = false;
01282         }
01283 
01284         // iterate over all expressions in first archive
01285         ex e1,e2;
01286         for(int i=0; i<n; i++)
01287         {
01288                 lst syms;
01289                 string exname;
01290 
01291                 e1 = a1.unarchive_ex(syms, exname, i);
01292 
01293                 syms = ex_to<lst>(extract_symbols(e1));
01294                 //        os << "Comparing " << exname << " with symbols " << syms << endl;
01295 
01296                 // is this in the second archive?
01297                 try
01298                 {
01299                         e2 = a2.unarchive_ex(syms, exname.c_str());
01300 
01301                         // got it, now compare
01302                         bool isequal = is_zero(e1-e2);
01303                         if(!isequal)
01304                         {
01305                                 if(ret)
01306                                 {
01307                                         os << "Archives " << first << " and " << second
01308                                                 << " are not equal, details follow:" << endl;
01309                                 }
01310                                 os << "Expression with name " << exname << " is not equal:" << endl;
01311                                 os << "First:  " << endl << e1 << endl;
01312                                 os << "Second: " << endl << e2 << endl;
01313                                 ret = false;
01314                         }
01315                 }
01316                 catch(...)
01317                 {
01318                         os << "Expression " << exname << " is missing from " << second << "." << endl;
01319                         ret = false;
01320                 }
01321         }
01322 
01323         return ret;
01324 }
01325 
01326 
01327 class ExStatsVisitor:
01328 public visitor,
01329         public power::visitor,
01330         public mul::visitor,
01331         public add::visitor,
01332         public function::visitor
01333 {
01334         public:
01335                 ExStats es;
01336 
01337                 void visit(const power & e)
01338                 {
01339                         //cout << "pow" << endl;
01340                         ex b = e.op(1);
01341                         ex c = b.evalf();
01342                         if( is_a<numeric>(c) )
01343                         {
01344                                 numeric nu = ex_to<numeric>(c);
01345                                 int n = (int) to_double(nu);
01346                                 if( is_zero(nu-n) )
01347                                 {
01348                                         // is an integer power, interpret as a sequence of multiplications
01349                                         es.muls  += n-1;
01350                                         es.flops += n-1;
01351                                 }
01352                         }
01353 
01354                         es.pows++;
01355                 }
01356 
01357                 void visit(const mul & e)
01358                 {
01359                         //cout << "mul" << endl;
01360                         es.muls  += e.nops()-1;
01361                         es.flops += e.nops()-1;
01362                 }
01363 
01364                 void visit(const add & e)
01365                 {
01366                         //cout << "add" << endl;
01367                         es.adds  += e.nops()-1;
01368                         es.flops += e.nops()-1;
01369                 }
01370 
01371                 void visit(const function & e)
01372                 {
01373                         //cout << "func" << endl;
01374                         es.functions++;
01375                 }
01376 };
01377 
01378 ExStats count_ops(const ex & e)
01379 {
01380         //cout << "count_ops " << e << endl;
01381         //cout << "is an add: " << GiNaC::is<GiNaC::add>(e) << endl;
01382         //cout << "is a  mul: " << GiNaC::is<GiNaC::mul>(e) << endl;
01383         ExStatsVisitor v;
01384         e.traverse(v);
01385         return v.es;
01386 }
01387 
01388 
01389 // =========== expression manipulation utilities
01390 
01391 // Returns in sel a list with symbol/expression pairs for all
01392 // power replacement variables introduced. Works best on
01393 // expressions in expanded form.
01394 ex replace_powers(const ex & ein, const list<symbol> & symbols, list<symexpair> & sel, const string & tmpsymbolprefix)
01395 {
01396         ex e = ein;
01397         // build power expressions
01398         list<symbol>::const_iterator it = symbols.begin();
01399         for(; it != symbols.end(); it++)
01400         {
01401                 int deg      = e.degree(*it);
01402                 if(deg > 0)
01403                 {
01404                         symbol sym   = ex_to<symbol>(*it);
01405                         string sname = tmpsymbolprefix + sym.get_name();
01406 
01407                         // make list of new symbols
01408                         vector<symbol> symbols(deg);
01409                         symbols[0] = sym;
01410                         for(int i=1; i<deg; i++)
01411                         {
01412                                 symbols[i] = get_symbol( sname + int2string(i+1) );
01413                                 sel.push_back(make_pair(symbols[i], symbols[i-1]*sym));
01414                         }
01415 
01416                         // with highest order first, subs in e
01417                         ex prod = sym;
01418                         for(int i=deg-1; i>=1; i--)
01419                         {
01420                                 e = e.subs(power(sym,i+1) == symbols[i], subs_options::algebraic);
01421                         }
01422                 }
01423         }
01424         return e;
01425 }
01426 
01427 
01428 };                                                               // namespace SyFi
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator