Skip to content

Features 3.4 #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Sep 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions arrayfire/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
65 changes: 65 additions & 0 deletions arrayfire/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 38 additions & 0 deletions arrayfire/arith.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions arrayfire/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
100 changes: 1 addition & 99 deletions arrayfire/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down Expand Up @@ -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.
Expand Down
100 changes: 90 additions & 10 deletions arrayfire/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
"""
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions arrayfire/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading