[Numpy-discussion] casting

Robert Kern robert.kern@gmail....
Mon Jan 14 15:36:06 CST 2008


Neal Becker wrote:
> Jon Wright wrote:
> 
>>> I'm sorry, I still think we're talking past each other. What do you mean
>>> by "native data type"? If you just want to get an ndarray without
>>> specifying a type, use PyArray_FROM_O(). That's what it's for. You don't
>>> need to know the data type beforehand.
>> What I have wanted in the past (and what I thought Neal was after) is a
>> way to choose which function to call according to the typecode of the
>> data as it is currently in memory. I don't want to convert (or cast or
>> even touch the data) but just call a type specific function instead. C++
>> templates can take some of the tedium out of that, but in some cases
>> algorithms may be different too. Guessing which sort algorithm to use
>> springs to mind.
>>
>> Rather than saying "give me the right kind of array", I think there is
>> an interest in saying "choose which function is the best for this data".
>> Something like:
>>
>>    PyArrayObject* array = PyArray_FROM_O( (PyObject*) O );
>>    type = array -> descr -> type_num ;
>>    switch (type){
>>       case    NPY_BYTE   : signed_func(array);
>>       case    NPY_UBYTE  : unsigned_func(array);
>>       // etc
>>
>> It sort of implies having a C++ type hierarchy for numpy arrays and
>> casting array to be a PyFloatArray or PyDoubleArray etc?
>>
>> The extra confusion might be due to the way arrays can be laid out in
>> memory - indexing into array slices is not always obvious. Also if you
>> want to make sure your inner loop goes over the "fast" index you might
>> want an algorithm which reads the strides when it runs.
>>
>> Sorry if I've only added to the confusion.
>>
>> Cheers,
>>
>> Jon
> 
> This is close to what I'm doing.  If I really can handle any type, then
> FROM_O is fine.
> 
> Commonly, it's a little more complicated.
> 
> Here is an example, in pseudo-code (real code is in c++):  
> 
> if (native_type_of (x) is int or long):
>   do_something_with (convert_to_long_array(x))
> elif (native_type_of (x) is complex):
>   do_something_with (convert_to_complex_array (x))
> 
> In the above, native_type_of means:
> if (hasattr (x, "__array_struct__")):
>    array_if = PyCObject_AsVoidPtr (x.__array_struct__)
>    return (map_array_if_to_typenum (array_if))
> 
> So this means for any numpy array or any type supporting __array_struct__
> protocol, find out the native data type.
> 
> I don't want to use FROM_O here, because I really can only handle certain
> types.  If I used FROM_O, then after calling FROM_O, if the type was not
> one I could handle, I'd have to call FromAny and convert it.  Or, in the
> case above, if I was given an array of int32 which I'd want to handle as
> long (int64), I'd have to convert it again.

Okay, I think I see now. I'm not sure what numpy could do to make your code more 
elegant. I would recommend just using PyArray_FROM_O() or PyArray_EnsureArray() 
to get a real ndarray object. They should not copy when the object is already an 
ndarray or if it satisfies the array interface; however, it will also handle the 
cases when you have a Python-level __array_interface__ or just nested sequences, 
too. You can look at the PyArray_Descr directly, dispatch the types that you can 
handle directly, and then convert for the types which you can't. You will not 
get any extraneous conversions or copies of data.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco


More information about the Numpy-discussion mailing list