I see them imported in devel/sage/sage/ext/stdsage.pxi:
-----------------------
cdef extern from "stdsage.h":
ctypedef void PyObject
# Global tuple -- useful optimization
void init_global_empty_tuple()
object PY_NEW(object t)
object PY_NEW_SAME_TYPE(object t)
void* PY_TYPE(object o)
bint PY_TYPE_CHECK(object o, object t)
bint PY_TYPE_CHECK_EXACT(object o, object t)
object IS_INSTANCE(object o, object t)
void PY_SET_TP_NEW(object t1, object t2)
bint HAS_DICTIONARY(object o)
bint PY_IS_NUMERIC(object o)
-----------------------
The stdsage.h file is in devel/sage/c_lib/include/stdsage.h, where we find:
-----------------------
/** Tests whether zzz_obj is of type zzz_type. The zzz_type must be a
* built-in or extension type. This is just a C++-compatible wrapper
* for PyObject_TypeCheck.
*/
#define PY_TYPE_CHECK(zzz_obj, zzz_type) \
(PyObject_TypeCheck((PyObject*)(zzz_obj), (PyTypeObject*)(zzz_type)))
-----------------------
in fact, we find later on:
-----------------------
/** This is exactly the same as isinstance (and does return a Python
* bool), but the second argument must be a C-extension type -- so it
* can't be a Python class or a list. If you just want an int return
* value, i.e., aren't going to pass this back to Python, just use
* PY_TYPE_CHECK.
*/
#define IS_INSTANCE(zzz_obj, zzz_type) \
PyBool_FromLong(PY_TYPE_CHECK(zzz_obj, zzz_type))
-----------------------
...interpret how you will....
I notice in the generated C code, Cython is smart and makes isinstance
actually call PyInt_Check, which presumably is faster than PY_TYPE_CHECK.
If instead, you are checking for the Integer type, I get faster numbers
for PY_TYPE_CHECK than isinstance. I also tried to lessen the effects
of python call overhead by running the call in a loop in Cython:
http://demo.sagenb.org/home/pub/65/
Thanks,
Jason
On Mon, Dec 20, 2010 at 12:34 PM, Volker Braun <vbrau...@gmail.com> wrote:
> PY_TYPE_CHECK is just a wrapper macro around PyObject_TypeCheck which
> dereferences and compares the object type fields. So that part should be
> insanely fast.
If A is a cdef'd type (which is the precondition for using
PY_TYPE_CHECK), then "isinstance(x, A)" produces exactly the same code
as "PY_TYPE_CHECK(x, A)" (a single inline call to PyObject_TypeCheck).
Thus I'd say it's better to use the Pythonic isinstance. For some
builtins it can use even more specialized code.
No, it's because your loop is over 10000 rather than 1000.
- Robert
if you do "from sage.rings.integer cimport Integer" the speed
difference should go away.
- Robert
Yes, as long as the rhs is known by the compiler to be a type
(extension or built-in).
> I guess we should remove the
> PY_TYPE_CHECK macro from Sage altogether and replace every occurrence with
> isinstance?
Exactly. However, I just found a compiler crash with isinstance(x,
<type>t), so we should wait for the next Cython to go in before doing
this. There's a lot of cruft from when Cython just wasn't as good as
it is now that's still being used.
- Robert
Do you mean wait until Cython 0.14 goes into Sage, or wait until Cython
0.15 is released and goes into Sage?
Jason
0.14.1, which I'm thinking will be out in January (in time for 4.6.2,
and I think the 4.6.1 window is almost closed anyway).
- Robert