[GiNaC-devel] remove_dirac_ONE() and documentation patches

Vladimir V. Kisil kisilv at maths.leeds.ac.uk
Thu May 23 23:18:57 CEST 2019


	Dear Alexey,

	Many thanks for your detailed analysis. Probably I need to give
  a bit of explanation how the old throwing exceptions version of
  remove_dirac_ONE works.

  Of course, there are many cases in which throwing an exception is the
  only possible outcome, e.g. division by zero. The cases you quoted
  in your email (and numerous other exceptions in GiNaC) are of this
  sort. However, the old remove_dirac_ONE throws an exception also on a
  bit more delicate situation: if the expression does not look like (although
  it may be) a Clifford scalar due to a dummy summation. In this
  case an expansion of all dummy summations is called (which we do not
  want normally). Alternatives which I see are all disputable:

  * Leave it to a user to catch the exception and perform a dummy
  index expansion and re-try scalarisation;

  * Make all dummy summation expansion at the start of the method in all
  case.

  Regarding your comment on the duplicated code, I understand the
  concern on the library size. On the other hand the method with
  exceptions can be really faster on huge expressions since it
  aborts on the first problematic term. On the other hand to leave only
  algorithm based on the exceptions (which can occur on an admissible
  expression as well) may potentially produce a less portable code.

  I cannot make a decision here...

  Best wishes,
  Vladimir

-- 
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/
>>>>> On Thu, 23 May 2019 15:32:12 +0400, Alexey Sheplyakov <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

 



More information about the GiNaC-devel mailing list