Changeset 8274:8cfc8b071feb


Ignore:
Timestamp:
01/28/08 12:47:28 (5 years ago)
Author:
Robert Bradshaw <robertwb@…>
Branch:
default
Message:

Lots more explanation, fix sec() and extraneous printing.

Location:
sage
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • sage/categories/morphism.pyx

    r8258 r8274  
    132132             
    133133    cdef Element _call_c_impl(self, Element x): 
    134         print type(self), self 
    135         print <long>self._call_c 
    136         print <long>Morphism._call_c 
    137         print <long>FormalCoercionMorphism._call_c 
    138134        raise NotImplementedError 
    139135 
  • sage/ext/fast_eval.pxd

    r8264 r8274  
    66cdef struct fast_double_op: 
    77    char type 
    8     double_op_params params 
    9      
     8    double_op_params params     
    109 
    1110cdef class FastDoubleFunc: 
  • sage/ext/fast_eval.pyx

    r8273 r8274  
     1r""" 
     2For many applications such as numerical integration, differential equation  
     3approximation, plotting a 3d surface, optimization problems, monte-carlo  
     4simulations, etc. one wishes to pass around and evaluate a single algebraic  
     5many, many times at various floating point values. Doing this via recursive  
     6calls over a python representation of the object (even if maxima or other  
     7outside packages are not involved) is extremely inefficient.  
     8 
     9Up until now the solution has been to use lambda expressions, but this is neither  
     10intuitive, Sage-like, nor efficient (compared to operating on raw c doubles).  
     11This module provides a representation of algebraic expression in Reverse  
     12Polish Notation, and provides an efficient interpreter on c double values 
     13as a callable python object. It does what it can in C, and will call out 
     14to Python if necessary. 
     15 
     16Essential to the understanding of this class is the distinction between  
     17symbolic expressions and callable symbolic expressions (where the later  
     18binds argument names to argument positions). The \code{*vars} parameter  
     19passed around encapsulates this information.  
     20 
     21See the function \code{fast_float(f, *vars)} to create a fast-callable  
     22version of f.  
     23 
     24To provide this interface for a class, implement \code{_fast_float_(self, *vars)}.  
     25The basic building blocks are provided by the functions \code{fast_float_constant}  
     26(returns a constant function), \code{fast_float_arg} (selects the $n$-th  
     27value when called with $\ge n$ arguments), and \code{fast_float_func} which  
     28wraps a callable Python function. These may be combined with the standard  
     29Python arithmatic operators, and support many of the basic math functions  
     30such sqrt, exp, and trig functions.  
     31 
     32EXAMPLES:  
     33    sage: from sage.ext.fast_eval import fast_float 
     34    sage: f = fast_float(sqrt(x^2+1), 'x') 
     35    sage: f(1) 
     36    1.4142135623730951 
     37    sage: f.op_list() 
     38    ['load 0', 'push 2.0', 'call pow(2)', 'push 1.0', 'add', 'call sqrt(1)'] 
     39     
     40    To interpret that last line, we load argument 0 ('x' in this case) onto  
     41    the stack, push the constant 2.0 onto the stack, call the pow function  
     42    (which takes 2 arguments from the stack), push the constant 1.0, add the  
     43    top two arguments of the stack, and then call sqrt.  
     44 
     45Here we take sin of the first argument and add it to f:  
     46    sage: from sage.ext.fast_eval import fast_float_arg 
     47    sage: g = fast_float_arg(0).sin() 
     48    sage: (f+g).op_list() 
     49    'load 0', 'push 2.0', 'call pow(2)', 'push 1.0', 'add', 'call sqrt(1)', 'load 0', 'call sin(1)', 'add' 
     50 
     51AUTHOR:  
     52    -- Robert Bradshaw (2008-10): Initial version 
     53""" 
     54 
     55 
    156#***************************************************************************** 
    257#       Copyright (C) 2008 Robert Bradshaw <robertwb@math.washington.edu> 
     
    65120cdef enum: 
    66121# stack 
    67     LOAD_ARG 
     122    LOAD_ARG    # push input argument n onto the stack 
    68123    PUSH_CONST 
    69124    POP 
     
    85140    PY_FUNC 
    86141     
    87      
     142 
     143# These two dictionaries are just for machine independant representation.  
     144 
    88145op_names = { 
    89146    LOAD_ARG: 'load', 
     
    101158    INVERT: 'invert', 
    102159 
    103     ONE_ARG_FUNC: 'call 1', 
    104     TWO_ARG_FUNC: 'call 2', 
     160    ONE_ARG_FUNC: 'call', 
     161    TWO_ARG_FUNC: 'call', 
    105162    PY_FUNC: 'py_call', 
     163} 
     164 
     165cfunc_names = { 
     166    <size_t>&sqrt: 'sqrt', 
     167    <size_t>&pow: 'pow', 
     168     
     169    <size_t>&ceil: 'ceil', 
     170    <size_t>&floor: 'floor', 
     171     
     172    <size_t>&sin: 'sin', 
     173    <size_t>&cos: 'cos', 
     174    <size_t>&tan: 'tan', 
     175     
     176    <size_t>&asin: 'asin', 
     177    <size_t>&atan: 'atan', 
     178    <size_t>&atan2: 'atan2', 
     179     
     180    <size_t>&sinh: 'sinh', 
     181    <size_t>&cosh: 'cosh', 
     182    <size_t>&tanh: 'tanh', 
     183 
     184    <size_t>&asinh: 'asinh', 
     185    <size_t>&acosh: 'acosh', 
     186    <size_t>&atanh: 'atanh', 
     187 
     188    <size_t>&exp: 'exp', 
     189    <size_t>&log: 'log', 
     190    <size_t>&log2: 'log2', 
     191    <size_t>&log10: 'log10', 
     192 
    106193} 
    107194 
     
    113200        s += " %s" % op.params.c 
    114201    elif op.type in [ONE_ARG_FUNC, TWO_ARG_FUNC]: 
    115         s += " 0x%x" % <unsigned long>op.params.func 
     202        try: 
     203            cname = cfunc_names[<size_t>op.params.func] 
     204        except KeyError: 
     205            cname = "0x%x" % <size_t>op.params.func 
     206        s += " %s(%s)" % (cname, 1 if op.type == ONE_ARG_FUNC else 2) 
    116207    elif op.type == PY_FUNC: 
    117         s += " %s %s" % <object>(op.params.func) 
     208        n, func = <object>(op.params.func) 
     209        s += " %s(%s)" % (func, n) 
    118210    return s 
     211     
    119212     
    120213# This is where we wish we had case statements... 
     
    519612         
    520613    def sec(self): 
    521         return ~self.sec() 
     614        return ~self.cos() 
    522615         
    523616    def cot(self): 
     
    600693def fast_float_constant(x): 
    601694    """ 
    602     Return a fast-to-evaluate constant.  
     695    Return a fast-to-evaluate constant function.  
    603696     
    604697    EXAMPLES:  
     
    607700        sage: f() 
    608701        -2.75 
     702 
     703    This is all that goes on under the hood:  
     704        sage: fast_float_constant(pi).op_list() 
     705        ['push 3.14159265359'] 
    609706    """ 
    610707    return FastDoubleFunc('const', x) 
     
    625722        sage: f(1,2) 
    626723        2.0 
     724         
     725    This is all that goes on under the hood:  
     726        sage: fast_float_arg(10).op_list() 
     727        ['load 10'] 
    627728    """ 
    628729    return FastDoubleFunc('arg', n) 
     
    643744        sage: h(5, 10) 
    644745        -5.0 
     746 
     747    This is all that goes on under the hood:  
     748        sage: h.op_list() # random memory address 
     749        ['load 0', 'load 1', 'py_call <function <lambda> at 0xb62b230>(2)'] 
    645750    """ 
    646751    return FastDoubleFunc('callable', f, *args) 
     
    653758     
    654759    On failure, returns the input unchanged.  
     760     
     761    INPUT:  
     762        f    -- an expression 
     763        vars -- the names of the arguments 
     764         
     765    EXAMPLES:  
     766        sage: from sage.ext.fast_eval import fast_float 
     767        sage: x,y = var('x,y') 
     768        sage: f = fast_float(sqrt(x^2+y^2), 'x', 'y') 
     769        sage: f(3,4) 
     770        5.0 
     771 
     772    Specifying the argument names is essential, as fast_float objects 
     773    only distinguish between arguments by order.  
     774        sage: f = fast_float(x-y, 'x','y') 
     775        sage: f(1,2) 
     776        -1.0 
     777        sage: f = fast_float(x-y, 'y','x') 
     778        sage: f(1,2) 
     779        1.0 
    655780    """ 
    656781    if isinstance(f, (tuple, list)): 
Note: See TracChangeset for help on using the changeset viewer.