File:  [CENS] / python / pyGiNaC / lib / __init__.py
Revision 1.13: download - view: text, annotated - select for diffs - revision graph
Tue Apr 17 22:39:25 2001 UTC (16 years, 7 months ago) by pearu
Branches: MAIN
CVS tags: HEAD
Fixed bugs. Exposed/checked functions. Started testing framework.

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

# This file is part of the PyGiNaC package.
# http://cens.ioc.ee/projects/pyginac/
#
# $Revision: 1.13 $
# $Id: __init__.py,v 1.13 2001-04-17 22:39:25 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 as _sys
import types as _types

import _ginac
from _ginac import *

def eval(*args):
    if type(args[0]) in [_types.CodeType,_types.StringType]:
        return _builtin_eval(*args)
    return _ginac.eval(*args)

def unex(obj):
    """Returns o if obj == ex(o), otherwise obj."""
    if type(type(obj)) is type(ex):
        try: cln = _ginac._tinfo[obj.tinfo()]
        except KeyError:
            raise RuntimeError,'object\'s tinfo is not registered in GiNaC (must be a bug)'
        try:
            cl = _ginac._py_class[cln]
        except KeyError:
            raise NotImplementedError,'class %s is disabled in this _ginac built'%(cln)
        return cl(obj)
    return obj

if 1:
    def _get_arg_limits(f):
        assert callable(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 = _ginac._nof_function_params
        return minargs1,maxargs1

if 0:
    assert _get_arg_limits(lambda z,y,x:x)==(3,3)
    assert _get_arg_limits(lambda z,y,x=3:x)==(2,3)
    assert _get_arg_limits(lambda z,y,*x:x)==(2,_ginac._nof_function_params)
    assert _get_arg_limits(lambda z,y=2,*x:x)==(1,_ginac._nof_function_params)
    assert _get_arg_limits(lambda z,y=2,*x,**yy:x)==(1,_ginac._nof_function_params)
    assert _get_arg_limits(lambda x:x)==(1,1)
    assert _get_arg_limits(lambda :x)==(0,0)
    assert _get_arg_limits(lambda *x:x)==(0,_ginac._nof_function_params)


def build_function(name,texname=None,
                   eval_f=None,evalf_f=None,
                   derivative_f=None,series_f=None,
                   nofargs=None):
    """build_function(name, **opt) - returns 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, it uses the value in
      _ginac._nof_function_params);
    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. About `opt' see series_options.
    """

    if nofargs is None:
        minargs = 0
        maxargs = _ginac._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
    try:
        fun_reg = _ginac._build_function
    except AttributeError:
        raise NotImplementedError,'_build_function is disabled in this _ginac built'
    ser = fun_reg(nofargs,name,
                  texname=texname,
                  eval=eval_f,evalf=evalf_f,
                  derivative=derivative_f,series=series_f)
    if minargs==maxargs:
        exec '''
def %s(*a):
    args = list(a)+[%s]
    if not(%s == len(a)):
        raise TypeError,"%s() requires %s arguments (%%s given)"%%(len(a))
    return _ginac._function(*args)
fun = %s
'''%(name,ser,minargs,name,minargs,name)
    else:
        exec '''
def %s(*a):
    args = list(a)+[%s]
    if not(%s <= len(a) <= %s):
        raise TypeError,"%s() requires %s...%s arguments (%%s given)"%%(len(a))
    return _ginac._function(*args)
fun = %s
'''%(name,ser,minargs,maxargs,name,minargs,maxargs,name)
    fun.serial = ser
    return fun

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