From kreckel at ginac.de Tue Sep 4 20:23:27 2007
From: kreckel at ginac.de (Richard B. Kreckel)
Date: Tue, 04 Sep 2007 20:23:27 +0200
Subject: [GiNaC-devel] GiNaC release 1.4.0
In-Reply-To: <46D85457.1090503@physik.uni-wuppertal.de>
References: <46D85457.1090503@physik.uni-wuppertal.de>
Message-ID: <46DDA29F.5020402@ginac.de>
Hi!
Jens Vollinga wrote:
> - Added programming examples in doc/examples
While polishing the Debian packaging I noticed that not all CVS files in
that directory made it into the released package.
A minor nitpick: is it useful to provide texinfo documentation for the
examples? It's not clear where to put it in a system-wide info hierarchy
and if examples are ever installed into /usr/share/doc/ginac/examples/,
then the info file should go there too. But info won't find there. So, a
plain .txt file would suffice, IMHO. (I stumbled across this because I
found ginac-examples.info in my .deb archives.)
-richy.
PS: Anyway, have you remembered to open the champagne?
--
Richard B. Kreckel
From vollinga at physik.uni-wuppertal.de Tue Sep 4 20:44:35 2007
From: vollinga at physik.uni-wuppertal.de (Jens Vollinga)
Date: Tue, 04 Sep 2007 20:44:35 +0200
Subject: [GiNaC-devel] GiNaC release 1.4.0
In-Reply-To: <46DDA29F.5020402@ginac.de>
References: <46D85457.1090503@physik.uni-wuppertal.de>
<46DDA29F.5020402@ginac.de>
Message-ID: <46DDA793.200@physik.uni-wuppertal.de>
Hi,
Richard B. Kreckel schrieb:
> While polishing the Debian packaging I noticed that not all CVS files in
> that directory made it into the released package.
oh, now I checked and yes, the whole debian dir is missing! I've no
explanation for that at the moment. make distcheck doesn't cover that,
obviously. I will repair that. A new release shouldn't be nescessary, I
think. I will just re-package the tar file.
> A minor nitpick: is it useful to provide texinfo documentation for the
> examples? It's not clear where to put it in a system-wide info hierarchy
No, not useful.
> and if examples are ever installed into /usr/share/doc/ginac/examples/,
> then the info file should go there too. But info won't find there. So, a
> plain .txt file would suffice, IMHO. (I stumbled across this because I
> found ginac-examples.info in my .deb archives.)
Good point. I will change that in CVS for the next release.
> PS: Anyway, have you remembered to open the champagne?
Yes, of course. But maybe should remove that step from the release
procedure. That stupid bottle just sits there next to all the other
bottles and does nothing! What's the point?!?
Regards,
Jens
From vollinga at physik.uni-wuppertal.de Tue Sep 4 20:48:35 2007
From: vollinga at physik.uni-wuppertal.de (Jens Vollinga)
Date: Tue, 04 Sep 2007 20:48:35 +0200
Subject: [GiNaC-devel] GiNaC release 1.4.0
In-Reply-To: <46DDA793.200@physik.uni-wuppertal.de>
References: <46D85457.1090503@physik.uni-wuppertal.de> <46DDA29F.5020402@ginac.de>
<46DDA793.200@physik.uni-wuppertal.de>
Message-ID: <46DDA883.70806@physik.uni-wuppertal.de>
Hi again,
the explanation for the missing files is: I did an VPATH build! This
does not go well with make distcheck ...
Regards,
Jens
From vollinga at physik.uni-wuppertal.de Tue Sep 4 21:34:14 2007
From: vollinga at physik.uni-wuppertal.de (Jens Vollinga)
Date: Tue, 04 Sep 2007 21:34:14 +0200
Subject: [GiNaC-devel] GiNaC release 1.4.0
In-Reply-To: <46DDA29F.5020402@ginac.de>
References: <46D85457.1090503@physik.uni-wuppertal.de>
<46DDA29F.5020402@ginac.de>
Message-ID: <46DDB336.9040909@physik.uni-wuppertal.de>
Hi once again,
Richard B. Kreckel schrieb:
> Jens Vollinga wrote:
>> - Added programming examples in doc/examples
>
> While polishing the Debian packaging I noticed that not all CVS files in
> that directory made it into the released package.
ok, forget my last two emails, I completely misunderstood the thing. I
added the examples now to CVS.
What do you recommend: a new version number? just re-packaging?
Regards,
Jens
From kreckel at ginac.de Tue Sep 4 22:09:04 2007
From: kreckel at ginac.de (Richard B. Kreckel)
Date: Tue, 04 Sep 2007 22:09:04 +0200
Subject: [GiNaC-devel] GiNaC release 1.4.0
In-Reply-To: <46DDB336.9040909@physik.uni-wuppertal.de>
References: <46D85457.1090503@physik.uni-wuppertal.de> <46DDA29F.5020402@ginac.de>
<46DDB336.9040909@physik.uni-wuppertal.de>
Message-ID: <46DDBB60.3040900@ginac.de>
Jens Vollinga wrote:
> ok, forget my last two emails, I completely misunderstood the thing. I
> added the examples now to CVS.
Phew!
> What do you recommend: a new version number? just re-packaging?
Uhm, I do dislike repackaging without changing the version number. One
never knows what ways that tarball took in the meanwhile (it could've
been sitting in the Debian archives already) and diffs have a potential
to cause confusion later on. And I don't think missing example files
warrant a new release anyway. Can the issue just be ignored until the
next release is rolled anyway?
Cheers
-richy.
PS: I think we should meet and talk about that bottle.
--
Richard B. Kreckel
From varg at theor.jinr.ru Wed Sep 5 07:52:05 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Wed, 5 Sep 2007 09:52:05 +0400
Subject: [GiNaC-devel] [PATCH] INSTALL: do not mention nonexisting autogen.sh
Message-ID: <20070905055205.GA25433@theor.jinr.ru>
That file was removed a long time ago, so...
---
INSTALL | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/INSTALL b/INSTALL
index 2c60d2d..1fda652 100644
--- a/INSTALL
+++ b/INSTALL
@@ -60,9 +60,8 @@ library works correctly you can use
$ make check
-The "configure" script (and "autogen.sh", which invokes "configure") can be
-given a number of options to enable and disable various features. For a
-complete list, type:
+The "configure" script can be given a number of options to enable and
+disable various features. For a complete list, type:
$ ./configure --help
--
1.4.4.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Wed Sep 5 08:52:57 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Wed, 5 Sep 2007 10:52:57 +0400
Subject: [GiNaC-devel] [PATCH] Add self-contained example of a GiNaC class.
Message-ID: <20070905065257.GA28224@theor.jinr.ru>
Hello!
Some people claim that extending GiNaC is "unnecessary complex" (see e.g.
http://www.ginac.de/pipermail/ginac-list/2006-July/000882.html). So I
think it is good idea to provide self-contained, minimalistic example
of a GiNaC class. The actual code is copy/pasted from the tutorial.
---
doc/examples/Makefile.am | 3 +-
doc/examples/mystring.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++++
doc/tutorial/ginac.texi | 3 +-
3 files changed, 108 insertions(+), 2 deletions(-)
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am
index 5ee2c5d..e63da35 100644
--- a/doc/examples/Makefile.am
+++ b/doc/examples/Makefile.am
@@ -1,6 +1,7 @@
## Process this file with automake to produce Makefile.in
-EXFILES = archive1.cpp compile1.cpp compile2.cpp compile3.cpp lanczos.cpp
+EXFILES = archive1.cpp compile1.cpp compile2.cpp compile3.cpp lanczos.cpp \
+ mystring.cpp
TEXI = ginac-examples.texi
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
+#include
+#include
+using namespace std;
+
+#include
+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(&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(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= '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(e) << endl;
+ cout << ex_to(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 a6befad..b2038db 100644
--- a/doc/tutorial/ginac.texi
+++ b/doc/tutorial/ginac.texi
@@ -7823,7 +7823,8 @@ Now we will start implementing a new class @code{mystring} that allows
placing character strings in algebraic expressions (this is not very useful,
but it's just an example). This class will be a direct subclass of
@code{basic}. You can use this sample implementation as a starting point
-for your own classes.
+for your own classes @footnote{The self-contained source for this example is
+included in GiNaC, see the @file{doc/examples/mystring.cpp} file.}.
The code snippets given here assume that you have included some header files
as follows:
--
1.4.4.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Wed Sep 5 09:30:32 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Wed, 5 Sep 2007 11:30:32 +0400
Subject: [GiNaC-devel] [PATCH] improved CLN C++ code output
Message-ID: <20070905073032.GA425@theor.jinr.ru>
* small integers are printed as int (not as cl_I)
* no more ugly x+-y output
* powers always printed using cln::expt function.
Please note: this patch is for development branch only, since it breaks
binary compatibility (due to power::do_print_csrc_cl_N). I'll post
patches for GiNaC 1.[34] later.
---
ginac/add.cpp | 34 +++++++++++++++-------------------
ginac/numeric.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
ginac/power.cpp | 35 +++++++++++++++++++++--------------
ginac/power.h | 1 +
4 files changed, 83 insertions(+), 38 deletions(-)
diff --git a/ginac/add.cpp b/ginac/add.cpp
index b37ab79..98e8c79 100644
--- a/ginac/add.cpp
+++ b/ginac/add.cpp
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include "add.h"
#include "mul.h"
@@ -172,37 +173,32 @@ void add::do_print_csrc(const print_csrc & c, unsigned level) const
if (precedence() <= level)
c.s << "(";
- // Print arguments, separated by "+"
+ // Print arguments, separated by "+" or "-"
epvector::const_iterator it = seq.begin(), itend = seq.end();
+ char separator = ' ';
while (it != itend) {
- // If the coefficient is -1, it is replaced by a single minus sign
- if (it->coeff.is_equal(_ex1)) {
+ // If the coefficient is negative, separator is "-"
+ if (it->coeff.is_equal(_ex_1) ||
+ ex_to(it->coeff).numer().is_equal(*_num_1_p))
+ separator = '-';
+ c.s << separator;
+ if (it->coeff.is_equal(_ex1) || it->coeff.is_equal(_ex_1)) {
it->rest.print(c, precedence());
- } else if (it->coeff.is_equal(_ex_1)) {
- c.s << "-";
+ } else if (ex_to(it->coeff).numer().is_equal(*_num1_p) ||
+ ex_to(it->coeff).numer().is_equal(*_num_1_p))
+ {
it->rest.print(c, precedence());
- } else if (ex_to(it->coeff).numer().is_equal(*_num1_p)) {
- it->rest.print(c, precedence());
- c.s << "/";
- ex_to(it->coeff).denom().print(c, precedence());
- } else if (ex_to(it->coeff).numer().is_equal(*_num_1_p)) {
- c.s << "-";
- it->rest.print(c, precedence());
- c.s << "/";
+ c.s << '/';
ex_to(it->coeff).denom().print(c, precedence());
} else {
it->coeff.print(c, precedence());
- c.s << "*";
+ c.s << '*';
it->rest.print(c, precedence());
}
- // Separator is "+", except if the following expression would have a leading minus sign or the sign is sitting in parenthesis (as in a ctor)
++it;
- if (it != itend
- && (is_a(c) || !it->coeff.info(info_flags::real) // sign inside ctor arguments
- || !(it->coeff.info(info_flags::negative) || (it->coeff.is_equal(*_num1_p) && is_exactly_a(it->rest) && it->rest.info(info_flags::negative)))))
- c.s << "+";
+ separator = '+';
}
if (!overall_coeff.is_zero()) {
diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp
index ef61ce7..74f0e50 100644
--- a/ginac/numeric.cpp
+++ b/ginac/numeric.cpp
@@ -399,6 +399,38 @@ static void print_real_csrc(const print_context & c, const cln::cl_R & x)
}
}
+template
+static inline bool coerce(T1& dst, const T2& arg);
+
+/**
+ * @brief Check if CLN integer can be converted into int
+ *
+ * @sa http://www.ginac.de/pipermail/cln-list/2006-October/000248.html
+ */
+template<> static inline bool
+coerce(int& dst, const cln::cl_I& arg) {
+ static const cln::cl_I cl_max_int =
+ (cln::cl_I)(long)(std::numeric_limits::max());
+ static const cln::cl_I cl_min_int =
+ (cln::cl_I)(long)(std::numeric_limits::min());
+ if ((arg >= cl_min_int) && (arg <= cl_max_int)) {
+ dst = cl_I_to_int(arg);
+ return true;
+ }
+ return false;
+}
+
+template<> static inline bool
+coerce(unsigned int& dst, const cln::cl_I& arg) {
+ static const cln::cl_I cl_max_uint =
+ (cln::cl_I)(unsigned long)(std::numeric_limits::max());
+ if ((! minusp(arg)) && (arg <= cl_max_uint)) {
+ dst = cl_I_to_uint(arg);
+ return true;
+ }
+ return false;
+}
+
/** Helper function to print real number in C++ source format using cl_N types.
*
* @see numeric::print() */
@@ -406,11 +438,20 @@ static void print_real_cl_N(const print_context & c, const cln::cl_R & x)
{
if (cln::instanceof(x, cln::cl_I_ring)) {
- // Integer number
- c.s << "cln::cl_I(\"";
- print_real_number(c, x);
- c.s << "\")";
-
+ int dst;
+ // fixnum
+ if (coerce(dst, cln::the(x))) {
+ // can be converted to native int
+ if (dst < 0)
+ c.s << "(-" << dst << ")";
+ else
+ c.s << dst;
+ } else {
+ // bignum
+ c.s << "cln::cl_I(\"";
+ print_real_number(c, x);
+ c.s << "\")";
+ }
} else if (cln::instanceof(x, cln::cl_RA_ring)) {
// Rational number
diff --git a/ginac/power.cpp b/ginac/power.cpp
index faa0d05..68bec71 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -50,7 +50,8 @@ GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(power, basic,
print_func(&power::do_print_latex).
print_func(&power::do_print_csrc).
print_func(&power::do_print_python).
- print_func(&power::do_print_python_repr))
+ print_func(&power::do_print_python_repr).
+ print_func(&power::do_print_csrc_cl_N))
typedef std::vector intvector;
@@ -162,6 +163,21 @@ static void print_sym_pow(const print_context & c, const symbol &x, int exp)
}
}
+void power::do_print_csrc_cl_N(const print_csrc_cl_N& c, unsigned level) const
+{
+ if (exponent.is_equal(_ex_1)) {
+ c.s << "recip(";
+ basis.print(c);
+ c.s << ')';
+ return;
+ }
+ c.s << "expt(";
+ basis.print(c);
+ c.s << ", ";
+ exponent.print(c);
+ c.s << ')';
+}
+
void power::do_print_csrc(const print_csrc & c, unsigned level) const
{
// Integer powers of symbols are printed in a special, optimized way
@@ -172,29 +188,20 @@ void power::do_print_csrc(const print_csrc & c, unsigned level) const
c.s << '(';
else {
exp = -exp;
- if (is_a(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
}
print_sym_pow(c, ex_to(basis), exp);
c.s << ')';
// ^-1 is printed as "1.0/" or with the recip() function of CLN
} else if (exponent.is_equal(_ex_1)) {
- if (is_a(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
basis.print(c);
c.s << ')';
- // Otherwise, use the pow() or expt() (CLN) functions
+ // Otherwise, use the pow() function
} else {
- if (is_a(c))
- c.s << "expt(";
- else
- c.s << "pow(";
+ c.s << "pow(";
basis.print(c);
c.s << ',';
exponent.print(c);
diff --git a/ginac/power.h b/ginac/power.h
index f5e65d6..3375040 100644
--- a/ginac/power.h
+++ b/ginac/power.h
@@ -88,6 +88,7 @@ protected:
void do_print_csrc(const print_csrc & c, unsigned level) const;
void do_print_python(const print_python & c, unsigned level) const;
void do_print_python_repr(const print_python_repr & c, unsigned level) const;
+ void do_print_csrc_cl_N(const print_csrc_cl_N & c, unsigned level) const;
ex expand_add(const add & a, int n, unsigned options) const;
ex expand_add_2(const add & a, unsigned options) const;
--
1.4.4.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Wed Sep 5 10:41:51 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Wed, 5 Sep 2007 12:41:51 +0400
Subject: [GiNaC-devel]
[PATCH] Improved CLN C++ code output (print_csrc_cln), for GiNaC 1.4
In-Reply-To: <20070905073032.GA425@theor.jinr.ru>
Message-ID: <20070905084151.GA6743@theor.jinr.ru>
* small integers are printed as int (not as cl_I)
* no more ugly x+-y output
* powers always printed using cln::expt function.
---
ginac/add.cpp | 34 +++++++++++++++-------------------
ginac/numeric.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
ginac/power.cpp | 32 +++++++++++++++++++-------------
3 files changed, 80 insertions(+), 37 deletions(-)
diff --git a/ginac/add.cpp b/ginac/add.cpp
index b37ab79..98e8c79 100644
--- a/ginac/add.cpp
+++ b/ginac/add.cpp
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include "add.h"
#include "mul.h"
@@ -172,37 +173,32 @@ void add::do_print_csrc(const print_csrc & c, unsigned level) const
if (precedence() <= level)
c.s << "(";
- // Print arguments, separated by "+"
+ // Print arguments, separated by "+" or "-"
epvector::const_iterator it = seq.begin(), itend = seq.end();
+ char separator = ' ';
while (it != itend) {
- // If the coefficient is -1, it is replaced by a single minus sign
- if (it->coeff.is_equal(_ex1)) {
+ // If the coefficient is negative, separator is "-"
+ if (it->coeff.is_equal(_ex_1) ||
+ ex_to(it->coeff).numer().is_equal(*_num_1_p))
+ separator = '-';
+ c.s << separator;
+ if (it->coeff.is_equal(_ex1) || it->coeff.is_equal(_ex_1)) {
it->rest.print(c, precedence());
- } else if (it->coeff.is_equal(_ex_1)) {
- c.s << "-";
+ } else if (ex_to(it->coeff).numer().is_equal(*_num1_p) ||
+ ex_to(it->coeff).numer().is_equal(*_num_1_p))
+ {
it->rest.print(c, precedence());
- } else if (ex_to(it->coeff).numer().is_equal(*_num1_p)) {
- it->rest.print(c, precedence());
- c.s << "/";
- ex_to(it->coeff).denom().print(c, precedence());
- } else if (ex_to(it->coeff).numer().is_equal(*_num_1_p)) {
- c.s << "-";
- it->rest.print(c, precedence());
- c.s << "/";
+ c.s << '/';
ex_to(it->coeff).denom().print(c, precedence());
} else {
it->coeff.print(c, precedence());
- c.s << "*";
+ c.s << '*';
it->rest.print(c, precedence());
}
- // Separator is "+", except if the following expression would have a leading minus sign or the sign is sitting in parenthesis (as in a ctor)
++it;
- if (it != itend
- && (is_a(c) || !it->coeff.info(info_flags::real) // sign inside ctor arguments
- || !(it->coeff.info(info_flags::negative) || (it->coeff.is_equal(*_num1_p) && is_exactly_a(it->rest) && it->rest.info(info_flags::negative)))))
- c.s << "+";
+ separator = '+';
}
if (!overall_coeff.is_zero()) {
diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp
index ef61ce7..74f0e50 100644
--- a/ginac/numeric.cpp
+++ b/ginac/numeric.cpp
@@ -399,6 +399,38 @@ static void print_real_csrc(const print_context & c, const cln::cl_R & x)
}
}
+template
+static inline bool coerce(T1& dst, const T2& arg);
+
+/**
+ * @brief Check if CLN integer can be converted into int
+ *
+ * @sa http://www.ginac.de/pipermail/cln-list/2006-October/000248.html
+ */
+template<> static inline bool
+coerce(int& dst, const cln::cl_I& arg) {
+ static const cln::cl_I cl_max_int =
+ (cln::cl_I)(long)(std::numeric_limits::max());
+ static const cln::cl_I cl_min_int =
+ (cln::cl_I)(long)(std::numeric_limits::min());
+ if ((arg >= cl_min_int) && (arg <= cl_max_int)) {
+ dst = cl_I_to_int(arg);
+ return true;
+ }
+ return false;
+}
+
+template<> static inline bool
+coerce(unsigned int& dst, const cln::cl_I& arg) {
+ static const cln::cl_I cl_max_uint =
+ (cln::cl_I)(unsigned long)(std::numeric_limits::max());
+ if ((! minusp(arg)) && (arg <= cl_max_uint)) {
+ dst = cl_I_to_uint(arg);
+ return true;
+ }
+ return false;
+}
+
/** Helper function to print real number in C++ source format using cl_N types.
*
* @see numeric::print() */
@@ -406,11 +438,20 @@ static void print_real_cl_N(const print_context & c, const cln::cl_R & x)
{
if (cln::instanceof(x, cln::cl_I_ring)) {
- // Integer number
- c.s << "cln::cl_I(\"";
- print_real_number(c, x);
- c.s << "\")";
-
+ int dst;
+ // fixnum
+ if (coerce(dst, cln::the(x))) {
+ // can be converted to native int
+ if (dst < 0)
+ c.s << "(-" << dst << ")";
+ else
+ c.s << dst;
+ } else {
+ // bignum
+ c.s << "cln::cl_I(\"";
+ print_real_number(c, x);
+ c.s << "\")";
+ }
} else if (cln::instanceof(x, cln::cl_RA_ring)) {
// Rational number
diff --git a/ginac/power.cpp b/ginac/power.cpp
index faa0d05..b490b8c 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -164,6 +164,21 @@ static void print_sym_pow(const print_context & c, const symbol &x, int exp)
void power::do_print_csrc(const print_csrc & c, unsigned level) const
{
+ if (is_a(c)) {
+ if (exponent.is_equal(_ex_1)) {
+ c.s << "recip(";
+ basis.print(c);
+ c.s << ')';
+ return;
+ }
+ c.s << "expt(";
+ basis.print(c);
+ c.s << ", ";
+ exponent.print(c);
+ c.s << ')';
+ return;
+ }
+
// Integer powers of symbols are printed in a special, optimized way
if (exponent.info(info_flags::integer)
&& (is_a(basis) || is_a(basis))) {
@@ -172,29 +187,20 @@ void power::do_print_csrc(const print_csrc & c, unsigned level) const
c.s << '(';
else {
exp = -exp;
- if (is_a(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
}
print_sym_pow(c, ex_to(basis), exp);
c.s << ')';
// ^-1 is printed as "1.0/" or with the recip() function of CLN
} else if (exponent.is_equal(_ex_1)) {
- if (is_a(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
basis.print(c);
c.s << ')';
- // Otherwise, use the pow() or expt() (CLN) functions
+ // Otherwise, use the pow() function
} else {
- if (is_a(c))
- c.s << "expt(";
- else
- c.s << "pow(";
+ c.s << "pow(";
basis.print(c);
c.s << ',';
exponent.print(c);
--
1.4.4.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Wed Sep 5 10:43:06 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Wed, 5 Sep 2007 12:43:06 +0400
Subject: [GiNaC-devel] [PATCH] Improved CLN C++ code output (print_csrc_cln)
for GiNaC 1.3
In-Reply-To: <20070905073032.GA425@theor.jinr.ru>
Message-ID: <20070905084306.GA7007@theor.jinr.ru>
* small integers are printed as int (not as cl_I)
* no more ugly x+-y output
* powers always printed using cln::expt function.
---
ginac/add.cpp | 34 +++++++++++++++-------------------
ginac/numeric.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
ginac/power.cpp | 32 +++++++++++++++++++-------------
3 files changed, 80 insertions(+), 37 deletions(-)
diff --git a/ginac/add.cpp b/ginac/add.cpp
index 067f9bf..4fd10d9 100644
--- a/ginac/add.cpp
+++ b/ginac/add.cpp
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include "add.h"
#include "mul.h"
@@ -170,37 +171,32 @@ void add::do_print_csrc(const print_csrc & c, unsigned level) const
if (precedence() <= level)
c.s << "(";
- // Print arguments, separated by "+"
+ // Print arguments, separated by "+" or "-"
epvector::const_iterator it = seq.begin(), itend = seq.end();
+ char separator = ' ';
while (it != itend) {
- // If the coefficient is -1, it is replaced by a single minus sign
- if (it->coeff.is_equal(_ex1)) {
+ // If the coefficient is negative, separator is "-"
+ if (it->coeff.is_equal(_ex_1) ||
+ ex_to(it->coeff).numer().is_equal(*_num_1_p))
+ separator = '-';
+ c.s << separator;
+ if (it->coeff.is_equal(_ex1) || it->coeff.is_equal(_ex_1)) {
it->rest.print(c, precedence());
- } else if (it->coeff.is_equal(_ex_1)) {
- c.s << "-";
+ } else if (ex_to(it->coeff).numer().is_equal(*_num1_p) ||
+ ex_to(it->coeff).numer().is_equal(*_num_1_p))
+ {
it->rest.print(c, precedence());
- } else if (ex_to(it->coeff).numer().is_equal(*_num1_p)) {
- it->rest.print(c, precedence());
- c.s << "/";
- ex_to(it->coeff).denom().print(c, precedence());
- } else if (ex_to(it->coeff).numer().is_equal(*_num_1_p)) {
- c.s << "-";
- it->rest.print(c, precedence());
- c.s << "/";
+ c.s << '/';
ex_to(it->coeff).denom().print(c, precedence());
} else {
it->coeff.print(c, precedence());
- c.s << "*";
+ c.s << '*';
it->rest.print(c, precedence());
}
- // Separator is "+", except if the following expression would have a leading minus sign or the sign is sitting in parenthesis (as in a ctor)
++it;
- if (it != itend
- && (is_a(c) || !it->coeff.info(info_flags::real) // sign inside ctor arguments
- || !(it->coeff.info(info_flags::negative) || (it->coeff.is_equal(*_num1_p) && is_exactly_a(it->rest) && it->rest.info(info_flags::negative)))))
- c.s << "+";
+ separator = '+';
}
if (!overall_coeff.is_zero()) {
diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp
index 208a89c..7640670 100644
--- a/ginac/numeric.cpp
+++ b/ginac/numeric.cpp
@@ -399,6 +399,38 @@ static void print_real_csrc(const print_context & c, const cln::cl_R & x)
}
}
+template
+static inline bool coerce(T1& dst, const T2& arg);
+
+/**
+ * @brief Check if CLN integer can be converted into int
+ *
+ * @sa http://www.ginac.de/pipermail/cln-list/2006-October/000248.html
+ */
+template<> static inline bool
+coerce(int& dst, const cln::cl_I& arg) {
+ static const cln::cl_I cl_max_int =
+ (cln::cl_I)(long)(std::numeric_limits::max());
+ static const cln::cl_I cl_min_int =
+ (cln::cl_I)(long)(std::numeric_limits::min());
+ if ((arg >= cl_min_int) && (arg <= cl_max_int)) {
+ dst = cl_I_to_int(arg);
+ return true;
+ }
+ return false;
+}
+
+template<> static inline bool
+coerce(unsigned int& dst, const cln::cl_I& arg) {
+ static const cln::cl_I cl_max_uint =
+ (cln::cl_I)(unsigned long)(std::numeric_limits::max());
+ if ((! minusp(arg)) && (arg <= cl_max_uint)) {
+ dst = cl_I_to_uint(arg);
+ return true;
+ }
+ return false;
+}
+
/** Helper function to print real number in C++ source format using cl_N types.
*
* @see numeric::print() */
@@ -406,11 +438,20 @@ static void print_real_cl_N(const print_context & c, const cln::cl_R & x)
{
if (cln::instanceof(x, cln::cl_I_ring)) {
- // Integer number
- c.s << "cln::cl_I(\"";
- print_real_number(c, x);
- c.s << "\")";
-
+ int dst;
+ // fixnum
+ if (coerce(dst, cln::the(x))) {
+ // can be converted to native int
+ if (dst < 0)
+ c.s << "(-" << dst << ")";
+ else
+ c.s << dst;
+ } else {
+ // bignum
+ c.s << "cln::cl_I(\"";
+ print_real_number(c, x);
+ c.s << "\")";
+ }
} else if (cln::instanceof(x, cln::cl_RA_ring)) {
// Rational number
diff --git a/ginac/power.cpp b/ginac/power.cpp
index 4ebf0ac..f243147 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -164,6 +164,21 @@ static void print_sym_pow(const print_context & c, const symbol &x, int exp)
void power::do_print_csrc(const print_csrc & c, unsigned level) const
{
+ if (is_a(c)) {
+ if (exponent.is_equal(_ex_1)) {
+ c.s << "recip(";
+ basis.print(c);
+ c.s << ')';
+ return;
+ }
+ c.s << "expt(";
+ basis.print(c);
+ c.s << ", ";
+ exponent.print(c);
+ c.s << ')';
+ return;
+ }
+
// Integer powers of symbols are printed in a special, optimized way
if (exponent.info(info_flags::integer)
&& (is_a(basis) || is_a(basis))) {
@@ -172,29 +187,20 @@ void power::do_print_csrc(const print_csrc & c, unsigned level) const
c.s << '(';
else {
exp = -exp;
- if (is_a(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
}
print_sym_pow(c, ex_to(basis), exp);
c.s << ')';
// ^-1 is printed as "1.0/" or with the recip() function of CLN
} else if (exponent.is_equal(_ex_1)) {
- if (is_a(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
basis.print(c);
c.s << ')';
- // Otherwise, use the pow() or expt() (CLN) functions
+ // Otherwise, use the pow() function
} else {
- if (is_a(c))
- c.s << "expt(";
- else
- c.s << "pow(";
+ c.s << "pow(";
basis.print(c);
c.s << ',';
exponent.print(c);
--
1.4.4.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Wed Sep 5 15:07:36 2007
From: varg at theor.jinr.ru (Sheplyakov Alexei)
Date: Wed, 5 Sep 2007 17:07:36 +0400
Subject: [GiNaC-devel] Volunteer to continue the work on NTL factorisation
bindings
In-Reply-To: <200708281802.09118.R.Bloemen@student.utwente.nl>
References: <200708281802.09118.R.Bloemen@student.utwente.nl>
Message-ID: <20070905130736.GA25958@theor.jinr.ru>
Hello!
On Tue, Aug 28, 2007 at 06:02:08PM +0200, Remco Bloemen wrote:
> I have created a simple factorisation for polynomials in Q[x] with real roots
> (source attached, based on [2]) but it's really slow.
I _think_ there are two reasons for that. First, GiNaC::add and GiNaC::mul
are way to abstract to repersent polynomials (especially univariate ones)
efficiently. For example, this snippet of code
> if(is_exactly_a(poly))
> {
> ex result = 0;
> for (size_t i=0; i < poly.nops(); i++)
> {
> result += polymod2n(poly.op(i), n);
> }
> return result;
> }
involves N = poly.nops() calls to add.eval(), each of them is O(N).
poly.op(i) is O(N) too. So, you'd better use std::vector to represent
univariate polynomials:
void mod2n(std::vector& result, std::vector& poly,
const unsigned int n)
{
result.reserve(poly.size());
cln::cl_modint_ring R(cln::cl_I(1) << n);
for (std::size_t i = 0; i < poly.size(); ++i)
result.push_back(R.canonhom(poly[i]));
}
Secondly, your implementation of mod 2^n arithmetic is really
far from optimal.
> numeric mod2n(const numeric &p, const int n)
> {
> numeric modulus = pow(numeric(2), numeric(n));
> return mod(p, modulus);
> }
Operations on mod 2^n integers and polynomials can (and should) be done
using bit shifts (a very fast operation). Actually this is why yacas (and some
other software) use them in first place. So, it should be
static inline const cln::cl_MI mod2n(const cln::cl_I& p, const unsigned int n)
{
cln::cl_modint_ring R(cln::cl_I(1) << n);
return R.canonhom(p);
}
> Creating a reasonable implementation would require much work.
Sure.
> An NTL based implementation would be very powerfull and feasible, as said in
> [1]. I would like to volunteer to continue this work.
IMHO, using two different bignum libraries and converting expressions (and
numbers) between them is a bad idea. Much better option is to port NTL's
algorithms to CLN.
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From remco.bloemen at gmail.com Thu Sep 6 14:20:08 2007
From: remco.bloemen at gmail.com (Remco Bloemen)
Date: Thu, 6 Sep 2007 14:20:08 +0200
Subject: [GiNaC-devel] Volunteer to continue the work on NTL factorisation
bindings
In-Reply-To: <20070905130736.GA25958@theor.jinr.ru>
References: <200708281802.09118.R.Bloemen@student.utwente.nl>
<20070905130736.GA25958@theor.jinr.ru>
Message-ID: <200709061420.08784.R.Bloemen@student.utwente.nl>
Alexei,
First of all, thank you very much for looking at my code and giving good
pointers! It really makes a newcomer feel appreciated.
On Wednesday 05 September 2007 15:07:36 Sheplyakov Alexei wrote:
> On Tue, Aug 28, 2007 at 06:02:08PM +0200, Remco Bloemen wrote:
> > I have created a simple factorisation for polynomials in Q[x] with real
> > roots (source attached, based on [2]) but it's really slow.
>
> I _think_ there are two reasons for that. First, GiNaC::add and GiNaC::mul
> are way to abstract to repersent polynomials (especially univariate ones)
> efficiently.
Your suggestion of using std::vector was already on my mind, I will certainly
implement it. It's just that I wanted to evaluate the NTL way before I would
spent time improving my own humble factorizer.
> Secondly, your implementation of mod 2^n arithmetic is really
> far from optimal.
Yes, I am aware of that. I wrote the *2n functions as a temporary solution,
mainly because I did not know how to do it efficiently using CLN. Your
examples teach me that this can be easily done.
> > An NTL based implementation would be very powerfull and feasible, as said
> > in [1]. I would like to volunteer to continue this work.
>
> IMHO, using two different bignum libraries and converting expressions (and
> numbers) between them is a bad idea. Much better option is to port NTL's
> algorithms to CLN.
I also looked at Singular and I came to the same conclusion that it would be
best to port the algorithms. The main reasons was that NTL only supports
univariate integer factorization and that is only a fairly small (though
performance-wise important) part of full multivariate polynomial
factorization over extension fields.
Kind regards,
Remco
From varg at theor.jinr.ru Mon Sep 17 15:15:03 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 17:15:03 +0400
Subject: [GiNaC-devel] Restore the speed of polynomial operations.
Message-ID:
Hello!
These patches
commit 0633ed8082961673eedc092689e06fa39d6bc322
Author: Jens Vollinga
Date: Thu May 19 18:10:40 2005 +0000
Fixed bug in expanding expressions containing dummy indices. [V.Kisil]
(see )
commit 6b1b11264fe4872132fef8cb8b22cb983ba01736
Author: Chris Dams
Date: Thu Jul 13 20:02:38 2006 +0000
Needed to call get_all_dummy_indices_safely more often.
(see http://www.ginac.de/pipermail/ginac-cvs/2006-July/001780.html)
commit 4cf53676d7823ec3c55a90df7723f7f1492a95b2
Author: Chris Dams
Date: Mon Jul 24 16:47:43 2006 +0000
Improved dummy index renaming.
(see http://www.ginac.de/pipermail/ginac-cvs/2006-July/001782.html)
made polynomial operations (in particular expand()) substantially slower.
For example, Fateman's polynomial expanding benchark degraded from 32sec.
to 80sec. My own code which uses multivariate GCD (which in turn uses
.expand() extensively) become 4x slower.
I'll post 4 patches which address the issue in reply to this message.
Comments, questions, suggestions, etc. are wellcome.
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 15:18:24 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 17:18:24 +0400
Subject: [GiNaC-devel] [PATCH 1/4] Improve info(info_flags::has_indices),
introduce flags to cache the result.
In-Reply-To:
References:
Message-ID:
info(info_flags::has_indices) now works for sums and products. It
returns true if the expression has indices (no matter dummy or free),
and false otherwise.
---
ginac/expairseq.cpp | 23 +++++++++++++++++++++--
ginac/flags.h | 4 +++-
ginac/idx.cpp | 7 +++++--
ginac/power.cpp | 15 +++++++++++++++
ginac/symbol.cpp | 35 +++++++++++++++++++----------------
5 files changed, 63 insertions(+), 21 deletions(-)
diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp
index 757f3c3..79c741a 100644
--- a/ginac/expairseq.cpp
+++ b/ginac/expairseq.cpp
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include "expairseq.h"
#include "lst.h"
@@ -267,8 +268,26 @@ void expairseq::do_print_tree(const print_tree & c, unsigned level) const
bool expairseq::info(unsigned inf) const
{
- if (inf == info_flags::expanded)
- return (flags & status_flags::expanded);
+ switch(inf) {
+ case info_flags::expanded:
+ return (flags & status_flags::expanded);
+ case info_flags::has_indices: {
+ if (flags & status_flags::has_indices)
+ return true;
+ else if (flags & status_flags::has_no_indices)
+ return false;
+ for (epvector::const_iterator i = seq.begin(); i != seq.end(); ++i) {
+ if (i->rest.info(info_flags::has_indices)) {
+ this->setflag(status_flags::has_indices);
+ this->clearflag(status_flags::has_no_indices);
+ return true;
+ }
+ }
+ this->clearflag(status_flags::has_indices);
+ this->setflag(status_flags::has_no_indices);
+ return false;
+ }
+ }
return inherited::info(inf);
}
diff --git a/ginac/flags.h b/ginac/flags.h
index 86d8238..372b899 100644
--- a/ginac/flags.h
+++ b/ginac/flags.h
@@ -193,7 +193,9 @@ public:
evaluated = 0x0002, ///< .eval() has already done its job
expanded = 0x0004, ///< .expand(0) has already done its job (other expand() options ignore this flag)
hash_calculated = 0x0008, ///< .calchash() has already done its job
- not_shareable = 0x0010 ///< don't share instances of this object between different expressions unless explicitly asked to (used by ex::compare())
+ not_shareable = 0x0010, ///< don't share instances of this object between different expressions unless explicitly asked to (used by ex::compare())
+ has_indices = 0x0020,
+ has_no_indices = 0x0040 // ! (has_indices || has_no_indices) means "don't know"
};
};
diff --git a/ginac/idx.cpp b/ginac/idx.cpp
index 3e17569..e966b14 100644
--- a/ginac/idx.cpp
+++ b/ginac/idx.cpp
@@ -234,8 +234,11 @@ void spinidx::do_print_tree(const print_tree & c, unsigned level) const
bool idx::info(unsigned inf) const
{
- if (inf == info_flags::idx)
- return true;
+ switch(inf) {
+ case info_flags::idx:
+ case info_flags::has_indices:
+ return true;
+ }
return inherited::info(inf);
}
diff --git a/ginac/power.cpp b/ginac/power.cpp
index b490b8c..fe7132a 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -240,6 +240,21 @@ bool power::info(unsigned inf) const
basis.info(inf);
case info_flags::expanded:
return (flags & status_flags::expanded);
+ case info_flags::has_indices: {
+ if (flags & status_flags::has_indices)
+ return true;
+ else if (flags & status_flags::has_no_indices)
+ return false;
+ else if (basis.info(info_flags::has_indices)) {
+ setflag(status_flags::has_indices);
+ clearflag(status_flags::has_no_indices);
+ return true;
+ } else {
+ clearflag(status_flags::has_indices);
+ setflag(status_flags::has_no_indices);
+ return false;
+ }
+ }
}
return inherited::info(inf);
}
diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp
index 9f3b1c6..b68fed8 100644
--- a/ginac/symbol.cpp
+++ b/ginac/symbol.cpp
@@ -207,22 +207,25 @@ void symbol::do_print_python_repr(const print_python_repr & c, unsigned level) c
bool symbol::info(unsigned inf) const
{
- 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 ||
- inf == info_flags::expanded)
- return true;
- if (inf == info_flags::real)
- return domain==domain::real || domain==domain::positive;
- if (inf == info_flags::positive || inf == info_flags::nonnegative)
- return domain == domain::positive;
- else
- return inherited::info(inf);
+ switch (inf) {
+ case info_flags::symbol:
+ case info_flags::polynomial:
+ case info_flags::integer_polynomial:
+ case info_flags::cinteger_polynomial:
+ case info_flags::rational_polynomial:
+ case info_flags::crational_polynomial:
+ case info_flags::rational_function:
+ case info_flags::expanded:
+ return true;
+ case info_flags::real:
+ return domain == domain::real || domain == domain::positive;
+ case info_flags::positive:
+ case info_flags::nonnegative:
+ return domain == domain::positive;
+ case info_flags::has_indices:
+ return false;
+ }
+ return inherited::info(inf);
}
ex symbol::eval(int level) const
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 15:19:40 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 17:19:40 +0400
Subject: [GiNaC-devel] [PATCH 2/4] Tell mul::expand() to not
rename_indices_... if object has no indices at all.
In-Reply-To:
References:
Message-ID: <6770460ca07bbe2af9d49d6d1c2f8a17237f791e.1190034683.git.varg@theor.jinr.ru>
Patially solves performance regression in expand(), gcd(), etc.
---
ginac/mul.cpp | 56 ++++++++++++++++++++++++++++++++++----------------------
1 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/ginac/mul.cpp b/ginac/mul.cpp
index 9ed27c6..db8b9f1 100644
--- a/ginac/mul.cpp
+++ b/ginac/mul.cpp
@@ -992,6 +992,7 @@ bool mul::can_be_further_expanded(const ex & e)
ex mul::expand(unsigned options) const
{
+ const bool skip_idx_rename = ! info(info_flags::has_indices);
// First, expand the children
std::auto_ptr expanded_seqp = expandchildren(options);
const epvector & expanded_seq = (expanded_seqp.get() ? *expanded_seqp : seq);
@@ -1047,28 +1048,34 @@ ex mul::expand(unsigned options) const
ex tmp_accu = (new add(distrseq, add1.overall_coeff*add2.overall_coeff))->setflag(status_flags::dynallocated);
exvector add1_dummy_indices, add2_dummy_indices, add_indices;
+ lst dummy_subs;
- for (epvector::const_iterator i=add1begin; i!=add1end; ++i) {
- add_indices = get_all_dummy_indices_safely(i->rest);
- add1_dummy_indices.insert(add1_dummy_indices.end(), add_indices.begin(), add_indices.end());
- }
- for (epvector::const_iterator i=add2begin; i!=add2end; ++i) {
- add_indices = get_all_dummy_indices_safely(i->rest);
- add2_dummy_indices.insert(add2_dummy_indices.end(), add_indices.begin(), add_indices.end());
- }
+ if (!skip_idx_rename) {
+ for (epvector::const_iterator i=add1begin; i!=add1end; ++i) {
+ add_indices = get_all_dummy_indices_safely(i->rest);
+ add1_dummy_indices.insert(add1_dummy_indices.end(), add_indices.begin(), add_indices.end());
+ }
+ for (epvector::const_iterator i=add2begin; i!=add2end; ++i) {
+ add_indices = get_all_dummy_indices_safely(i->rest);
+ add2_dummy_indices.insert(add2_dummy_indices.end(), add_indices.begin(), add_indices.end());
+ }
- sort(add1_dummy_indices.begin(), add1_dummy_indices.end(), ex_is_less());
- sort(add2_dummy_indices.begin(), add2_dummy_indices.end(), ex_is_less());
- lst dummy_subs = rename_dummy_indices_uniquely(add1_dummy_indices, add2_dummy_indices);
+ sort(add1_dummy_indices.begin(), add1_dummy_indices.end(), ex_is_less());
+ sort(add2_dummy_indices.begin(), add2_dummy_indices.end(), ex_is_less());
+ dummy_subs = rename_dummy_indices_uniquely(add1_dummy_indices, add2_dummy_indices);
+ }
// Multiply explicitly all non-numeric terms of add1 and add2:
for (epvector::const_iterator i2=add2begin; i2!=add2end; ++i2) {
// We really have to combine terms here in order to compactify
// the result. Otherwise it would become waayy tooo bigg.
- numeric oc;
- distrseq.clear();
- ex i2_new = (dummy_subs.op(0).nops()>0?
- i2->rest.subs((lst)dummy_subs.op(0), (lst)dummy_subs.op(1), subs_options::no_pattern) : i2->rest);
+ numeric oc(*_num0_p);
+ epvector distrseq2;
+ distrseq2.reserve(add1.seq.size());
+ const ex i2_new = (skip_idx_rename || (dummy_subs.op(0).nops() == 0) ?
+ i2->rest :
+ i2->rest.subs(ex_to(dummy_subs.op(0)),
+ ex_to(dummy_subs.op(1)), subs_options::no_pattern));
for (epvector::const_iterator i1=add1begin; i1!=add1end; ++i1) {
// Don't push_back expairs which might have a rest that evaluates to a numeric,
// since that would violate an invariant of expairseq:
@@ -1076,13 +1083,12 @@ ex mul::expand(unsigned options) const
if (is_exactly_a(rest)) {
oc += ex_to(rest).mul(ex_to(i1->coeff).mul(ex_to(i2->coeff)));
} else {
- distrseq.push_back(expair(rest, ex_to(i1->coeff).mul_dyn(ex_to(i2->coeff))));
+ distrseq2.push_back(expair(rest, ex_to(i1->coeff).mul_dyn(ex_to(i2->coeff))));
}
}
- tmp_accu += (new add(distrseq, oc))->setflag(status_flags::dynallocated);
- }
+ tmp_accu += (new add(distrseq2, oc))->setflag(status_flags::dynallocated);
+ }
last_expanded = tmp_accu;
-
} else {
if (!last_expanded.is_equal(_ex1))
non_adds.push_back(split_ex_to_pair(last_expanded));
@@ -1100,12 +1106,18 @@ ex mul::expand(unsigned options) const
size_t n = last_expanded.nops();
exvector distrseq;
distrseq.reserve(n);
- exvector va = get_all_dummy_indices_safely(mul(non_adds));
- sort(va.begin(), va.end(), ex_is_less());
+ exvector va;
+ if (! skip_idx_rename) {
+ va = get_all_dummy_indices_safely(mul(non_adds));
+ sort(va.begin(), va.end(), ex_is_less());
+ }
for (size_t i=0; isetflag(status_flags::dynallocated);
if (can_be_further_expanded(term)) {
distrseq.push_back(term.expand());
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 15:21:42 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 17:21:42 +0400
Subject: [GiNaC-devel] [PATCH 3/4] {mul,
power}::expand: expand monomials faster.
In-Reply-To:
References:
Message-ID: <8678cf40b17a9fffcadeb20b7b60154461b78968.1190034683.git.varg@theor.jinr.ru>
Apparently, in ~ 30% of calls to mul::expand the expression is monomial.
Expanding monomials should be done as fast as possible.
---
ginac/mul.cpp | 10 ++++++++++
ginac/power.cpp | 3 +++
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/ginac/mul.cpp b/ginac/mul.cpp
index db8b9f1..298715b 100644
--- a/ginac/mul.cpp
+++ b/ginac/mul.cpp
@@ -34,6 +34,7 @@
#include "lst.h"
#include "archive.h"
#include "utils.h"
+#include "symbol.h"
#include "compiler.h"
namespace GiNaC {
@@ -992,6 +993,15 @@ bool mul::can_be_further_expanded(const ex & e)
ex mul::expand(unsigned options) const
{
+ {
+ // trivial case: expanding the monomial (~ 30% of all calls)
+ epvector::const_iterator i = seq.begin(), seq_end = seq.end();
+ while ((i != seq.end()) && is_a(i->rest) && i->coeff.info(info_flags::integer))
+ ++i;
+ if (i == seq_end)
+ return (new mul(*this))->setflag(status_flags::dynallocated | status_flags::expanded);
+ }
+
const bool skip_idx_rename = ! info(info_flags::has_indices);
// First, expand the children
std::auto_ptr expanded_seqp = expandchildren(options);
diff --git a/ginac/power.cpp b/ginac/power.cpp
index fe7132a..cc003bc 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -771,6 +771,9 @@ tinfo_t power::return_type_tinfo() const
ex power::expand(unsigned options) const
{
+ if (is_a(basis) && exponent.info(info_flags::integer))
+ return (new power(*this))->setflag(status_flags::dynallocated | status_flags::expanded);
+
if (options == 0 && (flags & status_flags::expanded))
return *this;
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 15:24:25 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 17:24:25 +0400
Subject: [GiNaC-devel] [PATCH 4/4] introduce
expand_options::expand_idx_rename and use it in mul::expand().
In-Reply-To:
References:
Message-ID:
This helps mul::expand() and friends to recognize objects which have
no indices at all.
---
ginac/flags.h | 3 ++-
ginac/mul.cpp | 8 +++++++-
ginac/power.cpp | 7 ++++++-
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/ginac/flags.h b/ginac/flags.h
index 372b899..39a2113 100644
--- a/ginac/flags.h
+++ b/ginac/flags.h
@@ -30,7 +30,8 @@ class expand_options {
public:
enum {
expand_indexed = 0x0001, ///< expands (a+b).i to a.i+b.i
- expand_function_args = 0x0002 ///< expands the arguments of functions
+ expand_function_args = 0x0002, ///< expands the arguments of functions
+ expand_rename_idx = 0x0004 ///< used internally by mul::expand()
};
};
diff --git a/ginac/mul.cpp b/ginac/mul.cpp
index 298715b..4e95a63 100644
--- a/ginac/mul.cpp
+++ b/ginac/mul.cpp
@@ -1002,7 +1002,13 @@ ex mul::expand(unsigned options) const
return (new mul(*this))->setflag(status_flags::dynallocated | status_flags::expanded);
}
- const bool skip_idx_rename = ! info(info_flags::has_indices);
+ // do not rename indices if the object has no indices at all
+ if ((!(options & expand_options::expand_rename_idx)) &&
+ this->info(info_flags::has_indices))
+ options |= expand_options::expand_rename_idx;
+
+ const bool skip_idx_rename = !(options & expand_options::expand_rename_idx);
+
// First, expand the children
std::auto_ptr expanded_seqp = expandchildren(options);
const epvector & expanded_seq = (expanded_seqp.get() ? *expanded_seqp : seq);
diff --git a/ginac/power.cpp b/ginac/power.cpp
index cc003bc..7d909e8 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -1009,8 +1009,13 @@ ex power::expand_mul(const mul & m, const numeric & n, unsigned options, bool fr
return _ex1;
}
+ // do not bother to rename indices if there are no any.
+ if ((!(options & expand_options::expand_rename_idx))
+ && m.info(info_flags::has_indices))
+ options |= expand_options::expand_rename_idx;
// Leave it to multiplication since dummy indices have to be renamed
- if (get_all_dummy_indices(m).size() > 0 && n.is_positive()) {
+ if ((options & expand_options::expand_rename_idx) &&
+ (get_all_dummy_indices(m).size() > 0) && n.is_positive()) {
ex result = m;
exvector va = get_all_dummy_indices(m);
sort(va.begin(), va.end(), ex_is_less());
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 15:50:22 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 17:50:22 +0400
Subject: [GiNaC-devel] [PATCH] Apparently mul ctors do index renaming too.
Fix them also.
In-Reply-To:
References:
Message-ID:
Do not bother to rename indices if object has no indices at all.
---
ginac/expairseq.cpp | 15 ++++++++++++---
1 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp
index 79c741a..788f783 100644
--- a/ginac/expairseq.cpp
+++ b/ginac/expairseq.cpp
@@ -812,8 +812,8 @@ void expairseq::construct_from_2_ex(const ex &lh, const ex &rh)
construct_from_2_ex_via_exvector(lh,rh);
} else {
#endif // EXPAIRSEQ_USE_HASHTAB
- if(is_a(lh))
- {
+ if (is_a(lh) && lh.info(info_flags::has_indices) &&
+ rh.info(info_flags::has_indices)) {
ex newrh=rename_dummy_indices_uniquely(lh, rh);
construct_from_2_expairseq(ex_to(lh),
ex_to(newrh));
@@ -1057,6 +1057,7 @@ void expairseq::make_flat(const exvector &v)
// and their cumulative number of operands
int nexpairseqs = 0;
int noperands = 0;
+ bool do_idx_rename = false;
cit = v.begin();
while (cit!=v.end()) {
@@ -1064,6 +1065,9 @@ void expairseq::make_flat(const exvector &v)
++nexpairseqs;
noperands += ex_to(*cit).seq.size();
}
+ if (is_a(*this) && (!do_idx_rename) &&
+ cit->info(info_flags::has_indices))
+ do_idx_rename = true;
++cit;
}
@@ -1071,7 +1075,7 @@ void expairseq::make_flat(const exvector &v)
seq.reserve(v.size()+noperands-nexpairseqs);
// copy elements and split off numerical part
- make_flat_inserter mf(v, this->tinfo() == &mul::tinfo_static);
+ make_flat_inserter mf(v, do_idx_rename);
cit = v.begin();
while (cit!=v.end()) {
if (ex_to(*cit).tinfo()==this->tinfo()) {
@@ -1105,6 +1109,7 @@ void expairseq::make_flat(const epvector &v, bool do_index_renaming)
// and their cumulative number of operands
int nexpairseqs = 0;
int noperands = 0;
+ bool really_need_rename_inds = false;
cit = v.begin();
while (cit!=v.end()) {
@@ -1112,8 +1117,12 @@ void expairseq::make_flat(const epvector &v, bool do_index_renaming)
++nexpairseqs;
noperands += ex_to(cit->rest).seq.size();
}
+ if ((!really_need_rename_inds) && is_a(*this) &&
+ cit->rest.info(info_flags::has_indices))
+ really_need_rename_inds = true;
++cit;
}
+ do_index_renaming = do_index_renaming && really_need_rename_inds;
// reserve seq and coeffseq which will hold all operands
seq.reserve(v.size()+noperands-nexpairseqs);
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 17:02:29 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 19:02:29 +0400
Subject: [GiNaC-devel] [PATCH 1/5,
GiNaC 1.3] Improve info(info_flags::has_indices),
introduce flags to cache the result.
In-Reply-To:
References:
Message-ID:
This is the similar set of patches for GiNaC 1.3
---
ginac/expairseq.cpp | 23 +++++++++++++++++++++--
ginac/flags.h | 4 +++-
ginac/idx.cpp | 7 +++++--
ginac/power.cpp | 15 +++++++++++++++
ginac/symbol.cpp | 30 ++++++++++++++++--------------
5 files changed, 60 insertions(+), 19 deletions(-)
diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp
index be8790f..97cf961 100644
--- a/ginac/expairseq.cpp
+++ b/ginac/expairseq.cpp
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include "expairseq.h"
#include "lst.h"
@@ -261,8 +262,26 @@ void expairseq::do_print_tree(const print_tree & c, unsigned level) const
bool expairseq::info(unsigned inf) const
{
- if (inf == info_flags::expanded)
- return (flags & status_flags::expanded);
+ switch(inf) {
+ case info_flags::expanded:
+ return (flags & status_flags::expanded);
+ case info_flags::has_indices: {
+ if (flags & status_flags::has_indices)
+ return true;
+ else if (flags & status_flags::has_no_indices)
+ return false;
+ for (epvector::const_iterator i = seq.begin(); i != seq.end(); ++i) {
+ if (i->rest.info(info_flags::has_indices)) {
+ this->setflag(status_flags::has_indices);
+ this->clearflag(status_flags::has_no_indices);
+ return true;
+ }
+ }
+ this->clearflag(status_flags::has_indices);
+ this->setflag(status_flags::has_no_indices);
+ return false;
+ }
+ }
return inherited::info(inf);
}
diff --git a/ginac/flags.h b/ginac/flags.h
index a42f869..33622f9 100644
--- a/ginac/flags.h
+++ b/ginac/flags.h
@@ -179,7 +179,9 @@ public:
evaluated = 0x0002, ///< .eval() has already done its job
expanded = 0x0004, ///< .expand(0) has already done its job (other expand() options ignore this flag)
hash_calculated = 0x0008, ///< .calchash() has already done its job
- not_shareable = 0x0010 ///< don't share instances of this object between different expressions unless explicitly asked to (used by ex::compare())
+ not_shareable = 0x0010, ///< don't share instances of this object between different expressions unless explicitly asked to (used by ex::compare())
+ has_indices = 0x0020,
+ has_no_indices = 0x0040 // ! (has_indices || has_no_indices) means "don't know"
};
};
diff --git a/ginac/idx.cpp b/ginac/idx.cpp
index 3d363e0..601a77c 100644
--- a/ginac/idx.cpp
+++ b/ginac/idx.cpp
@@ -232,8 +232,11 @@ void spinidx::do_print_tree(const print_tree & c, unsigned level) const
bool idx::info(unsigned inf) const
{
- if (inf == info_flags::idx)
- return true;
+ switch(inf) {
+ case info_flags::idx:
+ case info_flags::has_indices:
+ return true;
+ }
return inherited::info(inf);
}
diff --git a/ginac/power.cpp b/ginac/power.cpp
index f243147..676b862 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -240,6 +240,21 @@ bool power::info(unsigned inf) const
basis.info(inf);
case info_flags::expanded:
return (flags & status_flags::expanded);
+ case info_flags::has_indices: {
+ if (flags & status_flags::has_indices)
+ return true;
+ else if (flags & status_flags::has_no_indices)
+ return false;
+ else if (basis.info(info_flags::has_indices)) {
+ setflag(status_flags::has_indices);
+ clearflag(status_flags::has_no_indices);
+ return true;
+ } else {
+ clearflag(status_flags::has_indices);
+ setflag(status_flags::has_no_indices);
+ return false;
+ }
+ }
}
return inherited::info(inf);
}
diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp
index 2edd714..0e51f0e 100644
--- a/ginac/symbol.cpp
+++ b/ginac/symbol.cpp
@@ -190,20 +190,22 @@ void symbol::do_print_python_repr(const print_python_repr & c, unsigned level) c
bool symbol::info(unsigned inf) const
{
- 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 ||
- inf == info_flags::expanded)
- return true;
- if (inf == info_flags::real)
- return domain == domain::real;
- else
- return inherited::info(inf);
+ switch (inf) {
+ case info_flags::symbol:
+ case info_flags::polynomial:
+ case info_flags::integer_polynomial:
+ case info_flags::cinteger_polynomial:
+ case info_flags::rational_polynomial:
+ case info_flags::crational_polynomial:
+ case info_flags::rational_function:
+ case info_flags::expanded:
+ return true;
+ case info_flags::has_indices:
+ return false;
+ case info_flags::real:
+ return domain == domain::real;
+ }
+ return inherited::info(inf);
}
ex symbol::eval(int level) const
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 17:03:00 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 19:03:00 +0400
Subject: [GiNaC-devel] [PATCH 2/5,
GiNaC 1.3] Tell mul::expand() to not rename indices
if the product has no indices at all.
In-Reply-To:
References:
Message-ID:
---
ginac/mul.cpp | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/ginac/mul.cpp b/ginac/mul.cpp
index 3c87d5a..5176218 100644
--- a/ginac/mul.cpp
+++ b/ginac/mul.cpp
@@ -940,6 +940,7 @@ bool mul::can_be_further_expanded(const ex & e)
ex mul::expand(unsigned options) const
{
+ const bool skip_idx_rename = ! info(info_flags::has_indices);
// First, expand the children
std::auto_ptr expanded_seqp = expandchildren(options);
const epvector & expanded_seq = (expanded_seqp.get() ? *expanded_seqp : seq);
@@ -1003,7 +1004,7 @@ ex mul::expand(unsigned options) const
for (epvector::const_iterator i2=add2begin; i2!=add2end; ++i2) {
// Don't push_back expairs which might have a rest that evaluates to a numeric,
// since that would violate an invariant of expairseq:
- const ex rest = (new mul(i1->rest, rename_dummy_indices_uniquely(i1->rest, i2->rest)))->setflag(status_flags::dynallocated);
+ const ex rest = (new mul(i1->rest, skip_idx_rename ? i2->rest : rename_dummy_indices_uniquely(i1->rest, i2->rest)))->setflag(status_flags::dynallocated);
if (is_exactly_a(rest)) {
oc += ex_to(rest).mul(ex_to(i1->coeff).mul(ex_to(i2->coeff)));
} else {
@@ -1034,7 +1035,10 @@ ex mul::expand(unsigned options) const
for (size_t i=0; isetflag(status_flags::dynallocated);
if (can_be_further_expanded(term)) {
distrseq.push_back(term.expand());
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 17:03:27 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 19:03:27 +0400
Subject: [GiNaC-devel] [PATCH 3/5,
GiNaC 1.3] power::expand_mul: do not try to rename
indices if the object has no indices at all.
In-Reply-To:
References:
Message-ID:
---
ginac/power.cpp | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/ginac/power.cpp b/ginac/power.cpp
index 676b862..bbcb453 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -916,7 +916,7 @@ ex power::expand_mul(const mul & m, const numeric & n, unsigned options, bool fr
}
// Leave it to multiplication since dummy indices have to be renamed
- if (get_all_dummy_indices(m).size() > 0 && n.is_positive()) {
+ if (m.info(info_flags::has_indices) && (get_all_dummy_indices(m).size() > 0) && n.is_positive()) {
ex result = m;
for (int i=1; i < n.to_int(); i++)
result *= rename_dummy_indices_uniquely(m,m);
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 17:04:01 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 19:04:01 +0400
Subject: [GiNaC-devel] [PATCH 4/5, GiNaC 1.3] {mul,
power}::expand: expand monomials faster.
In-Reply-To:
References:
Message-ID:
---
ginac/mul.cpp | 12 ++++++++++++
ginac/power.cpp | 3 +++
2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/ginac/mul.cpp b/ginac/mul.cpp
index 5176218..d6ff7cb 100644
--- a/ginac/mul.cpp
+++ b/ginac/mul.cpp
@@ -34,6 +34,7 @@
#include "lst.h"
#include "archive.h"
#include "utils.h"
+#include "symbol.h"
#include "compiler.h"
namespace GiNaC {
@@ -940,7 +941,18 @@ bool mul::can_be_further_expanded(const ex & e)
ex mul::expand(unsigned options) const
{
+ {
+ // trivial case: expanding the monomial (~ 30% of all calls)
+ epvector::const_iterator i = seq.begin(), seq_end = seq.end();
+ while ((i != seq.end()) && is_a(i->rest) && i->coeff.info(info_flags::integer))
+ ++i;
+ if (i == seq_end)
+ return (new mul(*this))->setflag(status_flags::dynallocated | status_flags::expanded);
+ }
+
const bool skip_idx_rename = ! info(info_flags::has_indices);
+ if (skip_idx_rename)
+ ++(mul_expand_stats::n_indexless);
// First, expand the children
std::auto_ptr expanded_seqp = expandchildren(options);
const epvector & expanded_seq = (expanded_seqp.get() ? *expanded_seqp : seq);
diff --git a/ginac/power.cpp b/ginac/power.cpp
index bbcb453..010af6c 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -680,6 +680,9 @@ unsigned power::return_type_tinfo() const
ex power::expand(unsigned options) const
{
+ if (is_a(basis) && exponent.info(info_flags::integer))
+ return (new power(*this))->setflag(status_flags::dynallocated | status_flags::expanded);
+
if (options == 0 && (flags & status_flags::expanded))
return *this;
--
1.5.2.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From varg at theor.jinr.ru Mon Sep 17 17:05:24 2007
From: varg at theor.jinr.ru (Alexei Sheplyakov)
Date: Mon, 17 Sep 2007 19:05:24 +0400
Subject: [GiNaC-devel] [PATCH 5/5, GiNaC 1.3] introduce
expand_options::expand_idx_rename and use it in mul::expand().
In-Reply-To:
References:
Message-ID:
Helps to avoid useless (and expansive) rename_dummy_indices_uniquely().
---
ginac/flags.h | 3 ++-
ginac/mul.cpp | 10 +++++++---
ginac/power.cpp | 7 ++++++-
3 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/ginac/flags.h b/ginac/flags.h
index 33622f9..478da32 100644
--- a/ginac/flags.h
+++ b/ginac/flags.h
@@ -30,7 +30,8 @@ class expand_options {
public:
enum {
expand_indexed = 0x0001, ///< expands (a+b).i to a.i+b.i
- expand_function_args = 0x0002 ///< expands the arguments of functions
+ expand_function_args = 0x0002, ///< expands the arguments of functions
+ expand_rename_idx = 0x0004 ///< used internally by mul::expand()
};
};
diff --git a/ginac/mul.cpp b/ginac/mul.cpp
index d6ff7cb..b7e0e82 100644
--- a/ginac/mul.cpp
+++ b/ginac/mul.cpp
@@ -950,9 +950,13 @@ ex mul::expand(unsigned options) const
return (new mul(*this))->setflag(status_flags::dynallocated | status_flags::expanded);
}
- const bool skip_idx_rename = ! info(info_flags::has_indices);
- if (skip_idx_rename)
- ++(mul_expand_stats::n_indexless);
+ // do not rename indices if the object has no indices at all
+ if ((!(options & expand_options::expand_rename_idx)) &&
+ this->info(info_flags::has_indices))
+ options |= expand_options::expand_rename_idx;
+
+ const bool skip_idx_rename = !(options & expand_options::expand_rename_idx);
+
// First, expand the children
std::auto_ptr expanded_seqp = expandchildren(options);
const epvector & expanded_seq = (expanded_seqp.get() ? *expanded_seqp : seq);
diff --git a/ginac/power.cpp b/ginac/power.cpp
index 010af6c..42e14c1 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -918,8 +918,13 @@ ex power::expand_mul(const mul & m, const numeric & n, unsigned options, bool fr
return _ex1;
}
+ // do not bother to rename indices if there are no any.
+ if ((!(options & expand_options::expand_rename_idx))
+ && m.info(info_flags::has_indices))
+ options |= expand_options::expand_rename_idx;
// Leave it to multiplication since dummy indices have to be renamed
- if (m.info(info_flags::has_indices) && (get_all_dummy_indices(m).size() > 0) && n.is_positive()) {
+ if ((!(options & expand_options::expand_rename_idx)) &&
+ (get_all_dummy_indices(m).size() > 0) && n.is_positive()) {
ex result = m;
for (int i=1; i < n.to_int(); i++)
result *= rename_dummy_indices_uniquely(m,m);
--
1.5.2.4
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL:
From kreckel at ginac.de Mon Sep 17 21:30:04 2007
From: kreckel at ginac.de (Richard B. Kreckel)
Date: Mon, 17 Sep 2007 21:30:04 +0200
Subject: [GiNaC-devel] [PATCH 1/5,
GiNaC 1.3] Improve info(info_flags::has_indices),
introduce flags to cache the result.
In-Reply-To:
References:
Message-ID: <46EED5BC.5090404@ginac.de>
Alexei Sheplyakov wrote:
> This is the similar set of patches for GiNaC 1.3
A simple proposal: let's not care about release 1.3 so much. It is a
waste of time now that 1.4 is out.
If there's some really serious issue with 1.3 we can fix it for the 1.3
branch, but only as long as it is still in use by people out there. But
making an effort to backport as much as possible appears pointless to
me. And as soon as there are radical proposals that break the ABI it
would make more sense to branch 1.4.
Cheers
-richy.
--
Richard B. Kreckel
From varg at theor.jinr.ru Tue Sep 18 09:18:40 2007
From: varg at theor.jinr.ru (Sheplyakov Alexei)
Date: Tue, 18 Sep 2007 11:18:40 +0400
Subject: [GiNaC-devel] about "obsolete" versions
In-Reply-To: <46EED5BC.5090404@ginac.de>
References:
<46EED5BC.5090404@ginac.de>
Message-ID: <20070918071840.GB20384@theor.jinr.ru>
Hello!
On Mon, Sep 17, 2007 at 09:30:04PM +0200, Richard B. Kreckel wrote:
> A simple proposal: let's not care about release 1.3 so much. It is a
> waste of time now that 1.4 is out.
Frankly, I'm not going to switch to 1.4 anytime soon, so I do care about 1.3.
In general, I don't like to upgrade unless there is a compelling reason to
do so (e.g. new version is 2x faster, or has some feature I need very
much, etc).
> If there's some really serious issue with 1.3 we can fix it for the 1.3
> branch,
I think this particular regression is pretty serious.
> but only as long as it is still in use by people out there.
There is at least 1 user :) People don't like to upgrade (especially if
their code breaks, gets substantially slower, etc), so I think there
will be more.
> But making an effort to backport as much as possible appears pointless
> to me.
Actually, [almost] all patches for 1.4 (and HEAD) I've submitted were
forward ported (in most cases porting boils down to git-cherry-pick).
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL: