[Numpy-tickets] [NumPy] #474: Record type inconsistency between rank 0 recarrays and rank > 0 recarrays

NumPy numpy-tickets@scipy....
Fri Mar 23 15:03:07 CDT 2007


#474: Record type inconsistency between rank 0 recarrays and rank > 0 recarrays
---------------------------+------------------------------------------------
 Reporter:  SuperElectric  |       Owner:  somebody                                     
     Type:  defect         |      Status:  new                                          
 Priority:  normal         |   Milestone:                                               
Component:  numpy.core     |     Version:                                               
 Severity:  normal         |    Keywords:  rank, rank-0, vectorization, recarray, record
---------------------------+------------------------------------------------
 = Short description =

 The records of rank-N record arrays are usually returned as rank-N
 ndarrays. However, if N is 0, the records are returned as scalars. This
 makes it problematic to write general vectorized code that operates on
 arbitrary-rank record arrays, as expressions like "recarr.x[...] = 2" fail
 if rank = 0.

 = Example =
 {{{
 >>> import numpy as N
 >>> dt = N.dtype([('x','f8'),('y','f8')])
 >>> rarr = N.zeros((), dtype = dt).view(N.recarray)
 >>> rarr
 recarray((0.0, 0.0),
      dtype=[('x', '<f8'), ('y', '<f8')])
 >>> # oddly, rarr.x is not an array
 >>> rarr.x
 0.0
 >>> # This makes it impossible to fill values in the usual manner
 >>> rarr.x[...] = 2.0
 TypeError: object does not support item assignment
 >>> # A workaround is to reshape to non-zero rank
 >>> rarr.shape = [1]
 >>> # Now rarr.x returns a ndarray of the same rank as rarr
 >>> rarr.x
 array([ 0.])
 >>> # Value-setting now works as expected. >>> rarr.x[...] = 2.0
 >>> rarr   recarray([(2.0, 0.0)],
      dtype=[('x', '<f8'), ('y', '<f8')])
 }}}

 = Workaround =
 The fallout of this bug can be illustrated by its workaround. You need to
 insert special checks for ndim==0, and temporarily reshape the record
 array to rank > 0 before performing array operations on its records.

 In other words, you need to replace this:
 {{{
 rarr.x[...] = blah
 return rarr
 }}}

 With this:
 {{{
 if rarr.ndim == 0:
    rarr = output.reshape([1])
    rarrWas0dim = True
 else:
    rarrWas0dim = False

 rarr.x[...] = blah

 if rarrWas0dim:
    rarr = rarr.reshape([])

 return rarr
 }}}

 This code bloat quickly gets nasty when dealing with arithmetic between
 many record arrays, all of which may be of rank 0.

-- 
Ticket URL: <http://projects.scipy.org/scipy/numpy/ticket/474>
NumPy <http://projects.scipy.org/scipy/numpy>
The fundamental package needed for scientific computing with Python.


More information about the Numpy-tickets mailing list