# Add a personnal coercion rule

Hi all !

For some reasons I have to use a class MyAngle which basically describes an angle, but with some personal methods.

Obviously, sage's cos function cannot take an instance of my class as argument.

SAGE

#! /usr/bin/sage -python
# -*- coding: utf8 -*-

from sage.all import *

class MyAngle(object):
def __init__(self,value):
self.value=value

x=MyAngle(pi/2)
cos(x)


ERROR

Traceback (most recent call last):
File "./sagess.py", line 11, in <module>
cos(x)
File "function.pyx", line 733, in sage.symbolic.function.GinacFunction.__call__   (sage/symbolic/function.cpp:6572)
File "function.pyx", line 417, in sage.symbolic.function.Function.__call__ (sage/symbolic    /function.cpp:4336)
TypeError: cannot coerce arguments: no canonical coercion from <class '__main__.MyAngle'> to Symbolic Ring


What do I have to add to my class to make Sage's cosine understand that when x=MyAngle(pi/2),

cos(x)


means

cos(x.value)


I found that, but I didn't helped me so much. http://www.sagemath.org/doc/developer...

Thanks for help ! have a good night Laurent

edit retag close merge delete

Sort by ยป oldest newest most voted

Cos is defined for float only. So you can use the following code.

from sage.all import *

class MyAngle(object):
def __init__(self,value):
self.value=value
def cos(self):
return(n(cos(self.value)))
x=MyAngle(4/2)
cos(x)

more

You only mention cos, but presumably there are other things you're going to want to do with your angles: sin, tan, add them, subtract them, convert them to floats, possibly simplify them, and so on. That's a lot of hassle to implement, so instead let's subclass the built-in Expression class and let it do most of the work.

class FixedValue(Expression):
def __init__(self, value):
Expression.__init__(self, SR, value)
def new_method(self, *args):
print self, args

sage: x = FixedValue(pi/2)
sage: x
1/2*pi
sage: cos(x), sin(x), tan(x), float(x), complex(x)
(0, 1, Infinity, 1.5707963267948966, (1.5707963267948966+0j))
sage: x+x, x*3, simplify(exp(x*I))
(pi, 3/2*pi, I)
sage: x.new_method(99, 'fred')
1/2*pi (99, 'fred')


Note that the above doesn't store a copy of its value in ".value"; you can simply refer to the object itself. If you do store a copy you have to worry about them getting out of sync. Also note that while the above makes it easy to operate on these objects, the result of an operation won't be an instance of the class (e.g. x*1 is an Expression, not a FixedValue), but you can easily coerce back, or we can work around it if necessary.

more

Thanks for the idea of subclassing Expression. I'll dig in that direction.

Laurent

more