#1173: implement numerical evaluation of erf at complex arguments
----------------------------------------------------------------------+-----
   Reporter:  was                                                     |         
 Owner:  was         
       Type:  enhancement                                             |         
Status:  needs_work  
   Priority:  major                                                   |      
Milestone:  sage-4.7.2  
  Component:  calculus                                                |       
Keywords:              
Work_issues:  add erf(sqrt(2)) and erf(45000).n(), formatting, speed  |       
Upstream:  N/A         
   Reviewer:  Burcin Erocal                                           |         
Author:  D. S. McNeil
     Merged:                                                          |   
Dependencies:  #11513      
----------------------------------------------------------------------+-----

Comment(by burcin):

 Replying to [comment:26 dsm]:
 <snip>
 > To wrap up:
 >
 > (1) Both this patch and #11143 suffer a significant slowdown relative to
 PARI, and have major overheads relative to calling mpmath.  Some of that's
 unavoidable given the symbolic path, but ISTM we should be able to do
 better.  Ideally there would be a reasonably efficient general special
 function implementation pattern, along the lines of what Benjamin used,
 that intermittent developers like me could be pointed to as a reference.

 I agree that we should do better. Note that the pattern you request is
 being developed in #11143  and here. Even though pynac based symbolics was
 merged in Sage quite a while ago, it hasn't been used properly yet.

 The code path to call symbolic functions is rather convoluted. This is
 inevitable since symbolic functions have to play well with many different
 subsystems, such as fast float, numpy, etc. But it should still be
 possible to reduce the overhead.

 For `BuiltinFunction`s the code path for evaluation goes through
 `Function.__call__()` in `sage/symbolic/function.pyx`, then into pynac,
 then to the python method you define for `_eval_()`, if numeric evaluation
 is needed to `_evalf_()` later. Here, between the python and C++ code,
 conversion functions are called to wrap pynac objects in Expression
 instances or to remove these wrappers.

 I believe most of the overhead comes from the `__call__()` method, then
 having to decide if the arguments are numeric in `_eval_()`, and checking
 if an argument is zero (#11513).

 > (2) In the case of erf and erfc, mpfr offers a very fast evaluation for
 real numbers, fast enough that it might be worth using as the default in
 those cases (although Python-level branching is slow in my experience,
 maybe slow enough to wash away the benefits).  Once we settle on an
 approach for erf I'll do the same for erfc.

 MPFR should be the default numeric evaluation method if it is available.
 In general, it's better to let the types choose the numeric evaluation
 method. Most special functions in Sage first see if an object implements a
 method with the same name first and calls that. For instance `erf()`
 should call `.erf()` for element of `RR`.

 I see that for subclasses of `GinacFunction` the `__call__()` method does
 this automatically. This is not used for other `BuiltinFunction`s though.
 It might make sense to move this method to `BuiltinFunction`. This would
 speed up most of the timings for real numbers above.

 Unfortunately, floats would still go through the long path. Since these
 are used quite often in plotting, perhaps we should add a special case in
 `__call__()` to go directly to `_evalf_()` as well.

 I made this change in attachment:trac_1173-move_call.patch. Now I get:

 {{{
 sage: t = RR(2.0)
 sage: %timeit z = t.erf()
 625 loops, best of 3: 16.9 µs per loop
 sage: %timeit z = erf(t)
 625 loops, best of 3: 18.2 µs per loop
 }}}

 Performance for `float` is still pretty bad.

 {{{
 sage: u = 2.0r
 sage: %timeit z = erf(u)
 625 loops, best of 3: 156 µs per loop
 }}}

 I didn't check if this patch breaks anything.

 > (3) Should I move this out of other.py to special.py, where the
 complementary error_fcn function lives now?  It would seem a more natural
 location for it.  We also have some unfortunate naming (erf and error_fcn)
 it might be worth addressing.

 I don't think there is a need to move this to `special.py`. That file is
 also overcrowded and needs serious cleanup. You could create a new file
 names `error_fn.py` if you think that's necessary.

 What names do other systems use for these functions? AFAIK, `erf()` and
 `erfc()` are pretty much standard. I wonder where `error_fcn()` came from.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/1173#comment:27>
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 post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to