3

According the offical doc: http://docs.cython.org/en/latest/src/tutorial/numpy.html we should "ctypedef" a corresponding compile-time type,but I tried several methods to deal with numpy.bool. It's still wrong.

1.

DTYPE2 = np.bool

ctypedef np.bool_t DTYPE2_t

raise: 'bool_t' is not a type identifier

2.

DTYPE2 = np.bint

ctypedef np.bint_t DTYPE2_t

raise: 'bint_t' is not a type identifier

3. add on the top of the .pyx file:

from libcpp cimport bool
#? As recommended by McKelvin in  [https://stackoverflow.com/questions/24659723/cython-issue-bool-is-not-a-type-identifier][2]
#from libcpp cimport bool_t 
from libcpp.vector cimport vector

no helpful!

4. I've seen the post: Declaring a numpy boolean mask in Cython But I need define the variable in function's parameter to pass a numpy.bool array in.

def Func(np.ndarray[np.bool_t, ndim=1] f)

## def Func(np.ndarray[np.bool, ndim=1] f)

raise: Invalid type

5. ignore the declare? It seems necessory in function's parameters according the offical doc if I want to speedup it:

def naive_convolve(np.ndarray[**DTYPE_t**, ndim=2] f, np.ndarray[DTYPE_t, ndim=2] g):

So what should I do with numpy.bool?

My test is based on the following simple codes:

import numpy as np
cimport numpy as np
cimport cython

DTYPE2 = np.bint
ctypedef np.bint_t DTYPE2_t
def Func(np.ndarray[DTYPE2_t, ndim=1] npdata):
    print(npdata)

cython: the most recent version

windows7 OS

I'm sure cython was installed correctly.It can work well when there isn't np.bool.

neuron
  • 1,949
  • 1
  • 15
  • 30
Stone
  • 31
  • 1
  • 4

1 Answers1

7

The name of the numpy boolean ctype is npy_bool. So the correct version of your test code would be:

import numpy as np
cimport numpy as np
cimport cython

def Func(np.ndarray[np.npy_bool, ndim=1, cast=True] npdata):
    print(npdata)
    return npdata

Note the cast=True above (I also added a return statement for testing purposes). Here's some code testing Func out:

arr = np.random.randint(0,2, size=3, dtype=int)
boolArr = np.array(arr, dtype=bool)

# Func(arr)                     # raises "ValueError: Item size of buffer (8 bytes) does not match size of 'npy_bool' (1 byte)"
returnArr = Func(boolArr)
assert returnArr.dtype is np.dtype(bool)

note about cast

Without the cast keyword, you get a really weird error message when you try to call Func:

ValueError: Does not understand character buffer dtype format string ('?')

Diving into the Cython source code gives a bit of insight into the above ValueError. One of the representations of dtypes that Numpy uses is "array-protocol type strings". The one for bool is '?'. Many of these can be specified using a number, like '4i', which represents how many bytes a single element of that type requires. Cython apparently interprets array types according to this string, and expects there to be a number, which it seems Numpy doesn't supply for bool. Probably just something (in either Numpy or Cython) needs a bugfix somewhere.

Update

The cast=True argument might not be needed for much longer. I submitted a pull request with a fix to Cython, and it seems to be wending its way through.

tel
  • 13,005
  • 2
  • 44
  • 62