As @DawidW has already pointed out, you should use fabs
from math.h
in your case.
I would like to elaborate a little bit about the causes (as I understand it):
- It is probably a bug: they can
cimport
abs
from everywhere: cython
, numpy
and so on. Or don't import it at all - this stays the build-in abs
.
- Cython tries to replace the Python-functionality through C-counterparts for build-in functions, the whole list is here. Depending on the type of the input Python-
abs
, C-abs
, fabs
, fabsf
and so on are used.
For example:
%%cython
from numpy cimport abs # just for fun, "cimport" abs from numpy!
cdef do_abs(object o, int i, double d):
print(abs(o))
print(abs(i))
print(abs(d))
Here, automatically:
abs(o)
is translated to __Pyx_PyNumber_Absolute
(Python's functionality)
abs(i)
is translated to abs
from stdlib.h
abs(d)
is translated to fabs
from math.h
In the case of 2. and 3. gil is not needed, however from the Cython's point of view the Python-abs is in use (even if it is mapped to different functions) which is not defined as "nogil" and thus gil is needed.
What happens if we really cimport abs
from clib.stdlib
?
%%cython
from libc.stdlib cimport abs
cdef do_abs(object o, int i, double d):
print(abs(o))
print(abs(i))
print(abs(d))
We get:
- Cython tries to cast
o
to an C-integer (which might fail during the run time) and to call C-abs
on its result.
- uses C-abs for the integer
i
- doesn't compile, because Cython prevents the usage of a
double
value as integer (which is a Good Thing, there were spent a lot of debugging hours because C-compilers just cast the double-value to an integer (giving a warning if you are lucky)).
The main difference: using abs
for the integer argument allows now nogil.
Some somewhat unrelated comments on your code:
A. Define cdef double my_abs(double a) nogil
to be able to use it a nogil-section.
B. I'm not sure, Cython understand everything correctly when you pass a python-object as a varargin, because how should it deduce the right type to which the Python-object should be coerced? It is probably better to help it via an explicit cast, for example:
printf("%d %s", abs(i), <char *>"\n")