- Renamed flag NO_GINAC_NAMESPACE to NO_NAMESPACE_GINAC because of m4.
[ginac.git] / ginac / function.pl
1 #!/usr/bin/perl -w
2
3 $maxargs=10;
4
5 sub generate_seq {
6     my ($seq_template,$n)=@_;
7     my ($res,$N);
8     
9     $res='';
10     for ($N=1; $N<=$n; $N++) {
11         $res .= eval('"' . $seq_template . '"');
12         if ($N!=$n) {
13             $res .= ', ';
14         }
15     }
16     return $res;
17 }
18
19 sub generate {
20     my ($template,$seq_template1,$seq_template2)=@_;
21     my ($res,$N,$SEQ);
22
23     $res='';
24     for ($N=1; $N<=$maxargs; $N++) {
25         $SEQ1=generate_seq($seq_template1,$N);
26         $SEQ2=generate_seq($seq_template2,$N);
27         $res .= eval('"' . $template . '"');
28         $SEQ1=''; # to avoid main::SEQ1 used only once warning
29         $SEQ2=''; # same as above
30     }
31     return $res;
32 }
33
34 $declare_function_macro_namespace=generate(
35     <<'END_OF_DECLARE_FUNCTION_MACRO_NAMESPACE','const GiNaC::ex & p${N}','p${N}');
36 #define DECLARE_FUNCTION_${N}P(NAME) \\
37 extern const unsigned function_index_##NAME; \\
38 inline GiNaC::function NAME(${SEQ1}) { \\
39     return GiNaC::function(function_index_##NAME, ${SEQ2}); \\
40 }
41
42 END_OF_DECLARE_FUNCTION_MACRO_NAMESPACE
43
44 $declare_function_macro_no_namespace=generate(
45     <<'END_OF_DECLARE_FUNCTION_MACRO_NO_NAMESPACE','const ex & p${N}','p${N}');
46 #define DECLARE_FUNCTION_${N}P(NAME) \\
47 extern const unsigned function_index_##NAME; \\
48 inline function NAME(${SEQ1}) { \\
49     return function(function_index_##NAME, ${SEQ2}); \\
50 }
51
52 END_OF_DECLARE_FUNCTION_MACRO_NO_NAMESPACE
53
54 $typedef_eval_funcp=generate(
55 'typedef ex (* eval_funcp_${N})(${SEQ1});'."\n",
56 'const ex &','');
57
58 $typedef_evalf_funcp=generate(
59 'typedef ex (* evalf_funcp_${N})(${SEQ1});'."\n",
60 'const ex &','');
61
62 $typedef_diff_funcp=generate(
63 'typedef ex (* diff_funcp_${N})(${SEQ1}, unsigned);'."\n",
64 'const ex &','');
65
66 $typedef_series_funcp=generate(
67 'typedef ex (* series_funcp_${N})(${SEQ1}, const symbol &, const ex &, int);'."\n",
68 'const ex &','');
69
70 $constructors_interface=generate(
71 '    function(unsigned ser, ${SEQ1});'."\n",
72 'const ex & param${N}','');
73
74 $register_new_interface=generate(
75 '    static unsigned register_new(const char * nm, eval_funcp_${N} e,'."\n".
76 '                                 evalf_funcp_${N} ef=0, diff_funcp_${N} d=0, series_funcp_${N} s=0);'.
77 "\n",'','');
78
79 $constructors_implementation=generate(
80     <<'END_OF_CONSTRUCTORS_IMPLEMENTATION','const ex & param${N}','param${N}');
81 function::function(unsigned ser, ${SEQ1})
82     : exprseq(${SEQ2}), serial(ser)
83 {
84     debugmsg(\"function constructor from unsigned,${N}*ex\",LOGLEVEL_CONSTRUCT);
85     tinfo_key = TINFO_function;
86 }
87 END_OF_CONSTRUCTORS_IMPLEMENTATION
88
89 $eval_switch_statement=generate(
90     <<'END_OF_EVAL_SWITCH_STATEMENT','eseq[${N}-1]','');
91     case ${N}:
92         return ((eval_funcp_${N})(registered_functions()[serial].e))(${SEQ1});
93         break;
94 END_OF_EVAL_SWITCH_STATEMENT
95
96 $evalf_switch_statement=generate(
97     <<'END_OF_EVALF_SWITCH_STATEMENT','eseq[${N}-1]','');
98     case ${N}:
99         return ((evalf_funcp_${N})(registered_functions()[serial].ef))(${SEQ1});
100         break;
101 END_OF_EVALF_SWITCH_STATEMENT
102
103 $diff_switch_statement=generate(
104     <<'END_OF_DIFF_SWITCH_STATEMENT','seq[${N}-1]','');
105     case ${N}:
106         return ((diff_funcp_${N})(registered_functions()[serial].d))(${SEQ1},diff_param);
107         break;
108 END_OF_DIFF_SWITCH_STATEMENT
109
110 $series_switch_statement=generate(
111     <<'END_OF_SERIES_SWITCH_STATEMENT','seq[${N}-1]','');
112     case ${N}:
113         try {
114             res = ((series_funcp_${N})(registered_functions()[serial].s))(${SEQ1},s,point,order);
115         } catch (do_taylor) {
116             res = basic::series(s, point, order);
117         }
118         return res;
119         break;
120 END_OF_SERIES_SWITCH_STATEMENT
121
122 $register_new_implementation=generate(
123     <<'END_OF_REGISTER_NEW_IMPLEMENTATION','','');
124 unsigned function::register_new(const char * nm, eval_funcp_${N} e,
125                                  evalf_funcp_${N} ef, diff_funcp_${N} d, series_funcp_${N} s)
126 {
127     registered_function_info rfi={nm,${N},0,eval_funcp(e),
128                                   evalf_funcp(ef),diff_funcp(d),series_funcp(s)};
129     registered_functions().push_back(rfi);
130     return registered_functions().size()-1;
131 }
132 END_OF_REGISTER_NEW_IMPLEMENTATION
133
134 $interface=<<END_OF_INTERFACE;
135 /** \@file function.h
136  *
137  *  Interface to abstract class function (new function concept). */
138
139 /*
140  *  This file was generated automatically by function.pl.
141  *  Please do not modify it directly, edit the perl script instead!
142  *  function.pl options: \$maxargs=${maxargs}
143  *
144  *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
145  *
146  *  This program is free software; you can redistribute it and/or modify
147  *  it under the terms of the GNU General Public License as published by
148  *  the Free Software Foundation; either version 2 of the License, or
149  *  (at your option) any later version.
150  *
151  *  This program is distributed in the hope that it will be useful,
152  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
153  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
154  *  GNU General Public License for more details.
155  *
156  *  You should have received a copy of the GNU General Public License
157  *  along with this program; if not, write to the Free Software
158  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
159  */
160
161 #ifndef __GINAC_FUNCTION_H__
162 #define __GINAC_FUNCTION_H__
163
164 #include <string>
165 #include <vector>
166
167 #ifdef __CINT__
168 // CINT needs <algorithm> to work properly with <vector> 
169 #include <algorithm>
170 #endif // def __CINT__
171
172 #include "exprseq.h"
173
174 #ifndef NO_NAMESPACE_GINAC
175
176 // the following lines have been generated for max. ${maxargs} parameters
177 $declare_function_macro_namespace
178 // end of generated lines
179
180 #else // ndef NO_NAMESPACE_GINAC
181
182 // the following lines have been generated for max. ${maxargs} parameters
183 $declare_function_macro_no_namespace
184 // end of generated lines
185
186 #endif // ndef NO_NAMESPACE_GINAC
187
188 #ifndef NO_NAMESPACE_GINAC
189
190 #define REGISTER_FUNCTION(NAME,E,EF,D,S) \\
191 const unsigned function_index_##NAME=GiNaC::function::register_new(#NAME,E,EF,D,S);
192
193 #else // ndef NO_NAMESPACE_GINAC
194
195 #define REGISTER_FUNCTION(NAME,E,EF,D,S) \\
196 const unsigned function_index_##NAME=function::register_new(#NAME,E,EF,D,S);
197
198 #endif // ndef NO_NAMESPACE_GINAC
199
200 #define BEGIN_TYPECHECK \\
201 bool automatic_typecheck=true;
202
203 #define TYPECHECK(VAR,TYPE) \\
204 if (!is_ex_exactly_of_type(VAR,TYPE)) { \\
205     automatic_typecheck=false; \\
206 } else
207
208 #ifndef NO_NAMESPACE_GINAC
209
210 #define TYPECHECK_INTEGER(VAR) \\
211 if (!(VAR).info(GiNaC::info_flags::integer)) { \\
212     automatic_typecheck=false; \\
213 } else
214
215 #else // ndef NO_NAMESPACE_GINAC
216
217 #define TYPECHECK_INTEGER(VAR) \\
218 if (!(VAR).info(info_flags::integer)) { \\
219     automatic_typecheck=false; \\
220 } else
221
222 #endif // ndef NO_NAMESPACE_GINAC
223
224 #define END_TYPECHECK(RV) \\
225 {} \\
226 if (!automatic_typecheck) { \\
227     return RV.hold(); \\
228 }
229
230 #ifndef NO_NAMESPACE_GINAC
231 namespace GiNaC {
232 #endif // ndef NO_NAMESPACE_GINAC
233
234 class function;
235
236 typedef ex (* eval_funcp)();
237 typedef ex (* evalf_funcp)();
238 typedef ex (* diff_funcp)();
239 typedef ex (* series_funcp)();
240
241 // the following lines have been generated for max. ${maxargs} parameters
242 $typedef_eval_funcp
243 $typedef_evalf_funcp
244 $typedef_diff_funcp
245 $typedef_series_funcp
246 // end of generated lines
247
248 struct registered_function_info {
249     const char * name;
250     unsigned nparams;
251     unsigned options;
252     eval_funcp e;
253     evalf_funcp ef;
254     diff_funcp d;
255     series_funcp s;
256 };
257
258 /** The class function is used to implement builtin functions like sin, cos...
259     and user defined functions */
260 class function : public exprseq
261 {
262     GINAC_DECLARE_REGISTERED_CLASS(function, exprseq)
263
264     // CINT has a linking problem
265     friend void ginsh_get_ginac_functions(void);
266
267 // member functions
268
269     // default constructor, destructor, copy constructor assignment operator and helpers
270 public:
271     function();
272     ~function();
273     function(const function & other);
274     const function & operator=(const function & other);
275 protected:
276     void copy(const function & other);
277     void destroy(bool call_parent);
278
279     // other constructors
280 public:
281     function(unsigned ser);
282     // the following lines have been generated for max. ${maxargs} parameters
283 $constructors_interface
284     // end of generated lines
285     function(unsigned ser, const exprseq & es);
286     function(unsigned ser, const exvector & v, bool discardable=0);
287     function(unsigned ser, exvector * vp); // vp will be deleted
288
289     // functions overriding virtual functions from bases classes
290 public:
291     basic * duplicate() const;
292     void printraw(ostream & os) const; 
293     void print(ostream & os, unsigned upper_precedence=0) const;
294     void printtree(ostream & os, unsigned indent) const;
295     void printcsrc(ostream & os, unsigned type, unsigned upper_precedence=0) const;
296     ex expand(unsigned options=0) const;
297     ex eval(int level=0) const;
298     ex evalf(int level=0) const;
299     ex diff(const symbol & s) const;
300     ex series(const symbol & s, const ex & point, int order) const;
301     ex thisexprseq(const exvector & v) const;
302     ex thisexprseq(exvector * vp) const;
303 protected:
304     int compare_same_type(const basic & other) const;
305     bool is_equal_same_type(const basic & other) const;
306     unsigned return_type(void) const;
307     unsigned return_type_tinfo(void) const;
308     
309     // new virtual functions which can be overridden by derived classes
310     // none
311     
312     // non-virtual functions in this class
313 protected:
314     ex pdiff(unsigned diff_param) const; // partial differentiation
315     static vector<registered_function_info> & registered_functions(void);
316 public:
317     // the following lines have been generated for max. ${maxargs} parameters
318 $register_new_interface
319     // end of generated lines
320     unsigned getserial(void) const {return serial;}
321     
322 // member variables
323
324 protected:
325     unsigned serial;
326 };
327
328 // utility macros
329
330 #ifndef NO_NAMESPACE_GINAC
331
332 #define is_ex_the_function(OBJ, FUNCNAME) \\
333     (is_ex_exactly_of_type(OBJ, function) && static_cast<GiNaC::function *>(OBJ.bp)->getserial() == function_index_##FUNCNAME)
334
335 #else // ndef NO_NAMESPACE_GINAC
336
337 #define is_ex_the_function(OBJ, FUNCNAME) \\
338     (is_ex_exactly_of_type(OBJ, function) && static_cast<function *>(OBJ.bp)->getserial() == function_index_##FUNCNAME)
339
340 #endif // ndef NO_NAMESPACE_GINAC
341
342 // global constants
343
344 extern const function some_function;
345 extern const type_info & typeid_function;
346
347 #ifndef NO_NAMESPACE_GINAC
348 } // namespace GiNaC
349 #endif // ndef NO_NAMESPACE_GINAC
350
351 #endif // ndef __GINAC_FUNCTION_H__
352
353 END_OF_INTERFACE
354
355 $implementation=<<END_OF_IMPLEMENTATION;
356 /** \@file function.cpp
357  *
358  *  Implementation of class function. */
359
360 /*
361  *  This file was generated automatically by function.pl.
362  *  Please do not modify it directly, edit the perl script instead!
363  *  function.pl options: \$maxargs=${maxargs}
364  *
365  *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
366  *
367  *  This program is free software; you can redistribute it and/or modify
368  *  it under the terms of the GNU General Public License as published by
369  *  the Free Software Foundation; either version 2 of the License, or
370  *  (at your option) any later version.
371  *
372  *  This program is distributed in the hope that it will be useful,
373  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
374  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
375  *  GNU General Public License for more details.
376  *
377  *  You should have received a copy of the GNU General Public License
378  *  along with this program; if not, write to the Free Software
379  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
380  */
381
382 #include <string>
383 #include <stdexcept>
384
385 #include "function.h"
386 #include "ex.h"
387 #include "archive.h"
388 #include "utils.h"
389 #include "debugmsg.h"
390
391 #ifndef NO_NAMESPACE_GINAC
392 namespace GiNaC {
393 #endif // ndef NO_NAMESPACE_GINAC
394
395 GINAC_IMPLEMENT_REGISTERED_CLASS(function, exprseq)
396
397 //////////
398 // default constructor, destructor, copy constructor assignment operator and helpers
399 //////////
400
401 // public
402
403 function::function() : serial(0)
404 {
405     debugmsg("function default constructor",LOGLEVEL_CONSTRUCT);
406     tinfo_key = TINFO_function;
407 }
408
409 function::~function()
410 {
411     debugmsg("function destructor",LOGLEVEL_DESTRUCT);
412     destroy(0);
413 }
414
415 function::function(const function & other)
416 {
417     debugmsg("function copy constructor",LOGLEVEL_CONSTRUCT);
418     copy(other);
419 }
420
421 const function & function::operator=(const function & other)
422 {
423     debugmsg("function operator=",LOGLEVEL_ASSIGNMENT);
424     if (this != &other) {
425         destroy(1);
426         copy(other);
427     }
428     return *this;
429 }
430
431 // protected
432
433 void function::copy(const function & other)
434 {
435     exprseq::copy(other);
436     serial=other.serial;
437 }
438
439 void function::destroy(bool call_parent)
440 {
441     if (call_parent) exprseq::destroy(call_parent);
442 }
443
444 //////////
445 // other constructors
446 //////////
447
448 // public
449
450 function::function(unsigned ser) : serial(ser)
451 {
452     debugmsg("function constructor from unsigned",LOGLEVEL_CONSTRUCT);
453     tinfo_key = TINFO_function;
454 }
455
456 // the following lines have been generated for max. ${maxargs} parameters
457 $constructors_implementation
458 // end of generated lines
459
460 function::function(unsigned ser, const exprseq & es) : exprseq(es), serial(ser)
461 {
462     debugmsg("function constructor from unsigned,exprseq",LOGLEVEL_CONSTRUCT);
463     tinfo_key = TINFO_function;
464 }
465
466 function::function(unsigned ser, const exvector & v, bool discardable) 
467     : exprseq(v,discardable), serial(ser)
468 {
469     debugmsg("function constructor from string,exvector,bool",LOGLEVEL_CONSTRUCT);
470     tinfo_key = TINFO_function;
471 }
472
473 function::function(unsigned ser, exvector * vp) 
474     : exprseq(vp), serial(ser)
475 {
476     debugmsg("function constructor from unsigned,exvector *",LOGLEVEL_CONSTRUCT);
477     tinfo_key = TINFO_function;
478 }
479
480 //////////
481 // archiving
482 //////////
483
484 /** Construct object from archive_node. */
485 function::function(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
486 {
487     debugmsg("function constructor from archive_node", LOGLEVEL_CONSTRUCT);
488
489     // Find serial number by function name
490     string s;
491     if (n.find_string("name", s)) {
492         unsigned int ser = 0;
493         vector<registered_function_info>::const_iterator i = registered_functions().begin(), iend = registered_functions().end();
494         while (i != iend) {
495             if (s == i->name) {
496                 serial = ser;
497                 return;
498             }
499             i++; ser++;
500         }
501         throw (std::runtime_error("unknown function '" + s + "' in archive"));
502     } else
503         throw (std::runtime_error("unnamed function in archive"));
504 }
505
506 /** Unarchive the object. */
507 ex function::unarchive(const archive_node &n, const lst &sym_lst)
508 {
509     return (new function(n, sym_lst))->setflag(status_flags::dynallocated);
510 }
511
512 /** Archive the object. */
513 void function::archive(archive_node &n) const
514 {
515     inherited::archive(n);
516     GINAC_ASSERT(serial < registered_functions().size());
517     n.add_string("name", registered_functions()[serial].name);
518 }
519
520 //////////
521 // functions overriding virtual functions from bases classes
522 //////////
523
524 // public
525
526 basic * function::duplicate() const
527 {
528     debugmsg("function duplicate",LOGLEVEL_DUPLICATE);
529     return new function(*this);
530 }
531
532 void function::printraw(ostream & os) const
533 {
534     debugmsg("function printraw",LOGLEVEL_PRINT);
535
536     GINAC_ASSERT(serial<registered_functions().size());
537
538     os << "function(name=" << registered_functions()[serial].name;
539     for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
540         os << ",";
541         (*it).bp->print(os);
542     }
543     os << ")";
544 }
545
546 void function::print(ostream & os, unsigned upper_precedence) const
547 {
548     debugmsg("function print",LOGLEVEL_PRINT);
549
550     GINAC_ASSERT(serial<registered_functions().size());
551
552     os << registered_functions()[serial].name;
553     printseq(os,'(',',',')',exprseq::precedence,function::precedence);
554 }
555
556 void function::printtree(ostream & os, unsigned indent) const
557 {
558     debugmsg("function printtree",LOGLEVEL_PRINT);
559
560     GINAC_ASSERT(serial<registered_functions().size());
561
562     os << string(indent,' ') << "function "
563        << registered_functions()[serial].name
564        << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
565        << ", flags=" << flags
566        << ", nops=" << nops() << endl;
567     for (unsigned i=0; i<nops(); ++i) {
568         seq[i].printtree(os,indent+delta_indent);
569     }
570     os << string(indent+delta_indent,' ') << "=====" << endl;
571 }
572
573 void function::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
574 {
575     debugmsg("function print csrc",LOGLEVEL_PRINT);
576
577     GINAC_ASSERT(serial<registered_functions().size());
578
579         // Print function name in lowercase
580     string lname;
581     lname=registered_functions()[serial].name;
582     for (unsigned i=0; i<lname.size(); i++)
583         lname[i] = tolower(lname[i]);
584     os << lname << "(";
585
586         // Print arguments, separated by commas
587     exvector::const_iterator it = seq.begin();
588     exvector::const_iterator itend = seq.end();
589     while (it != itend) {
590         it->bp->printcsrc(os, type, 0);
591         it++;
592         if (it != itend)
593             os << ",";
594     }
595     os << ")";
596 }
597
598 ex function::expand(unsigned options) const
599 {
600     return this->setflag(status_flags::expanded);
601 }
602
603 ex function::eval(int level) const
604 {
605     GINAC_ASSERT(serial<registered_functions().size());
606
607     exvector eseq=evalchildren(level);    
608
609     if (registered_functions()[serial].e==0) {
610         return function(serial,eseq).hold();
611     }
612     switch (registered_functions()[serial].nparams) {
613         // the following lines have been generated for max. ${maxargs} parameters
614 ${eval_switch_statement}
615         // end of generated lines
616     }
617     throw(std::logic_error("function::eval(): invalid nparams"));
618 }
619
620 ex function::evalf(int level) const
621 {
622     GINAC_ASSERT(serial<registered_functions().size());
623
624     exvector eseq=evalfchildren(level);
625     
626     if (registered_functions()[serial].ef==0) {
627         return function(serial,eseq).hold();
628     }
629     switch (registered_functions()[serial].nparams) {
630         // the following lines have been generated for max. ${maxargs} parameters
631 ${evalf_switch_statement}
632         // end of generated lines
633     }
634     throw(std::logic_error("function::evalf(): invalid nparams"));
635 }
636
637 ex function::thisexprseq(const exvector & v) const
638 {
639     return function(serial,v);
640 }
641
642 ex function::thisexprseq(exvector * vp) const
643 {
644     return function(serial,vp);
645 }
646
647 /** Implementation of ex::series for functions.
648  *  \@see ex::series */
649 ex function::series(const symbol & s, const ex & point, int order) const
650 {
651     GINAC_ASSERT(serial<registered_functions().size());
652
653     if (registered_functions()[serial].s==0) {
654         return basic::series(s, point, order);
655     }
656     ex res;
657     switch (registered_functions()[serial].nparams) {
658         // the following lines have been generated for max. ${maxargs} parameters
659 ${series_switch_statement}
660         // end of generated lines
661     }
662     throw(std::logic_error("function::series(): invalid nparams"));
663 }
664
665 // protected
666
667 int function::compare_same_type(const basic & other) const
668 {
669     GINAC_ASSERT(is_of_type(other, function));
670     const function & o=static_cast<function &>(const_cast<basic &>(other));
671
672     if (serial!=o.serial) {
673         return serial < o.serial ? -1 : 1;
674     }
675     return exprseq::compare_same_type(o);
676 }
677
678 bool function::is_equal_same_type(const basic & other) const
679 {
680     GINAC_ASSERT(is_of_type(other, function));
681     const function & o=static_cast<function &>(const_cast<basic &>(other));
682
683     if (serial!=o.serial) return false;
684     return exprseq::is_equal_same_type(o);
685 }
686
687 unsigned function::return_type(void) const
688 {
689     if (seq.size()==0) {
690         return return_types::commutative;
691     }
692     return (*seq.begin()).return_type();
693 }
694    
695 unsigned function::return_type_tinfo(void) const
696 {
697     if (seq.size()==0) {
698         return tinfo_key;
699     }
700     return (*seq.begin()).return_type_tinfo();
701 }
702
703 //////////
704 // new virtual functions which can be overridden by derived classes
705 //////////
706
707 // none
708
709 //////////
710 // non-virtual functions in this class
711 //////////
712
713 // protected
714
715 ex function::pdiff(unsigned diff_param) const // partial differentiation
716 {
717     GINAC_ASSERT(serial<registered_functions().size());
718     
719     if (registered_functions()[serial].d==0) {
720         throw(std::logic_error(string("function::pdiff(") + registered_functions()[serial].name + "): no diff function defined"));
721     }
722     switch (registered_functions()[serial].nparams) {
723         // the following lines have been generated for max. ${maxargs} parameters
724 ${diff_switch_statement}
725         // end of generated lines
726     }        
727     throw(std::logic_error("function::pdiff(): no diff function defined"));
728 }
729
730 vector<registered_function_info> & function::registered_functions(void)
731 {
732     static vector<registered_function_info> * rf=new vector<registered_function_info>;
733     return *rf;
734 }
735
736 // public
737
738 // the following lines have been generated for max. ${maxargs} parameters
739 $register_new_implementation
740 // end of generated lines
741
742 //////////
743 // static member variables
744 //////////
745
746 // none
747
748 //////////
749 // global constants
750 //////////
751
752 const function some_function;
753 const type_info & typeid_function=typeid(some_function);
754
755 #ifndef NO_NAMESPACE_GINAC
756 } // namespace GiNaC
757 #endif // ndef NO_NAMESPACE_GINAC
758
759 END_OF_IMPLEMENTATION
760
761 print "Creating interface file function.h...";
762 open OUT,">function.h" or die "cannot open function.h";
763 print OUT $interface;
764 close OUT;
765 print "ok.\n";
766
767 print "Creating implementation file function.cpp...";
768 open OUT,">function.cpp" or die "cannot open function.cpp";
769 print OUT $implementation;
770 close OUT;
771 print "ok.\n";
772
773 print "done.\n";