How does cython manage to cimport abs
from libc.math
from libc.math cimport abs
if it is not there?
> grep abs Cython/Includes/libc/math.pxd
<nothing>
I even tried deleting everything from that file (I got a 0 length math.pxd
)
yet it somehow contrives to find abs
there.
Update
This is my third question about cython:
In the first question I found out that libcpp.complex
is not written quite correctly, @axil raised a ticket in cython github repo then made a pull request with my fix that replaces about 20% of complex.pyd lines. So it makes sense for cython user to look into includes directory from time to time.
The second question addressed the abs
builtin which supposedly was overlooked by cython authors in that it doesn't translate python code to c at all and calls the original python abs function. The solution involves patching cython/compiler/Builtin.py
file.
Now my third question is again about abs
function, now imported from 'libc.math'. It does work, but they way it works looks really bizzare to me. In my opinion there's quite enough magic in Cython without importing a function from a module that doesn't have it.
Update 2:
It turns out that is that abs()
does not get imported from lib.math
. In fact, this import is just ignored:
1: from libc.math cimport abs # nothing changes when I comment it out
2:
+3: def f(): # yellow
+4: cdef double complex aaa = 1 + 2j # white
+5: cdef double bbb = abs(aaa) # yellow
__pyx_t_1 = __pyx_PyComplex_FromComplex(__pyx_v_aaa); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
__pyx_t_2 = PyNumber_Absolute(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 5, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 5, __pyx_L1_error)
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __pyx_v_bbb = __pyx_t_3;
It should be noted though that @DavidW's patch from my previous question fixes it in the sense that last line becomes white (gets compiled to c). Yet I don't understand why cimporting abs is ignored.
Update 3
Yet another observation is that importing abs()
from libcpp.complex
works as expected:
# distutils: language = c++
from libcpp.complex cimport complex, abs
ctypedef complex[double] dcomplex
def f():
cdef dcomplex aaa = dcomplex(1, 2)
cdef double bbb = abs[double](aaa)
return bbb
So it isn't a big deal for cython to cimport a builtin.
In C, the "built-in" or globally-available absolute-value function abs
is only for integers (and labs
for longs). The absolute-value function or floating-point numbers is fabs
, found in "math.h".
This translates to using libc.stdlib.abs
for integers, libc.math.fabs
for doubles, and abs
(built-in) for all Python objects. Only the built-in abs
requires GIL.
Cython pxd files located in {Python_path}/.../site_packages/Cython/Includes So if look at libc/stdlib.pxd then you will see that stdlib.pxd got abs() and libcpp/complex.pxd have a template function abs for complex numbers template class. In libc/math.pxd you can find fabs() for floating point types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With