]> www.ginac.de Git - ginac.git/blob - ginac/structure.pl
- is_zero() is now called on expanded expressions in gcd()
[ginac.git] / ginac / structure.pl
1 #!/usr/bin/perl -w
2
3 $input_structure='';
4 $original_input_structure='';
5 while (<>) {
6     $input_structure .= '// '.$_;
7     $original_input_structure .= $_;
8 }
9
10 $original_input_structure =~ tr/ \t\n\r\f/     /;
11 $original_input_structure =~ tr/ //s;
12
13 if ($original_input_structure =~ /^struct (\w+) ?\{ ?(.*)\}\;? ?$/) {
14     $STRUCTURE=$1;
15     $decl=$2;
16 } else {
17     die "illegal struct, must match 'struct name { type var; /*comment*/ ...};': $original_input_structure";
18 }
19
20 # split off a part 'type var[,var...];' with a possible C-comment '/* ... */'
21 while ($decl =~ /^ ?(\w+) ([\w \,]+)\; ?((\/\*.*?\*\/)?)(.*)$/) {
22     $type=$1;
23     $member=$2;
24     $comment=$3;
25     $decl=$5;
26     while ($member =~ /^(\w+) ?\, ?(.*)$/) {
27         push @TYPES,$type;
28         push @MEMBERS,$1;
29         push @COMMENTS,$comment;
30         if ($comment ne '') {
31             $comment='/* see above */';
32         }
33         $member=$2;
34     }
35     if ($member !~ /^\w$/) {
36         die "illegal struct, must match 'struct name { type var; /*comment*/ ...};': $input_structure";
37     }
38     push @TYPES,$type;
39     push @MEMBERS,$member;
40     push @COMMENTS,$comment;
41 }
42
43 if ($decl !~ /^ ?$/) {
44     die "illegal struct, must match 'struct name { type var; /*comment*/ ...};': $input_structure";
45 }
46
47 #$STRUCTURE='teststruct';
48 $STRUCTURE_UC=uc(${STRUCTURE});
49 #@TYPES=('ex','ex','ex');
50 #@MEMBERS=('q10','q20','q21');
51
52 sub generate {
53     my ($template,$conj)=@_;
54     my ($res,$N);
55
56     $res='';
57     for ($N=1; $N<=$#MEMBERS+1; $N++) {
58         $TYPE=$TYPES[$N-1];
59         $MEMBER=$MEMBERS[$N-1];
60         $COMMENT=$COMMENTS[$N-1];
61         $res .= eval('"' . $template . '"');
62         $TYPE=''; # to avoid main::TYPE used only once warning
63         $MEMBER=''; # same as above
64         $COMMENT=''; # same as above
65         if ($N!=$#MEMBERS+1) {
66             $res .= $conj;
67         }
68     }
69     return $res;
70 }
71
72 $number_of_members=$#MEMBERS+1;
73 $constructor_arglist=generate('ex tmp_${MEMBER}',', ');
74 $member_access_functions=generate('    ex const & ${MEMBER}(void) { return m_${MEMBER}; }',"\n");
75 $op_access_indices_decl=generate('    static unsigned op_${MEMBER};',"\n");
76 $op_access_indices_def=generate('unsigned ${STRUCTURE}::op_${MEMBER}=${N}-1;',"\n");
77 $members=generate('    ex m_${MEMBER}; ${COMMENT}',"\n");
78 $copy_statements=generate('    m_${MEMBER}=other.m_${MEMBER};',"\n");
79 $constructor_statements=generate('m_${MEMBER}(tmp_${MEMBER})',', ');
80 $let_op_statements=generate(
81 '    case ${N}-1:'."\n".
82 '        return m_${MEMBER};'."\n".
83 '        break;',
84 "\n");
85 $temporary_arglist=generate('tmp_${MEMBER}',', ');
86 $expand_statements=generate('    ex tmp_${MEMBER}=m_${MEMBER}.expand(options);',"\n");
87 $has_statements=generate('    if (m_${MEMBER}.has(other)) return true;',"\n");
88 $eval_statements=generate(
89 '    ex tmp_${MEMBER}=m_${MEMBER}.eval(level-1);'."\n".
90 '    all_are_trivially_equal = all_are_trivially_equal &&'."\n".
91 '                              are_ex_trivially_equal(tmp_${MEMBER},m_${MEMBER});',
92 "\n");
93 $evalf_statements=generate(
94 '    ex tmp_${MEMBER}=m_${MEMBER}.evalf(level-1);'."\n".
95 '    all_are_trivially_equal = all_are_trivially_equal &&'."\n".
96 '                              are_ex_trivially_equal(tmp_${MEMBER},m_${MEMBER});',
97 "\n");
98 $normal_statements=generate(
99 '    ex tmp_${MEMBER}=m_${MEMBER}.normal(level-1);'."\n".
100 '    all_are_trivially_equal = all_are_trivially_equal &&'."\n".
101 '                              are_ex_trivially_equal(tmp_${MEMBER},m_${MEMBER});',
102 "\n");
103 $diff_statements=generate('    ex tmp_${MEMBER}=m_${MEMBER}.diff(s);',"\n");
104 $subs_statements=generate(
105 '    ex tmp_${MEMBER}=m_${MEMBER}.subs(ls,lr);'."\n".
106 '    all_are_trivially_equal = all_are_trivially_equal &&'."\n".
107 '                              are_ex_trivially_equal(tmp_${MEMBER},m_${MEMBER});',
108 "\n");
109 $compare_statements=generate(
110 '    cmpval=m_${MEMBER}.compare(o.m_${MEMBER});'."\n".
111 '    if (cmpval!=0) return cmpval;',
112 "\n");
113 $is_equal_statements=generate('    if (!m_${MEMBER}.is_equal(o.m_${MEMBER})) return false;',"\n");
114 $types_ok_statements=generate(
115 '#ifndef SKIP_TYPE_CHECK_FOR_${TYPE}'."\n".
116 '    if (!is_ex_exactly_of_type(m_${MEMBER},${TYPE})) return false;'."\n".
117 '#endif // ndef SKIP_TYPE_CHECK_FOR_${TYPE}',"\n");
118
119 $interface=<<END_OF_INTERFACE;
120 /** \@file ${STRUCTURE}.h
121  *
122  *  Definition of GiNaC's user defined structure ${STRUCTURE}. */
123
124 /*
125  *  This file was generated automatically by structure.pl.
126  *  Please do not modify it directly, edit the perl script instead!
127  *
128  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
129  *
130  *  This program is free software; you can redistribute it and/or modify
131  *  it under the terms of the GNU General Public License as published by
132  *  the Free Software Foundation; either version 2 of the License, or
133  *  (at your option) any later version.
134  *
135  *  This program is distributed in the hope that it will be useful,
136  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
137  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
138  *  GNU General Public License for more details.
139  *
140  *  You should have received a copy of the GNU General Public License
141  *  along with this program; if not, write to the Free Software
142  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
143  */
144
145 // structure.pl input:
146 ${input_structure}
147
148 #ifndef __GINAC_${STRUCTURE_UC}_H__
149 #define __GINAC_${STRUCTURE_UC}_H__
150
151 #include <ginac/structure.h>
152
153 namespace GiNaC {
154
155 class ${STRUCTURE} : public structure
156 {
157 // member functions
158
159     // default constructor, destructor, copy constructor assignment operator and helpers
160 public:
161     ${STRUCTURE}();
162     ~${STRUCTURE}();
163     ${STRUCTURE}(${STRUCTURE} const & other);
164     ${STRUCTURE} const & operator=(${STRUCTURE} const & other);
165 protected:
166     void copy(${STRUCTURE} const & other);
167     void destroy(bool call_parent);
168
169     // other constructors
170 public:
171     ${STRUCTURE}(${constructor_arglist});
172
173     // functions overriding virtual functions from bases classes
174 public:
175     basic * duplicate() const;
176     void printraw(ostream & os) const;
177     void print(ostream & os, unsigned upper_precedence=0) const;
178     void printtree(ostream & os, unsigned indent) const;
179     int nops() const;
180     ex & let_op(int const i);
181     ex expand(unsigned options=0) const;
182     bool has(ex const & other) const;
183     ex eval(int level=0) const;
184     ex evalf(int level=0) const;
185     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
186     ex diff(symbol const & s) const;
187     ex subs(lst const & ls, lst const & lr) const;
188 protected:
189     int compare_same_type(basic const & other) const;
190     bool is_equal_same_type(basic const & other) const;
191     unsigned return_type(void) const;
192
193     // new virtual functions which can be overridden by derived classes
194     // none
195
196     // non-virtual functions in this class
197 public:
198 ${member_access_functions}
199     bool types_ok(void) const;
200     
201 // member variables
202 protected:
203 ${members}
204 public:
205 ${op_access_indices_decl}
206 };
207
208 // global constants
209
210 extern const ${STRUCTURE} some_${STRUCTURE};
211 extern type_info const & typeid_${STRUCTURE};
212 extern const unsigned tinfo_${STRUCTURE};
213
214 // macros
215
216 #define ex_to_${STRUCTURE}(X) (static_cast<${STRUCTURE} const &>(*(X).bp))
217
218 } // namespace GiNaC
219
220 #endif // ndef _${STRUCTURE_UC}_H_
221
222 END_OF_INTERFACE
223
224 $implementation=<<END_OF_IMPLEMENTATION;
225 /** \@file ${STRUCTURE}.cpp
226  *
227  *  Implementation of GiNaC's user defined structure ${STRUCTURE}. */
228
229 /*
230  *  This file was generated automatically by STRUCTURE.pl.
231  *  Please do not modify it directly, edit the perl script instead!
232  *
233  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
234  *
235  *  This program is free software; you can redistribute it and/or modify
236  *  it under the terms of the GNU General Public License as published by
237  *  the Free Software Foundation; either version 2 of the License, or
238  *  (at your option) any later version.
239  *
240  *  This program is distributed in the hope that it will be useful,
241  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
242  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
243  *  GNU General Public License for more details.
244  *
245  *  You should have received a copy of the GNU General Public License
246  *  along with this program; if not, write to the Free Software
247  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
248  */
249
250 // structure.pl input:
251 ${input_structure}
252
253 #include <iostream>
254
255 #include "${STRUCTURE}.h"
256
257 namespace GiNaC {
258
259 //////////
260 // default constructor, destructor, copy constructor assignment operator and helpers
261 //////////
262
263 // public
264
265 ${STRUCTURE}::${STRUCTURE}()
266 {
267     debugmsg("${STRUCTURE} default constructor",LOGLEVEL_CONSTRUCT);
268     tinfo_key=tinfo_${STRUCTURE};
269 }
270
271 ${STRUCTURE}::~${STRUCTURE}()
272 {
273     debugmsg("${STRUCTURE} destructor",LOGLEVEL_DESTRUCT);
274     destroy(0);
275 }
276
277 ${STRUCTURE}::${STRUCTURE}(${STRUCTURE} const & other)
278 {
279     debugmsg("${STRUCTURE} copy constructor",LOGLEVEL_CONSTRUCT);
280     copy(other);
281 }
282
283 ${STRUCTURE} const & ${STRUCTURE}::operator=(${STRUCTURE} const & other)
284 {
285     debugmsg("${STRUCTURE} operator=",LOGLEVEL_ASSIGNMENT);
286     if (this != &other) {
287         destroy(1);
288         copy(other);
289     }
290     return *this;
291 }
292
293 // protected
294
295 void ${STRUCTURE}::copy(${STRUCTURE} const & other)
296 {
297     structure::copy(other);
298 ${copy_statements}
299 }
300
301 void ${STRUCTURE}::destroy(bool call_parent)
302 {
303     if (call_parent) structure::destroy(call_parent);
304 }
305
306 //////////
307 // other constructors
308 //////////
309
310 // public
311
312 ${STRUCTURE}::${STRUCTURE}(${constructor_arglist}) 
313     : ${constructor_statements}
314 {
315     debugmsg("${STRUCTURE} constructor from children",
316              LOGLEVEL_CONSTRUCT);
317     tinfo_key=tinfo_${STRUCTURE};
318 }
319
320 //////////
321 // functions overriding virtual functions from bases classes
322 //////////
323
324 // public
325
326 basic * ${STRUCTURE}::duplicate() const
327 {
328     debugmsg("${STRUCTURE} duplicate",LOGLEVEL_DUPLICATE);
329     return new ${STRUCTURE}(*this);
330 }
331
332 void ${STRUCTURE}::printraw(ostream & os) const
333 {
334     debugmsg("${STRUCTURE} printraw",LOGLEVEL_PRINT);
335     os << "${STRUCTURE}()";
336 }
337
338 void ${STRUCTURE}::print(ostream & os, unsigned upper_precedence) const
339 {
340     debugmsg("${STRUCTURE} print",LOGLEVEL_PRINT);
341     os << "${STRUCTURE}()";
342 }
343
344 void ${STRUCTURE}::printtree(ostream & os, unsigned indent) const
345 {
346     debugmsg("${STRUCTURE} printtree",LOGLEVEL_PRINT);
347     os << "${STRUCTURE}()";
348 }
349
350 int ${STRUCTURE}::nops() const
351 {
352     return ${number_of_members};
353 }
354
355 ex & ${STRUCTURE}::let_op(int const i)
356 {
357     ASSERT(i>=0);
358     ASSERT(i<nops());
359
360     switch (i) {
361 ${let_op_statements}
362     }
363     errormsg("${STRUCTURE}::let_op(): should not reach this point");
364     return *new ex(fail());
365 }
366
367 ex ${STRUCTURE}::expand(unsigned options) const
368 {
369     bool all_are_trivially_equal=true;
370 ${expand_statements}
371     if (all_are_trivially_equal) {
372         return *this;
373     }
374     return ${STRUCTURE}(${temporary_arglist});
375 }
376
377 // a ${STRUCTURE} 'has' an expression if it is this expression itself or a child 'has' it
378
379 bool ${STRUCTURE}::has(ex const & other) const
380 {
381     ASSERT(other.bp!=0);
382     if (is_equal(*other.bp)) return true;
383 ${has_statements}
384     return false;
385 }
386
387 ex ${STRUCTURE}::eval(int level) const
388 {
389     if (level==1) {
390         return this->hold();
391     }
392     bool all_are_trivially_equal=true;
393 ${eval_statements}
394     if (all_are_trivially_equal) {
395         return this->hold();
396     }
397     return ${STRUCTURE}(${temporary_arglist});
398 }
399
400 ex ${STRUCTURE}::evalf(int level) const
401 {
402     if (level==1) {
403         return *this;
404     }
405     bool all_are_trivially_equal=true;
406 ${evalf_statements}
407     if (all_are_trivially_equal) {
408         return *this;
409     }
410     return ${STRUCTURE}(${temporary_arglist});
411 }
412
413 /** Implementation of ex::normal() for ${STRUCTURE}s. It normalizes the arguments
414  *  and replaces the ${STRUCTURE} by a temporary symbol.
415  *  \@see ex::normal */
416 ex ${STRUCTURE}::normal(lst &sym_lst, lst &repl_lst, int level) const
417 {
418     if (level==1) {
419         return basic::normal(sym_lst,repl_lst,level);
420     }
421     bool all_are_trivially_equal=true;
422 ${normal_statements}
423     if (all_are_trivially_equal) {
424         return basic::normal(sym_lst,repl_lst,level);
425     }
426     ex n=${STRUCTURE}(${temporary_arglist});
427     return n.bp->basic::normal(sym_lst,repl_lst,level);
428 }
429
430 /** ${STRUCTURE}::diff() differentiates the children.
431     there is no need to check for triavially equal, since diff usually
432     does not return itself unevaluated. */
433 ex ${STRUCTURE}::diff(symbol const & s) const
434 {
435 ${diff_statements}
436     return ${STRUCTURE}(${temporary_arglist});
437 }
438
439 ex ${STRUCTURE}::subs(lst const & ls, lst const & lr) const
440 {
441     bool all_are_trivially_equal=true;
442 ${subs_statements}
443     if (all_are_trivially_equal) {
444         return *this;
445     }
446     return ${STRUCTURE}(${temporary_arglist});
447 }
448
449 // protected
450
451 int ${STRUCTURE}::compare_same_type(basic const & other) const
452 {
453     ASSERT(is_of_type(other,${STRUCTURE}));
454     ${STRUCTURE} const & o=static_cast<${STRUCTURE} const &>
455                                     (const_cast<basic &>(other));
456     int cmpval;
457 ${compare_statements}
458     return 0;
459 }
460
461 bool ${STRUCTURE}::is_equal_same_type(basic const & other) const
462 {
463     ASSERT(is_of_type(other,${STRUCTURE}));
464     ${STRUCTURE} const & o=static_cast<${STRUCTURE} const &>
465                                     (const_cast<basic &>(other));
466 ${is_equal_statements}
467     return true;
468 }
469
470 unsigned ${STRUCTURE}::return_type(void) const
471 {
472     return return_types::noncommutative_composite;
473 }
474
475 //////////
476 // new virtual functions which can be overridden by derived classes
477 //////////
478
479 // none
480
481 //////////
482 // non-virtual functions in this class
483 //////////
484
485 // public
486
487 #define SKIP_TYPE_CHECK_FOR_ex
488 // this is a hack since there is no meaningful
489 // is_ex_exactly_of_type(...,ex) macro definition
490
491 bool ${STRUCTURE}::types_ok(void) const
492 {
493 ${types_ok_statements}
494     return true;
495 }
496
497 //////////
498 // static member variables
499 //////////
500
501 ${op_access_indices_def}
502
503 //////////
504 // global constants
505 //////////
506
507 const ${STRUCTURE} some_${STRUCTURE};
508 type_info const & typeid_${STRUCTURE}=typeid(some_${STRUCTURE});
509 const unsigned tinfo_${STRUCTURE}=structure::register_new("${STRUCTURE}");
510
511 } // namespace GiNaC
512
513 END_OF_IMPLEMENTATION
514
515 print "Creating interface file ${STRUCTURE}.h...";
516 open OUT,">${STRUCTURE}.h" or die "cannot open ${STRUCTURE}.h";
517 print OUT $interface;
518 close OUT;
519 print "ok.\n";
520
521 print "Creating implementation file ${STRUCTURE}.cpp...";
522 open OUT,">${STRUCTURE}.cpp" or die "cannot open ${STRUCTURE}.cpp";
523 print OUT $implementation;
524 close OUT;
525 print "ok.\n";
526
527 print "done.\n";