- enforced GiNaC coding standards :-)
[ginac.git] / ginac / printtree.cpp
1 /** @file printtree.cpp
2  *
3  * print in tree- (indented-) form, so developers can have a look at the
4  * underlying structure.
5  *
6  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <iostream>
24 #include <math.h>
25
26 #include "ginac.h"
27
28 void ex::printtree(ostream & os, unsigned indent) const
29 {
30     debugmsg("ex printtree",LOGLEVEL_PRINT);
31     ASSERT(bp!=0);
32     // os << "refcount=" << bp->refcount << " ";
33     bp->printtree(os,indent);
34 }
35
36 void ex::dbgprinttree(void) const
37 {
38     debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
39     ASSERT(bp!=0);
40     bp->dbgprinttree();
41 }
42
43 void basic::printtree(ostream & os, unsigned indent) const
44 {
45     debugmsg("basic printtree",LOGLEVEL_PRINT);
46     os << string(indent,' ') << "type=" << typeid(*this).name()
47        << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
48        << ", flags=" << flags
49        << ", nops=" << nops() << endl;
50     for (int i=0; i<nops(); ++i) {
51         op(i).printtree(os,indent+delta_indent);
52     }
53 }
54
55 void basic::dbgprinttree(void) const
56 {
57     printtree(cerr,0);
58 }
59
60 void numeric::printtree(ostream & os, unsigned indent) const
61 {
62     debugmsg("numeric printtree", LOGLEVEL_PRINT);
63     // We are cheating here, because we don't want to include the underlying
64     // bignum package's headers again, so we use ostream::operator<<(numeric):
65     os << string(indent,' ');
66     (*this).print(os);
67     os << " (numeric): "
68        << "hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
69        << ", flags=" << flags << endl;
70 }
71
72 void symbol::printtree(ostream & os, unsigned indent) const
73 {
74     debugmsg("symbol printtree",LOGLEVEL_PRINT);
75     os << string(indent,' ') << name << " (symbol): "
76        << "serial=" << serial
77        << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
78        << ", flags=" << flags << endl;
79 }
80
81 void power::printtree(ostream & os, unsigned indent) const
82 {
83     debugmsg("power printtree",LOGLEVEL_PRINT);
84
85     os << string(indent,' ') << "power: "
86        << "hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
87        << ", flags=" << flags << endl;
88     basis.printtree(os,indent+delta_indent);
89     exponent.printtree(os,indent+delta_indent);
90 }
91
92 void expairseq::printtree(ostream & os, unsigned indent) const
93 {
94     debugmsg("expairseq printtree",LOGLEVEL_PRINT);
95
96     os << string(indent,' ') << "type=" << typeid(*this).name()
97        << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
98        << ", flags=" << flags
99        << ", nops=" << nops() << endl;
100     for (unsigned i=0; i<seq.size(); ++i) {
101         seq[i].rest.printtree(os,indent+delta_indent);
102         seq[i].coeff.printtree(os,indent+delta_indent);
103         if (i!=seq.size()-1) {
104             os << string(indent+delta_indent,' ') << "-----" << endl;
105         }
106     }
107     if (!overall_coeff.is_equal(default_overall_coeff())) {
108         os << string(indent+delta_indent,' ') << "-----" << endl;
109         os << string(indent+delta_indent,' ') << "overall_coeff" << endl;
110         overall_coeff.printtree(os,indent+delta_indent);
111     }
112     os << string(indent+delta_indent,' ') << "=====" << endl;
113 #ifdef EXPAIRSEQ_USE_HASHTAB
114     os << string(indent+delta_indent,' ')
115        << "hashtab size " << hashtabsize << endl;
116     if (hashtabsize==0) return;
117 #define MAXCOUNT 5
118     unsigned count[MAXCOUNT+1];
119     for (int i=0; i<MAXCOUNT+1; ++i) count[i]=0;
120     unsigned this_bin_fill;
121     unsigned cum_fill_sq=0;
122     unsigned cum_fill=0;
123     for (unsigned i=0; i<hashtabsize; ++i) {
124         this_bin_fill=0;
125         if (hashtab[i].size()>0) {
126             os << string(indent+delta_indent,' ') 
127                << "bin " << i << " with entries ";
128             for (epplist::const_iterator it=hashtab[i].begin();
129                  it!=hashtab[i].end(); ++it) {
130                 os << *it-seq.begin() << " ";
131                 this_bin_fill++;
132             }
133             os << endl;
134             cum_fill += this_bin_fill;
135             cum_fill_sq += this_bin_fill*this_bin_fill;
136         }
137         if (this_bin_fill<MAXCOUNT) {
138             ++count[this_bin_fill];
139         } else {
140             ++count[MAXCOUNT];
141         }
142     }
143     unsigned fact=1;
144     double cum_prob=0;
145     double lambda=(1.0*seq.size())/hashtabsize;
146     for (int k=0; k<MAXCOUNT; ++k) {
147         if (k>0) fact *= k;
148         double prob=pow(lambda,k)/fact*exp(-lambda);
149         cum_prob += prob;
150         os << string(indent+delta_indent,' ') << "bins with " << k << " entries: "
151            << int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: "
152            << int(prob*1000)/10.0 << ")" << endl;
153     }
154     os << string(indent+delta_indent,' ') << "bins with more entries: "
155        << int(1000.0*count[MAXCOUNT]/hashtabsize)/10.0 << "% (expected: "
156        << int((1-cum_prob)*1000)/10.0 << ")" << endl;
157     
158     os << string(indent+delta_indent,' ') << "variance: "
159        << 1.0/hashtabsize*cum_fill_sq-(1.0/hashtabsize*cum_fill)*(1.0/hashtabsize*cum_fill)
160        << endl;
161     os << string(indent+delta_indent,' ') << "average fill: "
162        << (1.0*cum_fill)/hashtabsize
163        << " (should be equal to " << (1.0*seq.size())/hashtabsize << ")" << endl;
164 #endif // def EXPAIRSEQ_USE_HASHTAB
165 }
166