[GiNaC-devel] remove_dirac_ONE() and documentation patches
Vladimir V. Kisil
kisilv at maths.leeds.ac.uk
Fri Jun 7 09:45:36 CEST 2019
>>>>> On Wed, 05 Jun 2019 20:51:10 +0100, "Vladimir V. Kisil" <kisilv at maths.leeds.ac.uk> said:
VVK> Dear All, I finally managed to check Alexey's
VVK> proposition to wrap the throwing remove_dirac_ONE function. It
VVK> indeed prevents my Windows app from crashing. Thus I attach the
VVK> respective light-weighted patches.
Apology to everyone: the previously sent version had a debugging
printout. The clean patch is attached now.
--
Vladimir V. Kisil http://www.maths.leeds.ac.uk/~kisilv/
Book: Geometry of Mobius Transformations http://goo.gl/EaG2Vu
Software: Geometry of cycles http://moebinv.sourceforge.net/
VVK> Best wishes, Vladimir -- Vladimir V. Kisil
VVK> http://www.maths.leeds.ac.uk/~kisilv/ Book: Geometry of Mobius
VVK> Transformations http://goo.gl/EaG2Vu Software: Geometry of
VVK> cycles http://moebinv.sourceforge.net/
>>>>> On Thu, 23 May 2019 15:32:12 +0400, Alexey Sheplyakov
VVK> <asheplyakov at YANDEX.ru> said:
ASh> Hi,
ASh> 23.05.2019, 10:44, "Vladimir V. Kisil"
ASh> <kisilv at maths.leeds.ac.uk>:
>>> Dear Alexey,
>>>
>>> I am attaching another iteration of the patch as
>>> suggested. The exception-free method is used internally for a
>>> better protection.
ASh> Firstly making two almost identical copies of remove_dirac_ONE
ASh> is definitely a bad idea. Two possible approaches are:
ASh> a) wrap exception-throwing remove_dirac_ONE like this
ASh> ex remove_dirac_ONE(const ex& e, bool& success, unsigned char
ASh> rl, unsigned options) { ex ret; try {
ASh> ret = remove_dirac_ONE(e, rl, options); }
ASh> catch (...) { success = false;
ASh> ret = _ex0; } return ret; }
ASh> This way exceptions will propagate within ginac.dll itself
ASh> only, and there's no code duplication.
ASh> b) alternatively one could move the actual computation to
ASh> non-throwing variant of remove_dirac_ONE, and make a wrapper
ASh> which does throw exceptions:
ASh> ex remove_dirac_ONE(const ex& e, unsigned char rl, unsigned
ASh> options) { bool success = true; ex ret =
ASh> remove_dirac_ONE(e, success, rl, options); if (!success) {
ASh> // perhaps non-throwing variant should set an integer
ASh> status instead of a bool flag, so a more specific exception can
ASh> be thrown throw std::runtime_error("some meaningful
ASh> error message here"); } return ret; }
ASh> Secondly I don't quite get what's the point of replacing the
ASh> throwing variant of remove_dirac_ONE, and throwing the very
ASh> same exception manually:
>>> + bool success; + if (! ex_to<idx>(mu).is_dim_numeric())
>>> throw(std::invalid_argument("clifford_to_lst(): index should
>>> have a numeric dimension")); unsigned int D =
>>> ex_to<numeric>(ex_to<idx>(mu).get_dim()).to_int(); @@ -1341,7
>>> +1399,9 @@ lst clifford_to_lst(const ex & e, const ex & c, bool
>>> algebraic) || (! is_a<numeric>(pow(c.subs(mu == i,
>>> subs_options::no_pattern), 2)))) algebraic = false; lst V; - ex
>>> v0 =
>>> remove_dirac_ONE(canonicalize_clifford(e+clifford_prime(e)))/2;
>>> + ex v0 =
>>> remove_dirac_ONE(canonicalize_clifford(e+clifford_prime(e)),
>>> success)/2; + if (!success) +
>>> throw(std::invalid_argument("clifford_to_lst(): the argument is
>>> not a Clifford vector"));
ASh> I.e. why can't we keep calling
ASh> ex v0 =
ASh> remove_dirac_ONE(canonicalize_clifford(e+clifford_prime(e)))/2;
ASh> and have remove_dirac_ONE throw an appropriate exception?
>>> Previously remote_dirac_ONE() reported that an expression is not
>>> a Clifford scalar by throwing an exception. This produced
>>> crashes in Qt applications on Windows.
ASh> Not really. Throwing exceptions across shared libraries (DLLs)
ASh> on Windows is a little bit tricky, but it's certainly possible.
ASh> The crucial point is to make all DLLs use the same C++ runtime
ASh> (which implies the C++ runtime should be linked dynamically
ASh> into all DLLs linked into the application).
ASh> Also patching just remove_dirac_ONE is sort of pointless, since
ASh> most GiNaC methods and functions throw exceptions too.
ASh> Best regards, Alexey
VVK> From 91db78db3c8bb89a954be3f249333d3e1313b782 Mon Sep 17
VVK> 00:00:00 2001 From: "Vladimir V. Kisil"
VVK> <kisilv at maths.leeds.ac.uk> Date: Tue, 14 May 2019 12:06:42
VVK> +0100 Subject: [PATCH 1/3] Suggest ios::binary flag for
VVK> archiving files
VVK> Without the flag locales setting of the OS tempers the file
VVK> structure.
VVK> Signed-off-by: Vladimir V. Kisil <kisilv at maths.leeds.ac.uk> ---
VVK> doc/tutorial/ginac.texi | 8 +++++--- 1 file changed, 5
VVK> insertions(+), 3 deletions(-)
VVK> diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi
VVK> index 331c2125..bc4b87fc 100644 --- a/doc/tutorial/ginac.texi
VVK> +++ b/doc/tutorial/ginac.texi @@ -6743,14 +6743,16 @@ The
VVK> archive can then be written to a file:
VVK> @example // ... - ofstream out("foobar.gar"); + ofstream
VVK> out("foobar.gar", ios::binary); out << a; out.close(); // ...
VVK> @end example
VVK> The file @file{foobar.gar} contains all information that is
VVK> needed to -reconstruct the expressions @code{foo} and
VVK> @code{bar}. +reconstruct the expressions @code{foo} and
VVK> @code{bar}. The flag + at code{ios::binary} prevents locales
VVK> setting of your OS tampers the +archive file structure.
VVK> @cindex @command{viewgar} The tool @command{viewgar} that
VVK> comes with GiNaC can be used to view @@ -6768,7 +6770,7 @@ read
VVK> in again: @example // ... archive a2; - ifstream
VVK> in("foobar.gar"); + ifstream in("foobar.gar", ios::binary); in
VVK> >> a2; // ... @end example -- 2.20.1
VVK> From 61a028914d6e684ee50d5d32f3bdcdc7ec5f0cc0 Mon Sep 17
VVK> 00:00:00 2001 From: "Vladimir V. Kisil"
VVK> <kisilv at maths.leeds.ac.uk> Date: Tue, 14 May 2019 13:11:13
VVK> +0100 Subject: [PATCH 2/3] Additional examples on number
VVK> conversions.
VVK> Some aspects of these methods are not obvious for newbies.
VVK> Signed-off-by: Vladimir V. Kisil <kisilv at maths.leeds.ac.uk> ---
VVK> doc/tutorial/ginac.texi | 9 +++++++++ 1 file changed, 9
VVK> insertions(+)
VVK> diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi
VVK> index bc4b87fc..65ca5918 100644 --- a/doc/tutorial/ginac.texi
VVK> +++ b/doc/tutorial/ginac.texi @@ -1533,6 +1533,15 @@ rational
VVK> number will return a floating-point approximation. Both
VVK> @code{to_int()/to_long()} and @code{to_double()} discard the
VVK> imaginary part of complex numbers.
VVK> +Note the signature of the above methods, you may need to apply
VVK> a type +conversion and call @code{evalf()} as shown in the
VVK> following example: + at example + ... + ex e1 = 1, e2 =
VVK> sin(Pi/5); + cout << ex_to<numeric>(e1).to_int() << endl + <<
VVK> ex_to<numeric>(e2.evalf()).to_double() << endl; + ... + at end
VVK> example
VVK> @node Constants, Fundamental containers, Numbers, Basic
VVK> concepts @c node-name, next, previous, up -- 2.20.1
VVK> From 284c38d43c8579ef59a7b4422150923f1d9d8e93 Mon Sep 17
VVK> 00:00:00 2001 From: "Vladimir V. Kisil"
VVK> <kisilv at maths.leeds.ac.uk> Date: Tue, 14 May 2019 20:42:50
VVK> +0100 Subject: [PATCH 3/3] Modify remove_dirac_ONE() to
VVK> eliminate exceptions.
VVK> Previously remote_dirac_ONE() reported that an expression is
VVK> not a Clifford scalar by throwing an exception. This produced
VVK> crashes in Qt applications on Windows. Now exceptions are only
VVK> used within the recursive calls of remote_dirac_ONE(). There is
VVK> a possibility to pass the information on non-scalar expression
VVK> through a Boolean variable.
VVK> This patch also adds some additional test to exam_clifford.cpp
VVK> and improves the tutorial description of the method.
VVK> Signed-off-by: Vladimir V. Kisil <kisilv at maths.leeds.ac.uk> ---
VVK> check/exam_clifford.cpp | 15 ++++++++++++---
VVK> doc/tutorial/ginac.texi | 15 +++++++++++++-- ginac/clifford.cpp
VVK> | 23 +++++++++++++++++++---- ginac/clifford.h | 15
VVK> +++++++++++++-- 4 files changed, 57 insertions(+), 11
VVK> deletions(-)
VVK> diff --git a/check/exam_clifford.cpp b/check/exam_clifford.cpp
VVK> index b067438b..9f1361fa 100644 --- a/check/exam_clifford.cpp
VVK> +++ b/check/exam_clifford.cpp @@ -417,9 +417,18 @@ template
VVK> <typename IDX> unsigned clifford_check6(const matrix &A)
VVK> realsymbol s("s"), t("t"), x("x"), y("y"), z("z");
VVK> ex c = clifford_unit(nu, A, 1); - e =
VVK> lst_to_clifford(lst{t, x, y, z}, mu, A, 1) *
VVK> lst_to_clifford(lst{1, 2, 3, 4}, c); - e1 =
VVK> clifford_inverse(e); - result +=
VVK> check_equal_simplify_term2((e*e1).simplify_indexed(),
VVK> dirac_ONE(1)); + lst elem = { dirac_ONE(1), /* Clifford scalar
VVK> */ + lst_to_clifford(lst{1, 0, 0, 0}, mu, A, 1), /* Clifford
VVK> vector */ + lst_to_clifford(lst{t, x, y, z}, mu, A, 1) *
VVK> lst_to_clifford(lst{1, 2, 3, 4}, c) /* Clifford bi-vector */ +
VVK> }; + + for (int i = 0; i < 3; ++i) { + e1 =
VVK> clifford_inverse(elem[i]); + result +=
VVK> check_equal_simplify_term2((elem[i]*e1).simplify_indexed(),
VVK> dirac_ONE(1)); + e = 3*pow(2*Pi, i)*elem[i]; + e1 =
VVK> clifford_inverse(e); + result +=
VVK> check_equal_simplify_term2((e*e1).simplify_indexed(),
VVK> dirac_ONE(1)); + }
VVK> /* lst_to_clifford() and clifford_to_lst() check for vectors*/
VVK> e = lst{t, x, y, z}; diff --git a/doc/tutorial/ginac.texi
VVK> b/doc/tutorial/ginac.texi index 65ca5918..c383b139 100644 ---
VVK> a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@
VVK> -3573,12 +3573,23 @@ then an exception is raised. @cindex
VVK> @code{remove_dirac_ONE()} If a Clifford number happens to be a
VVK> factor of @code{dirac_ONE()} then we can convert it to a
VVK> ``real'' (non-Clifford) -expression by the function +expression
VVK> by the functions
VVK> @example - ex remove_dirac_ONE(const ex & e); + ex
VVK> remove_dirac_ONE(const ex & e, bool & success, unsigned char rl
VVK> = 0); + ex remove_dirac_ONE(const ex & e, unsigned char rl =
VVK> 0); @end example
VVK> +The functions removes only @code{dirac_ONE()} with a
VVK> representation +label not smaller than
VVK> @code{rl}. Correspondingly, the default value of + at code{rl=0}
VVK> removes all @code{dirac_ONE()}. If the first argument is +not
VVK> a scalar multiple of @code{dirac_ONE()} and an output of the
VVK> +functions is not predictable, then the first method reports
VVK> this back by +the value @code{false} of the Boolean variable
VVK> @code{success}. The +second method in the case of a non-scalar
VVK> Clifford numbers aborts with +an exception raised. Usage of the
VVK> second method may crash in Windows +threaded applications. +
VVK> @cindex @code{canonicalize_clifford()} The function
VVK> @code{canonicalize_clifford()} works for a generic Clifford
VVK> algebra in a similar way as for Dirac gammas. diff --git
VVK> a/ginac/clifford.cpp b/ginac/clifford.cpp index
VVK> 860cce46..51b92599 100644 --- a/ginac/clifford.cpp +++
VVK> b/ginac/clifford.cpp @@ -1142,6 +1142,21 @@ ex
VVK> clifford_prime(const ex & e) return e; }
VVK> +ex remove_dirac_ONE(const ex & e, bool & success, unsigned
VVK> char rl, unsigned options) +{ + ex ret; + std::cerr << "New
VVK> remove_dirac";e.dbgprint(); + try { + ret = remove_dirac_ONE(e,
VVK> rl, options); + success = true; + } catch (...) { + success =
VVK> false; + ret = _ex0; + } + return ret; + +} + ex
VVK> remove_dirac_ONE(const ex & e, unsigned char rl, unsigned
VVK> options) { pointer_to_map_function_2args<unsigned char,
VVK> unsigned> fcn(remove_dirac_ONE, rl, options | 1); @@ -1152,13
VVK> +1167,13 @@ ex remove_dirac_ONE(const ex & e, unsigned char rl,
VVK> unsigned options) e1 = expand_dummy_sum(e, true); e1 =
VVK> canonicalize_clifford(e1); } - + if (is_a<clifford>(e1) &&
VVK> ex_to<clifford>(e1).get_representation_label() >= rl) { if
VVK> (is_a<diracone>(e1.op(0))) return 1; - else + else
VVK> throw(std::invalid_argument("remove_dirac_ONE(): expression is
VVK> a non-scalar Clifford number!")); - } else if (is_a<add>(e1) ||
VVK> is_a<ncmul>(e1) || is_a<mul>(e1) + } else if (is_a<add>(e1) ||
VVK> is_a<ncmul>(e1) || is_a<mul>(e1) || is_a<matrix>(e1) ||
VVK> e1.info(info_flags::list)) { if (options & 3) // is a child or
VVK> was already expanded return e1.map(fcn); @@ -1177,7 +1192,7 @@
VVK> ex remove_dirac_ONE(const ex & e, unsigned char rl, unsigned
VVK> options) } catch (std::exception &p) { need_reevaluation =
VVK> true; } - } + } if (need_reevaluation) return
VVK> remove_dirac_ONE(e, rl, options | 2); return e1; diff --git
VVK> a/ginac/clifford.h b/ginac/clifford.h index c076d615..dfa25347
VVK> 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -294,11
VVK> +294,22 @@ inline ex clifford_bar(const ex & e) { return
VVK> clifford_star_bar(e, true, 0); } inline ex clifford_star(const
VVK> ex & e) { return clifford_star_bar(e, false, 0); }
VVK> /** Replaces dirac_ONE's (with a representation_label no less
VVK> than rl) in e with 1. - * For the default value rl = 0 remove
VVK> all of them. Aborts if e contains any + * For the default value
VVK> rl = 0 remove all of them. Any clifford_unit with any
VVK> representation_label + * will be replaces by zero. An
VVK> occurrence of a such clifford_unit can be reported through the
VVK> false + * value of the success parameter. + * + * @param e
VVK> Expression to be processed + * @param success It is changed to
VVK> false if there is at least one clifford_unit() in the
VVK> expression + * @param rl Value of representation label, all
VVK> dirac_ONE with this or greater value will be processed + *
VVK> @param options Defines some internal value for recursive calls,
VVK> shall be ommited in user code */ +ex remove_dirac_ONE(const ex
VVK> & e, bool & success, unsigned char rl = 0, unsigned options =
VVK> 0); + +/** Replaces dirac_ONE's (with a representation_label no
VVK> less than rl) in e with 1. + * For the default value rl = 0
VVK> remove all of them. Aborts (raise an exception) if e contains
VVK> any * clifford_unit with representation_label to be removed. *
VVK> * @param e Expression to be processed - * @param rl Value of
VVK> representation label + * @param rl Value of representation
VVK> label * @param options Defines some internal use */ ex
VVK> remove_dirac_ONE(const ex & e, unsigned char rl = 0, unsigned
VVK> options = 0);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Suggest-ios-binary-flag-for-archiving-files.patch
Type: text/x-diff
Size: 1429 bytes
Desc: Doc patch
URL: <http://www.ginac.de/pipermail/ginac-devel/attachments/20190607/5aa3bb5d/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-Additional-examples-on-number-conversions.patch
Type: text/x-diff
Size: 1209 bytes
Desc: Number conversion
URL: <http://www.ginac.de/pipermail/ginac-devel/attachments/20190607/5aa3bb5d/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-Modify-remove_dirac_ONE-to-eliminate-exceptions.patch
Type: text/x-diff
Size: 6787 bytes
Desc: remove_dirac_ONE
URL: <http://www.ginac.de/pipermail/ginac-devel/attachments/20190607/5aa3bb5d/attachment-0002.bin>
More information about the GiNaC-devel
mailing list