def array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0): # We're going to ignore this for now # if(subok is not False): # raise NotImplementedError if(order is not None and order is not 'K' and order is not 'C'): raise NotImplementedError # If it's not a numpy or afnumpy array first create a numpy array from it if(not isinstance(object, ndarray) and not isinstance(object, numpy.ndarray)): object = numpy.array(object, dtype=dtype, copy=copy, order=order, subok=subok, ndmin=ndmin) shape = object.shape while(ndmin > len(shape)): shape = (1,)+shape if(dtype is None): dtype = object.dtype if(isinstance(object, ndarray)): if(copy): s = arrayfire.cast(object.d_array.copy(), pu.typemap(dtype)) else: s = arrayfire.cast(object.d_array, pu.typemap(dtype)) return ndarray(shape, dtype=dtype, af_array=s) elif(isinstance(object, numpy.ndarray)): return ndarray(shape, dtype=dtype, buffer=object.astype(dtype, copy=copy)) else: raise AssertionError
def wrapper(a, axis=None, dtype=None, keepdims=False): if not isinstance(axis, tuple): axis = (axis,) if axis[0] is None: # Special case for speed a_flat = a.flat s = func(a_flat, a_flat.d_array, pu.c2f(a_flat.shape, 0)) if keepdims: shape = (1,)*a.ndim else: shape = () ret = afnumpy.ndarray(tuple(shape), dtype=pu.typemap(s.dtype()), af_array=s) else: shape = list(a.shape) s = a.d_array # Do in decreasing axis order to avoid problems with the pop for ax in sorted(axis)[::-1]: # Optimization if(a.shape[ax] > 1): s = func(a, s, pu.c2f(a.shape, ax)) if keepdims: shape[ax] = 1 else: shape.pop(ax) ret = afnumpy.ndarray(tuple(shape), dtype=pu.typemap(s.dtype()), af_array=s) if(dtype is not None): ret = ret.astype(dtype) if(len(shape) == 0): ret = ret[()] return ret
def argmin(self, axis=None): if axis is None: return self.flat.argmin(axis=0) if not isinstance(axis, numbers.Number): raise TypeError('an integer is required for the axis') val, idx = arrayfire.imin(self.d_array, pu.c2f(self.shape, axis)) shape = list(self.shape) shape.pop(axis) if(len(shape)): return ndarray(shape, dtype=pu.typemap(idx.dtype()), af_array=idx) else: return ndarray(shape, dtype=pu.typemap(idx.dtype()), af_array=idx)[()]
def __rpow__(self, other): if(isinstance(other, numbers.Number) and numpy.issubdtype(type(other), numpy.float) and numpy.issubdtype(self.dtype, numpy.integer)): # AF does not automatically upconvert A**0.5 to float for integer arrays s = arrayfire.pow(pu.raw(other), self.astype(type(other)).d_array) else: s = arrayfire.pow(pu.raw(other), self.d_array) return ndarray(self.shape, dtype=pu.typemap(s.dtype()), af_array=s)
def round(self, decimals=0, out=None): if decimals != 0: raise NotImplementedError('only supports decimals=0') s = arrayfire.round(self.d_array) ret = ndarray(self.shape, dtype=pu.typemap(s.dtype()), af_array=s) if(out): out[:] = ret[:] return ret
def conj(self): if not numpy.issubdtype(self.dtype, numpy.complex): return afnumpy.copy(self) if(self.d_array is not None): s = arrayfire.conjg(self.d_array) return ndarray(self.shape, dtype=pu.typemap(s.dtype()), af_array=s) else: return self.h_array.conj()
def argsort(self, axis=-1, kind='quicksort', order=None): if kind != 'quicksort': print "argsort 'kind' argument ignored" if order is not None: raise ValueError('order argument is not supported') if(axis < 0): axis = self.ndim+axis val, idx = arrayfire.sort_index(self.d_array, pu.c2f(self.shape, axis)) return ndarray(self.shape, dtype=pu.typemap(idx.dtype()), af_array=idx)
def astype(self, dtype, order='K', casting='unsafe', subok=True, copy=True): if(self.d_array is not None): if(order != 'K'): raise NotImplementedError('only order=K implemented') if(casting != 'unsafe'): raise NotImplementedError('only casting=unsafe implemented') if(copy == False and order == 'K' and dtype == self.dtype): return self # s = self.d_array.astype(pu.typemap(dtype)) s = arrayfire.cast(self.d_array, pu.typemap(dtype)) return ndarray(self.shape, dtype=dtype, af_array=s) else: return array(self.h_array.astype(dtype, order, casting, subok, copy), dtype=dtype)
def imag(self): ret_type = numpy.real(numpy.zeros((),dtype=self.dtype)).dtype shape = list(self.shape) if not numpy.issubdtype(self.dtype, numpy.complexfloating): return afnumpy.zeros(self.shape) shape[-1] *= 2 dims = numpy.array(pu.c2f(shape),dtype=pu.dim_t) s = arrayfire.Array() arrayfire.backend.get().af_device_array(ctypes.pointer(s.arr), ctypes.c_void_p(self.d_array.device_ptr()), self.ndim, ctypes.c_void_p(dims.ctypes.data), pu.typemap(ret_type).value) arrayfire.backend.get().af_retain_array(ctypes.pointer(s.arr),s.arr) a = ndarray(shape, dtype=ret_type, af_array=s) ret = a[...,1::2] ret._base = a ret._base_index = (Ellipsis, slice(1,None,2)) return ret
def __fftn__(a, s, axes, direction='forward'): if len(s) != 3 and len(s) != 2 and len(s) != 1: raise NotImplementedError if axes is not None: raise NotImplementedError if(direction == 'forward'): if len(s) == 3: fa = arrayfire.fft3(a.d_array, s[2], s[1], s[0]) elif len(s) == 2: fa = arrayfire.fft2(a.d_array, s[1], s[0]) elif len(s) == 1: fa = arrayfire.fft(a.d_array, s[0]) elif direction == 'inverse': if len(s) == 3: fa = arrayfire.ifft3(a.d_array, s[2], s[1], s[0]) elif len(s) == 2: fa = arrayfire.ifft2(a.d_array, s[1], s[0]) elif len(s) == 1: fa = arrayfire.ifft(a.d_array, s[0]) else: raise ValueError('Wrong FFT direction') return ndarray(a.shape, dtype=pu.typemap(fa.dtype()), af_array=fa)
def __init__(self, shape, dtype=float, buffer=None, offset=0, strides=None, order=None, af_array=None): self._base = None if(offset != 0): raise NotImplementedError('offset must be 0') if(strides is not None): raise NotImplementedError('strides must be None') if(order is not None and order != 'C'): raise NotImplementedError('order must be None') if isinstance(shape, numbers.Number): self._shape = (shape,) else: self._shape = tuple(shape) self.dtype = dtype s_a = numpy.array(pu.c2f(shape),dtype=pu.dim_t) if(s_a.size < 1): # We'll use af_arrays of size (1) to keep scalars s_a = numpy.array((1),dtype=pu.dim_t) if(s_a.size <= 4): if(af_array is not None): # We need to make sure to keep a copy of af_array # Otherwise python will free it and havoc ensues self.d_array = af_array else: out_arr = ctypes.c_void_p(0) if(buffer is not None): arrayfire.backend.get().af_create_array(ctypes.pointer(out_arr), ctypes.c_void_p(buffer.ctypes.data), s_a.size, ctypes.c_void_p(s_a.ctypes.data), pu.typemap(dtype).value) else: arrayfire.backend.get().af_create_handle(ctypes.pointer(out_arr), s_a.size, ctypes.c_void_p(s_a.ctypes.data), pu.typemap(dtype).value) self.d_array = arrayfire.Array() self.d_array.arr = out_arr else: raise NotImplementedError('Only up to 4 dimensions are supported') self.h_array = numpy.ndarray(shape,dtype,buffer,offset,strides,order)
def __rdiv__(self, other): s = pu.raw(other) / self.d_array return ndarray(self.shape, dtype=pu.typemap(s.dtype()), af_array=s)
def prod(self, s, axis): if self.dtype == numpy.bool: s = s.astype(pu.typemap(numpy.int64)) return arrayfire.product(s, axis)
def mean(self, s, axis): if self.dtype == numpy.bool: s = s.astype(pu.typemap(numpy.float64)) return arrayfire.mean(s, axis)
def sum(self, s, axis): if self.dtype == numpy.bool: s = arrayfire.cast(s, pu.typemap(numpy.int64)) # s = s.astype(pu.typemap(numpy.int64)) return arrayfire.sum(s, axis)
def __mul__(self, other): s = self.d_array * pu.raw(other) return ndarray(self.shape, dtype=pu.typemap(s.dtype()), af_array=s)
def __abs__(self): s = arrayfire.abs(self.d_array) # dtype is wrong for complex types return ndarray(self.shape, dtype=pu.typemap(s.dtype()), af_array=s)