Skip to content
4 changes: 2 additions & 2 deletions __af_version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
# http://arrayfire.com/licenses/BSD-3-Clause
########################################################

version = "3.5"
release = "20170718"
version = "3.7"
release = "20200213"
full_version = version + "." + release
1 change: 1 addition & 0 deletions arrayfire/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
from .timer import *
from .random import *
from .sparse import *
from .ml import *

# do not export default modules as part of arrayfire
del ct
Expand Down
190 changes: 190 additions & 0 deletions arrayfire/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,31 @@ def _nan_reduce_all(a, c_func, nan_val):
imag = imag.value
return real if imag == 0 else real + imag * 1j

def _FNSD(dim, dims):
if dim >= 0:
return int(dim)

fnsd = 0
for i, d in enumerate(dims):
if d > 1:
fnsd = i
break
return int(fnsd)

def _rbk_dim(keys, vals, dim, c_func):
keys_out = Array()
vals_out = Array()
rdim = _FNSD(dim, vals.dims())
safe_call(c_func(c_pointer(keys_out.arr), c_pointer(vals_out.arr), keys.arr, vals.arr, c_int_t(rdim)))
return keys_out, vals_out

def _nan_rbk_dim(a, dim, c_func, nan_val):
keys_out = Array()
vals_out = Array()
rdim = _FNSD(dim, vals.dims())
safe_call(c_func(c_pointer(keys_out.arr), c_pointer(vals_out.arr), keys.arr, vals.arr, c_int_t(rdim), c_double_t(nan_val)))
return keys_out, vals_out

def sum(a, dim=None, nan_val=None):
"""
Calculate the sum of all the elements along a specified dimension.
Expand Down Expand Up @@ -74,6 +99,34 @@ def sum(a, dim=None, nan_val=None):
else:
return _reduce_all(a, backend.get().af_sum_all)


def sumByKey(keys, vals, dim=-1, nan_val=None):
"""
Calculate the sum of elements along a specified dimension according to a key.

Parameters
----------
keys : af.Array
One dimensional arrayfire array with reduction keys.
vals : af.Array
Multi dimensional arrayfire array that will be reduced.
dim: optional: int. default: -1
Dimension along which the sum will occur.
nan_val: optional: scalar. default: None
The value that replaces NaN in the array

Returns
-------
keys: af.Array or scalar number
The reduced keys of all elements in `vals` along dimension `dim`.
values: af.Array or scalar number
The sum of all elements in `vals` along dimension `dim` according to keys
"""
if (nan_val is not None):
return _nan_rbk_dim(keys, vals, dim, backend.get().af_sum_by_key_nan, nan_val)
else:
return _rbk_dim(keys, vals, dim, backend.get().af_sum_by_key)

def product(a, dim=None, nan_val=None):
"""
Calculate the product of all the elements along a specified dimension.
Expand Down Expand Up @@ -104,6 +157,33 @@ def product(a, dim=None, nan_val=None):
else:
return _reduce_all(a, backend.get().af_product_all)

def productByKey(keys, vals, dim=-1, nan_val=None):
"""
Calculate the product of elements along a specified dimension according to a key.

Parameters
----------
keys : af.Array
One dimensional arrayfire array with reduction keys.
vals : af.Array
Multi dimensional arrayfire array that will be reduced.
dim: optional: int. default: -1
Dimension along which the product will occur.
nan_val: optional: scalar. default: None
The value that replaces NaN in the array

Returns
-------
keys: af.Array or scalar number
The reduced keys of all elements in `vals` along dimension `dim`.
values: af.Array or scalar number
The product of all elements in `vals` along dimension `dim` according to keys
"""
if (nan_val is not None):
return _nan_rbk_dim(keys, vals, dim, backend.get().af_product_by_key_nan, nan_val)
else:
return _rbk_dim(keys, vals, dim, backend.get().af_product_by_key)

def min(a, dim=None):
"""
Find the minimum value of all the elements along a specified dimension.
Expand All @@ -126,6 +206,28 @@ def min(a, dim=None):
else:
return _reduce_all(a, backend.get().af_min_all)

def minByKey(keys, vals, dim=-1):
"""
Calculate the min of elements along a specified dimension according to a key.

Parameters
----------
keys : af.Array
One dimensional arrayfire array with reduction keys.
vals : af.Array
Multi dimensional arrayfire array that will be reduced.
dim: optional: int. default: -1
Dimension along which the min will occur.

Returns
-------
keys: af.Array or scalar number
The reduced keys of all elements in `vals` along dimension `dim`.
values: af.Array or scalar number
The min of all elements in `vals` along dimension `dim` according to keys
"""
return _rbk_dim(keys, vals, dim, backend.get().af_min_by_key)

def max(a, dim=None):
"""
Find the maximum value of all the elements along a specified dimension.
Expand All @@ -148,6 +250,28 @@ def max(a, dim=None):
else:
return _reduce_all(a, backend.get().af_max_all)

def maxByKey(keys, vals, dim=-1):
"""
Calculate the max of elements along a specified dimension according to a key.

Parameters
----------
keys : af.Array
One dimensional arrayfire array with reduction keys.
vals : af.Array
Multi dimensional arrayfire array that will be reduced.
dim: optional: int. default: -1
Dimension along which the max will occur.

Returns
-------
keys: af.Array or scalar number
The reduced keys of all elements in `vals` along dimension `dim`.
values: af.Array or scalar number
The max of all elements in `vals` along dimension `dim` according to keys.
"""
return _rbk_dim(keys, vals, dim, backend.get().af_max_by_key)

def all_true(a, dim=None):
"""
Check if all the elements along a specified dimension are true.
Expand All @@ -170,6 +294,28 @@ def all_true(a, dim=None):
else:
return _reduce_all(a, backend.get().af_all_true_all)

def allTrueByKey(keys, vals, dim=-1):
"""
Calculate if all elements are true along a specified dimension according to a key.

Parameters
----------
keys : af.Array
One dimensional arrayfire array with reduction keys.
vals : af.Array
Multi dimensional arrayfire array that will be reduced.
dim: optional: int. default: -1
Dimension along which the all true check will occur.

Returns
-------
keys: af.Array or scalar number
The reduced keys of all true check in `vals` along dimension `dim`.
values: af.Array or scalar number
Booleans denoting if all elements are true in `vals` along dimension `dim` according to keys
"""
return _rbk_dim(keys, vals, dim, backend.get().af_all_true_by_key)

def any_true(a, dim=None):
"""
Check if any the elements along a specified dimension are true.
Expand All @@ -192,6 +338,28 @@ def any_true(a, dim=None):
else:
return _reduce_all(a, backend.get().af_any_true_all)

def anyTrueByKey(keys, vals, dim=-1):
"""
Calculate if any elements are true along a specified dimension according to a key.

Parameters
----------
keys : af.Array
One dimensional arrayfire array with reduction keys.
vals : af.Array
Multi dimensional arrayfire array that will be reduced.
dim: optional: int. default: -1
Dimension along which the any true check will occur.

Returns
-------
keys: af.Array or scalar number
The reduced keys of any true check in `vals` along dimension `dim`.
values: af.Array or scalar number
Booleans denoting if any elements are true in `vals` along dimension `dim` according to keys.
"""
return _rbk_dim(keys, vals, dim, backend.get().af_any_true_by_key)

def count(a, dim=None):
"""
Count the number of non zero elements in an array along a specified dimension.
Expand All @@ -214,6 +382,28 @@ def count(a, dim=None):
else:
return _reduce_all(a, backend.get().af_count_all)

def countByKey(keys, vals, dim=-1):
"""
Counts non-zero elements along a specified dimension according to a key.

Parameters
----------
keys : af.Array
One dimensional arrayfire array with reduction keys.
vals : af.Array
Multi dimensional arrayfire array that will be reduced.
dim: optional: int. default: -1
Dimension along which to count elements.

Returns
-------
keys: af.Array or scalar number
The reduced keys of count in `vals` along dimension `dim`.
values: af.Array or scalar number
Count of non-zero elements in `vals` along dimension `dim` according to keys.
"""
return _rbk_dim(keys, vals, dim, backend.get().af_count_by_key)

def imin(a, dim=None):
"""
Find the value and location of the minimum value along a specified dimension
Expand Down
20 changes: 20 additions & 0 deletions arrayfire/arith.py
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,26 @@ def sqrt(a):
"""
return _arith_unary_func(a, backend.get().af_sqrt)

def rsqrt(a):
"""
Reciprocal or inverse square root of each element in the array.

Parameters
----------
a : af.Array
Multi dimensional arrayfire array.

Returns
--------
out : af.Array
array containing the inverse square root of each value from `a`.

Note
-------
`a` must not be complex.
"""
return _arith_unary_func(a, backend.get().af_rsqrt)

def cbrt(a):
"""
Cube root of each element in the array.
Expand Down
8 changes: 8 additions & 0 deletions arrayfire/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,14 @@ def is_single(self):
safe_call(backend.get().af_is_single(c_pointer(res), self.arr))
return res.value

def is_half(self):
"""
Check if the array is of half floating point type (fp16).
"""
res = c_bool_t(False)
safe_call(backend.get().af_is_half(c_pointer(res), self.arr))
return res.value

def is_real_floating(self):
"""
Check if the array is real and of floating point type.
Expand Down
52 changes: 52 additions & 0 deletions arrayfire/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,58 @@ def replace(lhs, cond, rhs):
else:
safe_call(backend.get().af_replace_scalar(lhs.arr, cond.arr, c_double_t(rhs)))

def pad(a, beginPadding, endPadding, padFillType = PAD.ZERO):
"""
Pad an array

This function will pad an array with the specified border size.
Newly padded values can be filled in several different ways.

Parameters
----------

a: af.Array
A multi dimensional input arrayfire array.

beginPadding: tuple of ints. default: (0, 0, 0, 0).

endPadding: tuple of ints. default: (0, 0, 0, 0).

padFillType: optional af.PAD default: af.PAD.ZERO
specifies type of values to fill padded border with

Returns
-------
output: af.Array
A padded array

Examples
---------
>>> import arrayfire as af
>>> a = af.randu(3,3)
>>> af.display(a)
[3 3 1 1]
0.4107 0.1794 0.3775
0.8224 0.4198 0.3027
0.9518 0.0081 0.6456

>>> padded = af.pad(a, (1, 1), (1, 1), af.ZERO)
>>> af.display(padded)
[5 5 1 1]
0.0000 0.0000 0.0000 0.0000 0.0000
0.0000 0.4107 0.1794 0.3775 0.0000
0.0000 0.8224 0.4198 0.3027 0.0000
0.0000 0.9518 0.0081 0.6456 0.0000
0.0000 0.0000 0.0000 0.0000 0.0000
"""
out = Array()
begin_dims = dim4(beginPadding[0], beginPadding[1], beginPadding[2], beginPadding[3])
end_dims = dim4(endPadding[0], endPadding[1], endPadding[2], endPadding[3])

safe_call(backend.get().af_pad(c_pointer(out.arr), a.arr, 4, c_pointer(begin_dims), 4, c_pointer(end_dims), padFillType.value))
return out


def lookup(a, idx, dim=0):
"""
Lookup the values of input array based on index.
Expand Down
19 changes: 19 additions & 0 deletions arrayfire/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,25 @@ def is_dbl_supported(device=None):
safe_call(backend.get().af_get_dbl_support(c_pointer(res), dev))
return res.value

def is_half_supported(device=None):
"""
Check if half precision is supported on specified device.

Parameters
-----------
device: optional: int. default: None.
id of the desired device.

Returns
--------
- True if half precision supported.
- False if half precision not supported.
"""
dev = device if device is not None else get_device()
res = c_bool_t(False)
safe_call(backend.get().af_get_half_support(c_pointer(res), dev))
return res.value

def sync(device=None):
"""
Block until all the functions on the device have completed execution.
Expand Down
Loading