[Cython] Interest in contributing to the project

Sturla Molden sturla at molden.no
Mon Apr 4 01:49:37 CEST 2011


Den 03.04.2011 04:17, skrev Arthur de Souza Ribeiro:
>
> static PyMethodDef cmath_methods[] = {
>     {"acos",   cmath_acos,  METH_VARARGS, c_acos_doc},
>     {"acosh",  cmath_acosh, METH_VARARGS, c_acosh_doc},
>     {"asin",   cmath_asin,  METH_VARARGS, c_asin_doc},
>     {"asinh",  cmath_asinh, METH_VARARGS, c_asinh_doc},
>     {"atan",   cmath_atan,  METH_VARARGS, c_atan_doc},
>     {"atanh",  cmath_atanh, METH_VARARGS, c_atanh_doc},
>     {"cos",    cmath_cos,   METH_VARARGS, c_cos_doc},
>     {"cosh",   cmath_cosh,  METH_VARARGS, c_cosh_doc},
>     {"exp",    cmath_exp,   METH_VARARGS, c_exp_doc},
>     {"isfinite", cmath_isfinite, METH_VARARGS, cmath_isfinite_doc},
>     {"isinf",  cmath_isinf, METH_VARARGS, cmath_isinf_doc},
>     {"isnan",  cmath_isnan, METH_VARARGS, cmath_isnan_doc},
>     {"log",    cmath_log,   METH_VARARGS, cmath_log_doc},
>     {"log10",  cmath_log10, METH_VARARGS, c_log10_doc},
>     {"phase",  cmath_phase, METH_VARARGS, cmath_phase_doc},
>     {"polar",  cmath_polar, METH_VARARGS, cmath_polar_doc},
>     {"rect",   cmath_rect,  METH_VARARGS, cmath_rect_doc},
>     {"sin",    cmath_sin,   METH_VARARGS, c_sin_doc},
>     {"sinh",   cmath_sinh,  METH_VARARGS, c_sinh_doc},
>     {"sqrt",   cmath_sqrt,  METH_VARARGS, c_sqrt_doc},
>     {"tan",    cmath_tan,   METH_VARARGS, c_tan_doc},
>     {"tanh",   cmath_tanh,  METH_VARARGS, c_tanh_doc},
>     {NULL,              NULL}           /* sentinel */
> };
>
>
> static struct PyModuleDef cmathmodule = {
>     PyModuleDef_HEAD_INIT,
>     "cmath",
>     module_doc,
>     -1,
>     cmath_methods,
>     NULL,
>     NULL,
>     NULL,
>     NULL
> };
>

Cython will make this, do not care about it. You don't have to set up 
jump tables to make Python get the right function from Cython generated 
C code. If you have 22 Python-callable functions (i.e. declared def or 
cpdef), Cython will make a jump table for those as above.



> Another stuff that I'm getting in trouble in this initial part is how 
> we would translate functions like PyArg_ParseTuple, any clue? I'm 
> studing ways to replace too.
>

Do not care about PyArg_ParseTuple either. It's what C Python needs to 
parse function call arguments from a tuple into C primitives. Cython 
will do this, which is some of the raison d'etre for using Cython.

Also observe that any initialisation done in PyInit_cmathshould go as a 
module level function call in Cython, i.e. PyInit_cmathis called on 
import just like module level Python and Cython code.

I don't have time to implement all of cmathmodule.c, but here is a 
starter (not tested & not complete).

It might actually be that we should use "cdef complex z" instead of 
"cdef double complex z". There might be a distinction in the generated 
C/C++ code between those types, e.g. Py_complex for complex and "double 
_Complex" or "std::complex<double>" for double complex,  even though 
they are binary equivalent. I'm not sure about the state of Cython with 
respect to complex numbers, so just try it and see which works better :-)

Also observe that we do not release the GIL here. That is not because 
these functions are not thread-safe, they are, but yielding the GIL will 
slow things terribly.

Sturla





cimport math
cimport stdlib


cdef extern from "_math.h":
     int Py_IS_FINITE(double)
     int Py_IS_NAN(double)
     double copysign(double,double)


cdef enum special_types:
     ST_NINF  # 0, negative infinity
     ST_NEG   # 1, negative finite number (nonzero)
     ST_NZERO # 2, -0.
     ST_PZERO # 3, +0.
     ST_POS   # 4, positive finite number (nonzero)
     ST_PINF  # 5, positive infinity
     ST_NAN   # 6, Not a Number


cdef inline special_types special_type(double d):
     if (Py_IS_FINITE(d)):
         if (d != 0):
             if (copysign(1., d) == 1.):
                 return ST_POS
             else
                 return ST_NEG
         else:
             if (copysign(1., d) == 1.):
                 return ST_PZERO
             else
                 return ST_NZERO
     if (Py_IS_NAN(d)):
         return ST_NAN
     if (copysign(1., d) == 1.):
         return ST_PINF
     else:
         return ST_NINF


cdef void INIT_SPECIAL_VALUES( double complex *table,
                                double complex arc[][7]):
     stdlib.memcpy(table, &(src[0][0]), 7*7*sizeof(double complex))



cdef inline double complex *SPECIAL_VALUE(double complex z, double 
complex table[][7]):
     if (not Py_IS_FINITE(z.real)) or (not Py_IS_FINITE(z.imag)):
         errno = 0
         return &(table[special_type(z.real)][special_type(z.imag)])
     else:
         return NULL



cdef double complex acosh_special_values[7][7]

INIT_SPECIAL_VALUES( acos_special_values, {
  C(P34,INF) C(P,INF) C(P,INF) C(P,-INF) C(P,-INF) C(P34,-INF) C(N,INF)
  C(P12,INF) C(U,U) C(U,U) C(U,U) C(U,U) C(P12,-INF) C(N,N)
  C(P12,INF) C(U,U) C(P12,0.) C(P12,-0.) C(U,U) C(P12,-INF) C(P12,N)
  C(P12,INF) C(U,U) C(P12,0.) C(P12,-0.) C(U,U) C(P12,-INF) C(P12,N)
  C(P12,INF) C(U,U) C(U,U) C(U,U) C(U,U) C(P12,-INF) C(N,N)
  C(P14,INF) C(0.,INF) C(0.,INF) C(0.,-INF) C(0.,-INF) C(P14,-INF) C(N,INF)
  C(N,INF) C(N,N) C(N,N) C(N,N) C(N,N) C(N,-INF) C(N,N)
  })



cdef double complex cmath_acosh(double complex z):

     cdef double complex s1, s2, r, *psv

     psv = SPECIAL_VALUE(z, acosh_special_values)
     if (psv != NULL):
         return psv[0]

     if (math.fabs(z.real) > CM_LARGE_DOUBLE or math.fabs(z.imag) > 
CM_LARGE_DOUBLE):
         # avoid unnecessary overflow for large arguments
         r.real = math.log(hypot(z.real/2., z.imag/2.)) + M_LN2*2.
         r.imag = math.atan2(z.imag, z.real)
     else:
         s1.real = z.real - 1.
         s1.imag = z.imag
         s1 = cmath_sqrt(s1) # cdef double complex cmath_sqrt(double 
complex z)
         s2.real = z.real + 1.
         s2.imag = z.imag
         s2 = cmath_sqrt(s2)
         r.real = math.asinh(s1.real*s2.real + s1.imag*s2.imag)
         r.imag = 2.*math.atan2(s1.imag, s2.real)
     errno = 0
     return r


def acosh(object arg):
     """acos(x)

Return the arc cosine of x."""
     double complex z
     z = cmath_acosh(<double complex> arg)
     return complex(z)






























More information about the cython-devel mailing list