diff --git a/arrayfire/__init__.py b/arrayfire/__init__.py index 74d1dca43..255fbbeeb 100644 --- a/arrayfire/__init__.py +++ b/arrayfire/__init__.py @@ -72,6 +72,8 @@ from .index import * from .interop import * from .timer import * +from .random import * +from .sparse import * # do not export default modules as part of arrayfire del ct diff --git a/arrayfire/algorithm.py b/arrayfire/algorithm.py index 6701d96a8..a219ea663 100644 --- a/arrayfire/algorithm.py +++ b/arrayfire/algorithm.py @@ -299,6 +299,71 @@ def accum(a, dim=0): """ return _parallel_dim(a, dim, backend.get().af_accum) +def scan(a, dim=0, op=BINARYOP.ADD, inclusive_scan=True): + """ + Generalized scan of an array. + + Parameters + ---------- + a : af.Array + Multi dimensional arrayfire array. + + dim : optional: int. default: 0 + Dimension along which the scan is performed. + + op : optional: af.BINARYOP. default: af.BINARYOP.ADD. + Binary option the scan algorithm uses. Can be one of: + - af.BINARYOP.ADD + - af.BINARYOP.MUL + - af.BINARYOP.MIN + - af.BINARYOP.MAX + + inclusive_scan: optional: bool. default: True + Specifies if the scan is inclusive + + Returns + --------- + out : af.Array + - will contain scan of input. + """ + out = Array() + safe_call(backend.get().af_scan(ct.pointer(out.arr), a.arr, dim, op.value, inclusive_scan)) + return out + +def scan_by_key(key, a, dim=0, op=BINARYOP.ADD, inclusive_scan=True): + """ + Generalized scan by key of an array. + + Parameters + ---------- + key : af.Array + key array. + + a : af.Array + Multi dimensional arrayfire array. + + dim : optional: int. default: 0 + Dimension along which the scan is performed. + + op : optional: af.BINARYOP. default: af.BINARYOP.ADD. + Binary option the scan algorithm uses. Can be one of: + - af.BINARYOP.ADD + - af.BINARYOP.MUL + - af.BINARYOP.MIN + - af.BINARYOP.MAX + + inclusive_scan: optional: bool. default: True + Specifies if the scan is inclusive + + Returns + --------- + out : af.Array + - will contain scan of input. + """ + out = Array() + safe_call(backend.get().af_scan_by_key(ct.pointer(out.arr), key.arr, a.arr, dim, op.value, inclusive_scan)) + return out + def where(a): """ Find the indices of non zero elements diff --git a/arrayfire/arith.py b/arrayfire/arith.py index 4c73e59bf..3b397c4a5 100644 --- a/arrayfire/arith.py +++ b/arrayfire/arith.py @@ -126,6 +126,44 @@ def maxof(lhs, rhs): """ return _arith_binary_func(lhs, rhs, backend.get().af_maxof) +def clamp(val, low, high): + """ + Clamp the input value between low and high + + + Parameters + ---------- + val : af.Array + Multi dimensional arrayfire array to be clamped. + + low : af.Array or scalar + Multi dimensional arrayfire array or a scalar number denoting the lower value(s). + + high : af.Array or scalar + Multi dimensional arrayfire array or a scalar number denoting the higher value(s). + """ + out = Array() + + is_low_array = isinstance(low, Array) + is_high_array = isinstance(high, Array) + + vdims = dim4_to_tuple(val.dims()) + vty = val.type() + + if not is_low_array: + low_arr = constant_array(low, vdims[0], vdims[1], vdims[2], vdims[3], vty) + else: + low_arr = low.arr + + if not is_high_array: + high_arr = constant_array(high, vdims[0], vdims[1], vdims[2], vdims[3], vty) + else: + high_arr = high.arr + + safe_call(backend.get().af_clamp(ct.pointer(out.arr), val.arr, low_arr, high_arr, _bcast_var.get())) + + return out + def rem(lhs, rhs): """ Find the remainder. diff --git a/arrayfire/array.py b/arrayfire/array.py index 2c2eda464..4e27af691 100644 --- a/arrayfire/array.py +++ b/arrayfire/array.py @@ -667,6 +667,14 @@ def is_vector(self): safe_call(backend.get().af_is_vector(ct.pointer(res), self.arr)) return res.value + def is_sparse(self): + """ + Check if the array is a sparse matrix. + """ + res = ct.c_bool(False) + safe_call(backend.get().af_is_sparse(ct.pointer(res), self.arr)) + return res.value + def is_complex(self): """ Check if the array is of complex type. diff --git a/arrayfire/data.py b/arrayfire/data.py index 0df045fca..786d64902 100644 --- a/arrayfire/data.py +++ b/arrayfire/data.py @@ -16,6 +16,7 @@ from .array import * from .util import * from .util import _is_number +from .random import randu, randn, set_seed, get_seed def constant(val, d0, d1=None, d2=None, d3=None, dtype=Dtype.f32): """ @@ -186,105 +187,6 @@ def iota(d0, d1=None, d2=None, d3=None, dim=-1, tile_dims=None, dtype=Dtype.f32) 4, ct.pointer(tdims), dtype.value)) return out -def randu(d0, d1=None, d2=None, d3=None, dtype=Dtype.f32): - """ - Create a multi dimensional array containing values from a uniform distribution. - - Parameters - ---------- - d0 : int. - Length of first dimension. - - d1 : optional: int. default: None. - Length of second dimension. - - d2 : optional: int. default: None. - Length of third dimension. - - d3 : optional: int. default: None. - Length of fourth dimension. - - dtype : optional: af.Dtype. default: af.Dtype.f32. - Data type of the array. - - Returns - ------- - - out : af.Array - Multi dimensional array whose elements are sampled uniformly between [0, 1]. - - If d1 is None, `out` is 1D of size (d0,). - - If d1 is not None and d2 is None, `out` is 2D of size (d0, d1). - - If d1 and d2 are not None and d3 is None, `out` is 3D of size (d0, d1, d2). - - If d1, d2, d3 are all not None, `out` is 4D of size (d0, d1, d2, d3). - """ - out = Array() - dims = dim4(d0, d1, d2, d3) - - safe_call(backend.get().af_randu(ct.pointer(out.arr), 4, ct.pointer(dims), dtype.value)) - return out - -def randn(d0, d1=None, d2=None, d3=None, dtype=Dtype.f32): - """ - Create a multi dimensional array containing values from a normal distribution. - - Parameters - ---------- - d0 : int. - Length of first dimension. - - d1 : optional: int. default: None. - Length of second dimension. - - d2 : optional: int. default: None. - Length of third dimension. - - d3 : optional: int. default: None. - Length of fourth dimension. - - dtype : optional: af.Dtype. default: af.Dtype.f32. - Data type of the array. - - Returns - ------- - - out : af.Array - Multi dimensional array whose elements are sampled from a normal distribution with mean 0 and sigma of 1. - - If d1 is None, `out` is 1D of size (d0,). - - If d1 is not None and d2 is None, `out` is 2D of size (d0, d1). - - If d1 and d2 are not None and d3 is None, `out` is 3D of size (d0, d1, d2). - - If d1, d2, d3 are all not None, `out` is 4D of size (d0, d1, d2, d3). - """ - - out = Array() - dims = dim4(d0, d1, d2, d3) - - safe_call(backend.get().af_randn(ct.pointer(out.arr), 4, ct.pointer(dims), dtype.value)) - return out - -def set_seed(seed=0): - """ - Set the seed for the random number generator. - - Parameters - ---------- - seed: int. - Seed for the random number generator - """ - safe_call(backend.get().af_set_seed(ct.c_ulonglong(seed))) - -def get_seed(): - """ - Get the seed for the random number generator. - - Returns - ---------- - seed: int. - Seed for the random number generator - """ - seed = ct.c_ulonglong(0) - safe_call(backend.get().af_get_seed(ct.pointer(seed))) - return seed.value - def identity(d0, d1, d2=None, d3=None, dtype=Dtype.f32): """ Create an identity matrix or batch of identity matrices. diff --git a/arrayfire/device.py b/arrayfire/device.py index 0a303851e..b13989b65 100644 --- a/arrayfire/device.py +++ b/arrayfire/device.py @@ -163,24 +163,87 @@ def sync(device=None): safe_call(backend.get().af_sync(dev)) def __eval(*args): - for A in args: - if isinstance(A, tuple): - __eval(*A) - if isinstance(A, list): - __eval(*A) - if isinstance(A, Array): - safe_call(backend.get().af_eval(A.arr)) + nargs = len(args) + if (nargs == 1): + safe_call(backend.get().af_eval(args[0].arr)) + else: + c_void_p_n = ct.c_void_p * nargs + arrs = c_void_p_n() + for n in range(nargs): + arrs[n] = args[n].arr + safe_call(backend.get().af_eval_multiple(ct.c_int(nargs), ct.pointer(arrs))) + return def eval(*args): """ - Evaluate the input + Evaluate one or more inputs together Parameters ----------- args : arguments to be evaluated + + Note + ----- + + All the input arrays to this function should be of the same size. + + Examples + -------- + + >>> a = af.constant(1, 3, 3) + >>> b = af.constant(2, 3, 3) + >>> c = a + b + >>> d = a - b + >>> af.eval(c, d) # A single kernel is launched here + >>> c + arrayfire.Array() + Type: float + [3 3 1 1] + 3.0000 3.0000 3.0000 + 3.0000 3.0000 3.0000 + 3.0000 3.0000 3.0000 + + >>> d + arrayfire.Array() + Type: float + [3 3 1 1] + -1.0000 -1.0000 -1.0000 + -1.0000 -1.0000 -1.0000 + -1.0000 -1.0000 -1.0000 + """ + for arg in args: + if not isinstance(arg, Array): + raise RuntimeError("All inputs to eval must be of type arrayfire.Array") + + __eval(*args) + +def set_manual_eval_flag(flag): + """ + Tells the backend JIT engine to disable heuristics for determining when to evaluate a JIT tree. + + Parameters + ---------- + + flag : optional: bool. + - Specifies if the heuristic evaluation of the JIT tree needs to be disabled. + + Note + ---- + This does not affect the evaluation that occurs when a non JIT function forces the evaluation. """ + safe_call(backend.get().af_set_manual_eval_flag(flag)) - __eval(args) +def get_manual_eval_flag(): + """ + Query the backend JIT engine to see if the user disabled heuristic evaluation of the JIT tree. + + Note + ---- + This does not affect the evaluation that occurs when a non JIT function forces the evaluation. + """ + res = ct.c_bool(False) + safe_call(backend.get().af_get_manual_eval_flag(ct.pointer(res))) + return res.value def device_mem_info(): """ @@ -258,10 +321,27 @@ def lock_array(a): Note ----- - - The device pointer of `a` is not freed by memory manager until `unlock_device_ptr()` is called. + - The device pointer of `a` is not freed by memory manager until `unlock_array()` is called. """ safe_call(backend.get().af_lock_array(a.arr)) +def is_locked_array(a): + """ + Check if the input array is locked by the user. + + Parameters + ---------- + a: af.Array + - A multi dimensional arrayfire array. + + Returns + ----------- + A bool specifying if the input array is locked. + """ + res = ct.c_bool(False) + safe_call(backend.get().af_is_locked_array(ct.pointer(res), a.arr)) + return res.value + def unlock_device_ptr(a): """ This functions is deprecated. Please use unlock_array instead. diff --git a/arrayfire/features.py b/arrayfire/features.py index 21705e260..6e006afcc 100644 --- a/arrayfire/features.py +++ b/arrayfire/features.py @@ -6,9 +6,11 @@ # The complete license agreement can be obtained at: # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## + """ Features class used for Computer Vision algorithms. """ + from .library import * from .array import * import numbers diff --git a/arrayfire/graphics.py b/arrayfire/graphics.py index 3d0b3f213..59da8dbf7 100644 --- a/arrayfire/graphics.py +++ b/arrayfire/graphics.py @@ -140,9 +140,9 @@ def image(self, img, title=None): _cell = _Cell(self._r, self._c, title, self._cmap) safe_call(backend.get().af_draw_image(self._wnd, img.arr, ct.pointer(_cell))) - def scatter(self, X, Y, marker=MARKER.POINT, title=None): + def scatter(self, X, Y, Z=None, points=None, marker=MARKER.POINT, title=None): """ - Renders input arrays as 2D scatter plot. + Renders input arrays as 2D or 3D scatter plot. Paramters --------- @@ -153,67 +153,212 @@ def scatter(self, X, Y, marker=MARKER.POINT, title=None): Y: af.Array. A 1 dimensional array containing Y co-ordinates. + Z: optional: af.Array. default: None. + - A 1 dimensional array containing Z co-ordinates. + - Not used if line is not None + + points: optional: af.Array. default: None. + - A 2 dimensional array of size [n 2]. Each column denotes X and Y co-ordinates for 2D scatter plot. + - A 3 dimensional array of size [n 3]. Each column denotes X, Y, and Z co-ordinates for 3D scatter plot. + + marker: af.MARKER + Specifies how the points look + + title: str. + Title used for the plot. + """ + _cell = _Cell(self._r, self._c, title, self._cmap) + + if points is None: + if Z is None: + safe_call(backend.get().af_draw_scatter_2d(self._wnd, X.arr, Y.arr, + marker.value, ct.pointer(_cell))) + else: + safe_call(backend.get().af_draw_scatter_3d(self._wnd, X.arr, Y.arr, Z.arr, + marker.value, ct.pointer(_cell))) + else: + safe_call(backend.get().af_draw_scatter_nd(self._wnd, points.arr, marker.value, ct.pointer(_cell))) + + def scatter2(self, points, marker=MARKER.POINT, title=None): + """ + Renders the input array as a 2D Scatter plot. + + Paramters + --------- + + points: af.Array. + A 2 dimensional array containing (X,Y) co-ordinates. + marker: af.MARKER Specifies how the points look title: str. Title used for the plot. """ + assert(points.numdims() == 2) _cell = _Cell(self._r, self._c, title, self._cmap) - safe_call(backend.get().af_draw_scatter(self._wnd, X.arr, Y.arr, - marker.value, ct.pointer(_cell))) + safe_call(backend.get().af_draw_scatter2(self._wnd, points.arr, + marker.value, ct.pointer(_cell))) - def scatter3(self, P, marker=MARKER.POINT, title=None): + def scatter3(self, points, marker=MARKER.POINT, title=None): """ Renders the input array as a 3D Scatter plot. Paramters --------- - P: af.Array. + points: af.Array. A 2 dimensional array containing (X,Y,Z) co-ordinates. + marker: af.MARKER + Specifies how the points look + title: str. Title used for the plot. """ + assert(points.numdims() == 3) _cell = _Cell(self._r, self._c, title, self._cmap) - safe_call(backend.get().af_draw_scatter3(self._wnd, P.arr, + safe_call(backend.get().af_draw_scatter3(self._wnd, points.arr, marker.value, ct.pointer(_cell))) - - def plot(self, X, Y, title=None): + def plot(self, X, Y, Z=None, line = None, title=None): """ - Display a 2D Plot. + Display a 2D or 3D Plot. Paramters --------- X: af.Array. - A 1 dimensional array containing X co-ordinates. + - A 1 dimensional array containing X co-ordinates. + - Not used if line is not None Y: af.Array. - A 1 dimensional array containing Y co-ordinates. + - A 1 dimensional array containing Y co-ordinates. + - Not used if line is not None + + Z: optional: af.Array. default: None. + - A 1 dimensional array containing Z co-ordinates. + - Not used if line is not None + + line: optional: af.Array. default: None. + - A 2 dimensional array of size [n 2]. Each column denotes X and Y co-ordinates for plotting 2D lines. + - A 3 dimensional array of size [n 3]. Each column denotes X, Y, and Z co-ordinates for plotting 3D lines. title: str. Title used for the plot. + + Note + ---- + + The line parameter takes precedence. """ _cell = _Cell(self._r, self._c, title, self._cmap) - safe_call(backend.get().af_draw_plot(self._wnd, X.arr, Y.arr, ct.pointer(_cell))) + if line is None: + if Z is None: + safe_call(backend.get().af_draw_plot_2d(self._wnd, X.arr, Y.arr, ct.pointer(_cell))) + else: + safe_call(backend.get().af_draw_plot_3d(self._wnd, X.arr, Y.arr, Z.arr, ct.pointer(_cell))) + else: + safe_call(backend.get().af_draw_plot_nd(self._wnd, line.arr, ct.pointer(_cell))) - def plot3(self, line, title=None): + def plot2(self, line, title=None): """ - Renders the input array as a 3D line plot. + Display a 2D Plot. Paramters --------- line: af.Array. - A 2 dimensional array containing (X,Y,Z) co-ordinates. + - A 2 dimensional array of size [n 2]. Each column denotes X, and Y co-ordinates for plotting 2D lines. title: str. Title used for the plot. + """ + + assert(line.numdims() == 2) _cell = _Cell(self._r, self._c, title, self._cmap) - safe_call(backend.get().af_draw_plot3(self._wnd, line.arr, ct.pointer(_cell))) + safe_call(backend.get().af_draw_plot_nd(self._wnd, line.arr, ct.pointer(_cell))) + + def plot3(self, X=None, Y=None, Z=None, line=None, title=None): + """ + Display a 3D Plot. + + Paramters + --------- + + line: af.Array. + - A 3 dimensional array of size [n 3]. Each column denotes X, Y, and Z co-ordinates for plotting 3D lines. + + title: str. + Title used for the plot. + """ + + assert(line.numdims() == 3) + _cell = _Cell(self._r, self._c, title, self._cmap) + safe_call(backend.get().af_draw_plot_nd(self._wnd, line.arr, ct.pointer(_cell))) + + def vector_field(self, xpoints, xdirs, ypoints, ydirs, zpoints=None, zdirs=None, + points = None, dirs = None, title=None): + """ + Display a 2D or 3D Vector_Field. + + Paramters + --------- + + xpoints : af.Array. + - A 1 dimensional array containing X co-ordinates. + - Not used if points is not None + + xdirs : af.Array. + - A 1 dimensional array specifying direction at current location. + - Not used if dirs is not None + + ypoints : af.Array. + - A 1 dimensional array containing Y co-ordinates. + - Not used if points is not None + + ydirs : af.Array. + - A 1 dimensional array specifying direction at current location. + - Not used if dirs is not None + + zpoints : optional: af.Array. default: None. + - A 1 dimensional array containing Z co-ordinates. + - Not used if points is not None + + zdirs : optional: af.Array. default: none. + - A 1 dimensional array specifying direction at current location. + - Not used if dirs is not None + + points : optional: af.Array. default: None. + - A 2 dimensional array of size [n 2]. Each column denotes X and Y co-ordinates for plotting 2D lines. + - A 3 dimensional array of size [n 3]. Each column denotes X, Y, and Z co-ordinates for plotting 3D lines. + + dirs : optional: af.Array. default: None. + - A 2 dimensional array of size [n 2]. Each column denotes X and Y directions for plotting 2D lines. + - A 3 dimensional array of size [n 3]. Each column denotes X, Y, and Z directions for plotting 3D lines. + + title : str. + Title used for the plot. + + Note + ---- + + The line parameter takes precedence. + """ + _cell = _Cell(self._r, self._c, title, self._cmap) + if line is None: + if Z is None: + safe_call(backend.get().af_draw_vector_field_2d(self._wnd, + xpoints.arr, ypoints.arr, + xdirs.arr, ydirs.arr, + ct.pointer(_cell))) + else: + safe_call(backend.get().af_draw_vector_field_2d(self._wnd, + xpoints.arr, ypoints.arr, zpoints.arr, + xdirs.arr, ydirs.arr, zdirs.arr, + ct.pointer(_cell))) + else: + safe_call(backend.get().af_draw_plot_nd(self._wnd, points.arr, dirs.arr, ct.pointer(_cell))) def surface(self, x_vals, y_vals, z_vals, title=None): """ @@ -305,6 +450,52 @@ def set_visibility(is_visible): """ safe_call(backend.get().af_set_visibility(self._wnd, is_visible)) + def set_axes_limits(self, xmin, xmax, ymin, ymax, zmin=None, zmax=None, exact=False): + """ + Set axis limits. + + Paramters + --------- + + xmin : af.Array. + - lower limit of the x axis. + + xmax : af.Array. + - upper limit of the x axis. + + ymin : af.Array. + - lower limit of the y axis. + + ymax : af.Array. + - upper limit of the y axis. + + zmin : optional: af.Array. default: None. + - lower limit of the z axis. + + zmax : optional: af.Array. default: None. + - upper limit of the z axis. + + title : str. + Title used for the plot. + + Note + ---- + + The line parameter takes precedence. + """ + _cell = _Cell(self._r, self._c, "", self._cmap) + if (zmin is None or zmax is None): + safe_call(backend.get().af_set_axes_limits_2d(self._wnd, + ct.c_float(xmin), ct.c_float(xmax), + ct.c_float(ymin), ct.c_float(ymax), + exact, ct.pointer(_cell))) + else: + safe_call(backend.get().af_set_axes_limits_2d(self._wnd, + ct.c_float(xmin), ct.c_float(xmax), + ct.c_float(ymin), ct.c_float(ymax), + ct.c_float(zmin), ct.c_float(zmax), + exact, ct.pointer(_cell))) + def __getitem__(self, keys): """ Get access to a specific grid location within the window. diff --git a/arrayfire/image.py b/arrayfire/image.py index ac4b8ed19..7ddb6de9a 100644 --- a/arrayfire/image.py +++ b/arrayfire/image.py @@ -14,6 +14,7 @@ from .library import * from .array import * from .data import constant +from .signal import medfilt import os def gradient(image): @@ -619,38 +620,6 @@ def mean_shift(image, s_sigma, c_sigma, n_iter, is_color = False): ct.c_uint(n_iter), is_color)) return output -def medfilt(image, w0 = 3, w1 = 3, edge_pad = PAD.ZERO): - """ - Apply median filter for the image. - - Parameters - ---------- - image : af.Array - - A 2 D arrayfire array representing an image, or - - A multi dimensional array representing batch of images. - - w0 : optional: int. default: 3. - - The length of the filter along the first dimension. - - w1 : optional: int. default: 3. - - The length of the filter along the second dimension. - - edge_pad : optional: af.PAD. default: af.PAD.ZERO - - Flag specifying how the median at the edge should be treated. - - Returns - --------- - - output : af.Array - - The image after median filter is applied. - - """ - output = Array() - safe_call(backend.get().af_medfilt(ct.pointer(output.arr), - image.arr, c_dim_t(w0), - c_dim_t(w1), edge_pad.value)) - return output - def minfilt(image, w_len = 3, w_wid = 3, edge_pad = PAD.ZERO): """ Apply min filter for the image. @@ -1198,6 +1167,33 @@ def rgb2ycbcr(image, standard=YCC_STD.BT_601): safe_call(backend.get().af_rgb2ycbcr(ct.pointer(out.arr), image.arr, standard.value)) return out +def moments(image, moment = MOMENT.FIRST_ORDER): + """ + Calculate image moments. + + Parameters + ---------- + image : af.Array + - A 2 D arrayfire array representing an image, or + - A multi dimensional array representing batch of images. + + moment : optional: af.MOMENT. default: af.MOMENT.FIRST_ORDER. + Moment(s) to calculate. Can be one of: + - af.MOMENT.M00 + - af.MOMENT.M01 + - af.MOMENT.M10 + - af.MOMENT.M11 + - af.MOMENT.FIRST_ORDER + + Returns + --------- + out : af.Array + - array containing requested moment(s) of each image + """ + output = Array() + safe_call(backend.get().af_moments(ct.pointer(output.arr), image.arr, moment.value)) + return output + def is_image_io_available(): """ Function to check if the arrayfire library was built with Image IO support. diff --git a/arrayfire/library.py b/arrayfire/library.py index ff09f051d..c0541620d 100644 --- a/arrayfire/library.py +++ b/arrayfire/library.py @@ -113,11 +113,16 @@ class INTERP(_Enum): """ Interpolation method """ - NEAREST = _Enum_Type(0) - LINEAR = _Enum_Type(1) - BILINEAR = _Enum_Type(2) - CUBIC = _Enum_Type(3) - LOWER = _Enum_Type(4) + NEAREST = _Enum_Type(0) + LINEAR = _Enum_Type(1) + BILINEAR = _Enum_Type(2) + CUBIC = _Enum_Type(3) + LOWER = _Enum_Type(4) + LINEAR_COSINE = _Enum_Type(5) + BILINEAR_COSINE = _Enum_Type(6) + BICUBIC = _Enum_Type(7) + CUBIC_SPLINE = _Enum_Type(8) + BICUBIC_SPLINE = _Enum_Type(9) class PAD(_Enum): """ @@ -349,6 +354,45 @@ class MARKER(_Enum): PLUS = _Enum_Type(6) STAR = _Enum_Type(7) +class MOMENT(_Enum): + """ + Image Moments types + """ + M00 = _Enum_Type(1) + M01 = _Enum_Type(2) + M10 = _Enum_Type(4) + M11 = _Enum_Type(8) + FIRST_ORDER = _Enum_Type(15) + +class BINARYOP(_Enum): + """ + Binary Operators + """ + ADD = _Enum_Type(0) + MUL = _Enum_Type(1) + MIN = _Enum_Type(2) + MAX = _Enum_Type(3) + +class RANDOM_ENGINE(_Enum): + """ + Random engine types + """ + PHILOX_4X32_10 = _Enum_Type(100) + THREEFRY_2X32_16 = _Enum_Type(200) + MERSENNE_GP11213 = _Enum_Type(300) + PHILOX = PHILOX_4X32_10 + THREEFRY = THREEFRY_2X32_16 + DEFAULT = PHILOX + +class STORAGE(_Enum): + """ + Matrix Storage types + """ + DENSE = _Enum_Type(0) + CSR = _Enum_Type(1) + CSC = _Enum_Type(2) + COO = _Enum_Type(3) + def _setup(): import platform import os @@ -477,6 +521,10 @@ def __init__(self): except: pass + c_dim4 = c_dim_t*4 + out = ct.c_void_p(0) + dims = c_dim4(10, 10, 1, 1) + # Iterate in reverse order of preference for name in ('cpu', 'opencl', 'cuda', ''): libnames = self.__libname(name) @@ -484,15 +532,18 @@ def __init__(self): try: ct.cdll.LoadLibrary(libname) __name = 'unified' if name == '' else name - self.__clibs[__name] = ct.CDLL(libname) - self.__name = __name + clib = ct.CDLL(libname) + self.__clibs[__name] = clib + err = clib.af_randu(ct.pointer(out), 4, ct.pointer(dims), Dtype.f32.value) + if (err == ERR.NONE.value): + self.__name = __name + clib.af_release_array(out) break; except: pass if (self.__name is None): - raise RuntimeError("Could not load any ArrayFire libraries.\n" + - more_info_str) + raise RuntimeError("Could not load any ArrayFire libraries.\n" + more_info_str) def get_id(self, name): return self.__backend_name_map[name] @@ -620,4 +671,12 @@ def get_device_id(A): safe_call(backend.get().af_get_device_id(ct.pointer(device_id), A.arr)) return device_id +def get_size_of(dtype): + """ + Get the size of the type represented by arrayfire.Dtype + """ + size = ct.c_size_t(0) + safe_call(backend.get().af_get_size_of(ct.pointer(size), dtype.value)) + return size.value + from .util import safe_call diff --git a/arrayfire/random.py b/arrayfire/random.py new file mode 100644 index 000000000..d95fa9081 --- /dev/null +++ b/arrayfire/random.py @@ -0,0 +1,232 @@ +####################################################### +# Copyright (c) 2015, ArrayFire +# All rights reserved. +# +# This file is distributed under 3-clause BSD license. +# The complete license agreement can be obtained at: +# http://arrayfire.com/licenses/BSD-3-Clause +######################################################## + +""" +Random engine class and functions to generate random numbers. +""" + +from .library import * +from .array import * +import numbers + +class Random_Engine(object): + """ + Class to handle random number generator engines. + + Parameters + ---------- + + engine_type : optional: RANDOME_ENGINE. default: RANDOM_ENGINE.PHILOX + - Specifies the type of random engine to be created. Can be one of: + - RANDOM_ENGINE.PHILOX_4X32_10 + - RANDOM_ENGINE.THREEFRY_2X32_16 + - RANDOM_ENGINE.MERSENNE_GP11213 + - RANDOM_ENGINE.PHILOX (same as RANDOM_ENGINE.PHILOX_4X32_10) + - RANDOM_ENGINE.THREEFRY (same as RANDOM_ENGINE.THREEFRY_2X32_16) + - RANDOM_ENGINE.DEFAULT + - Not used if engine is not None + + seed : optional int. default: 0 + - Specifies the seed for the random engine + - Not used if engine is not None + + engine : optional ctypes.c_void_p. default: None. + - Used a handle created by the C api to create the Random_Engine. + """ + + def __init__(self, engine_type = RANDOM_ENGINE.PHILOX, seed = 0, engine = None): + if (engine is None): + self.engine = ct.c_void_p(0) + safe_call(backend.get().af_create_random_engine(ct.pointer(self.engine), engine_type.value, ct.c_longlong(seed))) + else: + self.engine = engine + + def __del__(self): + safe_call(backend.get().af_release_random_engine(self.engine)) + + def set_type(self, engine_type): + """ + Set the type of the random engine. + """ + safe_call(backend.get().af_random_engine_set_type(ct.pointer(self.engine), engine_type.value)) + + def get_type(self): + """ + Get the type of the random engine. + """ + __to_random_engine_type = [RANDOM_ENGINE.PHILOX_4X32_10, + RANDOM_ENGINE.THREEFRY_2X32_16, + RANDOM_ENGINE.MERSENNE_GP11213] + rty = ct.c_int(RANDOM_ENGINE.PHILOX.value) + safe_call(backend.get().af_random_engine_get_type(ct.pointer(rty), self.engine)) + return __to_random_engine_type[rty] + + def set_seed(self, seed): + """ + Set the seed for the random engine. + """ + safe_call(backend.get().af_random_engine_set_seed(ct.pointer(self.engine), ct.c_longlong(seed))) + + def get_seed(self): + """ + Get the seed for the random engine. + """ + seed = ct.c_longlong(0) + safe_call(backend.get().af_random_engine_get_seed(ct.pointer(seed), self.engine)) + return seed.value + +def randu(d0, d1=None, d2=None, d3=None, dtype=Dtype.f32, engine=None): + """ + Create a multi dimensional array containing values from a uniform distribution. + + Parameters + ---------- + d0 : int. + Length of first dimension. + + d1 : optional: int. default: None. + Length of second dimension. + + d2 : optional: int. default: None. + Length of third dimension. + + d3 : optional: int. default: None. + Length of fourth dimension. + + dtype : optional: af.Dtype. default: af.Dtype.f32. + Data type of the array. + + engine : optional: Random_Engine. default: None. + If engine is None, uses a default engine created by arrayfire. + + Returns + ------- + + out : af.Array + Multi dimensional array whose elements are sampled uniformly between [0, 1]. + - If d1 is None, `out` is 1D of size (d0,). + - If d1 is not None and d2 is None, `out` is 2D of size (d0, d1). + - If d1 and d2 are not None and d3 is None, `out` is 3D of size (d0, d1, d2). + - If d1, d2, d3 are all not None, `out` is 4D of size (d0, d1, d2, d3). + """ + out = Array() + dims = dim4(d0, d1, d2, d3) + + if engine is None: + safe_call(backend.get().af_randu(ct.pointer(out.arr), 4, ct.pointer(dims), dtype.value)) + else: + safe_call(backend.get().af_random_uniform(ct.pointer(out.arr), 4, ct.pointer(dims), dtype.value, engine.engine)) + + return out + +def randn(d0, d1=None, d2=None, d3=None, dtype=Dtype.f32, engine=None): + """ + Create a multi dimensional array containing values from a normal distribution. + + Parameters + ---------- + d0 : int. + Length of first dimension. + + d1 : optional: int. default: None. + Length of second dimension. + + d2 : optional: int. default: None. + Length of third dimension. + + d3 : optional: int. default: None. + Length of fourth dimension. + + dtype : optional: af.Dtype. default: af.Dtype.f32. + Data type of the array. + + engine : optional: Random_Engine. default: None. + If engine is None, uses a default engine created by arrayfire. + + Returns + ------- + + out : af.Array + Multi dimensional array whose elements are sampled from a normal distribution with mean 0 and sigma of 1. + - If d1 is None, `out` is 1D of size (d0,). + - If d1 is not None and d2 is None, `out` is 2D of size (d0, d1). + - If d1 and d2 are not None and d3 is None, `out` is 3D of size (d0, d1, d2). + - If d1, d2, d3 are all not None, `out` is 4D of size (d0, d1, d2, d3). + """ + + out = Array() + dims = dim4(d0, d1, d2, d3) + + if engine is None: + safe_call(backend.get().af_randn(ct.pointer(out.arr), 4, ct.pointer(dims), dtype.value)) + else: + safe_call(backend.get().af_random_normal(ct.pointer(out.arr), 4, ct.pointer(dims), dtype.value, engine.engine)) + + return out + +def set_seed(seed=0): + """ + Set the seed for the random number generator. + + Parameters + ---------- + seed: int. + Seed for the random number generator + """ + safe_call(backend.get().af_set_seed(ct.c_ulonglong(seed))) + +def get_seed(): + """ + Get the seed for the random number generator. + + Returns + ---------- + seed: int. + Seed for the random number generator + """ + seed = ct.c_ulonglong(0) + safe_call(backend.get().af_get_seed(ct.pointer(seed))) + return seed.value + +def set_default_random_engine_type(engine_type): + """ + Set random engine type for default random engine. + + Parameters + ---------- + engine_type : RANDOME_ENGINE. + - Specifies the type of random engine to be created. Can be one of: + - RANDOM_ENGINE.PHILOX_4X32_10 + - RANDOM_ENGINE.THREEFRY_2X32_16 + - RANDOM_ENGINE.MERSENNE_GP11213 + - RANDOM_ENGINE.PHILOX (same as RANDOM_ENGINE.PHILOX_4X32_10) + - RANDOM_ENGINE.THREEFRY (same as RANDOM_ENGINE.THREEFRY_2X32_16) + - RANDOM_ENGINE.DEFAULT + + Note + ---- + + This only affects randu and randn when a random engine is not specified. + """ + safe_call(backend.get().af_set_default_random_engine_type(ct.pointer(self.engine), engine_type.value)) + +def get_default_random_engine(): + """ + Get the default random engine + + Returns + ------ + + The default random engine used by randu and randn + """ + engine = ct.c_void_p(0) + default_engine = ct.c_void_p(0) + safe_call(backend.get().af_get_default_random_engine(ct.pointer(default_engine))) + safe_call(backend.get().af_retain_random_engine(ct.pointer(engine), default_engine)) + return Random_Engine(engine=engine) diff --git a/arrayfire/signal.py b/arrayfire/signal.py index fe377ed1c..363ed248c 100644 --- a/arrayfire/signal.py +++ b/arrayfire/signal.py @@ -1264,3 +1264,106 @@ def iir(B, A, X): Y = Array() safe_call(backend.get().af_iir(ct.pointer(Y.arr), B.arr, A.arr, X.arr)) return Y + +def medfilt(signal, w0 = 3, w1 = 3, edge_pad = PAD.ZERO): + """ + Apply median filter for the signal. + + Parameters + ---------- + signal : af.Array + - A 2 D arrayfire array representing a signal, or + - A multi dimensional array representing batch of signals. + + w0 : optional: int. default: 3. + - The length of the filter along the first dimension. + + w1 : optional: int. default: 3. + - The length of the filter along the second dimension. + + edge_pad : optional: af.PAD. default: af.PAD.ZERO + - Flag specifying how the median at the edge should be treated. + + Returns + --------- + + output : af.Array + - The signal after median filter is applied. + + """ + output = Array() + safe_call(backend.get().af_medfilt(ct.pointer(output.arr), + signal.arr, c_dim_t(w0), + c_dim_t(w1), edge_pad.value)) + return output + +def medfilt1(signal, length = 3, edge_pad = PAD.ZERO): + """ + Apply median filter for the signal. + + Parameters + ---------- + signal : af.Array + - A 1 D arrayfire array representing a signal, or + - A multi dimensional array representing batch of signals. + + length : optional: int. default: 3. + - The length of the filter. + + edge_pad : optional: af.PAD. default: af.PAD.ZERO + - Flag specifying how the median at the edge should be treated. + + Returns + --------- + + output : af.Array + - The signal after median filter is applied. + + """ + output = Array() + safe_call(backend.get().af_medfilt1(ct.pointer(output.arr), signal.arr, c_dim_t(length), edge_pad.value)) + return output + +def medfilt2(signal, w0 = 3, w1 = 3, edge_pad = PAD.ZERO): + """ + Apply median filter for the signal. + + Parameters + ---------- + signal : af.Array + - A 2 D arrayfire array representing a signal, or + - A multi dimensional array representing batch of signals. + + w0 : optional: int. default: 3. + - The length of the filter along the first dimension. + + w1 : optional: int. default: 3. + - The length of the filter along the second dimension. + + edge_pad : optional: af.PAD. default: af.PAD.ZERO + - Flag specifying how the median at the edge should be treated. + + Returns + --------- + + output : af.Array + - The signal after median filter is applied. + + """ + output = Array() + safe_call(backend.get().af_medfilt2(ct.pointer(output.arr), + signal.arr, c_dim_t(w0), + c_dim_t(w1), edge_pad.value)) + return output + +def set_fft_plan_cache_size(cache_size): + """ + Sets plan cache size. + + Parameters + ---------- + + cache_size : scalar + the number of plans that shall be cached + """ + safe_call(backend.get().af_set_fft_plan_cache_size(ct.c_size_t(cache_size))) diff --git a/arrayfire/sparse.py b/arrayfire/sparse.py new file mode 100644 index 000000000..9a4c30460 --- /dev/null +++ b/arrayfire/sparse.py @@ -0,0 +1,275 @@ +####################################################### +# Copyright (c) 2015, ArrayFire +# All rights reserved. +# +# This file is distributed under 3-clause BSD license. +# The complete license agreement can be obtained at: +# http://arrayfire.com/licenses/BSD-3-Clause +######################################################## + +""" +Functions to create and manipulate sparse matrices. +""" + +from .library import * +from .array import * +import numbers +from .interop import to_array + +__to_sparse_enum = [STORAGE.DENSE, + STORAGE.CSR, + STORAGE.CSC, + STORAGE.COO] + + +def sparse(values, row_idx, col_idx, nrows, ncols, storage = STORAGE.CSR): + """ + Create a sparse matrix from it's constituent parts. + + Parameters + ---------- + + values : af.Array. + - Contains the non zero elements of the sparse array. + + row_idx : af.Array. + - Contains row indices of the sparse array. + + col_idx : af.Array. + - Contains column indices of the sparse array. + + nrows : int. + - specifies the number of rows in sparse matrix. + + ncols : int. + - specifies the number of columns in sparse matrix. + + storage : optional: arrayfire.STORAGE. default: arrayfire.STORAGE.CSR. + - Can be one of arrayfire.STORAGE.CSR, arrayfire.STORAGE.COO. + + Returns + ------- + + A sparse matrix. + """ + assert(isinstance(values, Array)) + assert(isinstance(row_idx, Array)) + assert(isinstance(col_idx, Array)) + out = Array() + safe_call(backend.get().af_create_sparse_array(ct.pointer(out.arr), c_dim_t(nrows), c_dim_t(ncols), + values.arr, row_idx.arr, col_idx.arr, storage.value)) + return out + +def sparse_from_host(values, row_idx, col_idx, nrows, ncols, storage = STORAGE.CSR): + """ + Create a sparse matrix from it's constituent parts. + + Parameters + ---------- + + values : Any datatype that can be converted to array. + - Contains the non zero elements of the sparse array. + + row_idx : Any datatype that can be converted to array. + - Contains row indices of the sparse array. + + col_idx : Any datatype that can be converted to array. + - Contains column indices of the sparse array. + + nrows : int. + - specifies the number of rows in sparse matrix. + + ncols : int. + - specifies the number of columns in sparse matrix. + + storage : optional: arrayfire.STORAGE. default: arrayfire.STORAGE.CSR. + - Can be one of arrayfire.STORAGE.CSR, arrayfire.STORAGE.COO. + + Returns + ------- + + A sparse matrix. + """ + return sparse(to_array(values), to_array(row_idx), to_array(col_idx), nrows, ncols, storage) + +def sparse_from_dense(dense, storage = STORAGE.CSR): + """ + Create a sparse matrix from a dense matrix. + + Parameters + ---------- + + dense : af.Array. + - A dense matrix. + + storage : optional: arrayfire.STORAGE. default: arrayfire.STORAGE.CSR. + - Can be one of arrayfire.STORAGE.CSR, arrayfire.STORAGE.COO. + + Returns + ------- + + A sparse matrix. + """ + assert(isinstance(dense, Array)) + out = Array() + safe_call(backend.get().af_create_sparse_array_from_dense(ct.pointer(out.arr), dense.arr, storage.value)) + return out + +def sparse_to_dense(sparse): + """ + Create a dense matrix from a sparse matrix. + + Parameters + ---------- + + sparse : af.Array. + - A sparse matrix. + + Returns + ------- + + A dense matrix. + """ + out = Array() + safe_call(backend.get().af_sparse_to_dense(ct.pointer(out.arr), sparse.arr)) + return out + +def sparse_get_info(sparse): + """ + Get the constituent arrays and storage info from a sparse matrix. + + Parameters + ---------- + + sparse : af.Array. + - A sparse matrix. + + Returns + -------- + (values, row_idx, col_idx, storage) where + values : arrayfire.Array containing non zero elements from sparse matrix + row_idx : arrayfire.Array containing the row indices + col_idx : arrayfire.Array containing the column indices + storage : sparse storage + """ + values = Array() + row_idx = Array() + col_idx = Array() + stype = ct.c_int(0) + safe_call(backend.get().af_sparse_get_info(ct.pointer(values.arr), ct.pointer(row_idx.arr), + ct.pointer(col_idx.arr), ct.pointer(stype), + sparse.arr)) + return (values, row_idx, col_idx, __to_sparse_enum[stype.value]) + +def sparse_get_values(sparse): + """ + Get the non zero values from sparse matrix. + + Parameters + ---------- + + sparse : af.Array. + - A sparse matrix. + + Returns + -------- + arrayfire array containing the non zero elements. + + """ + values = Array() + safe_call(backend.get().af_sparse_get_values(ct.pointer(values.arr), sparse.arr)) + return values + +def sparse_get_row_idx(sparse): + """ + Get the row indices from sparse matrix. + + Parameters + ---------- + + sparse : af.Array. + - A sparse matrix. + + Returns + -------- + arrayfire array containing the non zero elements. + + """ + row_idx = Array() + safe_call(backend.get().af_sparse_get_row_idx(ct.pointer(row_idx.arr), sparse.arr)) + return row_idx + +def sparse_get_col_idx(sparse): + """ + Get the column indices from sparse matrix. + + Parameters + ---------- + + sparse : af.Array. + - A sparse matrix. + + Returns + -------- + arrayfire array containing the non zero elements. + + """ + col_idx = Array() + safe_call(backend.get().af_sparse_get_col_idx(ct.pointer(col_idx.arr), sparse.arr)) + return col_idx + +def sparse_get_nnz(sparse): + """ + Get the column indices from sparse matrix. + + Parameters + ---------- + + sparse : af.Array. + - A sparse matrix. + + Returns + -------- + Number of non zero elements in the sparse matrix. + + """ + nnz = c_dim_t(0) + safe_call(backend.get().af_sparse_get_nnz(ct.pointer(nnz), sparse.arr)) + return nnz.value + +def sparse_get_storage(sparse): + """ + Get the column indices from sparse matrix. + + Parameters + ---------- + + sparse : af.Array. + - A sparse matrix. + + Returns + -------- + Number of non zero elements in the sparse matrix. + + """ + storage = ct.c_int(0) + safe_call(backend.get().af_sparse_get_storage(ct.pointer(storage), sparse.arr)) + return __to_sparse_enum[storage.value] + +def sparse_convert_to(sparse, storage): + """ + Convert sparse matrix from one format to another. + + Parameters + ---------- + + storage : arrayfire.STORAGE. + + Returns + ------- + + Sparse matrix converted to the appropriate type. + """ + out = Array() + safe_call(backend.get().af_sparse_convert_to(ct.pointer(out.arr), sparse.arr, storage.value)) + return out diff --git a/arrayfire/tests/simple/__init__.py b/arrayfire/tests/simple/__init__.py index 465197202..528215ffc 100644 --- a/arrayfire/tests/simple/__init__.py +++ b/arrayfire/tests/simple/__init__.py @@ -18,4 +18,6 @@ from .lapack import * from .signal import * from .statistics import * +from .random import * +from .sparse import * from ._util import tests diff --git a/arrayfire/tests/simple/algorithm.py b/arrayfire/tests/simple/algorithm.py index f68e354e4..75ab814d4 100644 --- a/arrayfire/tests/simple/algorithm.py +++ b/arrayfire/tests/simple/algorithm.py @@ -16,6 +16,7 @@ def simple_algorithm(verbose = False): print_func = _util.print_func(verbose) a = af.randu(3, 3) + k = af.constant(1, 3, 3, dtype=af.Dtype.u32) print_func(af.sum(a), af.product(a), af.min(a), af.max(a), af.count(a), af.any_true(a), af.all_true(a)) @@ -44,6 +45,12 @@ def simple_algorithm(verbose = False): display_func(af.accum(a, 0)) display_func(af.accum(a, 1)) + display_func(af.scan(a, 0, af.BINARYOP.ADD)) + display_func(af.scan(a, 1, af.BINARYOP.MAX)) + + display_func(af.scan_by_key(k, a, 0, af.BINARYOP.ADD)) + display_func(af.scan_by_key(k, a, 1, af.BINARYOP.MAX)) + display_func(af.sort(a, is_ascending=True)) display_func(af.sort(a, is_ascending=False)) diff --git a/arrayfire/tests/simple/arith.py b/arrayfire/tests/simple/arith.py index f8407c17f..84c291aec 100644 --- a/arrayfire/tests/simple/arith.py +++ b/arrayfire/tests/simple/arith.py @@ -134,6 +134,11 @@ def simple_arith(verbose = False): display_func(af.cast(a, af.Dtype.c32)) display_func(af.maxof(a,b)) display_func(af.minof(a,b)) + + display_func(af.clamp(a, 0, 1)) + display_func(af.clamp(a, 0, b)) + display_func(af.clamp(a, b, 1)) + display_func(af.rem(a,b)) a = af.randu(3,3) - 0.5 diff --git a/arrayfire/tests/simple/array_test.py b/arrayfire/tests/simple/array_test.py index 1aec93494..0c6ab5262 100644 --- a/arrayfire/tests/simple/array_test.py +++ b/arrayfire/tests/simple/array_test.py @@ -60,4 +60,6 @@ def simple_array(verbose=False): print_func(arr) print_func(lst) + print_func(a.is_sparse()) + _util.tests['array'] = simple_array diff --git a/arrayfire/tests/simple/data.py b/arrayfire/tests/simple/data.py index 7c95a8194..86b900baf 100644 --- a/arrayfire/tests/simple/data.py +++ b/arrayfire/tests/simple/data.py @@ -24,16 +24,6 @@ def simple_data(verbose=False): display_func(af.range(3, 3)) display_func(af.iota(3, 3, tile_dims=(2,2))) - display_func(af.randu(3, 3, 1, 2)) - display_func(af.randu(3, 3, 1, 2, af.Dtype.b8)) - display_func(af.randu(3, 3, dtype=af.Dtype.c32)) - - display_func(af.randn(3, 3, 1, 2)) - display_func(af.randn(3, 3, dtype=af.Dtype.c32)) - - af.set_seed(1024) - assert(af.get_seed() == 1024) - display_func(af.identity(3, 3, 1, 2, af.Dtype.b8)) display_func(af.identity(3, 3, dtype=af.Dtype.c32)) diff --git a/arrayfire/tests/simple/device.py b/arrayfire/tests/simple/device.py index 925add294..279fa3168 100644 --- a/arrayfire/tests/simple/device.py +++ b/arrayfire/tests/simple/device.py @@ -51,4 +51,23 @@ def simple_device(verbose=False): af.lock_array(c) af.unlock_array(c) + a = af.constant(1, 3, 3) + b = af.constant(2, 3, 3) + af.eval(a) + af.eval(b) + print_func(a) + print_func(b) + c = a + b + d = a - b + af.eval(c, d) + print_func(c) + print_func(d) + + print_func(af.set_manual_eval_flag(True)) + assert(af.get_manual_eval_flag() == True) + print_func(af.set_manual_eval_flag(False)) + assert(af.get_manual_eval_flag() == False) + + display_func(af.is_locked_array(a)) + _util.tests['device'] = simple_device diff --git a/arrayfire/tests/simple/random.py b/arrayfire/tests/simple/random.py new file mode 100644 index 000000000..544389836 --- /dev/null +++ b/arrayfire/tests/simple/random.py @@ -0,0 +1,38 @@ +#!/usr/bin/python +####################################################### +# Copyright (c) 2015, ArrayFire +# All rights reserved. +# +# This file is distributed under 3-clause BSD license. +# The complete license agreement can be obtained at: +# http://arrayfire.com/licenses/BSD-3-Clause +######################################################## + +import arrayfire as af +from . import _util + +def simple_random(verbose=False): + display_func = _util.display_func(verbose) + print_func = _util.print_func(verbose) + + display_func(af.randu(3, 3, 1, 2)) + display_func(af.randu(3, 3, 1, 2, af.Dtype.b8)) + display_func(af.randu(3, 3, dtype=af.Dtype.c32)) + + display_func(af.randn(3, 3, 1, 2)) + display_func(af.randn(3, 3, dtype=af.Dtype.c32)) + + af.set_seed(1024) + assert(af.get_seed() == 1024) + + engine = af.Random_Engine(af.RANDOM_ENGINE.MERSENNE_GP11213, 100) + + display_func(af.randu(3, 3, 1, 2, engine=engine)) + display_func(af.randu(3, 3, 1, 2, af.Dtype.s32, engine=engine)) + display_func(af.randu(3, 3, dtype=af.Dtype.c32, engine=engine)) + + display_func(af.randn(3, 3, engine=engine)) + engine.set_seed(100) + assert(engine.get_seed() == 100) + +_util.tests['random'] = simple_random diff --git a/arrayfire/tests/simple/signal.py b/arrayfire/tests/simple/signal.py index 03d89b4a8..817685c5a 100644 --- a/arrayfire/tests/simple/signal.py +++ b/arrayfire/tests/simple/signal.py @@ -110,4 +110,8 @@ def simple_signal(verbose=False): display_func(af.fir(b, x)) display_func(af.iir(b, a, x)) + display_func(af.medfilt1(a)) + display_func(af.medfilt2(a)) + display_func(af.medfilt(a)) + _util.tests['signal'] = simple_signal diff --git a/arrayfire/tests/simple/sparse.py b/arrayfire/tests/simple/sparse.py new file mode 100644 index 000000000..b756cd5a5 --- /dev/null +++ b/arrayfire/tests/simple/sparse.py @@ -0,0 +1,28 @@ +#!/usr/bin/python +####################################################### +# Copyright (c) 2015, ArrayFire +# All rights reserved. +# +# This file is distributed under 3-clause BSD license. +# The complete license agreement can be obtained at: +# http://arrayfire.com/licenses/BSD-3-Clause +######################################################## + +import arrayfire as af +from . import _util + +def simple_sparse(verbose=False): + display_func = _util.display_func(verbose) + print_func = _util.print_func(verbose) + + dd = af.randu(5, 5) + ds = dd * (dd > 0.5) + sp = af.sparse_from_dense(ds) + display_func(af.sparse_get_info(sp)) + display_func(af.sparse_get_values(sp)) + display_func(af.sparse_get_row_idx(sp)) + display_func(af.sparse_get_col_idx(sp)) + print_func(af.sparse_get_nnz(sp)) + print_func(af.sparse_get_storage(sp)) + +_util.tests['sparse'] = simple_sparse