#13608: exp() does not work on mpmath mpf numbers
---------------------------+-----------------------------------------------
       Reporter:  ddrake   |         Owner:  burcin
           Type:  defect   |        Status:  needs_work
       Priority:  major    |     Milestone:  sage-5.11
      Component:           |    Resolution:
  symbolics                |     Merged in:
       Keywords:  exp      |     Reviewers:  Dan Drake, Karl-Dieter Crisman
  mpmath mpf               |   Work issues:
        Authors:           |  Dependencies:
Report Upstream:  N/A      |
         Branch:           |
       Stopgaps:           |
---------------------------+-----------------------------------------------

Comment (by gagern):

 Replying to [comment:14 burcin]:
 > We should check for speed regressions before accepting anything that
 modifies it.
 > I'm afraid adding a callable check […] might be too expensive.

 I did the following check:

 {{{
 a = [RDF(i*0.01) for i in range(100)]
 timeit('[sin(i) for i in a]', repeat=100, number=10000)
 }}}

 and studied the effect of the following code change:

 {{{
 -        if len(args) == 1 and not hold and not dont_call_method_on_arg
 and \
 -                hasattr(args[0], self._name):
 -            return getattr(args[0], self._name)()
 +        if len(args) == 1 and not hold and not dont_call_method_on_arg:
 +            memberfn = getattr(args[0], self._name, None)
 +            if callable(memberfn):
 +                return memberfn()
 }}}

 The time per loop went ''down'' from 47 µs to 42 µs. So the cost of that
 `callable` seems to be far less than the overhead due to the `hasattr` in
 the original code. And in any case the change is very small. Avoiding
 `hasattr` but doing a `memberfn is not None` instead of the
 `callable(memberfn)` I got those 42 µs again, so the cost of `callable`
 gets lost in the noise. For reference: the direct method invocation
 `i.sin()` amounts to 29 µs per loop.

 > or a new Python function call for mpmath function

 To judge the cost of the mpmath check, I used the two-argument function
 `atan2` like this:

 {{{
 a = [(RDF(i), RDF(i + 2)) for i in range(100)]
 timeit('[atan2(y, x) for y, x in a]', repeat=10, number=1000)
 }}}

 Subject to the whole patch (basically as submitted before, although I'll
 attach an updated version shortly) the running time increased from 5.7 ms
 to 5.8 ms per loop. Not much, perhaps not even significant. And this won't
 affect GiNaC functions that translate to member invocations, which should
 cover quite a large number of use cases. Even more after
 @a526457085e3f07440dc39cb77f93ef3e32ae2af which isn't included in my 5.10
 code base yet.

 Talking of turning function calls to member invocations: in
 
source:src/sage/symbolic/function.pyx@8118b2b39e3a129a5a6186fdc9917940f92b87a6#L387
 the `Function.__call__` implementation claims to contain work which
 enables `exp(M)` for matrices `M`. But my experiments showed the
 `GinacFunction.__call__` implementation at
 
source:src/sage/symbolic/function.pyx@8118b2b39e3a129a5a6186fdc9917940f92b87a6#L738
 is actually responsible for this behavior. After
 @a526457085e3f07440dc39cb77f93ef3e32ae2af that will be
 `BuiltinFunction.__call__`. I'm a bit surprised about this duplicate code,
 haven't really figured out whether or not this makes sense.

--
Ticket URL: <http://trac.sagemath.org/ticket/13608#comment:15>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to