[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.cebix.net/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.cebix.net/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.cebix.net/pipermail/ginac-devel/attachments/20190607/5aa3bb5d/attachment-0002.bin>


More information about the GiNaC-devel mailing list