]> www.ginac.de Git - ginac.git/blobdiff - ginac/expairseq.cpp
- implemented global class registry (for class basic and derived classes)
[ginac.git] / ginac / expairseq.cpp
index ec88239471a393ee20f6cb239b72d1939812e308..0d4a01c79a0e175b2b0f4637f1c1be43abced81f 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of sequences of expression pairs. */
 
 /*
- *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 #include <algorithm>
 #include <string>
 #include <stdexcept>
+#include <cmath>
 
 #include "expairseq.h"
 #include "lst.h"
+#include "archive.h"
 #include "debugmsg.h"
 #include "utils.h"
 
@@ -37,6 +39,8 @@ namespace GiNaC {
 #error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F."
 #endif // def EXPAIRSEQ_USE_HASHTAB
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(expairseq, basic)
+
 //////////
 // helper classes
 //////////
@@ -76,7 +80,7 @@ expairseq const & expairseq::operator=(expairseq const & other)
 
 void expairseq::copy(expairseq const & other)
 {
-    basic::copy(other);
+    inherited::copy(other);
     seq=other.seq;
     overall_coeff=other.overall_coeff;
 #ifdef EXPAIRSEQ_USE_HASHTAB
@@ -103,14 +107,14 @@ void expairseq::copy(expairseq const & other)
 // other constructors
 //////////
 
-expairseq::expairseq(ex const & lh, ex const & rh) : basic(TINFO_expairseq)
+expairseq::expairseq(ex const & lh, ex const & rh) : inherited(TINFO_expairseq)
 {
     debugmsg("expairseq constructor from ex,ex",LOGLEVEL_CONSTRUCT);
     construct_from_2_ex(lh,rh);
     GINAC_ASSERT(is_canonical());
 }
 
-expairseq::expairseq(exvector const & v) : basic(TINFO_expairseq)
+expairseq::expairseq(exvector const & v) : inherited(TINFO_expairseq)
 {
     debugmsg("expairseq constructor from exvector",LOGLEVEL_CONSTRUCT);
     construct_from_exvector(v);
@@ -119,7 +123,7 @@ expairseq::expairseq(exvector const & v) : basic(TINFO_expairseq)
 
 /*
 expairseq::expairseq(epvector const & v, bool do_not_canonicalize) :
-    basic(TINFO_expairseq)
+    inherited(TINFO_expairseq)
 {
     debugmsg("expairseq constructor from epvector",LOGLEVEL_CONSTRUCT);
     if (do_not_canonicalize) {
@@ -135,7 +139,7 @@ expairseq::expairseq(epvector const & v, bool do_not_canonicalize) :
 */
 
 expairseq::expairseq(epvector const & v, ex const & oc) :
-    basic(TINFO_expairseq), overall_coeff(oc)
+    inherited(TINFO_expairseq), overall_coeff(oc)
 {
     debugmsg("expairseq constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
     construct_from_epvector(v);
@@ -143,7 +147,7 @@ expairseq::expairseq(epvector const & v, ex const & oc) :
 }
 
 expairseq::expairseq(epvector * vp, ex const & oc) :
-    basic(TINFO_expairseq), overall_coeff(oc)
+    inherited(TINFO_expairseq), overall_coeff(oc)
 {
     debugmsg("expairseq constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
     GINAC_ASSERT(vp!=0);
@@ -152,6 +156,47 @@ expairseq::expairseq(epvector * vp, ex const & oc) :
     GINAC_ASSERT(is_canonical());
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+expairseq::expairseq(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+#ifdef EXPAIRSEQ_USE_HASHTAB
+    , hashtabsize(0)
+#endif
+{
+    debugmsg("expairseq constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    for (unsigned int i=0; true; i++) {
+        ex rest;
+        ex coeff;
+        if (n.find_ex("rest", rest, sym_lst, i) && n.find_ex("coeff", coeff, sym_lst, i))
+            seq.push_back(expair(rest, coeff));
+        else
+            break;
+    }
+    n.find_ex("overall_coeff", overall_coeff, sym_lst);
+}
+
+/** Unarchive the object. */
+ex expairseq::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new expairseq(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void expairseq::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    epvector::const_iterator i = seq.begin(), iend = seq.end();
+    while (i != iend) {
+        n.add_ex("rest", i->rest);
+        n.add_ex("coeff", i->coeff);
+        i++;
+    }
+    n.add_ex("overall_coeff", overall_coeff);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
@@ -164,12 +209,110 @@ basic * expairseq::duplicate() const
     return new expairseq(*this);
 }
 
+void expairseq::print(ostream & os, unsigned upper_precedence) const
+{
+    debugmsg("expairseq print",LOGLEVEL_PRINT);
+    os << "[[";
+    printseq(os,',',precedence,upper_precedence);
+    os << "]]";
+}
+
+void expairseq::printraw(ostream & os) const
+{
+    debugmsg("expairseq printraw",LOGLEVEL_PRINT);
+
+    os << "expairseq(";
+    for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
+        os << "(";
+        (*cit).rest.printraw(os);
+        os << ",";
+        (*cit).coeff.printraw(os);
+        os << "),";
+    }
+    os << ")";
+}
+
+void expairseq::printtree(ostream & os, unsigned indent) const
+{
+    debugmsg("expairseq printtree",LOGLEVEL_PRINT);
+
+    os << string(indent,' ') << "type=" << typeid(*this).name()
+       << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
+       << ", flags=" << flags
+       << ", nops=" << nops() << endl;
+    for (unsigned i=0; i<seq.size(); ++i) {
+        seq[i].rest.printtree(os,indent+delta_indent);
+        seq[i].coeff.printtree(os,indent+delta_indent);
+        if (i!=seq.size()-1) {
+            os << string(indent+delta_indent,' ') << "-----" << endl;
+        }
+    }
+    if (!overall_coeff.is_equal(default_overall_coeff())) {
+        os << string(indent+delta_indent,' ') << "-----" << endl;
+        os << string(indent+delta_indent,' ') << "overall_coeff" << endl;
+        overall_coeff.printtree(os,indent+delta_indent);
+    }
+    os << string(indent+delta_indent,' ') << "=====" << endl;
+#ifdef EXPAIRSEQ_USE_HASHTAB
+    os << string(indent+delta_indent,' ')
+       << "hashtab size " << hashtabsize << endl;
+    if (hashtabsize==0) return;
+#define MAXCOUNT 5
+    unsigned count[MAXCOUNT+1];
+    for (int i=0; i<MAXCOUNT+1; ++i) count[i]=0;
+    unsigned this_bin_fill;
+    unsigned cum_fill_sq=0;
+    unsigned cum_fill=0;
+    for (unsigned i=0; i<hashtabsize; ++i) {
+        this_bin_fill=0;
+        if (hashtab[i].size()>0) {
+            os << string(indent+delta_indent,' ') 
+               << "bin " << i << " with entries ";
+            for (epplist::const_iterator it=hashtab[i].begin();
+                 it!=hashtab[i].end(); ++it) {
+                os << *it-seq.begin() << " ";
+                this_bin_fill++;
+            }
+            os << endl;
+            cum_fill += this_bin_fill;
+            cum_fill_sq += this_bin_fill*this_bin_fill;
+        }
+        if (this_bin_fill<MAXCOUNT) {
+            ++count[this_bin_fill];
+        } else {
+            ++count[MAXCOUNT];
+        }
+    }
+    unsigned fact=1;
+    double cum_prob=0;
+    double lambda=(1.0*seq.size())/hashtabsize;
+    for (int k=0; k<MAXCOUNT; ++k) {
+        if (k>0) fact *= k;
+        double prob=pow(lambda,k)/fact*exp(-lambda);
+        cum_prob += prob;
+        os << string(indent+delta_indent,' ') << "bins with " << k << " entries: "
+           << int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: "
+           << int(prob*1000)/10.0 << ")" << endl;
+    }
+    os << string(indent+delta_indent,' ') << "bins with more entries: "
+       << int(1000.0*count[MAXCOUNT]/hashtabsize)/10.0 << "% (expected: "
+       << int((1-cum_prob)*1000)/10.0 << ")" << endl;
+    
+    os << string(indent+delta_indent,' ') << "variance: "
+       << 1.0/hashtabsize*cum_fill_sq-(1.0/hashtabsize*cum_fill)*(1.0/hashtabsize*cum_fill)
+       << endl;
+    os << string(indent+delta_indent,' ') << "average fill: "
+       << (1.0*cum_fill)/hashtabsize
+       << " (should be equal to " << (1.0*seq.size())/hashtabsize << ")" << endl;
+#endif // def EXPAIRSEQ_USE_HASHTAB
+}
+
 bool expairseq::info(unsigned inf) const
 {
-    return basic::info(inf);
+    return inherited::info(inf);
 }
 
-int expairseq::nops() const
+unsigned expairseq::nops() const
 {
     if (overall_coeff.is_equal(default_overall_coeff())) {
         return seq.size();
@@ -411,9 +554,36 @@ ex expairseq::thisexpairseq(epvector * vp, ex const & oc) const
     return expairseq(vp,oc);
 }
 
+void expairseq::printpair(ostream & os, expair const & p, unsigned upper_precedence) const
+{
+    os << "[[";
+    p.rest.bp->print(os,precedence);
+    os << ",";
+    p.coeff.bp->print(os,precedence);
+    os << "]]";
+}
+
+void expairseq::printseq(ostream & os, char delim, unsigned this_precedence,
+                         unsigned upper_precedence) const
+{
+    if (this_precedence<=upper_precedence) os << "(";
+    epvector::const_iterator it,it_last;
+    it_last=seq.end();
+    --it_last;
+    for (it=seq.begin(); it!=it_last; ++it) {
+        printpair(os,*it,this_precedence);
+        os << delim;
+    }
+    printpair(os,*it,this_precedence);
+    if (!overall_coeff.is_equal(default_overall_coeff())) {
+        os << delim << overall_coeff;
+    }
+    if (this_precedence<=upper_precedence) os << ")";
+}
+    
 expair expairseq::split_ex_to_pair(ex const & e) const
 {
-    return expair(e,exONE());
+    return expair(e,_ex1());
 }
 
 expair expairseq::combine_ex_with_coeff_to_pair(ex const & e,
@@ -445,7 +615,7 @@ bool expairseq::expair_needs_further_processing(epp it)
 
 ex expairseq::default_overall_coeff(void) const
 {
-    return exZERO();
+    return _ex0();
 }
 
 void expairseq::combine_overall_coeff(ex const & c)
@@ -1188,7 +1358,7 @@ void expairseq::drop_coeff_0_terms(epvector::iterator & first_numeric,
         if (!touched[i]) {
             ++current;
             ++i;
-        } else if (!ex_to_numeric((*current).coeff).is_equal(numZERO())) {
+        } else if (!ex_to_numeric((*current).coeff).is_equal(_num0())) {
             ++current;
             ++i;
         } else {
@@ -1230,7 +1400,7 @@ void expairseq::drop_coeff_0_terms(epvector::iterator & first_numeric,
 bool expairseq::has_coeff_0(void) const
 {
     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
-        if ((*cit).coeff.is_equal(exZERO())) {
+        if ((*cit).coeff.is_equal(_ex0())) {
             return true;
         }
     }
@@ -1421,7 +1591,7 @@ epvector * expairseq::evalchildren(int level) const
         ex const & evaled_ex=(*cit).rest.eval(level);
         if (!are_ex_trivially_equal((*cit).rest,evaled_ex)) {
 
-           // something changed, copy seq, eval and return it
+            // something changed, copy seq, eval and return it
             epvector *s=new epvector;
             s->reserve(seq.size());