| 221 | |
| 222 | |
| 223 | cdef class CCallableConvertMap_class(Map): |
| 224 | cdef Element (*_func)(Parent, object) |
| 225 | cdef public _name |
| 226 | |
| 227 | def __init__(self, domain, codomain, name): |
| 228 | if PY_TYPE_CHECK(domain, type): |
| 229 | domain = Set_PythonType(domain) |
| 230 | Map.__init__(self, domain, codomain) |
| 231 | self._coerce_cost = 10 |
| 232 | self._name = name |
| 233 | |
| 234 | cpdef Element _call_(self, x): |
| 235 | return self._func(self._codomain, x) |
| 236 | |
| 237 | def _repr_type(self): |
| 238 | """ |
| 239 | EXAMPLES: |
| 240 | sage: from sage.structure.coerce_maps import test_CCallableConvertMap |
| 241 | sage: test_CCallableConvertMap(ZZ, 'any name') |
| 242 | Conversion via c call 'any name' map: |
| 243 | From: Integer Ring |
| 244 | To: Integer Ring |
| 245 | sage: test_CCallableConvertMap(ZZ, None) # random address |
| 246 | Conversion via c call at 0xc339000 map: |
| 247 | From: Integer Ring |
| 248 | To: Integer Ring |
| 249 | """ |
| 250 | if self._name is None: |
| 251 | return "Conversion via c call at 0x%x" % <long>self._func |
| 252 | else: |
| 253 | return "Conversion via c call '%s'" % self._name |
| 254 | |
| 255 | |
| 256 | cdef Map CCallableConvertMap(domain, codomain, void* func, name): |
| 257 | """ |
| 258 | Use this to create a map from domain to codomain by calling func |
| 259 | (which must be a function pointer taking a Parent and object, and |
| 260 | returning an Element in the given Parent). |
| 261 | |
| 262 | This is the c analogue of CallableConvertMap. |
| 263 | """ |
| 264 | # Cython doesn't yet accept function pointers as arguments, |
| 265 | # change this when it does. |
| 266 | cdef CCallableConvertMap_class map = CCallableConvertMap_class(domain, codomain, name) |
| 267 | map._func = <Element (*)(Parent, object)>func |
| 268 | return map |
| 269 | |
| 270 | cpdef Element _ccall_test_function(codomain, x): |
| 271 | """ |
| 272 | For testing CCallableConvertMap_class. Returns x*x*x-x in the codomain. |
| 273 | |
| 274 | TESTS: |
| 275 | sage: from sage.structure.coerce_maps import _ccall_test_function |
| 276 | sage: _ccall_test_function(ZZ, 1) |
| 277 | 0 |
| 278 | sage: _ccall_test_function(ZZ, 2) |
| 279 | 6 |
| 280 | sage: _ccall_test_function(ZZ, -3) |
| 281 | -24 |
| 282 | """ |
| 283 | return codomain(x*x*x-x) |
| 284 | |
| 285 | def test_CCallableConvertMap(domain, name=None): |
| 286 | """ |
| 287 | For testing CCallableConvertMap_class. |
| 288 | |
| 289 | TESTS: |
| 290 | sage: from sage.structure.coerce_maps import test_CCallableConvertMap |
| 291 | sage: f = test_CCallableConvertMap(ZZ, 'test'); f |
| 292 | Conversion via c call 'test' map: |
| 293 | From: Integer Ring |
| 294 | To: Integer Ring |
| 295 | sage: f(3) |
| 296 | 24 |
| 297 | sage: f(9) |
| 298 | 720 |
| 299 | """ |
| 300 | return CCallableConvertMap(domain, domain, <void*>&_ccall_test_function, name) |
| 301 | |