[GiNaC-devel] [PATCH] Update documentation on extending GiNaC
Alexei Sheplyakov
varg at theor.jinr.ru
Thu Feb 22 11:24:40 CET 2007
---
doc/examples/mystring.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++++
doc/tutorial/ginac.texi | 51 ++++++++++++++--------
2 files changed, 136 insertions(+), 19 deletions(-)
diff --git a/doc/examples/mystring.cpp b/doc/examples/mystring.cpp
new file mode 100644
index 0000000..cf0d8a2
--- /dev/null
+++ b/doc/examples/mystring.cpp
@@ -0,0 +1,104 @@
+/**
+ * @file mystring.cpp Example of extending GiNaC: writing new classes
+ */
+#include <iostream>
+#include <string>
+#include <stdexcept>
+using namespace std;
+
+#include <ginac/ginac.h>
+using namespace GiNaC;
+
+class mystring : public basic
+{
+ GINAC_DECLARE_REGISTERED_CLASS(mystring, basic)
+
+public:
+ mystring(const string &s);
+ mystring(const char *s);
+ ex eval(int level) const;
+
+private:
+ string str;
+
+protected:
+ void do_print(const print_context &c, unsigned level = 0) const;
+
+};
+
+GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(mystring, basic,
+ print_func<print_context>(&mystring::do_print))
+
+// ctors
+mystring::mystring() : inherited(&mystring::tinfo_static) { }
+mystring::mystring(const string &s) : inherited(&mystring::tinfo_static), str(s) { }
+mystring::mystring(const char *s) : inherited(&mystring::tinfo_static), str(s) { }
+
+// comparison
+int mystring::compare_same_type(const basic &other) const
+{
+ const mystring &o = static_cast<const mystring &>(other);
+ int cmpval = str.compare(o.str);
+ if (cmpval == 0)
+ return 0;
+ else if (cmpval < 0)
+ return -1;
+ else
+ return 1;
+}
+
+// archiving/unarchiving
+mystring::mystring(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst)
+{
+ n.find_string("string", str);
+}
+
+void mystring::archive(archive_node &n) const
+{
+ inherited::archive(n);
+ n.add_string("string", str);
+}
+
+ex mystring::unarchive(const archive_node &n, lst &sym_lst)
+{
+ return (new mystring(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+// printing
+void mystring::do_print(const print_context &c, unsigned level) const
+{
+ // print_context::s is a reference to an ostream
+ c.s << '\"' << str << '\"';
+}
+
+/**
+ * evaluation: all strings automatically converted to lowercase with
+ * non-alphabetic characters stripped, and empty strings removed
+ */
+ex mystring::eval(int level) const
+{
+ string new_str;
+ for (size_t i=0; i<str.length(); i++) {
+ char c = str[i];
+ if (c >= 'A' && c <= 'Z')
+ new_str += tolower(c);
+ else if (c >= 'a' && c <= 'z')
+ new_str += c;
+ }
+
+ if (new_str.length() == 0)
+ return 0;
+ else
+ return mystring(new_str).hold();
+}
+
+int main(int argc, char** argv)
+{
+ ex e = mystring("Hello, world!");
+ cout << is_a<mystring>(e) << endl;
+ cout << ex_to<basic>(e).class_name() << endl;
+ cout << e << endl;
+ ex another = pow(mystring("One string"), 2*sin(Pi-mystring("Another string")));
+ cout << another << endl;
+ return 0;
+}
diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi
index 2560703..2650462 100644
--- a/doc/tutorial/ginac.texi
+++ b/doc/tutorial/ginac.texi
@@ -7733,9 +7733,8 @@ The RTTI in GiNaC is based on two mechanisms:
@item
The @code{basic} class declares a member variable @code{tinfo_key} which
-holds an unsigned integer that identifies the object's class. These numbers
-are defined in the @file{tinfos.h} header file for the built-in GiNaC
-classes. They all start with @code{TINFO_}.
+holds a variable of @code{tinfo_t} type (which is actually just
+ at code{const void*}) that identifies the object's class.
@item
By means of some clever tricks with static members, GiNaC maintains a list
@@ -7772,17 +7771,6 @@ using namespace std;
using namespace GiNaC;
@end example
-The first thing we have to do is to define a @code{tinfo_key} for our new
-class. This can be any arbitrary unsigned number that is not already taken
-by one of the existing classes but it's better to come up with something
-that is unlikely to clash with keys that might be added in the future. The
-numbers in @file{tinfos.h} are modeled somewhat after the class hierarchy
-which is not a requirement but we are going to stick with this scheme:
-
- at example
-const unsigned TINFO_mystring = 0x42420001U;
- at end example
-
Now we can write down the class declaration. The class stores a C++
@code{string} and the user shall be able to construct a @code{mystring}
object from a C or C++ string:
@@ -7866,11 +7854,14 @@ which are the two constructors we declared.
Let's proceed step-by-step. The default constructor looks like this:
@example
-mystring::mystring() : inherited(TINFO_mystring) @{@}
+mystring::mystring() : inherited(&mystring::tinfo_static) @{@}
@end example
The golden rule is that in all constructors you have to set the
- at code{tinfo_key} member to the @code{TINFO_*} value of your class. Otherwise
+ at code{tinfo_key} member to the @code{&your_class_name::tinfo_static}
+ at footnote{each GiNaC class has static member called tinfo_static.
+This member is declared by the GINAC_DECLARE_REGISTERED_CLASS macros
+and defined by the GINAC_IMPLEMENT_REGISTERED_CLASS macros}. Otherwise
it will be set by the constructor of the superclass and all hell will break
loose in the RTTI. For your convenience, the @code{basic} class provides
a constructor that takes a @code{tinfo_key} value, which we are using here
@@ -7960,8 +7951,8 @@ all relevant member variables.
Now the only thing missing is our two new constructors:
@example
-mystring::mystring(const string &s) : inherited(TINFO_mystring), str(s) @{@}
-mystring::mystring(const char *s) : inherited(TINFO_mystring), str(s) @{@}
+mystring::mystring(const string &s) : inherited(&mystring::tinfo_static), str(s) @{@}
+mystring::mystring(const char *s) : inherited(&mystring::tinfo_static), str(s) @{@}
@end example
No surprises here. We set the @code{str} member from the argument and
@@ -8100,7 +8091,7 @@ public:
ex mystring::eval(int level) const
@{
string new_str;
- for (int i=0; i<str.length(); i++) @{
+ for (size_t i=0; i<str.length(); i++) @{
char c = str[i];
if (c >= 'A' && c <= 'Z')
new_str += tolower(c);
@@ -8198,6 +8189,28 @@ should become a need.
That's it. May the source be with you!
+ at subsection Upgrading extension classes from older version of GiNaC
+
+If you got some extension classes for GiNaC 1.3.X some changes are
+necessary in order to make your code work with GiNaC 1.4.
+
+ at itemize @bullet
+ at item constructors which set @code{tinfo_key} such as
+
+ at example
+myclass::myclass() : inherited(TINFO_myclass) @{@}
+ at end example
+
+need to be rewritten as
+
+ at example
+myclass::myclass() : inherited(&myclass::tinfo_static) @{@}
+ at end example
+
+ at item TINO_myclass is not necessary any more and can be removed.
+
+ at end itemize
+
@node A comparison with other CAS, Advantages, Adding classes, Top
@c node-name, next, previous, up
--
1.4.4.4
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-devel/attachments/20070222/94a16823/attachment.pgp
More information about the GiNaC-devel
mailing list