@@ -1836,7 +1836,83 @@ cdef class GpuArray:
18361836 raise TypeError , " len() of unsized object"
18371837
18381838 def __getitem__ (self , key ):
1839- return self .__cgetitem__(key)
1839+ cdef unsigned int i
1840+
1841+ if key is Ellipsis :
1842+ return self .__cgetitem__(key)
1843+
1844+ # A list or a sequence of list should trigger "fancy" indexing.
1845+ # This is not implemented yet.
1846+ # Conversely, if a list contains slice or Ellipsis objects, it behaves
1847+ # the same as a tuple.
1848+ if isinstance (key, list ):
1849+ if any (isinstance (k, slice ) or k is Ellipsis for k in key):
1850+ return self .__getitem__ (tuple (key))
1851+ else :
1852+ raise NotImplementedError , " fancy indexing not supported"
1853+
1854+ try :
1855+ iter (key)
1856+ except TypeError :
1857+ key = (key,)
1858+ else :
1859+ if all (isinstance (k, list ) for k in key):
1860+ raise NotImplementedError , " fancy indexing not supported"
1861+
1862+ key = tuple (key)
1863+
1864+ # Need to massage Ellipsis here, to avoid packing it into a tuple.
1865+ if key.count(Ellipsis ) > 1 :
1866+ raise IndexError , " cannot use more than one Ellipsis"
1867+
1868+ # The following code replaces an Ellipsis found in the key by
1869+ # the corresponding number of slice(None) objects, depending on the
1870+ # number of dimensions. As example, this allows indexing on the last
1871+ # dimension with a[..., 1:] on any array (including 1-dim). This
1872+ # is also required for numpy compat.
1873+ try :
1874+ ell_idx = key.index(Ellipsis )
1875+ except ValueError :
1876+ pass
1877+ else :
1878+ # Need number of axes minus missing dimensions extra slice(None)
1879+ # objects, not counting None entries and the Ellipsis itself
1880+ num_slcs = self .ga.nd - (len (key) - key.count(None ) - 1 )
1881+ fill_slices = (slice (None ),) * num_slcs
1882+ key = key[:ell_idx] + fill_slices + key[ell_idx + 1 :]
1883+
1884+ # Remove the None entries for indexing
1885+ getitem_idcs = tuple (k for k in key if k is not None )
1886+
1887+ # For less than 1 index, fill up with slice(None) to the right.
1888+ # This allows indexing a[1:] in multi-dimensional arrays, where the
1889+ # slice is applied along the first axis only. It also allows
1890+ # a[()], which simply is a view in Numpy.
1891+ if len (getitem_idcs) <= 1 :
1892+ getitem_idcs = (getitem_idcs +
1893+ (slice (None ),) * (self .ga.nd - len (getitem_idcs)))
1894+
1895+ # Slice into array, then reshape, accommodating for None entries in key
1896+ sliced = self .__cgetitem__(getitem_idcs)
1897+ if key.count(None ) == 0 :
1898+ # Avoid unnecessary reshaping if there was no None
1899+ return sliced
1900+ else :
1901+ new_shape = []
1902+ i = 0
1903+ if sliced.shape:
1904+ for k in key:
1905+ if isinstance (k, int ):
1906+ continue
1907+ elif k is None :
1908+ new_shape.append(1 )
1909+ else :
1910+ new_shape.append(sliced.shape[i])
1911+ i += 1
1912+ # Add remaining entries from sliced.shape if existing (happens
1913+ # for 1 index or less if ndim >= 2).
1914+ new_shape.extend(sliced.shape[i:])
1915+ return sliced.reshape(new_shape)
18401916
18411917 cdef __cgetitem__(self , key):
18421918 cdef ssize_t * starts
@@ -1896,16 +1972,37 @@ cdef class GpuArray:
18961972 steps[i] = 1
18971973
18981974 return pygpu_index(self , starts, stops, steps)
1975+
18991976 finally :
19001977 free(starts)
19011978 free(stops)
19021979 free(steps)
19031980
19041981 def __setitem__ (self , idx , v ):
1905- cdef GpuArray tmp = self .__cgetitem__(idx)
1906- cdef GpuArray gv = carray(v, self .ga.typecode, False , ' A' , 0 ,
1907- self .context, GpuArray)
1982+ cdef GpuArray tmp, gv
1983+
1984+ if isinstance (idx, list ):
1985+ if any (isinstance (i, slice ) or i is Ellipsis for i in idx):
1986+ self .__setitem__ (tuple (idx), v)
1987+ else :
1988+ raise NotImplementedError , " fancy indexing not supported"
1989+ try :
1990+ iter (idx)
1991+ except TypeError :
1992+ idx = (idx,)
1993+ else :
1994+ if all (isinstance (i, list ) for i in idx):
1995+ raise NotImplementedError , " fancy indexing not supported"
1996+
1997+ idx = tuple (idx)
1998+
1999+ if idx.count(Ellipsis ) > 1 :
2000+ raise IndexError , " cannot use more than one Ellipsis"
19082001
2002+ # Remove None entries, they should be ignored (as in Numpy)
2003+ idx = tuple (i for i in idx if i is not None )
2004+ tmp = self .__cgetitem__(idx)
2005+ gv = carray(v, self .ga.typecode, False , ' A' , 0 , self .context, GpuArray)
19092006 array_setarray(tmp, gv)
19102007
19112008 def take1 (self , GpuArray idx ):
0 commit comments