]> www.ginac.de Git - ginac.git/blobdiff - ginac/symbol.cpp
documentation update
[ginac.git] / ginac / symbol.cpp
index f84d98cbe996bd9237f46b54012b7e7e7f1baede..f099967cb095c349cba4a1b19320391c0b6fa2ad 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of GiNaC's symbolic objects. */
 
 /*
- *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 
 #include "symbol.h"
 #include "lst.h"
+#include "print.h"
+#include "archive.h"
+#include "tostring.h"
 #include "utils.h"
-#include "idx.h"
 
-//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
-//////////
+namespace GiNaC {
 
-symbol::symbol() : basic(TINFO_symbol)
-{
-    debugmsg("symbol default constructor",LOGLEVEL_CONSTRUCT);
-    serial=next_serial++;
-    name=autoname_prefix()+ToString(serial);
-    asexinfop=new assigned_ex_info;
-    setflag(status_flags::evaluated);
-}
+GINAC_IMPLEMENT_REGISTERED_CLASS(symbol, basic)
 
-symbol::~symbol()
-{
-    debugmsg("symbol destructor",LOGLEVEL_DESTRUCT);
-    destroy(0);
-}
+//////////
+// default ctor, dtor, copy ctor, assignment operator and helpers
+//////////
 
-symbol::symbol(symbol const & other)
+symbol::symbol() : inherited(TINFO_symbol), serial(next_serial++)
 {
-    debugmsg("symbol copy constructor",LOGLEVEL_CONSTRUCT);
-    copy(other);
+       name = TeX_name = autoname_prefix()+ToString(serial);
+       asexinfop = new assigned_ex_info;
+       setflag(status_flags::evaluated | status_flags::expanded);
 }
 
-void symbol::copy(symbol const & other)
+/** For use by copy ctor and assignment operator. */
+void symbol::copy(const symbol & other)
 {
-    basic::copy(other);
-    name=other.name;
-    serial=other.serial;
-    asexinfop=other.asexinfop;
-    ++asexinfop->refcount;
+       inherited::copy(other);
+       name = other.name;
+       TeX_name = other.TeX_name;
+       serial = other.serial;
+       asexinfop = other.asexinfop;
+       ++(asexinfop->refcount);
 }
 
 void symbol::destroy(bool call_parent)
 {
-    if (--asexinfop->refcount == 0) {
-        delete asexinfop;
-    }
-    if (call_parent) {
-        basic::destroy(call_parent);
-    }
+       if (--asexinfop->refcount == 0)
+               delete asexinfop;
+       if (call_parent)
+               inherited::destroy(call_parent);
 }
 
-// how should the following be interpreted?
-// symbol x;
-// symbol y;
-// x=y;
-// probably as: x=ex(y);
-
 //////////
-// other constructors
+// other ctors
 //////////
 
 // public
 
-symbol::symbol(string const & initname) : basic(TINFO_symbol)
+symbol::symbol(const std::string & initname) : inherited(TINFO_symbol)
 {
-    debugmsg("symbol constructor from string",LOGLEVEL_CONSTRUCT);
-    name=initname;
-    serial=next_serial++;
-    asexinfop=new assigned_ex_info;
-    setflag(status_flags::evaluated);
+       name = initname;
+       TeX_name = default_TeX_name();
+       serial = next_serial++;
+       asexinfop = new assigned_ex_info;
+       setflag(status_flags::evaluated | status_flags::expanded);
+}
+
+symbol::symbol(const std::string & initname, const std::string & texname) : inherited(TINFO_symbol)
+{
+       name = initname;
+       TeX_name = texname;
+       serial = next_serial++;
+       asexinfop = new assigned_ex_info;
+       setflag(status_flags::evaluated | status_flags::expanded);
 }
 
 //////////
-// functions overriding virtual functions from bases classes
+// archiving
 //////////
 
-// public
-
-basic * symbol::duplicate() const
+/** Construct object from archive_node. */
+symbol::symbol(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
 {
-    debugmsg("symbol duplicate",LOGLEVEL_DUPLICATE);
-    return new symbol(*this);
+       serial = next_serial++;
+       if (!(n.find_string("name", name)))
+               name = autoname_prefix() + ToString(serial);
+       if (!(n.find_string("TeXname", TeX_name)))
+               TeX_name = default_TeX_name();
+       asexinfop = new assigned_ex_info;
+       setflag(status_flags::evaluated);
 }
 
-bool symbol::info(unsigned inf) const
+/** Unarchive the object. */
+ex symbol::unarchive(const archive_node &n, const lst &sym_lst)
 {
-    if (inf==info_flags::symbol) return true;
-    if (inf==info_flags::polynomial || inf==info_flags::integer_polynomial || inf==info_flags::rational_polynomial || inf==info_flags::rational_function) {
-        return true;
-    } else {
-        return basic::info(inf);
-    }
+       ex s = (new symbol(n, sym_lst))->setflag(status_flags::dynallocated);
+       
+       // If symbol is in sym_lst, return the existing symbol
+       for (unsigned i=0; i<sym_lst.nops(); i++) {
+               if (is_ex_of_type(sym_lst.op(i), symbol) && (ex_to<symbol>(sym_lst.op(i)).name == ex_to<symbol>(s).name))
+                       return sym_lst.op(i);
+       }
+       return s;
 }
 
-ex symbol::expand(unsigned options) const
+/** Archive the object. */
+void symbol::archive(archive_node &n) const
 {
-    return this->hold();
+       inherited::archive(n);
+       n.add_string("name", name);
+       if (TeX_name != default_TeX_name())
+               n.add_string("TeX_name", TeX_name);
 }
 
-bool symbol::has(ex const & other) const
-{
-    if (is_equal(*other.bp)) return true;
-    return false;
-}
+//////////
+// functions overriding virtual functions from base classes
+//////////
 
-int symbol::degree(symbol const & s) const
-{
-    return compare_same_type(s)==0 ? 1 : 0;
-}
+// public
 
-int symbol::ldegree(symbol const & s) const
+void symbol::print(const print_context & c, unsigned level) const
 {
-    return compare_same_type(s)==0 ? 1 : 0;
+       if (is_a<print_tree>(c)) {
+
+               c.s << std::string(level, ' ') << name << " (" << class_name() << ")"
+                   << ", serial=" << serial
+                   << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
+                   << std::endl;
+
+       } else if (is_a<print_latex>(c)) {
+               c.s << TeX_name;
+       } else if (is_a<print_python_repr>(c)) {
+               c.s << class_name() << "('" << name;
+               if (TeX_name != default_TeX_name())
+                       c.s << "','" << TeX_name;
+               c.s << "')";
+       } else
+               c.s << name;
 }
 
-ex symbol::coeff(symbol const & s, int const n) const
+bool symbol::info(unsigned inf) const
 {
-    if (compare_same_type(s)==0) {
-        return n==1 ? exONE() : exZERO();
-    } else {
-        return n==0 ? *this : exZERO();
-    }
+       if (inf==info_flags::symbol) return true;
+       if (inf==info_flags::polynomial ||
+           inf==info_flags::integer_polynomial ||
+           inf==info_flags::cinteger_polynomial ||
+           inf==info_flags::rational_polynomial ||
+           inf==info_flags::crational_polynomial ||
+           inf==info_flags::rational_function)
+               return true;
+       else
+               return inherited::info(inf);
 }
 
 ex symbol::eval(int level) const
 {
-    if (level == -max_recursion_level) {
-        throw(std::runtime_error("max recursion level reached"));
-    }
-    
-    if (asexinfop->is_assigned) {
-        setflag(status_flags::evaluated);
-        if (level==1) {
-            return (asexinfop->assigned_expression);
-        } else {
-            return (asexinfop->assigned_expression).eval(level);
-        }
-    } else {
-        return this->hold();
-    }
-}
-
-ex symbol::subs(lst const & ls, lst const & lr) const
-{
-    ASSERT(ls.nops()==lr.nops());
-#ifdef DOASSERT
-    for (int i=0; i<ls.nops(); i++) {
-        ASSERT(is_ex_exactly_of_type(ls.op(i),symbol)||
-               is_ex_of_type(ls.op(i),idx));
-    }
-#endif // def DOASSERT
-
-    for (int i=0; i<ls.nops(); i++) {
-        if (is_ex_exactly_of_type(ls.op(i),symbol)) {
-            if (compare_same_type(ex_to_symbol(ls.op(i)))==0) return lr.op(i);
-        }
-    }
-    return *this;
+       if (level == -max_recursion_level)
+               throw(std::runtime_error("max recursion level reached"));
+       
+       if (asexinfop->is_assigned) {
+               setflag(status_flags::evaluated);
+               if (level==1)
+                       return (asexinfop->assigned_expression);
+               else
+                       return (asexinfop->assigned_expression).eval(level);
+       } else {
+               return this->hold();
+       }
 }
 
 // protected
 
-int symbol::compare_same_type(basic const & other) const
+/** Implementation of ex::diff() for single differentiation of a symbol.
+ *  It returns 1 or 0.
+ *
+ *  @see ex::diff */
+ex symbol::derivative(const symbol & s) const
 {
-    ASSERT(is_of_type(other,symbol));
-    const symbol *o = static_cast<const symbol *>(&other);
-    if (serial==o->serial) return 0;
-    return serial < o->serial ? -1 : 1;
+       if (compare_same_type(s))
+               return _ex0;
+       else
+               return _ex1;
 }
 
-bool symbol::is_equal_same_type(basic const & other) const
+int symbol::compare_same_type(const basic & other) const
 {
-    ASSERT(is_of_type(other,symbol));
-    const symbol *o = static_cast<const symbol *>(&other);
-    return serial==o->serial;
+       GINAC_ASSERT(is_a<symbol>(other));
+       const symbol *o = static_cast<const symbol *>(&other);
+       if (serial==o->serial) return 0;
+       return serial < o->serial ? -1 : 1;
 }
 
-unsigned symbol::return_type(void) const
-{
-    return return_types::commutative;
-}
-   
-unsigned symbol::return_type_tinfo(void) const
+bool symbol::is_equal_same_type(const basic & other) const
 {
-    return tinfo_key;
+       GINAC_ASSERT(is_a<symbol>(other));
+       const symbol *o = static_cast<const symbol *>(&other);
+       return serial==o->serial;
 }
 
 unsigned symbol::calchash(void) const
 {
-    // return golden_ratio_hash(tinfo()) ^ serial;
-    hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555555U ^ serial));
-    setflag(status_flags::hash_calculated);
-    return hashvalue;
+       // this is where the schoolbook method
+       // (golden_ratio_hash(tinfo()) ^ serial)
+       // is not good enough yet...
+       hashvalue = golden_ratio_hash(golden_ratio_hash(tinfo()) ^ serial);
+       setflag(status_flags::hash_calculated);
+       return hashvalue;
 }
 
 //////////
@@ -228,28 +233,52 @@ unsigned symbol::calchash(void) const
 
 // public
 
-void symbol::assign(ex const & value)
+void symbol::assign(const ex & value)
 {
-    asexinfop->is_assigned=1;
-    asexinfop->assigned_expression=value;
-    clearflag(status_flags::evaluated);
+       asexinfop->is_assigned = 1;
+       asexinfop->assigned_expression = value;
+       clearflag(status_flags::evaluated | status_flags::expanded);
 }
 
 void symbol::unassign(void)
 {
-    if (asexinfop->is_assigned) {
-        asexinfop->is_assigned=0;
-        asexinfop->assigned_expression=exZERO();
-    }
-    setflag(status_flags::evaluated);
+       if (asexinfop->is_assigned) {
+               asexinfop->is_assigned = 0;
+               asexinfop->assigned_expression = _ex0;
+       }
+       setflag(status_flags::evaluated | status_flags::expanded);
 }
 
 // private
 
-string & symbol::autoname_prefix(void)
+/** Symbols not constructed with a string get one assigned using this
+ *  prefix and a number. */
+std::string & symbol::autoname_prefix(void)
 {
-    static string * s=new string("symbol");
-    return *s;
+       static std::string *s = new std::string("symbol");
+       return *s;
+}
+
+/** Return default TeX name for symbol. This recognizes some greek letters. */
+std::string symbol::default_TeX_name(void) const
+{
+       if (name=="alpha"        || name=="beta"         || name=="gamma"
+        || name=="delta"        || name=="epsilon"      || name=="varepsilon"
+        || name=="zeta"         || name=="eta"          || name=="theta"
+        || name=="vartheta"     || name=="iota"         || name=="kappa"
+        || name=="lambda"       || name=="mu"           || name=="nu"
+        || name=="xi"           || name=="omicron"      || name=="pi"
+        || name=="varpi"        || name=="rho"          || name=="varrho"
+        || name=="sigma"        || name=="varsigma"     || name=="tau"
+        || name=="upsilon"      || name=="phi"          || name=="varphi"
+        || name=="chi"          || name=="psi"          || name=="omega"
+        || name=="Gamma"        || name=="Delta"        || name=="Theta"
+        || name=="Lambda"       || name=="Xi"           || name=="Pi"
+        || name=="Sigma"        || name=="Upsilon"      || name=="Phi"
+        || name=="Psi"          || name=="Omega")
+               return "\\" + name;
+       else
+               return name;
 }
 
 //////////
@@ -258,16 +287,7 @@ string & symbol::autoname_prefix(void)
 
 // private
 
-unsigned symbol::next_serial=0;
-
-// string const symbol::autoname_prefix="symbol";
-
-//////////
-// global constants
-//////////
-
-const symbol some_symbol;
-type_info const & typeid_symbol=typeid(some_symbol);
+unsigned symbol::next_serial = 0;
 
 //////////
 // subclass assigned_ex_info
@@ -277,3 +297,5 @@ type_info const & typeid_symbol=typeid(some_symbol);
 symbol::assigned_ex_info::assigned_ex_info(void) : is_assigned(0), refcount(1)
 {
 }
+
+} // namespace GiNaC