- subs() can be used to substitute functions, tensors and indexed objects
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Thu, 5 Apr 2001 19:45:05 +0000 (19:45 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Thu, 5 Apr 2001 19:45:05 +0000 (19:45 +0000)
- op(0) of an idx object returns the index value; a nice side-effect of
  this is that idx'es no longer all have the same hash value
- added checks for clifford class

14 files changed:
check/Makefile.am
check/exam_clifford.cpp [new file with mode: 0644]
check/exams.cpp
check/exams.h
check/exams.ref
ginac/basic.cpp
ginac/function.pl
ginac/idx.cpp
ginac/idx.h
ginac/indexed.cpp
ginac/indexed.h
ginac/symbol.cpp
ginac/tensor.cpp
ginac/tensor.h

index 26ef258..fb943d0 100644 (file)
@@ -10,7 +10,8 @@ checks_LDADD = ../ginac/libginac.la
 exams_SOURCES = exam_paranoia.cpp exam_numeric.cpp exam_powerlaws.cpp \
   exam_inifcns.cpp exam_differentiation.cpp exam_polygcd.cpp \
   exam_normalization.cpp exam_pseries.cpp exam_matrices.cpp exam_lsolve.cpp \
-  exam_indexed.cpp exam_color.cpp exam_misc.cpp exams.cpp exams.h
+  exam_indexed.cpp exam_color.cpp exam_clifford.cpp exam_misc.cpp exams.cpp \
+  exams.h
 exams_LDADD = ../ginac/libginac.la
 
 times_SOURCES = time_dennyfliegner.cpp time_gammaseries.cpp \
diff --git a/check/exam_clifford.cpp b/check/exam_clifford.cpp
new file mode 100644 (file)
index 0000000..d449119
--- /dev/null
@@ -0,0 +1,85 @@
+/** @file exam_clifford.cpp
+ *
+ *  Here we test GiNaC's Clifford algebra objects. */
+
+/*
+ *  GiNaC Copyright (C) 1999-2001 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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "exams.h"
+
+static unsigned check_equal(const ex &e1, const ex &e2)
+{
+       ex e = e1 - e2;
+       if (!e.is_zero()) {
+               clog << e1 << "-" << e2 << " erroneously returned "
+                    << e << " instead of 0" << endl;
+               return 1;
+       }
+       return 0;
+}
+
+static unsigned check_equal_simplify(const ex &e1, const ex &e2)
+{
+       ex e = simplify_indexed(e1) - e2;
+       if (!e.is_zero()) {
+               clog << "simplify_indexed(" << e1 << ")-" << e2 << " erroneously returned "
+                    << e << " instead of 0" << endl;
+               return 1;
+       }
+       return 0;
+}
+
+static unsigned clifford_check1(void)
+{
+       // checks general identities and contractions
+
+       unsigned result = 0;
+
+       symbol dim("D");
+       varidx mu(symbol("mu"), dim), nu(symbol("nu"), dim);
+       ex e;
+
+       e = dirac_gamma(mu) * dirac_gamma(nu) *
+           dirac_gamma(nu.toggle_variance()) * dirac_gamma(mu.toggle_variance());
+       result += check_equal_simplify(e, pow(dim, 2) * dirac_one());
+
+       e = dirac_gamma(mu) * dirac_gamma(nu) *
+           dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance());
+       result += check_equal_simplify(e, 2*dim*dirac_one()-pow(dim, 2)*dirac_one());
+
+       return result;
+}
+
+unsigned exam_clifford(void)
+{
+       unsigned result = 0;
+       
+       cout << "examining clifford objects" << flush;
+       clog << "----------clifford objects:" << endl;
+
+       result += clifford_check1();  cout << '.' << flush;
+       
+       if (!result) {
+               cout << " passed " << endl;
+               clog << "(no output)" << endl;
+       } else {
+               cout << " failed " << endl;
+       }
+       
+       return result;
+}
index 429bfc1..b4ec8cb 100644 (file)
@@ -49,6 +49,7 @@ try { \
        EXAM(lsolve)
        EXAM(indexed)
        EXAM(color)
+       EXAM(clifford)
        EXAM(misc)
        
        if (result) {
index 94ae18a..ae454e4 100644 (file)
@@ -40,6 +40,7 @@ unsigned exam_matrices();
 unsigned exam_lsolve();
 unsigned exam_indexed();
 unsigned exam_color();
+unsigned exam_clifford();
 unsigned exam_misc();
 
 #endif // ndef EXAMS_H
index 47d3401..d44e910 100644 (file)
@@ -22,5 +22,7 @@
 (no output)
 ----------color objects:
 (no output)
+----------clifford objects:
+(no output)
 ----------miscellaneous other things:
 (no output)
index fe1d4ea..1b38825 100644 (file)
 #include "symbol.h"
 #include "lst.h"
 #include "ncmul.h"
+#include "idx.h"
+#include "indexed.h"
+#include "tensor.h"
+#include "function.h"
 #include "archive.h"
 #include "utils.h"
 #include "debugmsg.h"
@@ -462,11 +466,11 @@ ex basic::expand(unsigned options) const
 
 // public
 
-/** Substitute symbols in expression and return the result as a new expression.
- *  There are two valid types of replacement arguments: 1) a relational like
- *  symbol==ex and 2) a list of relationals lst(symbol1==ex1,symbol2==ex2,...),
- *  which is converted to subs(lst(symbol1,symbol2,...),lst(ex1,ex2,...)).
- *  In addition, an object of class idx can be used instead of a symbol. */
+/** Substitute objects (symbols, indices, tensors, functions, indexed) in
+ *  expression and return the result as a new expression.  There are two
+ *  valid types of replacement arguments: 1) a relational like object==ex
+ *  and 2) a list of relationals lst(object1==ex1,object2==ex2,...), which
+ *  is converted to subs(lst(object1,object2,...),lst(ex1,ex2,...)). */
 ex basic::subs(const ex & e) const
 {
        if (e.info(info_flags::relation_equal)) {
@@ -481,13 +485,15 @@ ex basic::subs(const ex & e) const
                if (!e.op(i).info(info_flags::relation_equal)) {
                        throw(std::invalid_argument("basic::subs(ex): argument must be a list or equations"));
                }
-               if (!e.op(i).op(0).info(info_flags::symbol)) {
-                       if (!e.op(i).op(0).info(info_flags::idx)) {
-                               throw(std::invalid_argument("basic::subs(ex): lhs must be a symbol or an idx"));
-                       }
+               ex s = e.op(i).op(0);
+               ex r = e.op(i).op(1);
+               if (!is_ex_of_type(s, symbol) && !is_ex_of_type(s, idx) &&
+                   !is_ex_of_type(s, tensor) && !is_ex_of_type(s, function) &&
+                       !is_ex_of_type(s, indexed)) {
+                       throw(std::invalid_argument("basic::subs(ex): lhs must be a symbol, idx, tensor, function or indexed"));
                }
-               ls.append(e.op(i).op(0));
-               lr.append(e.op(i).op(1));
+               ls.append(s);
+               lr.append(r);
        }
        return subs(ls,lr);
 }
index b36df87..f6e7b33 100755 (executable)
@@ -345,6 +345,7 @@ public:
        ex evalf(int level=0) const;
        unsigned calchash(void) const;
        ex series(const relational & r, int order, unsigned options = 0) const;
+       ex subs(const lst & ls, const lst & lr) const;
        ex thisexprseq(const exvector & v) const;
        ex thisexprseq(exvector * vp) const;
 protected:
@@ -821,6 +822,19 @@ ${series_switch_statement}
        throw(std::logic_error("function::series(): invalid nparams"));
 }
 
+ex function::subs(const lst & ls, const lst & lr) const
+{
+       GINAC_ASSERT(ls.nops() == lr.nops());
+
+       for (unsigned i=0; i<ls.nops(); i++) {
+               if (is_ex_of_type(ls.op(i), function) &&
+                   compare_same_type(ex_to_function(ls.op(i)))==0)
+                       return lr.op(i);
+       }
+
+       return inherited::subs(ls, lr);
+}
+
 // protected
 
 
index d8e8e70..0a8686d 100644 (file)
@@ -29,6 +29,8 @@
 #include "utils.h"
 #include "debugmsg.h"
 
+#include "exprseq.h" // !!
+
 namespace GiNaC {
 
 GINAC_IMPLEMENT_REGISTERED_CLASS(idx, basic)
@@ -182,6 +184,18 @@ bool idx::info(unsigned inf) const
        return inherited::info(inf);
 }
 
+unsigned idx::nops() const
+{
+       // don't count the dimension as that is not really a sub-expression
+       return 1;
+}
+
+ex & idx::let_op(int i)
+{
+       GINAC_ASSERT(i == 0);
+       return value;
+}
+
 /** Returns order relation between two indices of the same type. The order
  *  must be such that dummy indices lie next to each other. */
 int idx::compare_same_type(const basic & other) const
@@ -225,6 +239,7 @@ ex idx::subs(const lst & ls, const lst & lr) const
                        // Otherwise substitute value
                        idx *i_copy = static_cast<idx *>(duplicate());
                        i_copy->value = lr.op(i);
+                       i_copy->clearflag(status_flags::hash_calculated);
                        return i_copy->setflag(status_flags::dynallocated);
                }
        }
@@ -236,6 +251,7 @@ ex idx::subs(const lst & ls, const lst & lr) const
 
        idx *i_copy = static_cast<idx *>(duplicate());
        i_copy->value = subsed_value;
+       i_copy->clearflag(status_flags::hash_calculated);
        return i_copy->setflag(status_flags::dynallocated);
 }
 
index aa7f94e..a54ad7c 100644 (file)
@@ -51,6 +51,8 @@ public:
        void printtree(std::ostream & os, unsigned indent) const;
        void print(std::ostream & os, unsigned upper_precedence=0) const;
        bool info(unsigned inf) const;
+       unsigned nops() const;
+       ex & let_op(int i);
 protected:
        ex subs(const lst & ls, const lst & lr) const;
 
index 833d46c..c530c1f 100644 (file)
@@ -28,6 +28,7 @@
 #include "mul.h"
 #include "ncmul.h"
 #include "power.h"
+#include "lst.h"
 #include "archive.h"
 #include "utils.h"
 #include "debugmsg.h"
@@ -368,6 +369,19 @@ ex indexed::coeff(const ex & s, int n) const
                return n==0 ? ex(*this) : _ex0();
 }
 
+ex indexed::subs(const lst & ls, const lst & lr) const
+{
+       GINAC_ASSERT(ls.nops() == lr.nops());
+
+       for (unsigned i=0; i<ls.nops(); i++) {
+               if (is_ex_of_type(ls.op(i), indexed) &&
+                   compare_same_type(ex_to_indexed(ls.op(i)))==0)
+                       return lr.op(i);
+       }
+
+       return inherited::subs(ls, lr);
+}
+
 ex indexed::thisexprseq(const exvector & v) const
 {
        return indexed(symmetry, v);
index e98375d..5b34978 100644 (file)
@@ -159,6 +159,7 @@ public:
        int degree(const ex & s) const;
        int ldegree(const ex & s) const;
        ex coeff(const ex & s, int n = 1) const;
+       ex subs(const lst & ls, const lst & lr) const;
        exvector get_free_indices(void) const;
 
 protected:
index b905a9a..8547ffe 100644 (file)
@@ -223,7 +223,7 @@ ex symbol::eval(int level) const
 
 ex symbol::subs(const lst & ls, const lst & lr) const
 {
-       GINAC_ASSERT(ls.nops()==lr.nops());
+       GINAC_ASSERT(ls.nops() == lr.nops());
 
        for (unsigned i=0; i<ls.nops(); i++) {
                if (is_ex_exactly_of_type(ls.op(i),symbol)) {
index 414225d..b53d6f7 100644 (file)
@@ -27,6 +27,7 @@
 #include "idx.h"
 #include "indexed.h"
 #include "relational.h"
+#include "lst.h"
 #include "numeric.h"
 #include "archive.h"
 #include "utils.h"
@@ -165,6 +166,18 @@ DEFAULT_PRINT(tensmetric, "g")
 DEFAULT_PRINT(minkmetric, "eta")
 DEFAULT_PRINT(tensepsilon, "eps")
 
+ex tensor::subs(const lst & ls, const lst & lr) const
+{
+       GINAC_ASSERT(ls.nops() == lr.nops());
+
+       for (unsigned i=0; i<ls.nops(); i++) {
+               if (is_ex_of_type(ls.op(i), tensor) &&
+                   compare_same_type(ex_to_tensor(ls.op(i)))==0)
+                       return lr.op(i);
+       }
+       return *this;
+}
+
 /** Automatic symbolic evaluation of an indexed delta tensor. */
 ex tensdelta::eval_indexed(const basic & i) const
 {
index 65c86c4..ac991d5 100644 (file)
@@ -40,6 +40,8 @@ protected:
        tensor(unsigned ti);
 
        // functions overriding virtual functions from bases classes
+public:
+       ex subs(const lst & ls, const lst & lr) const;
 protected:
        unsigned return_type(void) const { return return_types::noncommutative_composite; }
 };