File:  [CENS] / python / pyGiNaC / lib3 / __init__.py
Revision 1.5: download - view: text, annotated - select for diffs - revision graph
Wed May 16 05:49:32 2001 UTC (16 years, 6 months ago) by pearu
Branches: MAIN
CVS tags: HEAD
Added some get_*() methods. Introduced function().

"""See `ginac.doc' for PyGiNaC class documentation."""

# This file is part of the PyGiNaC package.
# http://cens.ioc.ee/projects/pyginac/
#
# $Revision: 1.5 $
# $Id: __init__.py,v 1.5 2001-05-16 05:49:32 pearu Exp $
#
# Copyright 2001 Pearu Peterson all rights reserved,
# Pearu Peterson <pearu@cens.ioc.ee>
# Permission to use, modify, and distribute this software is given under the
# terms of the LGPL.  See http://www.fsf.org
#
# NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
#

_builtin_eval = eval

import ginac.doc
__version__ = ginac.doc.__version__
__author__ = ginac.doc.__author__
__date__ = ginac.doc.__date__
__credits__ = ginac.doc.__credits__

import sys,types
_sys = sys
_types = types
del sys, types

import _ginac
from _ginac import *

def eval(a1,a2=None,a3=None,eval_f=_builtin_eval):
    """Fix overloading built-in eval() with _ginac.eval()."""
    args = [a1]
    if a2 is not None: args.append(a2)
    if a3 is not None: args.append(a3)
    if type(args[0]) in [_types.CodeType,_types.StringType]:
        return eval_f(*args)
    return _ginac.eval(*args)
del _builtin_eval

_user_defined_function_serials = []
def build_function(name,texname=None,
                   eval_f=None,evalf_f=None,
                   derivative_f=None,series_f=None,
                   nofargs=None):
    """Construct symbolic function with a name `name'.

    Optional arguments:
    texname - LaTeX string;
    nofargs - the number of arguments to a function (if not specified,
      build_function tries to establish `nofargs' from functions `eval',
      `evalf', `derivative', `series'. If that fails, 12 is set.);
    eval_f    - eval_f(*args) is used for automatic non-interruptive symbolic
      evaluation;
    evalf_f   - evalf_f(*args) is used for numeric evaluation;
    derivative_f - derivative_f(*args,i) is used for computing
              the 1st derivative with respect to `i'-th argument (i>=0);
    series_f  - series_f(*args,rel,order,opts = 0) is used for computing
              the truncated series expansion around a point `rhs(rel)'
              with respect to variable `lhs(rel)'. `order' is the truncation
              order.
    """
    if nofargs is None:
        _nof_function_params = 12
        exec """\
def _get_arg_limits(f):
    '''Return the number of arguments required by a function `f\'.'''
    nofargs = len(f.func_code.co_varnames)
    argcount = f.func_code.co_argcount
    if f.func_defaults: nofdefargs = len(f.func_defaults)
    else: nofdefargs=0
    minargs1 = argcount - nofdefargs
    maxargs1 = nofargs
    if nofargs > argcount: maxargs1 = _nof_function_params
    return minargs1,maxargs1\n"""
        minargs = 0
        maxargs = _nof_function_params
        if eval_f is not None:
            mn,mx = _get_arg_limits(eval_f)
            minargs = mn
            maxargs = mx
        if evalf_f is not None:
            mn,mx = _get_arg_limits(evalf_f)
            minargs = max(minargs,mn)
            maxargs = min(maxargs,mx)
        if derivative_f is not None:
            mn,mx = _get_arg_limits(derivative_f)
            minargs = max(minargs,mn-1)
            maxargs = min(maxargs,mx-1)
        if series_f is not None:
            mn,mx = _get_arg_limits(series_f)
            minargs = max(minargs,mn-3)
            maxargs = min(maxargs,mx-3)
        if minargs <= maxargs:
            nofargs = minargs
        else:
            raise TypeError,'build_function() inconsistent arguments: minargs,maxargs=%s,%s'%(minargs,maxargs)
    else:
        minargs = maxargs = nofargs
    ser = _ginac._build_function(nofargs,name,
                                 texname=texname,
                                 eval=eval_f,evalf=evalf_f,
                                 derivative=derivative_f,series=series_f)
    _user_defined_function_serials.append(ser)
    if minargs==maxargs:
        exec '''
def %s(*a,**k):
    if k.has_key("hold"): hold = k["hold"]
    else: hold = 0
    args = list(a)+[_ginac._pyfunc(%s)]
    if not(%s == len(a)):
        raise TypeError,"function %s() takes exactly %s argument (%%s given)"%%(len(a))
    return _ginac._function(%s,hold,args)
fun = %s
'''%(name,ser,minargs,name,minargs,ser,name)
    else:
        exec '''
def %s(*a,**k):
    if k.has_key("hold"): hold = k["hold"]
    else: hold = 0
    args = list(a)+[_ginac._pyfunc(%s)]
    if not(%s <= len(a) <= %s):
        raise TypeError,"function %s() takes %s...%s arguments (%%s given)"%%(len(a))
    return _ginac._function(%s,hold,args)
fun = %s
'''%(name,ser,minargs,maxargs,name,minargs,maxargs,ser,name)
    return fun

def function(ser,*args,**kws):
    """\
    Return image of a function with a serial number `ser'
    applied to `args'.
    """
    if kws.has_key('hold'):
        hold = kws['hold']
    else:
        hold = 0
    if ser in _user_defined_function_serials:
        args = list(args) + [_ginac._pyfunc(ser)]
    return _ginac._function(ser,hold,args)
    

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>