[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