Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Import of trac_14802-dynamic_attribute_args.patch from
Browse files Browse the repository at this point in the history
trac 9556: additional features for dynamic methods of symbolic expressions
  • Loading branch information
burcin authored and rwst committed Apr 8, 2014
1 parent 37c8a8c commit 32e801a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 12 deletions.
41 changes: 35 additions & 6 deletions src/sage/symbolic/expression.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -4485,6 +4485,33 @@ cdef class Expression(CommutativeRingElement):
"""
return self.number_of_operands()

def _unpack_operands(self):
"""
Unpack the operands of this expression converting each to a Python
object if possible.
This corresponds to the conversion performed when arguments of a
function are unpacked as they are being passed to custom methods of
a symbolic function.
EXAMPLES::
sage: t = SR._force_pyobject((1, 2, x, x+1, x+2))
sage: t._unpack_operands()
(1, 2, x, x + 1, x + 2)
sage: type(t._unpack_operands())
<type 'tuple'>
sage: map(type, t._unpack_operands())
[<type 'sage.rings.integer.Integer'>, <type 'sage.rings.integer.Integer'>, <type 'sage.symbolic.expression.Expression'>, <type 'sage.symbolic.expression.Expression'>, <type 'sage.symbolic.expression.Expression'>]
sage: u = SR._force_pyobject((t, x^2))
sage: u._unpack_operands()
((1, 2, x, x + 1, x + 2), x^2)
sage: type(u._unpack_operands()[0])
<type 'tuple'>
"""
from sage.symbolic.pynac import unpack_operands
return unpack_operands(self)

def operands(self):
"""
Return a list containing the operands of this expression.
Expand Down Expand Up @@ -10267,7 +10294,7 @@ cdef get_dynamic_class_for_function(unsigned serial):
....: BuiltinFunction.__init__(self, 'tfunc', nargs=1)
....:
....: class EvaluationMethods:
....: def argp1(self, x):
....: def argp1(fn, self, x):
....: '''
....: Some documentation about a bogus function.
....: '''
Expand Down Expand Up @@ -10312,7 +10339,7 @@ cdef get_dynamic_class_for_function(unsigned serial):
....: BuiltinFunction.__init__(self, 'tfunc', nargs=2)
....:
....: class EvaluationMethods:
....: def argsum(self, x, y):
....: def argsum(fn, self, x, y):
....: return x + y
....:
sage: tfunc2 = TFunc2()
Expand All @@ -10330,13 +10357,15 @@ cdef get_dynamic_class_for_function(unsigned serial):
# callable methods need to be wrapped to extract the operands
# and pass them as arguments
from sage.symbolic.function_factory import eval_on_operands
from sage.structure.parent import getattr_from_other_class
from sage.structure.misc import getattr_from_other_class
for name in dir(eval_methods):
m = getattr_from_other_class(func_class, eval_methods, name)
m = getattr(eval_methods(), name)
if callable(m):
setattr(eval_methods, name, eval_on_operands(m))
new_m = eval_on_operands(getattr_from_other_class(
func_class, eval_methods, name))
setattr(eval_methods, name, new_m)
cls = dynamic_class('Expression_with_dynamic_methods',
(eval_methods, Expression))
(Expression,), eval_methods)
else:
cls = Expression

Expand Down
14 changes: 8 additions & 6 deletions src/sage/symbolic/function_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,18 +360,18 @@ def new_evalf(*args, **kwds):
def eval_on_operands(f):
"""
Given a method ``f`` return a new method which takes a single symbolic
expression argument and passes the operands of the given expression as
arguments to ``f``.
expression argument and appends operands of the given expression to
the arguments of ``f``.
EXAMPLES::
sage: def f(x, y):
sage: def f(ex, x, y):
....: '''
....: Some documentation.
....: '''
....: return x + 2*y
....:
sage: f(x, 1)
sage: f(None, x, 1)
x + 2
sage: from sage.symbolic.function_factory import eval_on_operands
sage: g = eval_on_operands(f)
Expand All @@ -381,6 +381,8 @@ def eval_on_operands(f):
'Some documentation.'
"""
@sage_wraps(f)
def new_f(ex):
return f(*ex.operands())
def new_f(ex, *args, **kwds):
new_args = list(ex._unpack_operands())
new_args.extend(args)
return f(ex, *new_args, **kwds)
return new_f
24 changes: 24 additions & 0 deletions src/sage/symbolic/pynac.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,30 @@ cdef public object exprseq_to_PyTuple(GEx seq):
res.append(new_Expression_from_GEx(SR, seq.op(i)))
return tuple(res)

def unpack_operands(Expression ex):
"""
EXAMPLES::
sage: from sage.symbolic.pynac import unpack_operands
sage: t = SR._force_pyobject((1, 2, x, x+1, x+2))
sage: unpack_operands(t)
(1, 2, x, x + 1, x + 2)
sage: type(unpack_operands(t))
<type 'tuple'>
sage: map(type, unpack_operands(t))
[<type 'sage.rings.integer.Integer'>,
<type 'sage.rings.integer.Integer'>,
<type 'sage.symbolic.expression.Expression'>,
<type 'sage.symbolic.expression.Expression'>,
<type 'sage.symbolic.expression.Expression'>]
sage: u = SR._force_pyobject((t, x^2))
sage: unpack_operands(u)
((1, 2, x, x + 1, x + 2), x^2)
sage: type(unpack_operands(u)[0])
<type 'tuple'>
"""
return exprseq_to_PyTuple(ex._gobj)

cdef public object exvector_to_PyTuple(GExVector seq):
"""
Converts arguments list given to a function to a PyTuple.
Expand Down

0 comments on commit 32e801a

Please sign in to comment.