1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
from rpython.rtyper.lltypesystem import lltype, rffi
from pypy.module.cpyext.api import (PyObjectFields, bootstrap_function,
cpython_api, cpython_struct, PyObject, build_type_checkers)
from pypy.module.cpyext.pyobject import (
make_typedescr, track_reference, from_ref)
from pypy.objspace.std.complexobject import W_ComplexObject, unpackcomplex
from pypy.interpreter.error import oefmt
PyComplex_Check, PyComplex_CheckExact = build_type_checkers("Complex")
Py_complex_t = rffi.CStruct('Py_complex_t',
('real', rffi.DOUBLE),
('imag', rffi.DOUBLE),
hints={'size': 2 * rffi.sizeof(rffi.DOUBLE)})
Py_complex_ptr = lltype.Ptr(Py_complex_t)
PyComplexObjectStruct = lltype.ForwardReference()
PyComplexObject = lltype.Ptr(PyComplexObjectStruct)
PyComplexObjectFields = PyObjectFields + \
(("cval", Py_complex_t),)
cpython_struct("PyComplexObject", PyComplexObjectFields, PyComplexObjectStruct)
@bootstrap_function
def init_complexobject(space):
"Type description of PyComplexObject"
make_typedescr(space.w_complex.layout.typedef,
basestruct=PyComplexObject.TO,
attach=complex_attach,
realize=complex_realize)
def complex_attach(space, py_obj, w_obj, w_userdata=None):
"""
Fills a newly allocated PyComplexObject with the given complex object. The
value must not be modified.
"""
assert isinstance(w_obj, W_ComplexObject)
py_obj = rffi.cast(PyComplexObject, py_obj)
py_obj.c_cval.c_real = w_obj.realval
py_obj.c_cval.c_imag = w_obj.imagval
def complex_realize(space, obj):
py_obj = rffi.cast(PyComplexObject, obj)
w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
w_obj = space.allocate_instance(W_ComplexObject, w_type)
w_obj.__init__(py_obj.c_cval.c_real, py_obj.c_cval.c_imag)
track_reference(space, obj, w_obj)
return w_obj
@cpython_api([lltype.Float, lltype.Float], PyObject)
def PyComplex_FromDoubles(space, real, imag):
return space.newcomplex(real, imag)
@cpython_api([PyObject], lltype.Float, error=-1)
def PyComplex_RealAsDouble(space, w_obj):
if space.isinstance_w(w_obj, space.w_complex):
assert isinstance(w_obj, W_ComplexObject)
return w_obj.realval
else:
return space.float_w(w_obj)
@cpython_api([PyObject], lltype.Float, error=-1)
def PyComplex_ImagAsDouble(space, w_obj):
if space.isinstance_w(w_obj, space.w_complex):
assert isinstance(w_obj, W_ComplexObject)
return w_obj.imagval
else:
# CPython also accepts anything
return 0.0
@cpython_api([Py_complex_ptr], PyObject)
def _PyComplex_FromCComplex(space, v):
"""Create a new Python complex number object from a C Py_complex value."""
return space.newcomplex(v.c_real, v.c_imag)
# lltype does not handle functions returning a structure. This implements a
# helper function, which takes as argument a reference to the return value.
# The real function is in src/complexobject.c
@cpython_api([PyObject, Py_complex_ptr], rffi.INT_real, error=-1)
def _PyComplex_AsCComplex(space, w_obj, result):
"""Return the Py_complex value of the complex number op.
If op is not a Python complex number object but has a __complex__()
method, this method will first be called to convert op to a Python complex
number object."""
# return -1 on failure
realvalue, imagvalue = unpackcomplex(space, w_obj, allow_subclass=True)
result.c_real = realvalue
result.c_imag = imagvalue
return 0
|