From 01e9840fab59576bc89b22e4acece25b872a82a3 Mon Sep 17 00:00:00 2001 From: Anton Chernyatevich Date: Fri, 13 Nov 2020 03:16:19 +0200 Subject: [PATCH 1/3] Remove import star --- LICENSE | 2 +- __af_version__.py | 4 +- arrayfire/__init__.py | 175 +++++++++--- arrayfire/algorithm.py | 114 ++++---- arrayfire/arith.py | 70 ++++- arrayfire/array.py | 301 ++++++++++---------- arrayfire/base.py | 9 +- arrayfire/bcast.py | 15 +- arrayfire/blas.py | 34 ++- arrayfire/cuda.py | 32 ++- arrayfire/data.py | 53 ++-- arrayfire/device.py | 81 ++++-- arrayfire/features.py | 17 +- arrayfire/graphics.py | 103 ++++--- arrayfire/image.py | 266 ++++++++--------- arrayfire/index.py | 98 ++++--- arrayfire/interop.py | 116 ++++---- arrayfire/lapack.py | 36 ++- arrayfire/library.py | 177 ++++++------ arrayfire/ml.py | 5 +- arrayfire/opencl.py | 86 +++--- arrayfire/random.py | 33 ++- arrayfire/signal.py | 228 ++++++++------- arrayfire/sparse.py | 56 ++-- arrayfire/statistics.py | 97 ++++--- arrayfire/timer.py | 17 +- arrayfire/util.py | 42 +-- arrayfire/vision.py | 109 +++---- docs/conf.py | 44 +-- examples/benchmarks/bench_blas.py | 11 +- examples/benchmarks/bench_cg.py | 51 ++-- examples/benchmarks/bench_fft.py | 17 +- examples/benchmarks/monte_carlo_pi.py | 27 +- examples/financial/black_scholes_options.py | 20 +- examples/financial/heston_model.py | 33 +-- examples/financial/monte_carlo_options.py | 37 +-- examples/getting_started/convolve.py | 20 +- examples/getting_started/intro.py | 27 +- examples/graphics/conway.py | 33 ++- examples/graphics/fractal.py | 22 +- examples/graphics/histogram.py | 18 +- examples/graphics/plot2d.py | 11 +- examples/graphics/plot3.py | 4 +- examples/graphics/surface.py | 10 +- examples/helloworld/helloworld.py | 42 +-- setup.py | 2 +- tests/__init__.py | 2 +- tests/__main__.py | 2 +- tests/simple/__init__.py | 2 +- tests/simple/_util.py | 2 +- tests/simple/algorithm.py | 2 +- tests/simple/arith.py | 12 +- tests/simple/array_test.py | 8 +- tests/simple/blas.py | 2 +- tests/simple/data.py | 2 +- tests/simple/device.py | 12 +- tests/simple/image.py | 5 +- tests/simple/index.py | 7 +- tests/simple/interop.py | 48 ++-- tests/simple/lapack.py | 2 +- tests/simple/random.py | 6 +- tests/simple/signal.py | 2 +- tests/simple/sparse.py | 2 +- tests/simple/statistics.py | 4 +- 64 files changed, 1648 insertions(+), 1279 deletions(-) diff --git a/LICENSE b/LICENSE index 211cf4e30..46131f7c6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015, ArrayFire +Copyright (c) 2019, ArrayFire All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/__af_version__.py b/__af_version__.py index dfa78b826..c8d51d332 100644 --- a/__af_version__.py +++ b/__af_version__.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/arrayfire/__init__.py b/arrayfire/__init__.py index 5cb009951..5708805f3 100644 --- a/arrayfire/__init__.py +++ b/arrayfire/__init__.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -48,39 +48,150 @@ """ +from .algorithm import ( + accum, all_true, allTrueByKey, any_true, anyTrueByKey, count, countByKey, diff1, diff2, imax, imin, max, maxByKey, min, minByKey, product, productByKey, scan, scan_by_key, set_intersect, + set_union, set_unique, sort, sort_by_key, sort_index, sum, sumByKey, where) +from .arith import ( + abs, acos, acosh, arg, asin, asinh, atan, atan2, atanh, cast, cbrt, ceil, clamp, conjg, cos, cosh, cplx, erf, erfc, exp, + expm1, factorial, floor, hypot, imag, isinf, isnan, iszero, lgamma, log, log1p, log2, log10, maxof, minof, + mod, pow, + pow2, real, rem, root, round, rsqrt, sigmoid, sign, sin, sinh, sqrt, tan, tanh, tgamma, trunc) +from .array import ( + Array, constant_array, display, get_display_dims_limit, read_array, save_array, + set_display_dims_limit, transpose, transpose_inplace) +from .base import BaseArray +from .bcast import broadcast +from .blas import dot, matmul, matmulNT, matmulTN, matmulTT, gemm +from .cuda import get_native_id, get_stream, set_native_id +from .data import ( + constant, diag, flat, flip, identity, iota, join, lookup, lower, moddims, pad, range, reorder, replace, select, shift, + tile, upper) +from .library import ( + BACKEND, BINARYOP, CANNY_THRESHOLD, COLORMAP, CONNECTIVITY, CONV_DOMAIN, CONV_GRADIENT, CONV_MODE, CSPACE, DIFFUSION, ERR, FLUX, + HOMOGRAPHY, IMAGE_FORMAT, INTERP, ITERATIVE_DECONV, INVERSE_DECONV, MARKER, MATCH, MATPROP, MOMENT, NORM, PAD, RANDOM_ENGINE, STORAGE, TOPK, VARIANCE, YCC_STD, Dtype, Source, AF_VER_MAJOR, FORGE_VER_MAJOR) +from .device import ( + alloc_device, alloc_host, alloc_pinned, device_gc, device_info, device_mem_info, eval, free_device, free_host, + free_pinned, get_device, get_device_count, get_device_ptr, get_manual_eval_flag, info, + info_str, init, is_dbl_supported, is_half_supported, is_locked_array, lock_array, lock_device_ptr, print_mem_info, set_device, + set_manual_eval_flag, sync, unlock_array, unlock_device_ptr) +from .graphics import Window +from .image import ( + anisotropic_diffusion, bilateral, canny, color_space, confidenceCC, dilate, dilate3, erode, erode3, gaussian_kernel, gradient, + gray2rgb, hist_equal, histogram, hsv2rgb, is_image_io_available, iterativeDeconv, inverseDeconv, load_image, load_image_native, maxfilt, + mean_shift, minfilt, moments, regions, resize, rgb2gray, rgb2hsv, rgb2ycbcr, rotate, sat, save_image, + save_image_native, scale, skew, sobel_derivatives, sobel_filter, transform, translate, unwrap, wrap, ycbcr2rgb) +from .index import Index, ParallelRange, Seq +from .interop import AF_NUMBA_FOUND, AF_NUMPY_FOUND, AF_PYCUDA_FOUND, AF_PYOPENCL_FOUND, to_array +from .lapack import ( + cholesky, cholesky_inplace, det, inverse, is_lapack_available, lu, lu_inplace, norm, pinverse, qr, qr_inplace, rank, solve, + solve_lu, svd, svd_inplace) +from .library import ( + get_active_backend, get_available_backends, get_backend, get_backend_count, get_backend_id, get_device_id, + get_size_of, safe_call, set_backend) +from .ml import convolve2GradientNN +from .random import ( + Random_Engine, get_default_random_engine, get_seed, randn, randu, set_default_random_engine_type, + set_seed) +from .signal import ( + approx1, approx1_uniform, approx2, approx2_uniform, convolve, convolve1, convolve2, convolve2NN, convolve2_separable, convolve3, dft, fft, fft2, fft2_c2r, + fft2_inplace, fft2_r2c, fft3, fft3_c2r, fft3_inplace, fft3_r2c, fft_c2r, fft_convolve, fft_convolve1, + fft_convolve2, fft_convolve3, fft_inplace, fft_r2c, fir, idft, ifft, ifft2, ifft2_inplace, ifft3, ifft3_inplace, + ifft_inplace, iir, medfilt, medfilt1, medfilt2, set_fft_plan_cache_size) +from .sparse import ( + convert_sparse, convert_sparse_to_dense, create_sparse, create_sparse_from_dense, create_sparse_from_host, + sparse_get_col_idx, sparse_get_info, sparse_get_nnz, sparse_get_row_idx, sparse_get_storage, sparse_get_values) +from .statistics import corrcoef, cov, mean, meanvar, median, stdev, topk, var +from .timer import timeit +from .util import dim4, dim4_to_tuple, implicit_dtype, number_dtype, to_str, get_reversion, get_version, to_dtype, to_typecode, to_c_type + try: + # FIXME: pycuda imported but unused import pycuda.autoinit except ImportError: pass -from .library import * -from .array import * -from .data import * -from .util import * -from .algorithm import * -from .device import * -from .blas import * -from .arith import * -from .statistics import * -from .lapack import * -from .signal import * -from .image import * -from .features import * -from .vision import * -from .graphics import * -from .bcast import * -from .index import * -from .interop import * -from .timer import * -from .random import * -from .sparse import * -from .ml import * - -# do not export default modules as part of arrayfire -del ct -del inspect -del numbers -del os - -if (AF_NUMPY_FOUND): - del np + +__all__ = [ + # algorithm + "accum", "all_true", "allTrueByKey", "any_true", "anyTrueByKey", "count", "countByKey", + "diff1", "diff2", "imax", "imin", "max", "maxByKey", "min", "minByKey", "product", + "productByKey", "scan", "scan_by_key", "set_intersect", "set_union", "set_unique", + "sort", "sort_by_key", "sort_index", "sum", "sumByKey", "where", + # arith + "abs", "acos", "acosh", "arg", "asin", "asinh", "atan", "atan2", "atanh", + "cast", "cbrt", "ceil", "clamp", "conjg", "cos", "cosh", "cplx", "erf", + "erfc", "exp", "expm1", "factorial", "floor", "hypot", "imag", "isinf", + "isnan", "iszero", "lgamma", "log", "log1p", "log2", "log10", "maxof", + "minof", "mod", "pow", "pow2", "real", "rem", "root", "round", "rsqrt", + "sigmoid", "sign", "sin", "sinh", "sqrt", "tan", "tanh", "tgamma", "trunc", + # array + "Array", "constant_array", "display", "get_display_dims_limit", "read_array", + "save_array", "set_display_dims_limit", "transpose", "transpose_inplace", + # base + "BaseArray", + # bcast + "broadcast", + # blas + "dot", "matmul", "matmulNT", "matmulTN", "matmulTT", "gemm", + #cuda + "get_native_id", "get_stream", "set_native_id", + # data + "constant", "diag", "flat", "flip", "identity", "iota", "join", "lookup", + "lower", "moddims", "pad", "range", "reorder", "replace", "select", + "shift", "tile", "upper", + # library + "BACKEND", "BINARYOP", "CANNY_THRESHOLD", "COLORMAP", "CONNECTIVITY", "CONV_DOMAIN", + "CONV_GRADIENT", "CONV_MODE", "CSPACE", "DIFFUSION", "ERR", "FLUX", "HOMOGRAPHY", + "IMAGE_FORMAT", "INTERP", "ITERATIVE_DECONV", "INVERSE_DECONV", "MARKER", "MATCH", + "MATPROP", "MOMENT", "NORM", "PAD", "RANDOM_ENGINE", "STORAGE", "TOPK", "VARIANCE", + "YCC_STD", "Dtype", "Source", "AF_VER_MAJOR", "FORGE_VER_MAJOR", + # device + "alloc_device", "alloc_host", "alloc_pinned", "device_gc", "device_info", "device_mem_info", + "eval", "free_device", "free_host", "free_pinned", "get_device", "get_device_count", + "get_device_ptr", "get_manual_eval_flag", "info", "info_str", "init", "is_dbl_supported", + "is_half_supported", "is_locked_array", "lock_array", "lock_device_ptr", "print_mem_info", + "set_device", "set_manual_eval_flag", "sync", "unlock_array", "unlock_device_ptr", + # graphics + "Window", + # image + "anisotropic_diffusion", "bilateral", "canny", "color_space", "confidenceCC", "dilate", "dilate3", + "erode", "erode3", "gaussian_kernel", "gradient", "gray2rgb", "hist_equal", "histogram", "hsv2rgb", + "is_image_io_available", "iterativeDeconv", "inverseDeconv", "load_image", "load_image_native", + "maxfilt", "mean_shift", "minfilt", "moments", "regions", "resize", "rgb2gray", "rgb2hsv", "rgb2ycbcr", + "rotate", "sat", "save_image", "save_image_native", "scale", "skew", "sobel_derivatives", "sobel_filter", + "transform", "translate", "unwrap", "wrap", "ycbcr2rgb", + # index + "Index", "ParallelRange", "Seq", + # interop + "AF_NUMBA_FOUND", "AF_NUMPY_FOUND", "AF_PYCUDA_FOUND", "AF_PYOPENCL_FOUND", "to_array", + # lapack + "cholesky", "cholesky_inplace", "det", "inverse", "is_lapack_available", "lu", "lu_inplace", + "norm", "pinverse", "qr", "qr_inplace", "rank", "solve", "solve_lu", "svd", "svd_inplace", + # library + "get_active_backend", "get_available_backends", "get_backend", "get_backend_count", + "get_backend_id", "get_device_id", "get_size_of", "safe_call", "set_backend", + # ml + "convolve2GradientNN", + # random + "Random_Engine", "get_default_random_engine", "get_seed", "randn", "randu", + "set_default_random_engine_type", "set_seed", + # signal + "approx1", "approx1_uniform", "approx2", "approx2_uniform", "convolve", "convolve1", + "convolve2", "convolve2NN", "convolve2_separable", "convolve3", "dft", "fft", + "fft2", "fft2_c2r", "fft2_inplace", "fft2_r2c", "fft3", "fft3_c2r", "fft3_inplace", + "fft3_r2c", "fft_c2r", "fft_convolve", "fft_convolve1", "fft_convolve2", "fft_convolve3", + "fft_inplace", "fft_r2c", "fir", "idft", "ifft", "ifft2", "ifft2_inplace", "ifft3", + "ifft3_inplace", "ifft_inplace", "iir", "medfilt", "medfilt1", "medfilt2", + "set_fft_plan_cache_size", + # sparse + "convert_sparse", "convert_sparse_to_dense", "create_sparse", "create_sparse_from_dense", + "create_sparse_from_host", "sparse_get_col_idx", "sparse_get_info", "sparse_get_nnz", + "sparse_get_row_idx", "sparse_get_storage", "sparse_get_values", + # statistics + "corrcoef", "cov", "mean", "meanvar", "median", "stdev", "topk", "var", + # timer + "timeit", + # util + "dim4", "dim4_to_tuple", "implicit_dtype", "number_dtype", "to_str", "get_reversion", + "get_version", "to_dtype", "to_typecode", "to_c_type" +] diff --git a/arrayfire/algorithm.py b/arrayfire/algorithm.py index d5adbcce5..84d02422f 100644 --- a/arrayfire/algorithm.py +++ b/arrayfire/algorithm.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,8 +11,8 @@ Vector algorithms (sum, min, sort, etc). """ -from .library import * -from .array import * +from .array import Array +from .library import backend, safe_call, BINARYOP, c_bool_t, c_double_t, c_int_t, c_pointer, c_uint_t def _parallel_dim(a, dim, c_func): out = Array() @@ -88,16 +88,16 @@ def sum(a, dim=None, nan_val=None): The sum of all elements in `a` along dimension `dim`. If `dim` is `None`, sum of the entire Array is returned. """ - if (nan_val is not None): + if nan_val is not None: if dim is not None: return _nan_parallel_dim(a, dim, backend.get().af_sum_nan, nan_val) - else: - return _nan_reduce_all(a, backend.get().af_sum_nan_all, nan_val) - else: - if dim is not None: - return _parallel_dim(a, dim, backend.get().af_sum) - else: - return _reduce_all(a, backend.get().af_sum_all) + return _nan_reduce_all(a, backend.get().af_sum_nan_all, nan_val) + + if dim is not None: + return _parallel_dim(a, dim, backend.get().af_sum) + return _reduce_all(a, backend.get().af_sum_all) + + def sumByKey(keys, vals, dim=-1, nan_val=None): @@ -146,16 +146,15 @@ def product(a, dim=None, nan_val=None): The product of all elements in `a` along dimension `dim`. If `dim` is `None`, product of the entire Array is returned. """ - if (nan_val is not None): + if nan_val is not None: if dim is not None: return _nan_parallel_dim(a, dim, backend.get().af_product_nan, nan_val) - else: - return _nan_reduce_all(a, backend.get().af_product_nan_all, nan_val) - else: - if dim is not None: - return _parallel_dim(a, dim, backend.get().af_product) - else: - return _reduce_all(a, backend.get().af_product_all) + return _nan_reduce_all(a, backend.get().af_product_nan_all, nan_val) + + if dim is not None: + return _parallel_dim(a, dim, backend.get().af_product) + return _reduce_all(a, backend.get().af_product_all) + def productByKey(keys, vals, dim=-1, nan_val=None): """ @@ -203,8 +202,8 @@ def min(a, dim=None): """ if dim is not None: return _parallel_dim(a, dim, backend.get().af_min) - else: - return _reduce_all(a, backend.get().af_min_all) + return _reduce_all(a, backend.get().af_min_all) + def minByKey(keys, vals, dim=-1): """ @@ -247,8 +246,8 @@ def max(a, dim=None): """ if dim is not None: return _parallel_dim(a, dim, backend.get().af_max) - else: - return _reduce_all(a, backend.get().af_max_all) + return _reduce_all(a, backend.get().af_max_all) + def maxByKey(keys, vals, dim=-1): """ @@ -291,8 +290,8 @@ def all_true(a, dim=None): """ if dim is not None: return _parallel_dim(a, dim, backend.get().af_all_true) - else: - return _reduce_all(a, backend.get().af_all_true_all) + return _reduce_all(a, backend.get().af_all_true_all) + def allTrueByKey(keys, vals, dim=-1): """ @@ -382,6 +381,7 @@ 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. @@ -426,16 +426,17 @@ def imin(a, dim=None): out = Array() idx = Array() safe_call(backend.get().af_imin(c_pointer(out.arr), c_pointer(idx.arr), a.arr, c_int_t(dim))) - return out,idx - else: - real = c_double_t(0) - imag = c_double_t(0) - idx = c_uint_t(0) - safe_call(backend.get().af_imin_all(c_pointer(real), c_pointer(imag), c_pointer(idx), a.arr)) - real = real.value - imag = imag.value - val = real if imag == 0 else real + imag * 1j - return val,idx.value + return out, idx + + real = c_double_t(0) + imag = c_double_t(0) + idx = c_uint_t(0) + safe_call(backend.get().af_imin_all(c_pointer(real), c_pointer(imag), c_pointer(idx), a.arr)) + real = real.value + imag = imag.value + val = real if imag == 0 else real + imag * 1j + return val, idx.value + def imax(a, dim=None): """ @@ -459,16 +460,16 @@ def imax(a, dim=None): out = Array() idx = Array() safe_call(backend.get().af_imax(c_pointer(out.arr), c_pointer(idx.arr), a.arr, c_int_t(dim))) - return out,idx - else: - real = c_double_t(0) - imag = c_double_t(0) - idx = c_uint_t(0) - safe_call(backend.get().af_imax_all(c_pointer(real), c_pointer(imag), c_pointer(idx), a.arr)) - real = real.value - imag = imag.value - val = real if imag == 0 else real + imag * 1j - return val,idx.value + return out, idx + + real = c_double_t(0) + imag = c_double_t(0) + idx = c_uint_t(0) + safe_call(backend.get().af_imax_all(c_pointer(real), c_pointer(imag), c_pointer(idx), a.arr)) + real = real.value + imag = imag.value + val = real if imag == 0 else real + imag * 1j + return val, idx.value def accum(a, dim=0): @@ -489,6 +490,7 @@ 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. @@ -520,6 +522,7 @@ def scan(a, dim=0, op=BINARYOP.ADD, inclusive_scan=True): safe_call(backend.get().af_scan(c_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. @@ -554,6 +557,7 @@ def scan_by_key(key, a, dim=0, op=BINARYOP.ADD, inclusive_scan=True): safe_call(backend.get().af_scan_by_key(c_pointer(out.arr), key.arr, a.arr, dim, op.value, inclusive_scan)) return out + def where(a): """ Find the indices of non zero elements @@ -572,6 +576,7 @@ def where(a): safe_call(backend.get().af_where(c_pointer(out.arr), a.arr)) return out + def diff1(a, dim=0): """ Find the first order differences along specified dimensions @@ -590,6 +595,7 @@ def diff1(a, dim=0): """ return _parallel_dim(a, dim, backend.get().af_diff1) + def diff2(a, dim=0): """ Find the second order differences along specified dimensions @@ -608,6 +614,7 @@ def diff2(a, dim=0): """ return _parallel_dim(a, dim, backend.get().af_diff2) + def sort(a, dim=0, is_ascending=True): """ Sort the array along a specified dimension @@ -634,6 +641,7 @@ def sort(a, dim=0, is_ascending=True): safe_call(backend.get().af_sort(c_pointer(out.arr), a.arr, c_uint_t(dim), c_bool_t(is_ascending))) return out + def sort_index(a, dim=0, is_ascending=True): """ Sort the array along a specified dimension and get the indices. @@ -659,9 +667,10 @@ def sort_index(a, dim=0, is_ascending=True): """ out = Array() idx = Array() - safe_call(backend.get().af_sort_index(c_pointer(out.arr), c_pointer(idx.arr), a.arr, - c_uint_t(dim), c_bool_t(is_ascending))) - return out,idx + safe_call(backend.get().af_sort_index( + c_pointer(out.arr), c_pointer(idx.arr), a.arr, c_uint_t(dim), c_bool_t(is_ascending))) + return out, idx + def sort_by_key(ik, iv, dim=0, is_ascending=True): """ @@ -690,9 +699,10 @@ def sort_by_key(ik, iv, dim=0, is_ascending=True): """ ov = Array() ok = Array() - safe_call(backend.get().af_sort_by_key(c_pointer(ok.arr), c_pointer(ov.arr), - ik.arr, iv.arr, c_uint_t(dim), c_bool_t(is_ascending))) - return ov,ok + safe_call(backend.get().af_sort_by_key( + c_pointer(ok.arr), c_pointer(ov.arr), ik.arr, iv.arr, c_uint_t(dim), c_bool_t(is_ascending))) + return ov, ok + def set_unique(a, is_sorted=False): """ @@ -714,6 +724,7 @@ def set_unique(a, is_sorted=False): safe_call(backend.get().af_set_unique(c_pointer(out.arr), a.arr, c_bool_t(is_sorted))) return out + def set_union(a, b, is_unique=False): """ Find the union of two arrays. @@ -736,6 +747,7 @@ def set_union(a, b, is_unique=False): safe_call(backend.get().af_set_union(c_pointer(out.arr), a.arr, b.arr, c_bool_t(is_unique))) return out + def set_intersect(a, b, is_unique=False): """ Find the intersect of two arrays. diff --git a/arrayfire/arith.py b/arrayfire/arith.py index e4dc2fdfd..85176436a 100644 --- a/arrayfire/arith.py +++ b/arrayfire/arith.py @@ -1,5 +1,6 @@ + ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,10 +12,11 @@ Math functions (sin, sqrt, exp, etc). """ -from .library import * -from .array import * +from .array import Array, constant_array from .bcast import _bcast_var -from .util import _is_number +from .library import backend, safe_call, c_pointer +from .util import _is_number, dim4_to_tuple, implicit_dtype + def _arith_binary_func(lhs, rhs, c_func): out = Array() @@ -25,10 +27,10 @@ def _arith_binary_func(lhs, rhs, c_func): if not (is_left_array or is_right_array): raise TypeError("Atleast one input needs to be of type arrayfire.array") - elif (is_left_array and is_right_array): + if is_left_array and is_right_array: safe_call(c_func(c_pointer(out.arr), lhs.arr, rhs.arr, _bcast_var.get())) - elif (_is_number(rhs)): + elif _is_number(rhs): ldims = dim4_to_tuple(lhs.dims()) rty = implicit_dtype(rhs, lhs.type()) other = Array() @@ -44,15 +46,16 @@ def _arith_binary_func(lhs, rhs, c_func): return out + def _arith_unary_func(a, c_func): out = Array() safe_call(c_func(c_pointer(out.arr), a.arr)) return out + def cast(a, dtype): """ Cast an array to a specified type - Parameters ---------- a : af.Array @@ -78,6 +81,7 @@ def cast(a, dtype): safe_call(backend.get().af_cast(c_pointer(out.arr), a.arr, dtype.value)) return out + def minof(lhs, rhs): """ Find the minimum value of two inputs at each location. @@ -102,6 +106,7 @@ def minof(lhs, rhs): """ return _arith_binary_func(lhs, rhs, backend.get().af_minof) + def maxof(lhs, rhs): """ Find the maximum value of two inputs at each location. @@ -126,6 +131,7 @@ 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 @@ -164,6 +170,7 @@ def clamp(val, low, high): return out + def mod(lhs, rhs): """ Find the modulus. @@ -184,6 +191,7 @@ def mod(lhs, rhs): """ return _arith_binary_func(lhs, rhs, backend.get().af_mod) + def rem(lhs, rhs): """ Find the remainder. @@ -208,6 +216,7 @@ def rem(lhs, rhs): """ return _arith_binary_func(lhs, rhs, backend.get().af_rem) + def abs(a): """ Find the absolute values. @@ -224,6 +233,7 @@ def abs(a): """ return _arith_unary_func(a, backend.get().af_abs) + def arg(a): """ Find the theta value of the inputs in polar co-ordinates. @@ -240,6 +250,7 @@ def arg(a): """ return _arith_unary_func(a, backend.get().af_arg) + def sign(a): """ Find the sign of the inputs. @@ -256,6 +267,7 @@ def sign(a): """ return _arith_unary_func(a, backend.get().af_sign) + def round(a): """ Round the values to nearest integer. @@ -272,6 +284,7 @@ def round(a): """ return _arith_unary_func(a, backend.get().af_round) + def trunc(a): """ Round the values towards zero. @@ -288,6 +301,7 @@ def trunc(a): """ return _arith_unary_func(a, backend.get().af_trunc) + def floor(a): """ Round the values towards a smaller integer. @@ -304,6 +318,7 @@ def floor(a): """ return _arith_unary_func(a, backend.get().af_floor) + def ceil(a): """ Round the values towards a bigger integer. @@ -320,6 +335,7 @@ def ceil(a): """ return _arith_unary_func(a, backend.get().af_ceil) + def hypot(lhs, rhs): """ Find the value of the hypotunese. @@ -344,6 +360,7 @@ def hypot(lhs, rhs): """ return _arith_binary_func(lhs, rhs, backend.get().af_hypot) + def sin(a): """ Sine of each element in the array. @@ -364,6 +381,7 @@ def sin(a): """ return _arith_unary_func(a, backend.get().af_sin) + def cos(a): """ Cosine of each element in the array. @@ -384,6 +402,7 @@ def cos(a): """ return _arith_unary_func(a, backend.get().af_cos) + def tan(a): """ Tangent of each element in the array. @@ -404,6 +423,7 @@ def tan(a): """ return _arith_unary_func(a, backend.get().af_tan) + def asin(a): """ Arc Sine of each element in the array. @@ -424,6 +444,7 @@ def asin(a): """ return _arith_unary_func(a, backend.get().af_asin) + def acos(a): """ Arc Cosine of each element in the array. @@ -444,6 +465,7 @@ def acos(a): """ return _arith_unary_func(a, backend.get().af_acos) + def atan(a): """ Arc Tangent of each element in the array. @@ -464,6 +486,7 @@ def atan(a): """ return _arith_unary_func(a, backend.get().af_atan) + def atan2(lhs, rhs): """ Find the arc tan using two values. @@ -490,6 +513,7 @@ def atan2(lhs, rhs): """ return _arith_binary_func(lhs, rhs, backend.get().af_atan2) + def cplx(lhs, rhs=None): """ Create a complex array from real inputs. @@ -516,8 +540,8 @@ def cplx(lhs, rhs=None): """ if rhs is None: return _arith_unary_func(lhs, backend.get().af_cplx) - else: - return _arith_binary_func(lhs, rhs, backend.get().af_cplx2) + return _arith_binary_func(lhs, rhs, backend.get().af_cplx2) + def real(a): """ @@ -536,6 +560,7 @@ def real(a): """ return _arith_unary_func(a, backend.get().af_real) + def imag(a): """ Find the imaginary values of the input. @@ -552,6 +577,7 @@ def imag(a): """ return _arith_unary_func(a, backend.get().af_imag) + def conjg(a): """ Find the complex conjugate values of the input. @@ -568,6 +594,7 @@ def conjg(a): """ return _arith_unary_func(a, backend.get().af_conjg) + def sinh(a): """ Hyperbolic Sine of each element in the array. @@ -588,6 +615,7 @@ def sinh(a): """ return _arith_unary_func(a, backend.get().af_sinh) + def cosh(a): """ Hyperbolic Cosine of each element in the array. @@ -608,6 +636,7 @@ def cosh(a): """ return _arith_unary_func(a, backend.get().af_cosh) + def tanh(a): """ Hyperbolic Tangent of each element in the array. @@ -628,6 +657,7 @@ def tanh(a): """ return _arith_unary_func(a, backend.get().af_tanh) + def asinh(a): """ Arc Hyperbolic Sine of each element in the array. @@ -648,6 +678,7 @@ def asinh(a): """ return _arith_unary_func(a, backend.get().af_asinh) + def acosh(a): """ Arc Hyperbolic Cosine of each element in the array. @@ -668,6 +699,7 @@ def acosh(a): """ return _arith_unary_func(a, backend.get().af_acosh) + def atanh(a): """ Arc Hyperbolic Tangent of each element in the array. @@ -688,6 +720,7 @@ def atanh(a): """ return _arith_unary_func(a, backend.get().af_atanh) + def root(lhs, rhs): """ Find the root values of two inputs at each location. @@ -712,6 +745,7 @@ def root(lhs, rhs): """ return _arith_binary_func(lhs, rhs, backend.get().af_root) + def pow(lhs, rhs): """ Find the power of two inputs at each location. @@ -736,6 +770,7 @@ def pow(lhs, rhs): """ return _arith_binary_func(lhs, rhs, backend.get().af_pow) + def pow2(a): """ Raise 2 to the power of each element in input. @@ -756,6 +791,7 @@ def pow2(a): """ return _arith_unary_func(a, backend.get().af_pow2) + def sigmoid(a): """ Raise 2 to the power of each element in input. @@ -776,6 +812,7 @@ def sigmoid(a): """ return _arith_unary_func(a, backend.get().af_sigmoid) + def exp(a): """ Exponential of each element in the array. @@ -796,6 +833,7 @@ def exp(a): """ return _arith_unary_func(a, backend.get().af_exp) + def expm1(a): """ Exponential of each element in the array minus 1. @@ -817,6 +855,7 @@ def expm1(a): """ return _arith_unary_func(a, backend.get().af_expm1) + def erf(a): """ Error function of each element in the array. @@ -837,6 +876,7 @@ def erf(a): """ return _arith_unary_func(a, backend.get().af_erf) + def erfc(a): """ Complementary error function of each element in the array. @@ -857,6 +897,7 @@ def erfc(a): """ return _arith_unary_func(a, backend.get().af_erfc) + def log(a): """ Natural logarithm of each element in the array. @@ -877,6 +918,7 @@ def log(a): """ return _arith_unary_func(a, backend.get().af_log) + def log1p(a): """ Logarithm of each element in the array plus 1. @@ -898,6 +940,7 @@ def log1p(a): """ return _arith_unary_func(a, backend.get().af_log1p) + def log10(a): """ Logarithm base 10 of each element in the array. @@ -918,6 +961,7 @@ def log10(a): """ return _arith_unary_func(a, backend.get().af_log10) + def log2(a): """ Logarithm base 2 of each element in the array. @@ -938,6 +982,7 @@ def log2(a): """ return _arith_unary_func(a, backend.get().af_log2) + def sqrt(a): """ Square root of each element in the array. @@ -978,6 +1023,7 @@ def rsqrt(a): """ return _arith_unary_func(a, backend.get().af_rsqrt) + def cbrt(a): """ Cube root of each element in the array. @@ -998,6 +1044,7 @@ def cbrt(a): """ return _arith_unary_func(a, backend.get().af_cbrt) + def factorial(a): """ factorial of each element in the array. @@ -1018,6 +1065,7 @@ def factorial(a): """ return _arith_unary_func(a, backend.get().af_factorial) + def tgamma(a): """ Performs the gamma function for each element in the array. @@ -1038,6 +1086,7 @@ def tgamma(a): """ return _arith_unary_func(a, backend.get().af_tgamma) + def lgamma(a): """ Performs the logarithm of gamma function for each element in the array. @@ -1058,6 +1107,7 @@ def lgamma(a): """ return _arith_unary_func(a, backend.get().af_lgamma) + def iszero(a): """ Check if each element of the input is zero. @@ -1078,6 +1128,7 @@ def iszero(a): """ return _arith_unary_func(a, backend.get().af_iszero) + def isinf(a): """ Check if each element of the input is infinity. @@ -1098,6 +1149,7 @@ def isinf(a): """ return _arith_unary_func(a, backend.get().af_isinf) + def isnan(a): """ Check if each element of the input is NaN. diff --git a/arrayfire/array.py b/arrayfire/array.py index 1b71db2c7..acbf14230 100644 --- a/arrayfire/array.py +++ b/arrayfire/array.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -13,18 +13,22 @@ import inspect import os -from .library import * -from .util import * -from .util import _is_number + +from .base import BaseArray from .bcast import _bcast_var -from .base import * -from .index import * -from .index import _Index4 +from .index import Index, ParallelRange, _Index4 +from .library import backend, safe_call +from .library import ( + Dtype, Source, c_bool_t, c_char_ptr_t, c_dim_t, c_double_t, c_int_t, c_longlong_t, c_pointer, c_size_t, c_uint_t, + c_ulonglong_t, c_void_ptr_t) +from .util import ( + _is_number, dim4, dim4_to_tuple, implicit_dtype, to_c_type, to_dtype, to_str, to_typecode, to_typename) _is_running_in_py_charm = "PYCHARM_HOSTED" in os.environ _display_dims_limit = None + def set_display_dims_limit(*dims): """ Sets the dimension limit after which array's data won't get @@ -44,6 +48,7 @@ def set_display_dims_limit(*dims): global _display_dims_limit _display_dims_limit = dims + def get_display_dims_limit(): """ Gets the dimension limit after which array's data won't get @@ -67,6 +72,7 @@ def get_display_dims_limit(): """ return _display_dims_limit + def _in_display_dims_limit(dims): if _is_running_in_py_charm: return False @@ -80,17 +86,19 @@ def _in_display_dims_limit(dims): return False return True + def _create_array(buf, numdims, idims, dtype, is_device): out_arr = c_void_ptr_t(0) c_dims = dim4(idims[0], idims[1], idims[2], idims[3]) - if (not is_device): - safe_call(backend.get().af_create_array(c_pointer(out_arr), c_void_ptr_t(buf), - numdims, c_pointer(c_dims), dtype.value)) + if not is_device: + safe_call(backend.get().af_create_array( + c_pointer(out_arr), c_void_ptr_t(buf), numdims, c_pointer(c_dims), dtype.value)) else: - safe_call(backend.get().af_device_array(c_pointer(out_arr), c_void_ptr_t(buf), - numdims, c_pointer(c_dims), dtype.value)) + safe_call(backend.get().af_device_array( + c_pointer(out_arr), c_void_ptr_t(buf), numdims, c_pointer(c_dims), dtype.value)) return out_arr + def _create_strided_array(buf, numdims, idims, dtype, is_device, offset, strides): out_arr = c_void_ptr_t(0) c_dims = dim4(idims[0], idims[1], idims[2], idims[3]) @@ -106,27 +114,27 @@ def _create_strided_array(buf, numdims, idims, dtype, is_device, offset, strides location = Source.device else: location = Source.host - safe_call(backend.get().af_create_strided_array(c_pointer(out_arr), c_void_ptr_t(buf), - offset, numdims, c_pointer(c_dims), - c_pointer(strides), dtype.value, - location.value)) + safe_call(backend.get().af_create_strided_array( + c_pointer(out_arr), c_void_ptr_t(buf), offset, numdims, c_pointer(c_dims), c_pointer(strides), dtype.value, + location.value)) return out_arr + def _create_empty_array(numdims, idims, dtype): out_arr = c_void_ptr_t(0) - if numdims == 0: return out_arr + if numdims == 0: + return out_arr c_dims = dim4(idims[0], idims[1], idims[2], idims[3]) - safe_call(backend.get().af_create_handle(c_pointer(out_arr), - numdims, c_pointer(c_dims), dtype.value)) + safe_call(backend.get().af_create_handle(c_pointer(out_arr), numdims, c_pointer(c_dims), dtype.value)) return out_arr + def constant_array(val, d0, d1=None, d2=None, d3=None, dtype=Dtype.f32): """ Internal function to create a C array. Should not be used externall. """ - if not isinstance(dtype, c_int_t): if isinstance(dtype, int): dtype = c_int_t(dtype) @@ -142,11 +150,10 @@ def constant_array(val, d0, d1=None, d2=None, d3=None, dtype=Dtype.f32): c_real = c_double_t(val.real) c_imag = c_double_t(val.imag) - if (dtype.value != Dtype.c32.value and dtype.value != Dtype.c64.value): + if dtype.value != Dtype.c32.value and dtype.value != Dtype.c64.value: dtype = Dtype.c32.value - safe_call(backend.get().af_constant_complex(c_pointer(out), c_real, c_imag, - 4, c_pointer(dims), dtype)) + safe_call(backend.get().af_constant_complex(c_pointer(out), c_real, c_imag, 4, c_pointer(dims), dtype)) elif dtype.value == Dtype.s64.value: c_val = c_longlong_t(val.real) safe_call(backend.get().af_constant_long(c_pointer(out), c_val, 4, c_pointer(dims))) @@ -164,7 +171,7 @@ def _binary_func(lhs, rhs, c_func): out = Array() other = rhs - if (_is_number(rhs)): + if _is_number(rhs): ldims = dim4_to_tuple(lhs.dims()) rty = implicit_dtype(rhs, lhs.type()) other = Array() @@ -176,11 +183,12 @@ def _binary_func(lhs, rhs, c_func): return out + def _binary_funcr(lhs, rhs, c_func): out = Array() other = lhs - if (_is_number(lhs)): + if _is_number(lhs): rdims = dim4_to_tuple(rhs.dims()) lty = implicit_dtype(lhs, rhs.type()) other = Array() @@ -192,16 +200,18 @@ def _binary_funcr(lhs, rhs, c_func): return out + def _ctype_to_lists(ctype_arr, dim, shape, offset=0): - if (dim == 0): - return list(ctype_arr[offset : offset + shape[0]]) - else: - dim_len = shape[dim] - res = [[]] * dim_len - for n in range(dim_len): - res[n] = _ctype_to_lists(ctype_arr, dim - 1, shape, offset) - offset += shape[0] - return res + if dim == 0: + return list(ctype_arr[offset: offset + shape[0]]) + + dim_len = shape[dim] + res = [[]] * dim_len + for n in range(dim_len): + res[n] = _ctype_to_lists(ctype_arr, dim - 1, shape, offset) + offset += shape[0] + return res + def _slice_to_length(key, dim): tkey = [key.start, key.stop, key.step] @@ -221,6 +231,7 @@ def _slice_to_length(key, dim): return int(((tkey[1] - tkey[0] - 1) / tkey[2]) + 1) + def _get_info(dims, buf_len): elements = 1 numdims = 0 @@ -230,7 +241,7 @@ def _get_info(dims, buf_len): for i in range(numdims): elements *= dims[i] idims[i] = dims[i] - elif (buf_len != 0): + elif buf_len != 0: idims = [buf_len, 1, 1, 1] numdims = 1 else: @@ -250,51 +261,53 @@ def _get_indices(key): return inds -def _get_assign_dims(key, idims): +def _get_assign_dims(key, idims): + from .algorithm import sum dims = [1]*4 - for n in range(len(idims)): + for n, _ in enumerate(idims): dims[n] = idims[n] if _is_number(key): dims[0] = 1 return dims - elif isinstance(key, slice): + if isinstance(key, slice): dims[0] = _slice_to_length(key, idims[0]) return dims - elif isinstance(key, ParallelRange): + if isinstance(key, ParallelRange): dims[0] = _slice_to_length(key.S, idims[0]) return dims - elif isinstance(key, BaseArray): + if isinstance(key, BaseArray): # If the array is boolean take only the number of nonzeros - if(key.dtype() is Dtype.b8): + if key.dtype() is Dtype.b8: dims[0] = int(sum(key)) else: dims[0] = key.elements() return dims - elif isinstance(key, tuple): - n_inds = len(key) - - for n in range(n_inds): - if (_is_number(key[n])): - dims[n] = 1 - elif (isinstance(key[n], BaseArray)): - # If the array is boolean take only the number of nonzeros - if(key[n].dtype() is Dtype.b8): - dims[n] = int(sum(key[n])) - else: - dims[n] = key[n].elements() - elif (isinstance(key[n], slice)): - dims[n] = _slice_to_length(key[n], idims[n]) - elif (isinstance(key[n], ParallelRange)): - dims[n] = _slice_to_length(key[n].S, idims[n]) + if not isinstance(key, tuple): + raise IndexError("Invalid type while assigning to arrayfire.array") + + n_inds = len(key) + + for n in range(n_inds): + if _is_number(key[n]): + dims[n] = 1 + elif isinstance(key[n], BaseArray): + # If the array is boolean take only the number of nonzeros + if key[n].dtype() is Dtype.b8: + dims[n] = int(sum(key[n])) else: - raise IndexError("Invalid type while assigning to arrayfire.array") + dims[n] = key[n].elements() + elif isinstance(key[n], slice): + dims[n] = _slice_to_length(key[n], idims[n]) + elif isinstance(key[n], ParallelRange): + dims[n] = _slice_to_length(key[n].S, idims[n]) + else: + raise IndexError("Invalid type while assigning to arrayfire.array") + + return dims - return dims - else: - raise IndexError("Invalid type while assigning to arrayfire.array") def transpose(a, conj=False): """ @@ -318,6 +331,7 @@ def transpose(a, conj=False): safe_call(backend.get().af_transpose(c_pointer(out.arr), a.arr, conj)) return out + def transpose_inplace(a, conj=False): """ Perform inplace transpose on an input. @@ -338,6 +352,7 @@ def transpose_inplace(a, conj=False): """ safe_call(backend.get().af_transpose_inplace(a.arr, conj)) + class Array(BaseArray): """ @@ -436,7 +451,6 @@ class Array(BaseArray): - numpy uses row major format by default which can cause issues during conversion """ - # Numpy checks this attribute to know which class handles binary builtin operations, such as __add__. # Setting to such a high value should make sure that arrayfire has priority over # other classes, ensuring that e.g. numpy.float32(1)*arrayfire.randu(3) is handled by @@ -444,11 +458,10 @@ class Array(BaseArray): __array_priority__ = 30 def __init__(self, src=None, dims=None, dtype=None, is_device=False, offset=None, strides=None): + super().__init__() - super(Array, self).__init__() - - buf=None - buf_len=0 + buf = None + buf_len = 0 if dtype is not None: if isinstance(dtype, str): @@ -458,26 +471,26 @@ def __init__(self, src=None, dims=None, dtype=None, is_device=False, offset=None else: type_char = None - _type_char='f' + _type_char = 'f' if src is not None: - if (isinstance(src, Array)): + if isinstance(src, Array): safe_call(backend.get().af_retain_array(c_pointer(self.arr), src.arr)) return host = __import__("array") if isinstance(src, host.array): - buf,buf_len = src.buffer_info() + buf, buf_len = src.buffer_info() _type_char = src.typecode numdims, idims = _get_info(dims, buf_len) elif isinstance(src, list): tmp = host.array('f', src) - buf,buf_len = tmp.buffer_info() + buf, buf_len = tmp.buffer_info() _type_char = tmp.typecode numdims, idims = _get_info(dims, buf_len) - elif isinstance(src, int) or isinstance(src, c_void_ptr_t): + elif isinstance(src, (c_void_ptr_t, int)): buf = src if not isinstance(src, c_void_ptr_t) else src.value numdims, idims = _get_info(dims, buf_len) @@ -486,10 +499,10 @@ def __init__(self, src=None, dims=None, dtype=None, is_device=False, offset=None for dim in idims: elements *= dim - if (elements == 0): + if elements == 0: raise RuntimeError("Expected dims when src is data pointer") - if (type_char is None): + if type_char is None: raise TypeError("Expected type_char when src is data pointer") _type_char = type_char @@ -497,18 +510,13 @@ def __init__(self, src=None, dims=None, dtype=None, is_device=False, offset=None else: raise TypeError("src is an object of unsupported class") - if (type_char is not None and - type_char != _type_char): + if type_char is not None and type_char != _type_char: raise TypeError("Can not create array of requested type from input data type") - if(offset is None and strides is None): + if offset is None and strides is None: self.arr = _create_array(buf, numdims, idims, to_dtype[_type_char], is_device) else: - self.arr = _create_strided_array(buf, numdims, idims, - to_dtype[_type_char], - is_device, offset, strides) - + self.arr = _create_strided_array(buf, numdims, idims, to_dtype[_type_char], is_device, offset, strides) else: - if type_char is None: type_char = 'f' @@ -528,6 +536,7 @@ def as_type(self, ty): ---------- ty : Return data type """ + from .arith import cast return cast(self, ty) def copy(self): @@ -547,9 +556,10 @@ def __del__(self): """ Release the C array when going out of scope """ - if self.arr.value: - backend.get().af_release_array(self.arr) - self.arr.value = 0 + if not self.arr.value: + return + backend.get().af_release_array(self.arr) + self.arr.value = 0 def device_ptr(self): """ @@ -563,10 +573,13 @@ def device_ptr(self): Note ---- - This can be used to integrate with custom C code and / or PyCUDA or PyOpenCL. - - Implies `af.device.lock_array()`. The device pointer of `a` is not freed by memory manager until `unlock_device_ptr()` is called. + - Implies `af.device.lock_array()`. The device pointer of `a` is not freed by memory + manager until `unlock_device_ptr()` is called. - No other arrays will share the same device pointer. - - A copy of the memory is done if multiple arrays share the same memory or the array is not the owner of the memory. - - In case of a copy the return value points to the newly allocated memory which is now exclusively owned by the array. + - A copy of the memory is done if multiple arrays share the same memory or the array + is not the owner of the memory. + - In case of a copy the return value points to the newly allocated memory which is + now exclusively owned by the array. """ ptr = c_void_ptr_t(0) backend.get().af_get_device_ptr(c_pointer(ptr), self.arr) @@ -619,9 +632,8 @@ def strides(self): s1 = c_dim_t(0) s2 = c_dim_t(0) s3 = c_dim_t(0) - safe_call(backend.get().af_get_strides(c_pointer(s0), c_pointer(s1), - c_pointer(s2), c_pointer(s3), self.arr)) - strides = (s0.value,s1.value,s2.value,s3.value) + safe_call(backend.get().af_get_strides(c_pointer(s0), c_pointer(s1), c_pointer(s2), c_pointer(s3), self.arr)) + strides = (s0.value, s1.value, s2.value, s3.value) return strides[:self.numdims()] def elements(self): @@ -633,7 +645,7 @@ def elements(self): return num.value def __len__(self): - return(self.elements()) + return self.elements() def allocated(self): """ @@ -679,9 +691,8 @@ def dims(self): d1 = c_dim_t(0) d2 = c_dim_t(0) d3 = c_dim_t(0) - safe_call(backend.get().af_get_dims(c_pointer(d0), c_pointer(d1), - c_pointer(d2), c_pointer(d3), self.arr)) - dims = (d0.value,d1.value,d2.value,d3.value) + safe_call(backend.get().af_get_dims(c_pointer(d0), c_pointer(d1), c_pointer(d2), c_pointer(d3), self.arr)) + dims = (d0.value, d1.value, d2.value, d3.value) return dims[:self.numdims()] @property @@ -906,7 +917,7 @@ def __itruediv__(self, other): """ Perform self /= other. """ - self = _binary_func(self, other, backend.get().af_div) + self = _binary_func(self, other, backend.get().af_div) return self def __rtruediv__(self, other): @@ -925,7 +936,7 @@ def __idiv__(self, other): """ Perform other / self. """ - self = _binary_func(self, other, backend.get().af_div) + self = _binary_func(self, other, backend.get().af_div) return self def __rdiv__(self, other): @@ -944,7 +955,7 @@ def __imod__(self, other): """ Perform self %= other. """ - self = _binary_func(self, other, backend.get().af_mod) + self = _binary_func(self, other, backend.get().af_mod) return self def __rmod__(self, other): @@ -963,7 +974,7 @@ def __ipow__(self, other): """ Perform self **= other. """ - self = _binary_func(self, other, backend.get().af_pow) + self = _binary_func(self, other, backend.get().af_pow) return self def __rpow__(self, other): @@ -1120,7 +1131,7 @@ def logical_or(self, other): def __nonzero__(self): return self != 0 - # TODO: + # TODO: define abs # def __abs__(self): # return self @@ -1133,23 +1144,22 @@ def __getitem__(self, key): Ellipsis not supported as key """ try: + from .algorithm import count out = Array() n_dims = self.numdims() - if (isinstance(key, Array) and key.type() == Dtype.b8.value): + if isinstance(key, Array) and key.type() == Dtype.b8.value: n_dims = 1 - if (count(key) == 0): + if count(key) == 0: return out inds = _get_indices(key) - safe_call(backend.get().af_index_gen(c_pointer(out.arr), - self.arr, c_dim_t(n_dims), inds.pointer)) + safe_call(backend.get().af_index_gen(c_pointer(out.arr), self.arr, c_dim_t(n_dims), inds.pointer)) return out except RuntimeError as e: raise IndexError(str(e)) - def __setitem__(self, key, val): """ Perform self[key] = val @@ -1159,34 +1169,34 @@ def __setitem__(self, key, val): Ellipsis not supported as key """ try: + from .algorithm import count n_dims = self.numdims() is_boolean_idx = isinstance(key, Array) and key.type() == Dtype.b8.value - if (is_boolean_idx): + if is_boolean_idx: n_dims = 1 num = count(key) - if (num == 0): + if num == 0: return - if (_is_number(val)): + if _is_number(val): tdims = _get_assign_dims(key, self.dims()) - if (is_boolean_idx): + if is_boolean_idx: n_dims = 1 other_arr = constant_array(val, int(num), dtype=self.type()) else: - other_arr = constant_array(val, tdims[0] , tdims[1], tdims[2], tdims[3], self.type()) + other_arr = constant_array(val, tdims[0], tdims[1], tdims[2], tdims[3], self.type()) del_other = True else: other_arr = val.arr del_other = False out_arr = c_void_ptr_t(0) - inds = _get_indices(key) + inds = _get_indices(key) - safe_call(backend.get().af_assign_gen(c_pointer(out_arr), - self.arr, c_dim_t(n_dims), inds.pointer, - other_arr)) + safe_call(backend.get().af_assign_gen( + c_pointer(out_arr), self.arr, c_dim_t(n_dims), inds.pointer, other_arr)) safe_call(backend.get().af_release_array(self.arr)) if del_other: safe_call(backend.get().af_release_array(other_arr)) @@ -1200,7 +1210,7 @@ def _reorder(self): Returns a reordered array to help interoperate with row major formats. """ ndims = self.numdims() - if (ndims == 1): + if ndims == 1: return self rdims = tuple(reversed(range(ndims))) + tuple(range(ndims, 4)) @@ -1230,19 +1240,17 @@ def to_ctype(self, row_major=False, return_shape=False): (res, dims): tuple of the ctypes array and the shape of the array """ - if (self.arr.value == 0): + if self.arr.value == 0: raise RuntimeError("Can not call to_ctype on empty array") - tmp = self._reorder() if (row_major) else self - ctype_type = to_c_type[self.type()] * self.elements() res = ctype_type() safe_call(backend.get().af_get_data_ptr(c_pointer(res), self.arr)) - if (return_shape): + if return_shape: return res, self.dims() - else: - return res + + return res def to_array(self, row_major=False, return_shape=False): """ @@ -1266,7 +1274,7 @@ def to_array(self, row_major=False, return_shape=False): (res, dims): array.array and the shape of the array """ - if (self.arr.value == 0): + if self.arr.value == 0: raise RuntimeError("Can not call to_array on empty array") res = self.to_ctype(row_major, return_shape) @@ -1274,10 +1282,10 @@ def to_array(self, row_major=False, return_shape=False): host = __import__("array") h_type = to_typecode[self.type()] - if (return_shape): + if return_shape: return host.array(h_type, res[0]), res[1] - else: - return host.array(h_type, res) + + return host.array(h_type, res) def to_list(self, row_major=False): """ @@ -1308,8 +1316,7 @@ def scalar(self): """ Return the first element of the array """ - - if (self.arr.value == 0): + if self.arr.value == 0: raise RuntimeError("Can not call to_ctype on empty array") ctype_type = to_c_type[self.type()] @@ -1325,7 +1332,6 @@ def __str__(self): ---- You can also use af.display(a, pres) to display the contents of the array with better precision. """ - if not _in_display_dims_limit(self.dims()): return self._get_metadata_str() @@ -1339,12 +1345,11 @@ def __repr__(self): ---- You can use af.display(a, pres) to display the contents of the array. """ - return self._get_metadata_str() def _get_metadata_str(self, dims=True): - return 'arrayfire.Array()\nType: {}\n{}' \ - .format(to_typename[self.type()], 'Dims: {}'.format(str(self.dims())) if dims else '') + _dims = "Dims: {}".format(str(self.dims())) if dims else "" + return "arrayfire.Array()\nType: {}\n{}".format(to_typename[self.type()], _dims) def _as_str(self): arr_str = c_char_ptr_t(0) @@ -1358,6 +1363,7 @@ def __array__(self): """ Constructs a numpy.array from arrayfire.Array """ + # FIXME: import insdie of a function import numpy as np res = np.empty(self.dims(), dtype=np.dtype(to_typecode[self.type()]), order='F') safe_call(backend.get().af_get_data_ptr(c_void_ptr_t(res.ctypes.data), self.arr)) @@ -1383,10 +1389,10 @@ def to_ndarray(self, output=None): if output is None: return self.__array__() - if (output.dtype != to_typecode[self.type()]): + if output.dtype != to_typecode[self.type()]: raise TypeError("Output is not the same type as the array") - if (output.size != self.elements()): + if output.size != self.elements(): raise RuntimeError("Output size does not match that of input") flags = output.flags @@ -1401,6 +1407,7 @@ def to_ndarray(self, output=None): safe_call(backend.get().af_get_data_ptr(c_void_ptr_t(output.ctypes.data), tmp.arr)) return output + def display(a, precision=4): """ Displays the contents of an array. @@ -1416,15 +1423,15 @@ def display(a, precision=4): name = "" try: - if (expr is not None): + if expr is not None: st = expr[0].find('(') + 1 en = expr[0].rfind(')') name = expr[0][st:en] except IndexError: pass - safe_call(backend.get().af_print_array_gen(name.encode('utf-8'), - a.arr, c_int_t(precision))) + safe_call(backend.get().af_print_array_gen(name.encode('utf-8'), a.arr, c_int_t(precision))) + def save_array(key, a, filename, append=False): """ @@ -1450,13 +1457,11 @@ def save_array(key, a, filename, append=False): The index of the array stored in the file. """ index = c_int_t(-1) - safe_call(backend.get().af_save_array(c_pointer(index), - key.encode('utf-8'), - a.arr, - filename.encode('utf-8'), - append)) + safe_call(backend.get().af_save_array( + c_pointer(index), key.encode('utf-8'), a.arr, filename.encode('utf-8'), append)) return index.value + def read_array(filename, index=None, key=None): """ Read an array from disk. @@ -1480,16 +1485,10 @@ def read_array(filename, index=None, key=None): """ assert((index is not None) or (key is not None)) out = Array() - if (index is not None): - safe_call(backend.get().af_read_array_index(c_pointer(out.arr), - filename.encode('utf-8'), - index)) - elif (key is not None): - safe_call(backend.get().af_read_array_key(c_pointer(out.arr), - filename.encode('utf-8'), - key.encode('utf-8'))) - + if index is not None: + safe_call(backend.get().af_read_array_index(c_pointer(out.arr), filename.encode('utf-8'), index)) + elif key is not None: + safe_call(backend.get().af_read_array_key(c_pointer(out.arr), filename.encode('utf-8'), key.encode('utf-8'))) return out -from .algorithm import (sum, count) -from .arith import cast + diff --git a/arrayfire/base.py b/arrayfire/base.py index ca072fa2c..df3112676 100644 --- a/arrayfire/base.py +++ b/arrayfire/base.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,12 +11,13 @@ Implementation of BaseArray class. """ -from .library import * -from .util import * +from .library import c_void_ptr_t -class BaseArray(object): + +class BaseArray: """ Base array class for arrayfire. For internal use only. """ + def __init__(self): self.arr = c_void_ptr_t(0) diff --git a/arrayfire/bcast.py b/arrayfire/bcast.py index 0b8109244..c838b1b1b 100644 --- a/arrayfire/bcast.py +++ b/arrayfire/bcast.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,8 +11,10 @@ Function to perform broadcasting operations. """ -class _bcast(object): + +class _bcast: _flag = False + def get(self): return _bcast._flag @@ -22,8 +24,10 @@ def set(self, flag): def toggle(self): _bcast._flag ^= True + _bcast_var = _bcast() + def broadcast(func, *args): """ Function to perform broadcast operations. @@ -83,14 +87,13 @@ def broadcast(func, *args): 1.5328 0.8898 0.7185 """ - def wrapper(*func_args): _bcast_var.toggle() res = func(*func_args) _bcast_var.toggle() return res - if len(args) == 0: + if not args: return wrapper - else: - return wrapper(*args) + + return wrapper(*args) diff --git a/arrayfire/blas.py b/arrayfire/blas.py index 448261e90..a62110fc1 100644 --- a/arrayfire/blas.py +++ b/arrayfire/blas.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,8 +11,9 @@ BLAS functions (matmul, dot, etc) """ -from .library import * -from .array import * +from .array import Array +from .library import backend, safe_call, MATPROP, c_double_t, c_pointer + def matmul(lhs, rhs, lhs_opts=MATPROP.NONE, rhs_opts=MATPROP.NONE): """ @@ -53,10 +54,11 @@ def matmul(lhs, rhs, lhs_opts=MATPROP.NONE, rhs_opts=MATPROP.NONE): """ out = Array() - safe_call(backend.get().af_matmul(c_pointer(out.arr), lhs.arr, rhs.arr, - lhs_opts.value, rhs_opts.value)) + safe_call(backend.get().af_matmul( + c_pointer(out.arr), lhs.arr, rhs.arr, lhs_opts.value, rhs_opts.value)) return out + def matmulTN(lhs, rhs): """ Matrix multiplication after transposing the first matrix. @@ -84,10 +86,11 @@ def matmulTN(lhs, rhs): """ out = Array() - safe_call(backend.get().af_matmul(c_pointer(out.arr), lhs.arr, rhs.arr, - MATPROP.TRANS.value, MATPROP.NONE.value)) + safe_call(backend.get().af_matmul( + c_pointer(out.arr), lhs.arr, rhs.arr, MATPROP.TRANS.value, MATPROP.NONE.value)) return out + def matmulNT(lhs, rhs): """ Matrix multiplication after transposing the second matrix. @@ -115,10 +118,11 @@ def matmulNT(lhs, rhs): """ out = Array() - safe_call(backend.get().af_matmul(c_pointer(out.arr), lhs.arr, rhs.arr, - MATPROP.NONE.value, MATPROP.TRANS.value)) + safe_call(backend.get().af_matmul( + c_pointer(out.arr), lhs.arr, rhs.arr, MATPROP.NONE.value, MATPROP.TRANS.value)) return out + def matmulTT(lhs, rhs): """ Matrix multiplication after transposing both inputs. @@ -146,11 +150,12 @@ def matmulTT(lhs, rhs): """ out = Array() - safe_call(backend.get().af_matmul(c_pointer(out.arr), lhs.arr, rhs.arr, - MATPROP.TRANS.value, MATPROP.TRANS.value)) + safe_call(backend.get().af_matmul( + c_pointer(out.arr), lhs.arr, rhs.arr, MATPROP.TRANS.value, MATPROP.TRANS.value)) return out -def dot(lhs, rhs, lhs_opts=MATPROP.NONE, rhs_opts=MATPROP.NONE, return_scalar = False): + +def dot(lhs, rhs, lhs_opts=MATPROP.NONE, rhs_opts=MATPROP.NONE, return_scalar=False): """ Dot product of two input vectors. @@ -192,8 +197,8 @@ def dot(lhs, rhs, lhs_opts=MATPROP.NONE, rhs_opts=MATPROP.NONE, return_scalar = if return_scalar: real = c_double_t(0) imag = c_double_t(0) - safe_call(backend.get().af_dot_all(c_pointer(real), c_pointer(imag), - lhs.arr, rhs.arr, lhs_opts.value, rhs_opts.value)) + safe_call(backend.get().af_dot_all( + c_pointer(real), c_pointer(imag), lhs.arr, rhs.arr, lhs_opts.value, rhs_opts.value)) real = real.value imag = imag.value return real if imag == 0 else real + imag * 1j @@ -203,6 +208,7 @@ def dot(lhs, rhs, lhs_opts=MATPROP.NONE, rhs_opts=MATPROP.NONE, return_scalar = lhs_opts.value, rhs_opts.value)) return out + def gemm(lhs, rhs, alpha=1.0, beta=0.0, lhs_opts=MATPROP.NONE, rhs_opts=MATPROP.NONE, C=None): """ BLAS general matrix multiply (GEMM) of two af_array objects. diff --git a/arrayfire/cuda.py b/arrayfire/cuda.py index ea24c0e30..ab5c5673b 100644 --- a/arrayfire/cuda.py +++ b/arrayfire/cuda.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -13,6 +13,9 @@ This module provides interoperability with other CUDA libraries. """ +from .library import c_int_t, c_pointer, c_void_ptr_t + + def get_stream(idx): """ Get the CUDA stream used for the device `idx` by ArrayFire. @@ -27,18 +30,19 @@ def get_stream(idx): ----------- stream : integer denoting the stream id. """ - + # FIXME: ctypes imported but unused import ctypes as ct - from .util import safe_call as safe_call - from .library import backend as backend + from .util import safe_call + from .library import backend - if (backend.name() != "cuda"): + if backend.name() != "cuda": raise RuntimeError("Invalid backend loaded") stream = c_void_ptr_t(0) safe_call(backend.get().afcu_get_stream(c_pointer(stream), idx)) return stream.value + def get_native_id(idx): """ Get native (unsorted) CUDA device ID @@ -53,18 +57,19 @@ def get_native_id(idx): ----------- native_idx : integer denoting the native cuda id. """ - + # FIXME: ctypes imported but unused import ctypes as ct - from .util import safe_call as safe_call - from .library import backend as backend + from .util import safe_call + from .library import backend - if (backend.name() != "cuda"): + if backend.name() != "cuda": raise RuntimeError("Invalid backend loaded") native = c_int_t(0) safe_call(backend.get().afcu_get_native_id(c_pointer(native), idx)) return native.value + def set_native_id(idx): """ Set native (unsorted) CUDA device ID @@ -75,13 +80,12 @@ def set_native_id(idx): idx : int. Specifies the (unsorted) native index of the device. """ - + # FIXME: ctypes imported but unused import ctypes as ct - from .util import safe_call as safe_call - from .library import backend as backend + from .util import safe_call + from .library import backend - if (backend.name() != "cuda"): + if backend.name() != "cuda": raise RuntimeError("Invalid backend loaded") safe_call(backend.get().afcu_set_native_id(idx)) - return diff --git a/arrayfire/data.py b/arrayfire/data.py index 1fbe17a53..9fac5a3cc 100644 --- a/arrayfire/data.py +++ b/arrayfire/data.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,12 +11,10 @@ Functions to create and manipulate arrays. """ -from sys import version_info -from .library import * -from .array import * -from .util import * -from .util import _is_number -from .random import randu, randn, set_seed, get_seed +from .array import Array, constant_array +from .library import backend, safe_call, Dtype, c_double_t, c_int_t, c_pointer, c_void_ptr_t, PAD +from .util import _is_number, dim4 + def constant(val, d0, d1=None, d2=None, d3=None, dtype=Dtype.f32): """ @@ -52,14 +50,15 @@ def constant(val, d0, d1=None, d2=None, d3=None, dtype=Dtype.f32): - 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() out.arr = constant_array(val, d0, d1, d2, d3, dtype.value) return out + # Store builtin range function to be used later _brange = range + def range(d0, d1=None, d2=None, d3=None, dim=0, dtype=Dtype.f32): """ Create a multi dimensional array using length of a dimension as range. @@ -122,7 +121,7 @@ def range(d0, d1=None, d2=None, d3=None, dim=0, dtype=Dtype.f32): return out -def iota(d0, d1=None, d2=None, d3=None, dim=-1, tile_dims=None, dtype=Dtype.f32): +def iota(d0, d1=None, d2=None, d3=None, tile_dims=None, dtype=Dtype.f32): """ Create a multi dimensional array using the number of elements in the array as the range. @@ -175,7 +174,7 @@ def iota(d0, d1=None, d2=None, d3=None, dim=-1, tile_dims=None, dtype=Dtype.f32) """ out = Array() dims = dim4(d0, d1, d2, d3) - td=[1]*4 + td = [1]*4 if tile_dims is not None: for i in _brange(len(tile_dims)): @@ -183,10 +182,11 @@ def iota(d0, d1=None, d2=None, d3=None, dim=-1, tile_dims=None, dtype=Dtype.f32) tdims = dim4(td[0], td[1], td[2], td[3]) - safe_call(backend.get().af_iota(c_pointer(out.arr), 4, c_pointer(dims), - 4, c_pointer(tdims), dtype.value)) + safe_call(backend.get().af_iota( + c_pointer(out.arr), 4, c_pointer(dims), 4, c_pointer(tdims), dtype.value)) return out + def identity(d0, d1, d2=None, d3=None, dtype=Dtype.f32): """ Create an identity matrix or batch of identity matrices. @@ -217,13 +217,13 @@ def identity(d0, d1, d2=None, d3=None, dtype=Dtype.f32): - If d2 is not None and d3 is None, `out` is 3D of size (d0, d1, d2). - If d2, d3 are not None, `out` is 4D of size (d0, d1, d2, d3). """ - out = Array() dims = dim4(d0, d1, d2, d3) safe_call(backend.get().af_identity(c_pointer(out.arr), 4, c_pointer(dims), dtype.value)) return out + def diag(a, num=0, extract=True): """ Create a diagonal matrix or Extract the diagonal from a matrix. @@ -257,6 +257,7 @@ def diag(a, num=0, extract=True): safe_call(backend.get().af_diag_create(c_pointer(out.arr), a.arr, c_int_t(num))) return out + def join(dim, first, second, third=None, fourth=None): """ Join two or more arrayfire arrays along a specified dimension. @@ -316,7 +317,7 @@ def join(dim, first, second, third=None, fourth=None): 0.5367 0.8359 0.8719 0.6275 0.0495 0.6591 """ out = Array() - if (third is None and fourth is None): + if third is None and fourth is None: safe_call(backend.get().af_join(c_pointer(out.arr), dim, first.arr, second.arr)) else: c_void_p_4 = c_void_ptr_t * 4 @@ -324,10 +325,10 @@ def join(dim, first, second, third=None, fourth=None): num = 2 if third is not None: c_array_vec[num] = third.arr - num+=1 + num += 1 if fourth is not None: c_array_vec[num] = fourth.arr - num+=1 + num += 1 safe_call(backend.get().af_join_many(c_pointer(out.arr), dim, num, c_pointer(c_array_vec))) return out @@ -397,6 +398,7 @@ def tile(a, d0, d1=1, d2=1, d3=1): safe_call(backend.get().af_tile(c_pointer(out.arr), a.arr, d0, d1, d2, d3)) return out + def reorder(a, d0=1, d1=0, d2=2, d3=3): """ Reorder the dimensions of the input. @@ -481,6 +483,7 @@ def reorder(a, d0=1, d1=0, d2=2, d3=3): safe_call(backend.get().af_reorder(c_pointer(out.arr), a.arr, d0, d1, d2, d3)) return out + def shift(a, d0, d1=0, d2=0, d3=0): """ Shift the input along each dimension. @@ -537,6 +540,7 @@ def shift(a, d0, d1=0, d2=0, d3=0): safe_call(backend.get().af_shift(c_pointer(out.arr), a.arr, d0, d1, d2, d3)) return out + def moddims(a, d0, d1=1, d2=1, d3=1): """ Modify the shape of the array without changing the data layout. @@ -571,6 +575,7 @@ def moddims(a, d0, d1=1, d2=1, d3=1): safe_call(backend.get().af_moddims(c_pointer(out.arr), a.arr, 4, c_pointer(dims))) return out + def flat(a): """ Flatten the input array. @@ -591,6 +596,7 @@ def flat(a): safe_call(backend.get().af_flat(c_pointer(out.arr), a.arr)) return out + def flip(a, dim=0): """ Flip an array along a dimension. @@ -638,6 +644,7 @@ def flip(a, dim=0): safe_call(backend.get().af_flip(c_pointer(out.arr), a.arr, c_int_t(dim))) return out + def lower(a, is_unit_diag=False): """ Extract the lower triangular matrix from the input. @@ -661,6 +668,7 @@ def lower(a, is_unit_diag=False): safe_call(backend.get().af_lower(c_pointer(out.arr), a.arr, is_unit_diag)) return out + def upper(a, is_unit_diag=False): """ Extract the upper triangular matrix from the input. @@ -684,6 +692,7 @@ def upper(a, is_unit_diag=False): safe_call(backend.get().af_upper(c_pointer(out.arr), a.arr, is_unit_diag)) return out + def select(cond, lhs, rhs): """ Select elements from one of two arrays based on condition. @@ -741,16 +750,16 @@ def select(cond, lhs, rhs): if not (is_left_array or is_right_array): raise TypeError("Atleast one input needs to be of type arrayfire.array") - elif (is_left_array and is_right_array): + if is_left_array and is_right_array: safe_call(backend.get().af_select(c_pointer(out.arr), cond.arr, lhs.arr, rhs.arr)) - - elif (_is_number(rhs)): + elif _is_number(rhs): safe_call(backend.get().af_select_scalar_r(c_pointer(out.arr), cond.arr, lhs.arr, c_double_t(rhs))) else: safe_call(backend.get().af_select_scalar_l(c_pointer(out.arr), cond.arr, c_double_t(lhs), rhs.arr)) return out + def replace(lhs, cond, rhs): """ Select elements from one of two arrays based on condition. @@ -794,10 +803,10 @@ def replace(lhs, cond, rhs): """ is_right_array = isinstance(rhs, Array) - if (is_right_array): + if is_right_array: safe_call(backend.get().af_replace(lhs.arr, cond.arr, rhs.arr)) - else: - safe_call(backend.get().af_replace_scalar(lhs.arr, cond.arr, c_double_t(rhs))) + safe_call(backend.get().af_replace_scalar(lhs.arr, cond.arr, c_double_t(rhs))) + def pad(a, beginPadding, endPadding, padFillType = PAD.ZERO): """ diff --git a/arrayfire/device.py b/arrayfire/device.py index 53f302db5..e12f74c41 100644 --- a/arrayfire/device.py +++ b/arrayfire/device.py @@ -1,17 +1,20 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, 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 handle the available devices in the backend. """ -from .library import * -from .util import (safe_call, to_str, get_version) +from .array import Array +from .library import backend, safe_call, c_bool_t, c_char_t, c_dim_t, c_int_t, c_pointer, c_size_t, c_void_ptr_t +from .util import to_str + def init(): """ @@ -21,6 +24,7 @@ def init(): """ safe_call(backend.get().af_init()) + def info(): """ Displays the information about the following: @@ -31,6 +35,7 @@ def info(): """ safe_call(backend.get().af_info()) + def device_info(): """ Returns a map with the following fields: @@ -45,8 +50,8 @@ def device_info(): toolkit = c_char_256() compute = c_char_256() - safe_call(backend.get().af_device_info(c_pointer(device_name), c_pointer(backend_name), - c_pointer(toolkit), c_pointer(compute))) + safe_call(backend.get().af_device_info( + c_pointer(device_name), c_pointer(backend_name), c_pointer(toolkit), c_pointer(compute))) dev_info = {} dev_info['device'] = to_str(device_name) dev_info['backend'] = to_str(backend_name) @@ -55,6 +60,7 @@ def device_info(): return dev_info + def get_device_count(): """ Returns the number of devices available. @@ -63,6 +69,7 @@ def get_device_count(): safe_call(backend.get().af_get_device_count(c_pointer(c_num))) return c_num.value + def get_device(): """ Returns the id of the current device. @@ -71,6 +78,7 @@ def get_device(): safe_call(backend.get().af_get_device(c_pointer(c_dev))) return c_dev.value + def set_device(num): """ Change the active device to the specified id. @@ -82,7 +90,8 @@ def set_device(num): """ safe_call(backend.get().af_set_device(num)) -def info_str(verbose = False): + +def info_str(): """ Returns information about the following as a string: - ArrayFire version number. @@ -90,6 +99,7 @@ def info_str(verbose = False): - The names of the devices. - The current device being used. """ + # FIXME: import inside of a function import platform res_str = 'ArrayFire' @@ -105,32 +115,33 @@ def info_str(verbose = False): for n in range(num_devices): # To suppress warnings on CPU - if (n != curr_device_id): + if n != curr_device_id: set_device(n) - if (n == curr_device_id): + if n == curr_device_id: res_str += '[%d] ' % n else: res_str += '-%d- ' % n dev_info = device_info() - if (backend_str.lower() == 'opencl'): + if backend_str.lower() == 'opencl': res_str += dev_info['toolkit'] res_str += ': ' + dev_info['device'] - if (backend_str.lower() != 'cpu'): + if backend_str.lower() != 'cpu': res_str += ' (Compute ' + dev_info['compute'] + ')' res_str += '\n' # To suppress warnings on CPU - if (curr_device_id != get_device()): + if curr_device_id != get_device(): set_device(curr_device_id) return res_str + def is_dbl_supported(device=None): """ Check if double precision is supported on specified device. @@ -150,6 +161,7 @@ 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. @@ -181,17 +193,18 @@ def sync(device=None): dev = device if device is not None else get_device() safe_call(backend.get().af_sync(dev)) + def __eval(*args): nargs = len(args) - if (nargs == 1): + if nargs == 1: safe_call(backend.get().af_eval(args[0].arr)) - else: - c_void_p_n = c_void_ptr_t * nargs - arrs = c_void_p_n() - for n in range(nargs): - arrs[n] = args[n].arr - safe_call(backend.get().af_eval_multiple(c_int_t(nargs), c_pointer(arrs))) - return + + c_void_p_n = c_void_ptr_t * nargs + arrs = c_void_p_n() + for n in range(nargs): + arrs[n] = args[n].arr + safe_call(backend.get().af_eval_multiple(c_int_t(nargs), c_pointer(arrs))) + def eval(*args): """ @@ -236,6 +249,7 @@ def eval(*args): __eval(*args) + def set_manual_eval_flag(flag): """ Tells the backend JIT engine to disable heuristics for determining when to evaluate a JIT tree. @@ -252,6 +266,7 @@ def set_manual_eval_flag(flag): """ safe_call(backend.get().af_set_manual_eval_flag(flag)) + def get_manual_eval_flag(): """ Query the backend JIT engine to see if the user disabled heuristic evaluation of the JIT tree. @@ -264,6 +279,7 @@ def get_manual_eval_flag(): safe_call(backend.get().af_get_manual_eval_flag(c_pointer(res))) return res.value + def device_mem_info(): """ Returns a map with the following fields: @@ -285,14 +301,15 @@ def device_mem_info(): alloc_buffers = c_size_t(0) lock_bytes = c_size_t(0) lock_buffers = c_size_t(0) - safe_call(backend.get().af_device_mem_info(c_pointer(alloc_bytes), c_pointer(alloc_buffers), - c_pointer(lock_bytes), c_pointer(lock_buffers))) + safe_call(backend.get().af_device_mem_info( + c_pointer(alloc_bytes), c_pointer(alloc_buffers), c_pointer(lock_bytes), c_pointer(lock_buffers))) mem_info = {} - mem_info['alloc'] = {'buffers' : alloc_buffers.value, 'bytes' : alloc_bytes.value} - mem_info['lock'] = {'buffers' : lock_buffers.value, 'bytes' : lock_bytes.value} + mem_info['alloc'] = {'buffers': alloc_buffers.value, 'bytes': alloc_bytes.value} + mem_info['lock'] = {'buffers': lock_buffers.value, 'bytes': lock_bytes.value} return mem_info -def print_mem_info(title = "Memory Info", device_id = None): + +def print_mem_info(title="Memory Info", device_id=None): """ Prints the memory used for the specified device. @@ -338,12 +355,14 @@ def print_mem_info(title = "Memory Info", device_id = None): device_id = device_id if device_id else get_device() safe_call(backend.get().af_print_mem_info(title.encode('utf-8'), device_id)) + def device_gc(): """ Ask the garbage collector to free all unlocked memory """ safe_call(backend.get().af_device_gc()) + def get_device_ptr(a): """ Get the raw device pointer of an array @@ -367,14 +386,17 @@ def get_device_ptr(a): safe_call(backend.get().af_get_device_ptr(c_pointer(ptr), a.arr)) return ptr + def lock_device_ptr(a): """ This functions is deprecated. Please use lock_array instead. """ + # FIXME: import inside of a function import warnings warnings.warn("This function is deprecated. Use lock_array instead.", DeprecationWarning) lock_array(a) + def lock_array(a): """ Ask arrayfire to not perform garbage collection on raw data held by an array. @@ -390,6 +412,7 @@ def lock_array(a): """ safe_call(backend.get().af_lock_array(a.arr)) + def is_locked_array(a): """ Check if the input array is locked by the user. @@ -407,14 +430,17 @@ def is_locked_array(a): safe_call(backend.get().af_is_locked_array(c_pointer(res), a.arr)) return res.value + def unlock_device_ptr(a): """ This functions is deprecated. Please use unlock_array instead. """ + # FIXME: import inside of a function import warnings warnings.warn("This function is deprecated. Use unlock_array instead.", DeprecationWarning) unlock_array(a) + def unlock_array(a): """ Tell arrayfire to resume garbage collection on raw data held by an array. @@ -427,6 +453,7 @@ def unlock_array(a): """ safe_call(backend.get().af_unlock_array(a.arr)) + def alloc_device(num_bytes): """ Allocate a buffer on the device with specified number of bytes. @@ -436,6 +463,7 @@ def alloc_device(num_bytes): safe_call(backend.get().af_alloc_device(c_pointer(ptr), c_num_bytes)) return ptr.value + def alloc_host(num_bytes): """ Allocate a buffer on the host with specified number of bytes. @@ -445,6 +473,7 @@ def alloc_host(num_bytes): safe_call(backend.get().af_alloc_host(c_pointer(ptr), c_num_bytes)) return ptr.value + def alloc_pinned(num_bytes): """ Allocate a buffer on the host using pinned memory with specified number of bytes. @@ -454,6 +483,7 @@ def alloc_pinned(num_bytes): safe_call(backend.get().af_alloc_pinned(c_pointer(ptr), c_num_bytes)) return ptr.value + def free_device(ptr): """ Free the device memory allocated by alloc_device @@ -461,6 +491,7 @@ def free_device(ptr): cptr = c_void_ptr_t(ptr) safe_call(backend.get().af_free_device(cptr)) + def free_host(ptr): """ Free the host memory allocated by alloc_host @@ -468,6 +499,7 @@ def free_host(ptr): cptr = c_void_ptr_t(ptr) safe_call(backend.get().af_free_host(cptr)) + def free_pinned(ptr): """ Free the pinned memory allocated by alloc_pinned @@ -475,4 +507,3 @@ def free_pinned(ptr): cptr = c_void_ptr_t(ptr) safe_call(backend.get().af_free_pinned(cptr)) -from .array import Array diff --git a/arrayfire/features.py b/arrayfire/features.py index 2f76a97eb..3025f4c1b 100644 --- a/arrayfire/features.py +++ b/arrayfire/features.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,10 +11,12 @@ Features class used for Computer Vision algorithms. """ -from .library import * -from .array import * import numbers +from .array import Array +from .library import backend, safe_call, c_dim_t, c_pointer, c_void_ptr_t + + class Features(object): """ A container class used for various feature detectors. @@ -29,16 +31,17 @@ class Features(object): def __init__(self, num=0): self.feat = c_void_ptr_t(0) if num is not None: - assert(isinstance(num, numbers.Number)) + assert isinstance(num, numbers.Number) safe_call(backend.get().af_create_features(c_pointer(self.feat), c_dim_t(num))) def __del__(self): """ Release features' memory """ - if self.feat: - backend.get().af_release_features(self.feat) - self.feat = None + if not self.feat: + return + backend.get().af_release_features(self.feat) + self.feat = None def num_features(self): """ diff --git a/arrayfire/graphics.py b/arrayfire/graphics.py index 70881f42c..bb214d983 100644 --- a/arrayfire/graphics.py +++ b/arrayfire/graphics.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,15 +11,18 @@ Graphics functions (plot, image, etc). """ -from .library import * -from .array import * +import ctypes as ct + +from .library import backend, safe_call, COLORMAP, MARKER, c_bool_t, c_char_ptr_t, c_double_t, c_float_t, c_int_t, c_pointer, c_void_ptr_t from .util import _is_number + class _Cell(ct.Structure): - _fields_ = [("row", c_int_t), - ("col", c_int_t), - ("title", c_char_ptr_t), - ("cmap", c_int_t)] + _fields_ = [ + ("row", c_int_t), + ("col", c_int_t), + ("title", c_char_ptr_t), + ("cmap", c_int_t)] def __init__(self, r, c, title, cmap): self.row = r @@ -27,7 +30,8 @@ def __init__(self, r, c, title, cmap): self.title = title if title is not None else c_char_ptr_t() self.cmap = cmap.value -class Window(object): + +class Window: """ Class to create the Window object. @@ -51,15 +55,14 @@ def __init__(self, width=1280, height=720, title="ArrayFire"): self._wnd = c_void_ptr_t(0) self._cmap = COLORMAP.DEFAULT - _width = 1280 if width is None else width - _height = 720 if height is None else height - _title = "ArrayFire" if title is None else title + _width = 1280 if width is None else width + _height = 720 if height is None else height + _title = "ArrayFire" if title is None else title _title = _title.encode("ascii") - safe_call(backend.get().af_create_window(c_pointer(self._wnd), - c_int_t(_width), c_int_t(_height), - c_char_ptr_t(_title))) + safe_call(backend.get().af_create_window( + c_pointer(self._wnd), c_int_t(_width), c_int_t(_height), c_char_ptr_t(_title))) def __del__(self): """ @@ -171,11 +174,11 @@ def scatter(self, X, Y, Z=None, points=None, marker=MARKER.POINT, title=None): if points is None: if Z is None: - safe_call(backend.get().af_draw_scatter_2d(self._wnd, X.arr, Y.arr, - marker.value, c_pointer(_cell))) + safe_call( + backend.get().af_draw_scatter_2d(self._wnd, X.arr, Y.arr, marker.value, c_pointer(_cell))) else: - safe_call(backend.get().af_draw_scatter_3d(self._wnd, X.arr, Y.arr, Z.arr, - marker.value, c_pointer(_cell))) + safe_call( + backend.get().af_draw_scatter_3d(self._wnd, X.arr, Y.arr, Z.arr, marker.value, c_pointer(_cell))) else: safe_call(backend.get().af_draw_scatter_nd(self._wnd, points.arr, marker.value, c_pointer(_cell))) @@ -195,10 +198,9 @@ def scatter2(self, points, marker=MARKER.POINT, title=None): title: str. Title used for the plot. """ - assert(points.numdims() == 2) + assert points.numdims() == 2 _cell = _Cell(self._r, self._c, title, self._cmap) - safe_call(backend.get().af_draw_scatter2(self._wnd, points.arr, - marker.value, c_pointer(_cell))) + safe_call(backend.get().af_draw_scatter2(self._wnd, points.arr, marker.value, c_pointer(_cell))) def scatter3(self, points, marker=MARKER.POINT, title=None): """ @@ -216,11 +218,11 @@ def scatter3(self, points, marker=MARKER.POINT, title=None): title: str. Title used for the plot. """ - assert(points.numdims() == 3) + assert points.numdims() == 3 _cell = _Cell(self._r, self._c, title, self._cmap) - safe_call(backend.get().af_draw_scatter3(self._wnd, points.arr, - marker.value, c_pointer(_cell))) - def plot(self, X, Y, Z=None, line = None, title=None): + safe_call(backend.get().af_draw_scatter3(self._wnd, points.arr, marker.value, c_pointer(_cell))) + + def plot(self, X, Y, Z=None, line=None, title=None): """ Display a 2D or 3D Plot. @@ -274,8 +276,7 @@ def plot2(self, line, title=None): Title used for the plot. """ - - assert(line.numdims() == 2) + assert line.numdims() == 2 _cell = _Cell(self._r, self._c, title, self._cmap) safe_call(backend.get().af_draw_plot_nd(self._wnd, line.arr, c_pointer(_cell))) @@ -292,13 +293,12 @@ def plot3(self, X=None, Y=None, Z=None, line=None, title=None): title: str. Title used for the plot. """ - - assert(line.numdims() == 3) + 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, c_pointer(_cell))) def vector_field(self, xpoints, xdirs, ypoints, ydirs, zpoints=None, zdirs=None, - points = None, dirs = None, title=None): + points=None, dirs=None, title=None): """ Display a 2D or 3D Vector_Field. @@ -346,17 +346,15 @@ def vector_field(self, xpoints, xdirs, ypoints, ydirs, zpoints=None, zdirs=None, The line parameter takes precedence. """ _cell = _Cell(self._r, self._c, title, self._cmap) + # BUG: line and Z variables are not defined. 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, - c_pointer(_cell))) + safe_call(backend.get().af_draw_vector_field_2d( + self._wnd, xpoints.arr, ypoints.arr, xdirs.arr, ydirs.arr, c_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, - c_pointer(_cell))) + safe_call(backend.get().af_draw_vector_field_2d( + self._wnd, xpoints.arr, ypoints.arr, zpoints.arr, xdirs.arr, ydirs.arr, zdirs.arr, + c_pointer(_cell))) else: safe_call(backend.get().af_draw_plot_nd(self._wnd, points.arr, dirs.arr, c_pointer(_cell))) @@ -380,9 +378,8 @@ def surface(self, x_vals, y_vals, z_vals, title=None): Title used for the plot. """ _cell = _Cell(self._r, self._c, title, self._cmap) - safe_call(backend.get().af_draw_surface(self._wnd, - x_vals.arr, y_vals.arr, z_vals.arr, - c_pointer(_cell))) + safe_call(backend.get().af_draw_surface( + self._wnd, x_vals.arr, y_vals.arr, z_vals.arr, c_pointer(_cell))) def hist(self, X, min_val, max_val, title=None): """ @@ -404,9 +401,8 @@ def hist(self, X, min_val, max_val, title=None): Title used for the histogram. """ _cell = _Cell(self._r, self._c, title, self._cmap) - safe_call(backend.get().af_draw_hist(self._wnd, X.arr, - c_double_t(max_val), c_double_t(min_val), - c_pointer(_cell))) + safe_call(backend.get().af_draw_hist( + self._wnd, X.arr, c_double_t(max_val), c_double_t(min_val), c_pointer(_cell))) def grid(self, rows, cols): """ @@ -440,7 +436,7 @@ def close(self): safe_call(backend.get().af_is_window_closed(c_pointer(tmp), self._wnd)) return tmp - def set_visibility(is_visible): + def set_visibility(self, is_visible): """ A flag that shows or hides the window as requested. @@ -484,17 +480,14 @@ def set_axes_limits(self, xmin, xmax, ymin, ymax, zmin=None, zmax=None, exact=Fa 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, - c_float_t(xmin), c_float_t(xmax), - c_float_t(ymin), c_float_t(ymax), - exact, c_pointer(_cell))) + if zmin is None or zmax is None: + safe_call(backend.get().af_set_axes_limits_2d( + self._wnd, c_float_t(xmin), c_float_t(xmax), c_float_t(ymin), c_float_t(ymax), exact, + c_pointer(_cell))) else: - safe_call(backend.get().af_set_axes_limits_2d(self._wnd, - c_float_t(xmin), c_float_t(xmax), - c_float_t(ymin), c_float_t(ymax), - c_float_t(zmin), c_float_t(zmax), - exact, c_pointer(_cell))) + safe_call(backend.get().af_set_axes_limits_2d( + self._wnd, c_float_t(xmin), c_float_t(xmax), c_float_t(ymin), c_float_t(ymax), c_float_t(zmin), + c_float_t(zmax), exact, c_pointer(_cell))) def set_axes_label_format(self, xformat="4.1%f", yformat="4.1%f", zformat="4.1%f"): """ diff --git a/arrayfire/image.py b/arrayfire/image.py index f626a4802..325ee909b 100644 --- a/arrayfire/image.py +++ b/arrayfire/image.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,12 +11,16 @@ Image processing functions. """ -from .library import * -from .array import * -from .data import constant -from .signal import medfilt import os +from .array import Array +from .data import constant +from .library import ( + CANNY_THRESHOLD, CONNECTIVITY, DIFFUSION, FLUX, INTERP, ITERATIVE_DECONV, MOMENT, PAD, YCC_STD, Dtype, c_bool_t, c_char_ptr_t, + c_dim_t, c_double_t, c_float_t, c_int_t, c_pointer, c_uint_t) +from .library import backend, safe_call + + def gradient(image): """ Find the horizontal and vertical gradients. @@ -39,6 +43,7 @@ def gradient(image): safe_call(backend.get().af_gradient(c_pointer(dx.arr), c_pointer(dy.arr), image.arr)) return dx, dy + def load_image(file_name, is_color=False): """ Load an image on the disk as an array. @@ -57,12 +62,13 @@ def load_image(file_name, is_color=False): A 2 dimensional (1 channel) or 3 dimensional (3 channel) array containing the image. """ - assert(os.path.isfile(file_name)) + assert os.path.isfile(file_name) image = Array() - safe_call(backend.get().af_load_image(c_pointer(image.arr), - c_char_ptr_t(file_name.encode('ascii')), is_color)) + safe_call( + backend.get().af_load_image(c_pointer(image.arr), c_char_ptr_t(file_name.encode('ascii')), is_color)) return image + def save_image(image, file_name): """ Save an array as an image on the disk. @@ -75,7 +81,7 @@ def save_image(image, file_name): file_name: str - Full path of the file name on the disk. """ - assert(isinstance(file_name, str)) + assert isinstance(file_name, str) safe_call(backend.get().af_save_image(c_char_ptr_t(file_name.encode('ascii')), image.arr)) return image @@ -95,12 +101,13 @@ def load_image_native(file_name): A 2 dimensional (1 channel) or 3 dimensional (3 or 4 channel) array containing the image. """ - assert(os.path.isfile(file_name)) + assert os.path.isfile(file_name) image = Array() - safe_call(backend.get().af_load_image_native(c_pointer(image.arr), - c_char_ptr_t(file_name.encode('ascii')))) + safe_call( + backend.get().af_load_image_native(c_pointer(image.arr), c_char_ptr_t(file_name.encode('ascii')))) return image + def save_image_native(image, file_name): """ Save an array as an image on the disk in native format. @@ -113,10 +120,11 @@ def save_image_native(image, file_name): file_name: str - Full path of the file name on the disk. """ - assert(isinstance(file_name, str)) + assert isinstance(file_name, str) safe_call(backend.get().af_save_image_native(c_char_ptr_t(file_name.encode('ascii')), image.arr)) return image + def resize(image, scale=None, odim0=None, odim1=None, method=INTERP.NEAREST): """ Resize an image. @@ -151,22 +159,21 @@ def resize(image, scale=None, odim0=None, odim1=None, method=INTERP.NEAREST): - If `scale` is not None, `odim0` and `odim1` are ignored. """ - if (scale is None): - assert(odim0 is not None) - assert(odim1 is not None) + # FIXME: scale is not redefined. Consider changing to bool + if scale is None: + assert odim0 is not None + assert odim1 is not None else: idims = image.dims() odim0 = int(scale * idims[0]) odim1 = int(scale * idims[1]) output = Array() - safe_call(backend.get().af_resize(c_pointer(output.arr), - image.arr, c_dim_t(odim0), - c_dim_t(odim1), method.value)) - + safe_call(backend.get().af_resize(c_pointer(output.arr), image.arr, c_dim_t(odim0), c_dim_t(odim1), method.value)) return output -def transform(image, trans_mat, odim0 = 0, odim1 = 0, method=INTERP.NEAREST, is_inverse=True): + +def transform(image, trans_mat, odim0=0, odim1=0, method=INTERP.NEAREST, is_inverse=True): """ Transform an image using a transformation matrix. @@ -203,14 +210,12 @@ def transform(image, trans_mat, odim0 = 0, odim1 = 0, method=INTERP.NEAREST, is_ """ output = Array() - safe_call(backend.get().af_transform(c_pointer(output.arr), - image.arr, trans_mat.arr, - c_dim_t(odim0), c_dim_t(odim1), - method.value, is_inverse)) + safe_call(backend.get().af_transform( + c_pointer(output.arr), image.arr, trans_mat.arr, c_dim_t(odim0), c_dim_t(odim1), method.value, is_inverse)) return output -def rotate(image, theta, is_crop = True, method = INTERP.NEAREST): +def rotate(image, theta, is_crop=True, method=INTERP.NEAREST): """ Rotate an image. @@ -235,11 +240,11 @@ def rotate(image, theta, is_crop = True, method = INTERP.NEAREST): - Output image after rotating. """ output = Array() - safe_call(backend.get().af_rotate(c_pointer(output.arr), image.arr, - c_float_t(theta), is_crop, method.value)) + safe_call(backend.get().af_rotate(c_pointer(output.arr), image.arr, c_float_t(theta), is_crop, method.value)) return output -def translate(image, trans0, trans1, odim0 = 0, odim1 = 0, method = INTERP.NEAREST): + +def translate(image, trans0, trans1, odim0=0, odim1=0, method=INTERP.NEAREST): """ Translate an image. @@ -276,12 +281,12 @@ def translate(image, trans0, trans1, odim0 = 0, odim1 = 0, method = INTERP.NEARE """ output = Array() - safe_call(backend.get().af_translate(c_pointer(output.arr), - image.arr, trans0, trans1, - c_dim_t(odim0), c_dim_t(odim1), method.value)) + safe_call(backend.get().af_translate( + c_pointer(output.arr), image.arr, trans0, trans1, c_dim_t(odim0), c_dim_t(odim1), method.value)) return output -def scale(image, scale0, scale1, odim0 = 0, odim1 = 0, method = INTERP.NEAREST): + +def scale(image, scale0, scale1, odim0=0, odim1=0, method=INTERP.NEAREST): """ Scale an image. @@ -318,12 +323,13 @@ def scale(image, scale0, scale1, odim0 = 0, odim1 = 0, method = INTERP.NEAREST): """ output = Array() - safe_call(backend.get().af_scale(c_pointer(output.arr), - image.arr, c_float_t(scale0), c_float_t(scale1), - c_dim_t(odim0), c_dim_t(odim1), method.value)) + safe_call(backend.get().af_scale( + c_pointer(output.arr), image.arr, c_float_t(scale0), c_float_t(scale1), c_dim_t(odim0), c_dim_t(odim1), + method.value)) return output -def skew(image, skew0, skew1, odim0 = 0, odim1 = 0, method = INTERP.NEAREST, is_inverse=True): + +def skew(image, skew0, skew1, odim0=0, odim1=0, method=INTERP.NEAREST, is_inverse=True): """ Skew an image. @@ -363,14 +369,14 @@ def skew(image, skew0, skew1, odim0 = 0, odim1 = 0, method = INTERP.NEAREST, is_ """ output = Array() - safe_call(backend.get().af_skew(c_pointer(output.arr), - image.arr, c_float_t(skew0), c_float_t(skew1), - c_dim_t(odim0), c_dim_t(odim1), - method.value, is_inverse)) + safe_call(backend.get().af_skew( + c_pointer(output.arr), image.arr, c_float_t(skew0), c_float_t(skew1), c_dim_t(odim0), c_dim_t(odim1), + method.value, is_inverse)) return output -def histogram(image, nbins, min_val = None, max_val = None): + +def histogram(image, nbins, min_val=None, max_val=None): """ Find the histogram of an image. @@ -407,11 +413,11 @@ def histogram(image, nbins, min_val = None, max_val = None): max_val = af_max(image) output = Array() - safe_call(backend.get().af_histogram(c_pointer(output.arr), - image.arr, c_uint_t(nbins), - c_double_t(min_val), c_double_t(max_val))) + safe_call(backend.get().af_histogram( + c_pointer(output.arr), image.arr, c_uint_t(nbins), c_double_t(min_val), c_double_t(max_val))) return output + def hist_equal(image, hist): """ Equalize an image based on a histogram. @@ -436,7 +442,8 @@ def hist_equal(image, hist): safe_call(backend.get().af_hist_equal(c_pointer(output.arr), image.arr, hist.arr)) return output -def dilate(image, mask = None): + +def dilate(image, mask=None): """ Run image dilate on the image. @@ -462,10 +469,10 @@ def dilate(image, mask = None): output = Array() safe_call(backend.get().af_dilate(c_pointer(output.arr), image.arr, mask.arr)) - return output -def dilate3(volume, mask = None): + +def dilate3(volume, mask=None): """ Run volume dilate on a volume. @@ -491,10 +498,10 @@ def dilate3(volume, mask = None): output = Array() safe_call(backend.get().af_dilate3(c_pointer(output.arr), volume.arr, mask.arr)) - return output -def erode(image, mask = None): + +def erode(image, mask=None): """ Run image erode on the image. @@ -520,10 +527,10 @@ def erode(image, mask = None): output = Array() safe_call(backend.get().af_erode(c_pointer(output.arr), image.arr, mask.arr)) - return output -def erode3(volume, mask = None): + +def erode3(volume, mask=None): """ Run volume erode on the volume. @@ -544,16 +551,15 @@ def erode3(volume, mask = None): - The eroded volume. """ - if mask is None: mask = constant(1, 3, 3, 3, dtype=Dtype.f32) output = Array() safe_call(backend.get().af_erode3(c_pointer(output.arr), volume.arr, mask.arr)) - return output -def bilateral(image, s_sigma, c_sigma, is_color = False): + +def bilateral(image, s_sigma, c_sigma, is_color=False): """ Apply bilateral filter to the image. @@ -580,12 +586,12 @@ def bilateral(image, s_sigma, c_sigma, is_color = False): """ output = Array() - safe_call(backend.get().af_bilateral(c_pointer(output.arr), - image.arr, c_float_t(s_sigma), - c_float_t(c_sigma), is_color)) + safe_call(backend.get().af_bilateral( + c_pointer(output.arr), image.arr, c_float_t(s_sigma), c_float_t(c_sigma), is_color)) return output -def mean_shift(image, s_sigma, c_sigma, n_iter, is_color = False): + +def mean_shift(image, s_sigma, c_sigma, n_iter, is_color=False): """ Apply mean shift to the image. @@ -615,12 +621,12 @@ def mean_shift(image, s_sigma, c_sigma, n_iter, is_color = False): """ output = Array() - safe_call(backend.get().af_mean_shift(c_pointer(output.arr), - image.arr, c_float_t(s_sigma), c_float_t(c_sigma), - c_uint_t(n_iter), is_color)) + safe_call(backend.get().af_mean_shift( + c_pointer(output.arr), image.arr, c_float_t(s_sigma), c_float_t(c_sigma), c_uint_t(n_iter), is_color)) return output -def minfilt(image, w_len = 3, w_wid = 3, edge_pad = PAD.ZERO): + +def minfilt(image, w_len=3, w_wid=3, edge_pad=PAD.ZERO): """ Apply min filter for the image. @@ -647,12 +653,12 @@ def minfilt(image, w_len = 3, w_wid = 3, edge_pad = PAD.ZERO): """ output = Array() - safe_call(backend.get().af_minfilt(c_pointer(output.arr), - image.arr, c_dim_t(w_len), - c_dim_t(w_wid), edge_pad.value)) + safe_call( + backend.get().af_minfilt(c_pointer(output.arr), image.arr, c_dim_t(w_len), c_dim_t(w_wid), edge_pad.value)) return output -def maxfilt(image, w_len = 3, w_wid = 3, edge_pad = PAD.ZERO): + +def maxfilt(image, w_len=3, w_wid=3, edge_pad=PAD.ZERO): """ Apply max filter for the image. @@ -679,12 +685,12 @@ def maxfilt(image, w_len = 3, w_wid = 3, edge_pad = PAD.ZERO): """ output = Array() - safe_call(backend.get().af_maxfilt(c_pointer(output.arr), - image.arr, c_dim_t(w_len), - c_dim_t(w_wid), edge_pad.value)) + safe_call( + backend.get().af_maxfilt(c_pointer(output.arr), image.arr, c_dim_t(w_len), c_dim_t(w_wid), edge_pad.value)) return output -def regions(image, conn = CONNECTIVITY.FOUR, out_type = Dtype.f32): + +def regions(image, conn=CONNECTIVITY.FOUR, out_type=Dtype.f32): """ Find the connected components in the image. @@ -707,10 +713,10 @@ def regions(image, conn = CONNECTIVITY.FOUR, out_type = Dtype.f32): """ output = Array() - safe_call(backend.get().af_regions(c_pointer(output.arr), image.arr, - conn.value, out_type.value)) + safe_call(backend.get().af_regions(c_pointer(output.arr), image.arr, conn.value, out_type.value)) return output + def confidenceCC(image, seedx, seedy, radius, multiplier, iters, segmented_value): """ Find the confidence connected components in the image. @@ -754,6 +760,7 @@ def confidenceCC(image, seedx, seedy, radius, multiplier, iters, segmented_value c_uint_t(radius), c_uint_t(multiplier), c_int_t(iters), c_double_t(segmented_value))) return output + def sobel_derivatives(image, w_len=3): """ Find the sobel derivatives of the image. @@ -777,11 +784,11 @@ def sobel_derivatives(image, w_len=3): """ dx = Array() dy = Array() - safe_call(backend.get().af_sobel_operator(c_pointer(dx.arr), c_pointer(dy.arr), - image.arr, c_uint_t(w_len))) - return dx,dy + safe_call(backend.get().af_sobel_operator(c_pointer(dx.arr), c_pointer(dy.arr), image.arr, c_uint_t(w_len))) + return dx, dy -def gaussian_kernel(rows, cols, sigma_r = None, sigma_c = None): + +def gaussian_kernel(rows, cols, sigma_r=None, sigma_c=None): """ Create a gaussian kernel with the given parameters. @@ -812,18 +819,18 @@ def gaussian_kernel(rows, cols, sigma_r = None, sigma_c = None): """ out = Array() - if (sigma_r is None): + if sigma_r is None: sigma_r = 0.25 * rows + 0.75 - if (sigma_c is None): + if sigma_c is None: sigma_c = 0.25 * cols + 0.75 - safe_call(backend.get().af_gaussian_kernel(c_pointer(out.arr), - c_int_t(rows), c_int_t(cols), - c_double_t(sigma_r), c_double_t(sigma_c))) + safe_call(backend.get().af_gaussian_kernel( + c_pointer(out.arr), c_int_t(rows), c_int_t(cols), c_double_t(sigma_r), c_double_t(sigma_c))) return out -def sobel_filter(image, w_len = 3, is_fast = False): + +def sobel_filter(image, w_len=3, is_fast=False): """ Apply sobel filter to the image. @@ -846,16 +853,18 @@ def sobel_filter(image, w_len = 3, is_fast = False): - Image containing the magnitude of the sobel derivatives. """ + # FIXME: import inside of a function from .arith import abs as af_abs from .arith import hypot as af_hypot - dx,dy = sobel_derivatives(image, w_len) - if (is_fast): + dx, dy = sobel_derivatives(image, w_len) + if is_fast: return af_abs(dx) + af_abs(dy) - else: - return af_hypot(dx, dy) -def rgb2gray(image, r_factor = 0.2126, g_factor = 0.7152, b_factor = 0.0722): + return af_hypot(dx, dy) + + +def rgb2gray(image, r_factor=0.2126, g_factor=0.7152, b_factor=0.0722): """ Convert RGB image to Grayscale. @@ -881,12 +890,13 @@ def rgb2gray(image, r_factor = 0.2126, g_factor = 0.7152, b_factor = 0.0722): - A grayscale image. """ - output=Array() - safe_call(backend.get().af_rgb2gray(c_pointer(output.arr), - image.arr, c_float_t(r_factor), c_float_t(g_factor), c_float_t(b_factor))) + output = Array() + safe_call(backend.get().af_rgb2gray( + c_pointer(output.arr), image.arr, c_float_t(r_factor), c_float_t(g_factor), c_float_t(b_factor))) return output -def gray2rgb(image, r_factor = 1.0, g_factor = 1.0, b_factor = 1.0): + +def gray2rgb(image, r_factor=1.0, g_factor=1.0, b_factor=1.0): """ Convert Grayscale image to an RGB image. @@ -913,11 +923,12 @@ def gray2rgb(image, r_factor = 1.0, g_factor = 1.0, b_factor = 1.0): - The channels are not coalesced, i.e. they appear along the third dimension. """ - output=Array() - safe_call(backend.get().af_gray2rgb(c_pointer(output.arr), - image.arr, c_float_t(r_factor), c_float_t(g_factor), c_float_t(b_factor))) + output = Array() + safe_call(backend.get().af_gray2rgb( + c_pointer(output.arr), image.arr, c_float_t(r_factor), c_float_t(g_factor), c_float_t(b_factor))) return output + def hsv2rgb(image): """ Convert HSV image to RGB. @@ -939,6 +950,7 @@ def hsv2rgb(image): safe_call(backend.get().af_hsv2rgb(c_pointer(output.arr), image.arr)) return output + def rgb2hsv(image): """ Convert RGB image to HSV. @@ -960,6 +972,7 @@ def rgb2hsv(image): safe_call(backend.get().af_rgb2hsv(c_pointer(output.arr), image.arr)) return output + def color_space(image, to_type, from_type): """ Convert an image from one color space to another. @@ -983,10 +996,10 @@ def color_space(image, to_type, from_type): """ output = Array() - safe_call(backend.get().af_color_space(c_pointer(output.arr), image.arr, - to_type.value, from_type.value)) + safe_call(backend.get().af_color_space(c_pointer(output.arr), image.arr, to_type.value, from_type.value)) return output + def unwrap(image, wx, wy, sx, sy, px=0, py=0, is_column=True): """ Unrwap an image into an array. @@ -1047,15 +1060,13 @@ def unwrap(image, wx, wy, sx, sy, px=0, py=0, is_column=True): 0.3775 0.6456 0.6600 0.8060 0.8395 0.7270 0.9250 0.9313 0.6592 0.3027 0.5591 0.0764 0.5938 0.1933 0.0322 0.3063 0.8684 0.4387 """ - out = Array() - safe_call(backend.get().af_unwrap(c_pointer(out.arr), image.arr, - c_dim_t(wx), c_dim_t(wy), - c_dim_t(sx), c_dim_t(sy), - c_dim_t(px), c_dim_t(py), - is_column)) + safe_call(backend.get().af_unwrap( + c_pointer(out.arr), image.arr, c_dim_t(wx), c_dim_t(wy), c_dim_t(sx), c_dim_t(sy), c_dim_t(px), c_dim_t(py), + is_column)) return out + def wrap(a, ox, oy, wx, wy, sx, sy, px=0, py=0, is_column=True): """ Wrap an array into an image. @@ -1129,16 +1140,13 @@ def wrap(a, ox, oy, wx, wy, sx, sy, px=0, py=0, is_column=True): """ - out = Array() - safe_call(backend.get().af_wrap(c_pointer(out.arr), a.arr, - c_dim_t(ox), c_dim_t(oy), - c_dim_t(wx), c_dim_t(wy), - c_dim_t(sx), c_dim_t(sy), - c_dim_t(px), c_dim_t(py), - is_column)) + safe_call(backend.get().af_wrap( + c_pointer(out.arr), a.arr, c_dim_t(ox), c_dim_t(oy), c_dim_t(wx), c_dim_t(wy), c_dim_t(sx), c_dim_t(sy), + c_dim_t(px), c_dim_t(py), is_column)) return out + def sat(image): """ Summed Area Tables @@ -1153,11 +1161,11 @@ def sat(image): out : af.Array A multi dimensional array containing the summed area table of input image """ - out = Array() safe_call(backend.get().af_sat(c_pointer(out.arr), image.arr)) return out + def ycbcr2rgb(image, standard=YCC_STD.BT_601): """ YCbCr to RGB colorspace conversion. @@ -1179,11 +1187,11 @@ def ycbcr2rgb(image, standard=YCC_STD.BT_601): A multi dimensional array containing an image or batch of images in RGB format """ - out = Array() safe_call(backend.get().af_ycbcr2rgb(c_pointer(out.arr), image.arr, standard.value)) return out + def rgb2ycbcr(image, standard=YCC_STD.BT_601): """ RGB to YCbCr colorspace conversion. @@ -1205,12 +1213,12 @@ def rgb2ycbcr(image, standard=YCC_STD.BT_601): A multi dimensional array containing an image or batch of images in YCbCr format """ - out = Array() safe_call(backend.get().af_rgb2ycbcr(c_pointer(out.arr), image.arr, standard.value)) return out -def moments(image, moment = MOMENT.FIRST_ORDER): + +def moments(image, moment=MOMENT.FIRST_ORDER): """ Calculate image moments. @@ -1237,10 +1245,10 @@ def moments(image, moment = MOMENT.FIRST_ORDER): safe_call(backend.get().af_moments(c_pointer(output.arr), image.arr, moment.value)) return output -def canny(image, - low_threshold, high_threshold = None, - threshold_type = CANNY_THRESHOLD.MANUAL, - sobel_window = 3, is_fast = False): + +def canny( + image, low_threshold, high_threshold=None, threshold_type=CANNY_THRESHOLD.MANUAL, sobel_window=3, + is_fast=False): """ Canny edge detector. @@ -1274,16 +1282,17 @@ def canny(image, """ output = Array() if threshold_type.value == CANNY_THRESHOLD.MANUAL.value: - assert(high_threshold is not None) + assert high_threshold is not None high_threshold = high_threshold if high_threshold else 0 - safe_call(backend.get().af_canny(c_pointer(output.arr), image.arr, - c_int_t(threshold_type.value), - c_float_t(low_threshold), c_float_t(high_threshold), - c_uint_t(sobel_window), c_bool_t(is_fast))) + safe_call(backend.get().af_canny( + c_pointer(output.arr), image.arr, c_int_t(threshold_type.value), c_float_t(low_threshold), + c_float_t(high_threshold), c_uint_t(sobel_window), c_bool_t(is_fast))) return output -def anisotropic_diffusion(image, time_step, conductance, iterations, flux_function_type = FLUX.QUADRATIC, diffusion_kind = DIFFUSION.GRAD): + +def anisotropic_diffusion( + image, time_step, conductance, iterations, flux_function_type=FLUX.QUADRATIC, diffusion_kind=DIFFUSION.GRAD): """ Anisotropic smoothing filter. @@ -1318,12 +1327,12 @@ def anisotropic_diffusion(image, time_step, conductance, iterations, flux_functi """ out = Array() - safe_call(backend.get(). - af_anisotropic_diffusion(c_pointer(out.arr), image.arr, - c_float_t(time_step), c_float_t(conductance), c_uint_t(iterations), - flux_function_type.value, diffusion_kind.value)) + safe_call(backend.get().af_anisotropic_diffusion( + c_pointer(out.arr), image.arr, c_float_t(time_step), c_float_t(conductance), c_uint_t(iterations), + flux_function_type.value, diffusion_kind.value)) return out + def iterativeDeconv(image, psf, iterations, relax_factor, algo = ITERATIVE_DECONV.DEFAULT): """ Iterative deconvolution algorithm. @@ -1396,6 +1405,7 @@ def inverseDeconv(image, psf, gamma, algo = ITERATIVE_DECONV.DEFAULT): c_float_t(gamma), algo.value)) return out + def is_image_io_available(): """ Function to check if the arrayfire library was built with Image IO support. diff --git a/arrayfire/index.py b/arrayfire/index.py index 093a88336..ae49e4934 100644 --- a/arrayfire/index.py +++ b/arrayfire/index.py @@ -1,22 +1,25 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, 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 ######################################################## + """ Index and Seq classes used in indexing operations. """ -from .library import * -from .util import * -from .util import _is_number -from .base import * -from .bcast import _bcast_var +import ctypes as ct import math +from .base import BaseArray +from .bcast import _bcast_var +from .library import backend, safe_call, Dtype, c_bool_t, c_double_t, c_pointer, c_void_ptr_t +from .util import _is_number + + class Seq(ct.Structure): """ arrayfire equivalent of slice @@ -39,45 +42,46 @@ class Seq(ct.Structure): S: slice or number. """ - _fields_ = [("begin", c_double_t), - ("end" , c_double_t), - ("step" , c_double_t)] + _fields_ = [ + ("begin", c_double_t), + ("end", c_double_t), + ("step", c_double_t)] - def __init__ (self, S): - self.begin = c_double_t( 0) - self.end = c_double_t(-1) - self.step = c_double_t( 1) + def __init__(self, S): + self.begin = c_double_t(0) + self.end = c_double_t(-1) + self.step = c_double_t(1) if _is_number(S): self.begin = c_double_t(S) - self.end = c_double_t(S) + self.end = c_double_t(S) elif isinstance(S, slice): - if (S.step is not None): - self.step = c_double_t(S.step) - if(S.step < 0): + if S.step is not None: + self.step = c_double_t(S.step) + if S.step < 0: self.begin, self.end = self.end, self.begin - if (S.start is not None): + if S.start is not None: self.begin = c_double_t(S.start) - if (S.stop is not None): + if S.stop is not None: self.end = c_double_t(S.stop) # handle special cases - if self.begin >= 0 and self.end >=0 and self.end <= self.begin and self.step >= 0: + if self.begin >= 0 and self.end >= 0 and self.end <= self.begin and self.step >= 0: self.begin = 1 - self.end = 1 - self.step = 1 + self.end = 1 + self.step = 1 elif self.begin < 0 and self.end < 0 and self.end >= self.begin and self.step <= 0: self.begin = -2 - self.end = -2 - self.step = -1 + self.end = -2 + self.step = -1 - if (S.stop is not None): + if S.stop is not None: self.end = self.end - math.copysign(1, self.step) else: raise IndexError("Invalid type while indexing arrayfire.array") -class ParallelRange(Seq): +class ParallelRange(Seq): """ Class used to parallelize for loop. @@ -129,14 +133,14 @@ class ParallelRange(Seq): 1.4719 0.5282 1.1657 """ - def __init__(self, start, stop=None, step=None): - if (stop is None): + def __init__(self, start, stop=None, step=None): + if stop is None: stop = start start = 0 self.S = slice(start, stop, step) - super(ParallelRange, self).__init__(self.S) + super().__init__(self.S) def __iter__(self): return self @@ -145,12 +149,12 @@ def next(self): """ Function called by the iterator in Python 2 """ - if _bcast_var.get() is True: + if _bcast_var.get(): _bcast_var.toggle() raise StopIteration - else: - _bcast_var.toggle() - return self + + _bcast_var.toggle() + return self def __next__(self): """ @@ -158,14 +162,18 @@ def __next__(self): """ return self.next() + class _uidx(ct.Union): - _fields_ = [("arr", c_void_ptr_t), - ("seq", Seq)] + _fields_ = [ + ("arr", c_void_ptr_t), + ("seq", Seq)] + class Index(ct.Structure): - _fields_ = [("idx", _uidx), - ("isSeq", c_bool_t), - ("isBatch", c_bool_t)] + _fields_ = [ + ("idx", _uidx), + ("isSeq", c_bool_t), + ("isBatch", c_bool_t)] """ Container for the index class in arrayfire C library @@ -199,23 +207,23 @@ class Index(ct.Structure): """ - def __init__ (self, idx): + def __init__(self, idx): - self.idx = _uidx() + self.idx = _uidx() self.isBatch = False - self.isSeq = True + self.isSeq = True if isinstance(idx, BaseArray): arr = c_void_ptr_t(0) - if (idx.type() == Dtype.b8.value): + if idx.type() == Dtype.b8.value: safe_call(backend.get().af_where(c_pointer(arr), idx.arr)) else: safe_call(backend.get().af_retain_array(c_pointer(arr), idx.arr)) self.idx.arr = arr - self.isSeq = False + self.isSeq = False elif isinstance(idx, ParallelRange): self.idx.seq = idx self.isBatch = True @@ -230,7 +238,10 @@ def __del__(self): arr = c_void_ptr_t(self.idx.arr) backend.get().af_release_array(arr) + _span = Index(slice(None)) + + class _Index4(object): def __init__(self): index_vec = Index * 4 @@ -239,6 +250,7 @@ def __init__(self): # no reference to them. Otherwise the destructor # is prematurely called self.idxs = [_span, _span, _span, _span] + @property def pointer(self): return c_pointer(self.array) diff --git a/arrayfire/interop.py b/arrayfire/interop.py index f2b9a1f68..3c75d271f 100644 --- a/arrayfire/interop.py +++ b/arrayfire/interop.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -19,11 +19,12 @@ """ -from .array import * -from .device import * +from .array import Array +from .library import Dtype, c_void_ptr_t +from .device import get_device_count, info, lock_array, set_device -def _fc_to_af_array(in_ptr, in_shape, in_dtype, is_device=False, copy = True): +def _fc_to_af_array(in_ptr, in_shape, in_dtype, is_device=False, copy=True): """ Fortran Contiguous to af array """ @@ -35,40 +36,45 @@ def _fc_to_af_array(in_ptr, in_shape, in_dtype, is_device=False, copy = True): lock_array(res) return res.copy() if copy else res -def _cc_to_af_array(in_ptr, ndim, in_shape, in_dtype, is_device=False, copy = True): + +def _cc_to_af_array(in_ptr, ndim, in_shape, in_dtype, is_device=False, copy=True): """ C Contiguous to af array """ if ndim == 1: return _fc_to_af_array(in_ptr, in_shape, in_dtype, is_device, copy) - else: - shape = tuple(reversed(in_shape)) - res = Array(in_ptr, shape, in_dtype, is_device=is_device) - if is_device: lock_array(res) - return res._reorder() - -_nptype_to_aftype = {'b1' : Dtype.b8, - 'u1' : Dtype.u8, - 'u2' : Dtype.u16, - 'i2' : Dtype.s16, - 's4' : Dtype.u32, - 'i4' : Dtype.s32, - 'f4' : Dtype.f32, - 'c8' : Dtype.c32, - 's8' : Dtype.u64, - 'i8' : Dtype.s64, - 'f8' : Dtype.f64, - 'c16' : Dtype.c64} + + shape = tuple(reversed(in_shape)) + res = Array(in_ptr, shape, in_dtype, is_device=is_device) + if is_device: + lock_array(res) + # FIXME: access a protected member of Array class. + return res._reorder() + + +_nptype_to_aftype = { + 'b1': Dtype.b8, + 'u1': Dtype.u8, + 'u2': Dtype.u16, + 'i2': Dtype.s16, + 's4': Dtype.u32, + 'i4': Dtype.s32, + 'f4': Dtype.f32, + 'c8': Dtype.c32, + 's8': Dtype.u64, + 'i8': Dtype.s64, + 'f8': Dtype.f64, + 'c16': Dtype.c64} try: + # FIXME: numpy imported but unused import numpy as np except ImportError: - AF_NUMPY_FOUND=False + AF_NUMPY_FOUND = False else: from numpy import ndarray as NumpyArray - from .data import reorder - AF_NUMPY_FOUND=True + AF_NUMPY_FOUND = True def np_to_af_array(np_arr, copy=True): """ @@ -86,7 +92,6 @@ def np_to_af_array(np_arr, copy=True): --------- af_arr : arrayfire.Array() """ - in_shape = np_arr.shape in_ptr = np_arr.ctypes.data_as(c_void_ptr_t) in_dtype = _nptype_to_aftype[np_arr.dtype.str[1:]] @@ -94,22 +99,23 @@ def np_to_af_array(np_arr, copy=True): if not copy: raise RuntimeError("Copy can not be False for numpy arrays") - if (np_arr.flags['F_CONTIGUOUS']): + if np_arr.flags['F_CONTIGUOUS']: return _fc_to_af_array(in_ptr, in_shape, in_dtype) - elif (np_arr.flags['C_CONTIGUOUS']): + if np_arr.flags['C_CONTIGUOUS']: return _cc_to_af_array(in_ptr, np_arr.ndim, in_shape, in_dtype) - else: - return np_to_af_array(np_arr.copy()) + + return np_to_af_array(np_arr.copy()) from_ndarray = np_to_af_array try: + # FIXME: pycuda imported but unused import pycuda.gpuarray except ImportError: - AF_PYCUDA_FOUND=False + AF_PYCUDA_FOUND = False else: from pycuda.gpuarray import GPUArray as CudaArray - AF_PYCUDA_FOUND=True + AF_PYCUDA_FOUND = True def pycuda_to_af_array(pycu_arr, copy=True): """ @@ -131,7 +137,6 @@ def pycuda_to_af_array(pycu_arr, copy=True): ---------- The input array is copied to af.Array """ - in_ptr = pycu_arr.ptr in_shape = pycu_arr.shape in_dtype = pycu_arr.dtype.char @@ -139,23 +144,23 @@ def pycuda_to_af_array(pycu_arr, copy=True): if not copy and not pycu_arr.flags.f_contiguous: raise RuntimeError("Copy can only be False when arr.flags.f_contiguous is True") - if (pycu_arr.flags.f_contiguous): + if pycu_arr.flags.f_contiguous: return _fc_to_af_array(in_ptr, in_shape, in_dtype, True, copy) - elif (pycu_arr.flags.c_contiguous): + if pycu_arr.flags.c_contiguous: return _cc_to_af_array(in_ptr, pycu_arr.ndim, in_shape, in_dtype, True, copy) - else: - return pycuda_to_af_array(pycu_arr.copy()) + + return pycuda_to_af_array(pycu_arr.copy()) try: from pyopencl.array import Array as OpenclArray except ImportError: - AF_PYOPENCL_FOUND=False + AF_PYOPENCL_FOUND = False else: from .opencl import add_device_context as _add_device_context from .opencl import set_device_context as _set_device_context from .opencl import get_device_id as _get_device_id from .opencl import get_context as _get_context - AF_PYOPENCL_FOUND=True + AF_PYOPENCL_FOUND = True def pyopencl_to_af_array(pycl_arr, copy=True): """ @@ -177,7 +182,6 @@ def pyopencl_to_af_array(pycl_arr, copy=True): ---------- The input array is copied to af.Array """ - ctx = pycl_arr.context.int_ptr que = pycl_arr.queue.int_ptr dev = pycl_arr.queue.device.int_ptr @@ -188,11 +192,10 @@ def pyopencl_to_af_array(pycl_arr, copy=True): set_device(n) dev_idx = _get_device_id() ctx_idx = _get_context() - if (dev_idx == dev and ctx_idx == ctx): + if dev_idx == dev and ctx_idx == ctx: break - if (dev_idx == None or ctx_idx == None or - dev_idx != dev or ctx_idx != ctx): + if (dev_idx is None or ctx_idx is None or dev_idx != dev or ctx_idx != ctx): print("Adding context and queue") _add_device_context(dev, ctx, que) _set_device_context(dev, ctx) @@ -207,21 +210,22 @@ def pyopencl_to_af_array(pycl_arr, copy=True): print("Copying array") print(pycl_arr.base_data.int_ptr) - if (pycl_arr.flags.f_contiguous): + if pycl_arr.flags.f_contiguous: return _fc_to_af_array(in_ptr, in_shape, in_dtype, True, copy) - elif (pycl_arr.flags.c_contiguous): + if pycl_arr.flags.c_contiguous: return _cc_to_af_array(in_ptr, pycl_arr.ndim, in_shape, in_dtype, True, copy) - else: - return pyopencl_to_af_array(pycl_arr.copy()) + + return pyopencl_to_af_array(pycl_arr.copy()) try: + # FIXME: numba imported but unused import numba except ImportError: - AF_NUMBA_FOUND=False + AF_NUMBA_FOUND = False else: from numba import cuda NumbaCudaArray = cuda.cudadrv.devicearray.DeviceNDArray - AF_NUMBA_FOUND=True + AF_NUMBA_FOUND = True def numba_to_af_array(nb_arr, copy=True): """ @@ -243,7 +247,6 @@ def numba_to_af_array(nb_arr, copy=True): ---------- The input array is copied to af.Array """ - in_ptr = nb_arr.device_ctypes_pointer.value in_shape = nb_arr.shape in_dtype = _nptype_to_aftype[nb_arr.dtype.str[1:]] @@ -251,14 +254,15 @@ def numba_to_af_array(nb_arr, copy=True): if not copy and not nb_arr.flags.f_contiguous: raise RuntimeError("Copy can only be False when arr.flags.f_contiguous is True") - if (nb_arr.is_f_contiguous()): + if nb_arr.is_f_contiguous(): return _fc_to_af_array(in_ptr, in_shape, in_dtype, True, copy) - elif (nb_arr.is_c_contiguous()): + if nb_arr.is_c_contiguous(): return _cc_to_af_array(in_ptr, nb_arr.ndim, in_shape, in_dtype, True, copy) - else: - return numba_to_af_array(nb_arr.copy()) -def to_array(in_array, copy = True): + return numba_to_af_array(nb_arr.copy()) + + +def to_array(in_array, copy=True): """ Helper function to convert input from a different module to af.Array diff --git a/arrayfire/lapack.py b/arrayfire/lapack.py index 97ad92c7a..639a53006 100644 --- a/arrayfire/lapack.py +++ b/arrayfire/lapack.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,8 +11,9 @@ Dense Linear Algebra functions (solve, inverse, etc). """ -from .library import * -from .array import * +from .array import Array +from .library import backend, safe_call, MATPROP, NORM, c_bool_t, c_double_t, c_int_t, c_pointer, c_uint_t + def lu(A): """ @@ -42,7 +43,8 @@ def lu(A): U = Array() P = Array() safe_call(backend.get().af_lu(c_pointer(L.arr), c_pointer(U.arr), c_pointer(P.arr), A.arr)) - return L,U,P + return L, U, P + def lu_inplace(A, pivot="lapack"): """ @@ -67,10 +69,11 @@ def lu_inplace(A, pivot="lapack"): """ P = Array() - is_pivot_lapack = False if (pivot == "full") else True + is_pivot_lapack = bool(pivot != "full") safe_call(backend.get().af_lu_inplace(c_pointer(P.arr), A.arr, is_pivot_lapack)) return P + def qr(A): """ QR decomposition. @@ -99,7 +102,8 @@ def qr(A): R = Array() T = Array() safe_call(backend.get().af_qr(c_pointer(Q.arr), c_pointer(R.arr), c_pointer(T.arr), A.arr)) - return Q,R,T + return Q, R, T + def qr_inplace(A): """ @@ -125,6 +129,7 @@ def qr_inplace(A): safe_call(backend.get().af_qr_inplace(c_pointer(T.arr), A.arr)) return T + def cholesky(A, is_upper=True): """ Cholesky decomposition @@ -156,6 +161,7 @@ def cholesky(A, is_upper=True): safe_call(backend.get().af_cholesky(c_pointer(R.arr), c_pointer(info), A.arr, is_upper)) return R, info.value + def cholesky_inplace(A, is_upper=True): """ In place Cholesky decomposition. @@ -179,6 +185,7 @@ def cholesky_inplace(A, is_upper=True): safe_call(backend.get().af_cholesky_inplace(c_pointer(info), A.arr, is_upper)) return info.value + def solve(A, B, options=MATPROP.NONE): """ Solve a system of linear equations. @@ -206,6 +213,7 @@ def solve(A, B, options=MATPROP.NONE): safe_call(backend.get().af_solve(c_pointer(X.arr), A.arr, B.arr, options.value)) return X + def solve_lu(A, P, B, options=MATPROP.NONE): """ Solve a system of linear equations, using LU decomposition. @@ -234,6 +242,7 @@ def solve_lu(A, P, B, options=MATPROP.NONE): safe_call(backend.get().af_solve_lu(c_pointer(X.arr), A.arr, P.arr, B.arr, options.value)) return X + def inverse(A, options=MATPROP.NONE): """ Invert a matrix. @@ -264,6 +273,7 @@ def inverse(A, options=MATPROP.NONE): safe_call(backend.get().af_inverse(c_pointer(AI.arr), A.arr, options.value)) return AI + def pinverse(A, tol=1E-6, options=MATPROP.NONE): """ Find pseudo-inverse(Moore-Penrose) of a matrix. @@ -297,6 +307,7 @@ def pinverse(A, tol=1E-6, options=MATPROP.NONE): safe_call(backend.get().af_pinverse(c_pointer(AI.arr), A.arr, c_double_t(tol), options.value)) return AI + def rank(A, tol=1E-5): """ Rank of a matrix. @@ -320,6 +331,7 @@ def rank(A, tol=1E-5): safe_call(backend.get().af_rank(c_pointer(r), A.arr, c_double_t(tol))) return r.value + def det(A): """ Determinant of a matrix. @@ -341,7 +353,8 @@ def det(A): safe_call(backend.get().af_det(c_pointer(re), c_pointer(im), A.arr)) re = re.value im = im.value - return re if (im == 0) else re + im * 1j + return re if im == 0 else re + im * 1j + def norm(A, norm_type=NORM.EUCLID, p=1.0, q=1.0): """ @@ -370,10 +383,10 @@ def norm(A, norm_type=NORM.EUCLID, p=1.0, q=1.0): """ res = c_double_t(0) - safe_call(backend.get().af_norm(c_pointer(res), A.arr, norm_type.value, - c_double_t(p), c_double_t(q))) + safe_call(backend.get().af_norm(c_pointer(res), A.arr, norm_type.value, c_double_t(p), c_double_t(q))) return res.value + def svd(A): """ Singular Value Decomposition @@ -408,6 +421,7 @@ def svd(A): safe_call(backend.get().af_svd(c_pointer(U.arr), c_pointer(S.arr), c_pointer(Vt.arr), A.arr)) return U, S, Vt + def svd_inplace(A): """ Singular Value Decomposition @@ -439,10 +453,10 @@ def svd_inplace(A): U = Array() S = Array() Vt = Array() - safe_call(backend.get().af_svd_inplace(c_pointer(U.arr), c_pointer(S.arr), c_pointer(Vt.arr), - A.arr)) + safe_call(backend.get().af_svd_inplace(c_pointer(U.arr), c_pointer(S.arr), c_pointer(Vt.arr), A.arr)) return U, S, Vt + def is_lapack_available(): """ Function to check if the arrayfire library was built with lapack support. diff --git a/arrayfire/library.py b/arrayfire/library.py index 009a8e122..f4031cc5b 100644 --- a/arrayfire/library.py +++ b/arrayfire/library.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -13,8 +13,8 @@ import platform import ctypes as ct -import traceback import os +import traceback c_float_t = ct.c_float c_double_t = ct.c_double @@ -489,54 +489,53 @@ class VARIANCE(_Enum): SAMPLE = _Enum_Type(1) POPULATION = _Enum_Type(2) +from .util import to_str + +AF_VER_MAJOR = "3" +FORGE_VER_MAJOR = "1" _VER_MAJOR_PLACEHOLDER = "__VER_MAJOR__" + def _setup(): import platform platform_name = platform.system() try: - AF_PATH = os.environ['AF_PATH'] + AF_PATH = os.environ["AF_PATH"] except KeyError: AF_PATH = None - pass AF_SEARCH_PATH = AF_PATH try: - CUDA_PATH = os.environ['CUDA_PATH'] + CUDA_PATH = os.environ["CUDA_PATH"] except KeyError: - CUDA_PATH= None - pass + CUDA_PATH = None CUDA_FOUND = False - assert(len(platform_name) >= 3) - if platform_name == 'Windows' or platform_name[:3] == 'CYG': - - ## Windows specific setup - pre = '' - post = '.dll' + assert len(platform_name) >= 3 + if platform_name == "Windows" or platform_name[:3] == "CYG": + # Windows specific setup + pre = "" + post = ".dll" if platform_name == "Windows": - ''' - Supressing crashes caused by missing dlls - http://stackoverflow.com/questions/8347266/missing-dll-print-message-instead-of-launching-a-popup - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621.aspx - ''' + # Supressing crashes caused by missing dlls + # http://stackoverflow.com/questions/8347266/missing-dll-print-message-instead-of-launching-a-popup + # https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621.aspx ct.windll.kernel32.SetErrorMode(0x0001 | 0x0002) if AF_SEARCH_PATH is None: - AF_SEARCH_PATH="C:/Program Files/ArrayFire/v" + AF_VER_MAJOR +"/" + AF_SEARCH_PATH = "C:/Program Files/ArrayFire/v" + AF_VER_MAJOR + "/" if CUDA_PATH is not None: - CUDA_FOUND = os.path.isdir(CUDA_PATH + '/bin') and os.path.isdir(CUDA_PATH + '/nvvm/bin/') - - elif platform_name == 'Darwin': + CUDA_FOUND = os.path.isdir(CUDA_PATH + "/bin") and os.path.isdir(CUDA_PATH + "/nvvm/bin/") - ## OSX specific setup - pre = 'lib' - post = '.' + _VER_MAJOR_PLACEHOLDER + '.dylib' + elif platform_name == "Darwin": + # OSX specific setup + pre = "lib" + post = "." + _VER_MAJOR_PLACEHOLDER + ".dylib" if AF_SEARCH_PATH is None: if os.path.exists('/opt/arrayfire'): @@ -545,35 +544,36 @@ def _setup(): AF_SEARCH_PATH = '/usr/local/' if CUDA_PATH is None: - CUDA_PATH='/usr/local/cuda/' + CUDA_PATH = "/usr/local/cuda/" - CUDA_FOUND = os.path.isdir(CUDA_PATH + '/lib') and os.path.isdir(CUDA_PATH + '/nvvm/lib') + CUDA_FOUND = os.path.isdir(CUDA_PATH + "/lib") and os.path.isdir(CUDA_PATH + "/nvvm/lib") - elif platform_name == 'Linux': - pre = 'lib' - post = '.so.' + _VER_MAJOR_PLACEHOLDER + elif platform_name == "Linux": + pre = "lib" + post = ".so." + _VER_MAJOR_PLACEHOLDER if AF_SEARCH_PATH is None: - AF_SEARCH_PATH='/opt/arrayfire-' + AF_VER_MAJOR + '/' + AF_SEARCH_PATH = "/opt/arrayfire-" + AF_VER_MAJOR + "/" if CUDA_PATH is None: - CUDA_PATH='/usr/local/cuda/' + CUDA_PATH = "/usr/local/cuda/" - if platform.architecture()[0][:2] == '64': - CUDA_FOUND = os.path.isdir(CUDA_PATH + '/lib64') and os.path.isdir(CUDA_PATH + '/nvvm/lib64') + if platform.architecture()[0][:2] == "64": + CUDA_FOUND = os.path.isdir(CUDA_PATH + "/lib64") and os.path.isdir(CUDA_PATH + "/nvvm/lib64") else: - CUDA_FOUND = os.path.isdir(CUDA_PATH + '/lib') and os.path.isdir(CUDA_PATH + '/nvvm/lib') + CUDA_FOUND = os.path.isdir(CUDA_PATH + "/lib") and os.path.isdir(CUDA_PATH + "/nvvm/lib") else: - raise OSError(platform_name + ' not supported') + raise OSError(platform_name + " not supported") if AF_PATH is None: - os.environ['AF_PATH'] = AF_SEARCH_PATH + os.environ["AF_PATH"] = AF_SEARCH_PATH return pre, post, AF_SEARCH_PATH, CUDA_FOUND + class _clibrary(object): - def __libname(self, name, head='af', ver_major=AF_VER_MAJOR): + def __libname(self, name, head="af", ver_major=AF_VER_MAJOR): post = self.__post.replace(_VER_MAJOR_PLACEHOLDER, ver_major) libname = self.__pre + head + name + post if os.path.isdir(self.AF_PATH + '/lib64'): @@ -584,12 +584,11 @@ def __libname(self, name, head='af', ver_major=AF_VER_MAJOR): def set_unsafe(self, name): lib = self.__clibs[name] - if (lib is None): + if lib is None: raise RuntimeError("Backend not found") self.__name = name def __init__(self): - more_info_str = "Please look at https://github.com/arrayfire/arrayfire-python/wiki for more information." pre, post, AF_PATH, CUDA_FOUND = _setup() @@ -601,70 +600,71 @@ def __init__(self): self.__name = None - self.__clibs = {'cuda' : None, - 'opencl' : None, - 'cpu' : None, - 'unified' : None} - - self.__backend_map = {0 : 'unified', - 1 : 'cpu' , - 2 : 'cuda' , - 4 : 'opencl' } - - self.__backend_name_map = {'default' : 0, - 'unified' : 0, - 'cpu' : 1, - 'cuda' : 2, - 'opencl' : 4} + self.__clibs = { + "cuda": None, + "opencl": None, + "cpu": None, + "unified": None} + + self.__backend_map = { + 0: "unified", + 1: "cpu", + 2: "cuda", + 4: "opencl"} + + self.__backend_name_map = { + "default": 0, + "unified": 0, + "cpu": 1, + "cuda": 2, + "opencl": 4} # Try to pre-load forge library if it exists - libnames = self.__libname('forge', head='', ver_major=FORGE_VER_MAJOR) + libnames = self.__libname("forge", head="", ver_major=FORGE_VER_MAJOR) try: - VERBOSE_LOADS = os.environ['AF_VERBOSE_LOADS'] == '1' + VERBOSE_LOADS = os.environ["AF_VERBOSE_LOADS"] == "1" except KeyError: VERBOSE_LOADS = False - pass for libname in libnames: try: ct.cdll.LoadLibrary(libname) if VERBOSE_LOADS: - print('Loaded ' + libname) + print("Loaded " + libname) break except OSError: if VERBOSE_LOADS: traceback.print_exc() - print('Unable to load ' + libname) - pass + print("Unable to load " + libname) c_dim4 = c_dim_t*4 out = c_void_ptr_t(0) dims = c_dim4(10, 10, 1, 1) # Iterate in reverse order of preference - for name in ('cpu', 'opencl', 'cuda', ''): + for name in {"cpu", "opencl", "cuda", ""}: libnames = self.__libname(name) for libname in libnames: try: ct.cdll.LoadLibrary(libname) - __name = 'unified' if name == '' else name + __name = "unified" if name == "" else name clib = ct.CDLL(libname) self.__clibs[__name] = clib err = clib.af_randu(c_pointer(out), 4, c_pointer(dims), Dtype.f32.value) - if (err == ERR.NONE.value): - self.__name = __name - clib.af_release_array(out) - if VERBOSE_LOADS: - print('Loaded ' + libname) - break; + if err != ERR.NONE.value: + return + self.__name = __name + clib.af_release_array(out) + if VERBOSE_LOADS: + print("Loaded " + libname) + break except OSError: if VERBOSE_LOADS: traceback.print_exc() - print('Unable to load ' + libname) - pass + print("Unable to load " + libname) - if (self.__name is None): + if self.__name is None: raise RuntimeError("Could not load any ArrayFire libraries.\n" + more_info_str) def get_id(self, name): @@ -680,17 +680,19 @@ def name(self): return self.__name def is_unified(self): - return self.__name == 'unified' + return self.__name == "unified" def parse(self, res): lst = [] - for key,value in self.__backend_name_map.items(): - if (value & res): + for key, value in self.__backend_name_map.items(): + if value & res: lst.append(key) return tuple(lst) + backend = _clibrary() + def set_backend(name, unsafe=False): """ Set a specific backend by name @@ -703,14 +705,14 @@ def set_backend(name, unsafe=False): unsafe : optional: bool. Default: False. If False, does not switch backend if current backend is not unified backend. """ - if (backend.is_unified() == False and unsafe == False): + if not (backend.is_unified() or unsafe): raise RuntimeError("Can not change backend to %s after loading %s" % (name, backend.name())) - if (backend.is_unified()): + if backend.is_unified(): safe_call(backend.get().af_set_backend(backend.get_id(name))) - else: - backend.set_unsafe(name) - return + + backend.set_unsafe(name) + def get_backend(): """ @@ -718,6 +720,7 @@ def get_backend(): """ return backend.name() + def get_backend_id(A): """ Get backend name of an array @@ -736,6 +739,7 @@ def get_backend_id(A): safe_call(backend.get().af_get_backend_id(c_pointer(backend_id), A.arr)) return backend.get_name(backend_id.value) + def get_backend_count(): """ Get number of available backends @@ -750,6 +754,7 @@ def get_backend_count(): safe_call(backend.get().af_get_backend_count(c_pointer(count))) return count.value + def get_available_backends(): """ Get names of available backends @@ -764,6 +769,7 @@ def get_available_backends(): safe_call(backend.get().af_get_available_backends(c_pointer(available))) return backend.parse(int(available.value)) + def get_active_backend(): """ Get the current active backend @@ -775,6 +781,7 @@ def get_active_backend(): safe_call(backend.get().af_get_active_backend(c_pointer(backend_id))) return backend.get_name(backend_id.value) + def get_device_id(A): """ Get the device id of the array @@ -793,6 +800,7 @@ def get_device_id(A): safe_call(backend.get().af_get_device_id(c_pointer(device_id), A.arr)) return device_id + def get_size_of(dtype): """ Get the size of the type represented by arrayfire.Dtype @@ -801,4 +809,11 @@ def get_size_of(dtype): safe_call(backend.get().af_get_size_of(c_pointer(size), dtype.value)) return size.value -from .util import safe_call + +def safe_call(af_error): + if af_error == ERR.NONE.value: + return + err_str = c_char_ptr_t(0) + err_len = c_dim_t(0) + backend.get().af_get_last_error(c_pointer(err_str), c_pointer(err_len)) + raise RuntimeError(to_str(err_str)) diff --git a/arrayfire/ml.py b/arrayfire/ml.py index 7e0fc53de..5f612ca59 100644 --- a/arrayfire/ml.py +++ b/arrayfire/ml.py @@ -13,8 +13,9 @@ - Forward and backward convolution passes """ -from .library import * -from .array import * +from .array import Array +from .library import backend, safe_call, c_pointer, CONV_GRADIENT +from .util import dim4 def convolve2GradientNN(incoming_gradient, original_signal, original_kernel, convolved_output, stride = (1, 1), padding = (0, 0), dilation = (1, 1), gradType = CONV_GRADIENT.DEFAULT): """ diff --git a/arrayfire/opencl.py b/arrayfire/opencl.py index 266e1095a..5c21e5cb8 100644 --- a/arrayfire/opencl.py +++ b/arrayfire/opencl.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -13,30 +13,32 @@ This module provides interoperability with other OpenCL libraries. """ -from .util import * -from .library import (_Enum, _Enum_Type) +from .library import _Enum, _Enum_Type, c_int_t, c_pointer, c_void_ptr_t + class DEVICE_TYPE(_Enum): """ ArrayFire wrapper for CL_DEVICE_TYPE """ - CPU = _Enum_Type(1<<1) - GPU = _Enum_Type(1<<2) - ACC = _Enum_Type(1<<3) + CPU = _Enum_Type(1 << 1) + GPU = _Enum_Type(1 << 2) + ACC = _Enum_Type(1 << 3) UNKNOWN = _Enum_Type(-1) + class PLATFORM(_Enum): """ ArrayFire enum for common platforms """ - AMD = _Enum_Type(0) - APPLE = _Enum_Type(1) - INTEL = _Enum_Type(2) - NVIDIA = _Enum_Type(3) + AMD = _Enum_Type(0) + APPLE = _Enum_Type(1) + INTEL = _Enum_Type(2) + NVIDIA = _Enum_Type(3) BEIGNET = _Enum_Type(4) - POCL = _Enum_Type(5) + POCL = _Enum_Type(5) UNKNOWN = _Enum_Type(-1) + def get_context(retain=False): """ Get the current OpenCL context being used by ArrayFire. @@ -51,18 +53,19 @@ def get_context(retain=False): ----------- context : integer denoting the context id. """ - + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") context = c_void_ptr_t(0) safe_call(backend.get().afcl_get_context(c_pointer(context), retain)) return context.value + def get_queue(retain): """ Get the current OpenCL command queue being used by ArrayFire. @@ -77,18 +80,19 @@ def get_queue(retain): ----------- queue : integer denoting the queue id. """ - + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") queue = c_int_t(0) safe_call(backend.get().afcl_get_queue(c_pointer(queue), retain)) return queue.value + def get_device_id(): """ Get native (unsorted) OpenCL device ID @@ -99,18 +103,19 @@ def get_device_id(): idx : int. Specifies the `cl_device_id` of the device. """ - + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") idx = c_int_t(0) safe_call(backend.get().afcl_get_device_id(c_pointer(idx))) return idx.value + def set_device_id(idx): """ Set native (unsorted) OpenCL device ID @@ -121,17 +126,18 @@ def set_device_id(idx): idx : int. Specifies the `cl_device_id` of the device. """ - + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") safe_call(backend.get().afcl_set_device_id(idx)) return + def add_device_context(dev, ctx, que): """ Add a new device to arrayfire opencl device manager @@ -146,15 +152,17 @@ def add_device_context(dev, ctx, que): que : cl_command_queue """ + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") safe_call(backend.get().afcl_add_device_context(dev, ctx, que)) + def set_device_context(dev, ctx): """ Set a device as current active device @@ -167,15 +175,17 @@ def set_device_context(dev, ctx): ctx : cl_context """ + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") safe_call(backend.get().afcl_set_device_context(dev, ctx)) + def delete_device_context(dev, ctx): """ Delete a device @@ -188,54 +198,60 @@ def delete_device_context(dev, ctx): ctx : cl_context """ + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") safe_call(backend.get().afcl_delete_device_context(dev, ctx)) -_to_device_type = {DEVICE_TYPE.CPU.value : DEVICE_TYPE.CPU, - DEVICE_TYPE.GPU.value : DEVICE_TYPE.GPU, - DEVICE_TYPE.ACC.value : DEVICE_TYPE.ACC, - DEVICE_TYPE.UNKNOWN.value : DEVICE_TYPE.UNKNOWN} +_to_device_type = { + DEVICE_TYPE.CPU.value: DEVICE_TYPE.CPU, + DEVICE_TYPE.GPU.value: DEVICE_TYPE.GPU, + DEVICE_TYPE.ACC.value: DEVICE_TYPE.ACC, + DEVICE_TYPE.UNKNOWN.value: DEVICE_TYPE.UNKNOWN} -_to_platform = {PLATFORM.AMD.value : PLATFORM.AMD, - PLATFORM.APPLE.value : PLATFORM.APPLE, - PLATFORM.INTEL.value : PLATFORM.INTEL, - PLATFORM.NVIDIA.value : PLATFORM.NVIDIA, - PLATFORM.BEIGNET.value : PLATFORM.BEIGNET, - PLATFORM.POCL.value : PLATFORM.POCL, - PLATFORM.UNKNOWN.value : PLATFORM.UNKNOWN} +_to_platform = { + PLATFORM.AMD.value: PLATFORM.AMD, + PLATFORM.APPLE.value: PLATFORM.APPLE, + PLATFORM.INTEL.value: PLATFORM.INTEL, + PLATFORM.NVIDIA.value: PLATFORM.NVIDIA, + PLATFORM.BEIGNET.value: PLATFORM.BEIGNET, + PLATFORM.POCL.value: PLATFORM.POCL, + PLATFORM.UNKNOWN.value: PLATFORM.UNKNOWN} def get_device_type(): """ Get opencl device type """ + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") res = c_int_t(DEVICE_TYPE.UNKNOWN.value) safe_call(backend.get().afcl_get_device_type(c_pointer(res))) return _to_device_type[res.value] + def get_platform(): """ Get opencl platform """ + # FIXME: ctypes imported but unused import ctypes as ct from .util import safe_call as safe_call from .library import backend - if (backend.name() != "opencl"): + if backend.name() != "opencl": raise RuntimeError("Invalid backend loaded") res = c_int_t(PLATFORM.UNKNOWN.value) diff --git a/arrayfire/random.py b/arrayfire/random.py index 179833db8..622660342 100644 --- a/arrayfire/random.py +++ b/arrayfire/random.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,11 +11,12 @@ Random engine class and functions to generate random numbers. """ -from .library import * -from .array import * -import numbers +from .array import Array +from .library import backend, safe_call, RANDOM_ENGINE, Dtype, c_int_t, c_longlong_t, c_pointer, c_ulonglong_t, c_void_ptr_t +from .util import dim4 -class Random_Engine(object): + +class Random_Engine: """ Class to handle random number generator engines. @@ -40,10 +41,11 @@ class Random_Engine(object): - 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 = c_void_ptr_t(0) - safe_call(backend.get().af_create_random_engine(c_pointer(self.engine), engine_type.value, c_longlong_t(seed))) + def __init__(self, engine_type=RANDOM_ENGINE.PHILOX, seed=0, engine=None): + if engine is None: + self.engine = c_void_ptr_t(0) + safe_call(backend.get().af_create_random_engine( + c_pointer(self.engine), engine_type.value, c_longlong_t(seed))) else: self.engine = engine @@ -60,9 +62,8 @@ 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] + __to_random_engine_type = [ + RANDOM_ENGINE.PHILOX_4X32_10, RANDOM_ENGINE.THREEFRY_2X32_16, RANDOM_ENGINE.MERSENNE_GP11213] rty = c_int_t(RANDOM_ENGINE.PHILOX.value) safe_call(backend.get().af_random_engine_get_type(c_pointer(rty), self.engine)) return __to_random_engine_type[rty] @@ -81,6 +82,7 @@ def get_seed(self): safe_call(backend.get().af_random_engine_get_seed(c_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. @@ -125,6 +127,7 @@ def randu(d0, d1=None, d2=None, d3=None, dtype=Dtype.f32, engine=None): 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. @@ -159,7 +162,6 @@ def randn(d0, d1=None, d2=None, d3=None, dtype=Dtype.f32, engine=None): - 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) @@ -170,6 +172,7 @@ def randn(d0, d1=None, d2=None, d3=None, dtype=Dtype.f32, engine=None): return out + def set_seed(seed=0): """ Set the seed for the random number generator. @@ -181,6 +184,7 @@ def set_seed(seed=0): """ safe_call(backend.get().af_set_seed(c_ulonglong_t(seed))) + def get_seed(): """ Get the seed for the random number generator. @@ -194,6 +198,7 @@ def get_seed(): safe_call(backend.get().af_get_seed(c_pointer(seed))) return seed.value + def set_default_random_engine_type(engine_type): """ Set random engine type for default random engine. @@ -214,8 +219,10 @@ def set_default_random_engine_type(engine_type): This only affects randu and randn when a random engine is not specified. """ + # FIXME: not a class method. Remove self safe_call(backend.get().af_set_default_random_engine_type(c_pointer(self.engine), engine_type.value)) + def get_default_random_engine(): """ Get the default random engine diff --git a/arrayfire/signal.py b/arrayfire/signal.py index 35e0fba87..059b584a7 100644 --- a/arrayfire/signal.py +++ b/arrayfire/signal.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,21 +11,25 @@ Signal processing functions (fft, convolve, etc). """ -from .library import * -from .array import * +from .array import Array from .bcast import broadcast +from .library import backend, safe_call, CONV_DOMAIN, CONV_MODE, INTERP, PAD, c_dim_t, c_double_t, c_float_t, c_pointer, c_size_t +from .util import dim4, dim4_to_tuple + @broadcast def _scale_pos_axis0(x_curr, x_orig): x0 = x_orig[0, 0, 0, 0] dx = x_orig[1, 0, 0, 0] - x0 - return((x_curr - x0) / dx) + return (x_curr - x0) / dx + @broadcast def _scale_pos_axis1(y_curr, y_orig): y0 = y_orig[0, 0, 0, 0] dy = y_orig[0, 1, 0, 0] - y0 - return((y_curr - y0) / dy) + return (y_curr - y0) / dy + def approx1(signal, x, method=INTERP.LINEAR, off_grid=0.0, xp = None, output = None): """ @@ -39,7 +43,7 @@ def approx1(signal, x, method=INTERP.LINEAR, off_grid=0.0, xp = None, output = N Input signal array (signal = f(x)) x: af.Array - The x-coordinates of the interpolation points. The interpolation + The x-coordinates of the interpolation points. The interpolation function is queried at these set of points. method: optional: af.INTERP. default: af.INTERP.LINEAR. @@ -160,12 +164,12 @@ def approx2(signal, x, y, Input signal array (signal = f(x, y)) x : af.Array - The x-coordinates of the interpolation points. The interpolation + The x-coordinates of the interpolation points. The interpolation function is queried at these set of points. y : af.Array - The y-coordinates of the interpolation points. The interpolation + The y-coordinates of the interpolation points. The interpolation function is queried at these set of points. method: optional: af.INTERP. default: af.INTERP.LINEAR. @@ -232,6 +236,7 @@ def approx2(signal, x, y, return output + def approx2_uniform(signal, pos0, interp_dim0, idx_start0, idx_step0, pos1, interp_dim1, idx_start1, idx_step1, method=INTERP.LINEAR, off_grid=0.0, output = None): """ @@ -305,10 +310,10 @@ def approx2_uniform(signal, pos0, interp_dim0, idx_start0, idx_step0, pos1, inte pos0.arr, c_dim_t(interp_dim0), c_double_t(idx_start0), c_double_t(idx_step0), pos1.arr, c_dim_t(interp_dim1), c_double_t(idx_start1), c_double_t(idx_step1), method.value, c_float_t(off_grid))) - return output + def fft(signal, dim0 = None , scale = None): """ Fast Fourier Transform: 1D @@ -334,7 +339,6 @@ def fft(signal, dim0 = None , scale = None): A complex af.Array containing the full output of the fft. """ - if dim0 is None: dim0 = 0 @@ -345,7 +349,8 @@ def fft(signal, dim0 = None , scale = None): safe_call(backend.get().af_fft(c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0))) return output -def fft2(signal, dim0 = None, dim1 = None , scale = None): + +def fft2(signal, dim0=None, dim1=None, scale=None): """ Fast Fourier Transform: 2D @@ -384,11 +389,12 @@ def fft2(signal, dim0 = None, dim1 = None , scale = None): scale = 1.0 output = Array() - safe_call(backend.get().af_fft2(c_pointer(output.arr), signal.arr, c_double_t(scale), - c_dim_t(dim0), c_dim_t(dim1))) + safe_call(backend.get().af_fft2( + c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0), c_dim_t(dim1))) return output -def fft3(signal, dim0 = None, dim1 = None , dim2 = None, scale = None): + +def fft3(signal, dim0=None, dim1=None, dim2=None, scale=None): """ Fast Fourier Transform: 3D @@ -434,11 +440,12 @@ def fft3(signal, dim0 = None, dim1 = None , dim2 = None, scale = None): scale = 1.0 output = Array() - safe_call(backend.get().af_fft3(c_pointer(output.arr), signal.arr, c_double_t(scale), - c_dim_t(dim0), c_dim_t(dim1), c_dim_t(dim2))) + safe_call(backend.get().af_fft3( + c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0), c_dim_t(dim1), c_dim_t(dim2))) return output -def ifft(signal, dim0 = None , scale = None): + +def ifft(signal, dim0=None, scale=None): """ Inverse Fast Fourier Transform: 1D @@ -468,7 +475,6 @@ def ifft(signal, dim0 = None , scale = None): The output is always complex. """ - if dim0 is None: dim0 = signal.dims()[0] @@ -479,7 +485,8 @@ def ifft(signal, dim0 = None , scale = None): safe_call(backend.get().af_ifft(c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0))) return output -def ifft2(signal, dim0 = None, dim1 = None , scale = None): + +def ifft2(signal, dim0=None, dim1=None, scale=None): """ Inverse Fast Fourier Transform: 2D @@ -513,7 +520,6 @@ def ifft2(signal, dim0 = None, dim1 = None , scale = None): The output is always complex. """ - dims = signal.dims() if dim0 is None: @@ -526,11 +532,12 @@ def ifft2(signal, dim0 = None, dim1 = None , scale = None): scale = 1.0/float(dim0 * dim1) output = Array() - safe_call(backend.get().af_ifft2(c_pointer(output.arr), signal.arr, c_double_t(scale), - c_dim_t(dim0), c_dim_t(dim1))) + safe_call(backend.get().af_ifft2( + c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0), c_dim_t(dim1))) return output -def ifft3(signal, dim0 = None, dim1 = None , dim2 = None, scale = None): + +def ifft3(signal, dim0=None, dim1=None, dim2=None, scale=None): """ Inverse Fast Fourier Transform: 3D @@ -568,7 +575,6 @@ def ifft3(signal, dim0 = None, dim1 = None , dim2 = None, scale = None): The output is always complex. """ - dims = signal.dims() if dim0 is None: @@ -584,11 +590,12 @@ def ifft3(signal, dim0 = None, dim1 = None , dim2 = None, scale = None): scale = 1.0 / float(dim0 * dim1 * dim2) output = Array() - safe_call(backend.get().af_ifft3(c_pointer(output.arr), signal.arr, c_double_t(scale), - c_dim_t(dim0), c_dim_t(dim1), c_dim_t(dim2))) + safe_call(backend.get().af_ifft3( + c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0), c_dim_t(dim1), c_dim_t(dim2))) return output -def fft_inplace(signal, scale = None): + +def fft_inplace(signal, scale=None): """ In-place Fast Fourier Transform: 1D @@ -603,13 +610,13 @@ def fft_inplace(signal, scale = None): - If None, scale is set to 1. """ - if scale is None: scale = 1.0 safe_call(backend.get().af_fft_inplace(signal.arr, c_double_t(scale))) -def fft2_inplace(signal, scale = None): + +def fft2_inplace(signal, scale=None): """ In-place Fast Fourier Transform: 2D @@ -624,13 +631,13 @@ def fft2_inplace(signal, scale = None): - If None, scale is set to 1. """ - if scale is None: scale = 1.0 safe_call(backend.get().af_fft2_inplace(signal.arr, c_double_t(scale))) -def fft3_inplace(signal, scale = None): + +def fft3_inplace(signal, scale=None): """ In-place Fast Fourier Transform: 3D @@ -644,14 +651,15 @@ def fft3_inplace(signal, scale = None): - Specifies the scaling factor. - If None, scale is set to 1. """ - if scale is None: scale = 1.0 + # FIXME: output is assigned, but not used in function output = Array() safe_call(backend.get().af_fft3_inplace(signal.arr, c_double_t(scale))) -def ifft_inplace(signal, scale = None): + +def ifft_inplace(signal, scale=None): """ Inverse In-place Fast Fourier Transform: 1D @@ -665,14 +673,14 @@ def ifft_inplace(signal, scale = None): - Specifies the scaling factor. - If None, scale is set to 1.0 / (signal.dims()[0]) """ - if scale is None: dim0 = signal.dims()[0] scale = 1.0/float(dim0) safe_call(backend.get().af_ifft_inplace(signal.arr, c_double_t(scale))) -def ifft2_inplace(signal, scale = None): + +def ifft2_inplace(signal, scale=None): """ Inverse In-place Fast Fourier Transform: 2D @@ -686,7 +694,6 @@ def ifft2_inplace(signal, scale = None): - Specifies the scaling factor. - If None, scale is set to 1.0 / (signal.dims()[0] * signal.dims()[1]) """ - dims = signal.dims() if scale is None: @@ -696,7 +703,8 @@ def ifft2_inplace(signal, scale = None): safe_call(backend.get().af_ifft2_inplace(signal.arr, c_double_t(scale))) -def ifft3_inplace(signal, scale = None): + +def ifft3_inplace(signal, scale=None): """ Inverse In-place Fast Fourier Transform: 3D @@ -710,7 +718,6 @@ def ifft3_inplace(signal, scale = None): - Specifies the scaling factor. - If None, scale is set to 1.0 / (signal.dims()[0] * signal.dims()[1] * signal.dims()[2]). """ - dims = signal.dims() if scale is None: @@ -721,7 +728,8 @@ def ifft3_inplace(signal, scale = None): safe_call(backend.get().af_ifft3_inplace(signal.arr, c_double_t(scale))) -def fft_r2c(signal, dim0 = None , scale = None): + +def fft_r2c(signal, dim0=None, scale=None): """ Real to Complex Fast Fourier Transform: 1D @@ -746,7 +754,6 @@ def fft_r2c(signal, dim0 = None , scale = None): A complex af.Array containing the non-redundant parts of the full FFT. """ - if dim0 is None: dim0 = 0 @@ -757,7 +764,8 @@ def fft_r2c(signal, dim0 = None , scale = None): safe_call(backend.get().af_fft_r2c(c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0))) return output -def fft2_r2c(signal, dim0 = None, dim1 = None , scale = None): + +def fft2_r2c(signal, dim0=None, dim1=None, scale=None): """ Real to Complex Fast Fourier Transform: 2D @@ -796,11 +804,12 @@ def fft2_r2c(signal, dim0 = None, dim1 = None , scale = None): scale = 1.0 output = Array() - safe_call(backend.get().af_fft2_r2c(c_pointer(output.arr), signal.arr, c_double_t(scale), - c_dim_t(dim0), c_dim_t(dim1))) + safe_call(backend.get().af_fft2_r2c( + c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0), c_dim_t(dim1))) return output -def fft3_r2c(signal, dim0 = None, dim1 = None , dim2 = None, scale = None): + +def fft3_r2c(signal, dim0=None, dim1=None, dim2=None, scale=None): """ Real to Complex Fast Fourier Transform: 3D @@ -846,14 +855,16 @@ def fft3_r2c(signal, dim0 = None, dim1 = None , dim2 = None, scale = None): scale = 1.0 output = Array() - safe_call(backend.get().af_fft3_r2c(c_pointer(output.arr), signal.arr, c_double_t(scale), - c_dim_t(dim0), c_dim_t(dim1), c_dim_t(dim2))) + safe_call(backend.get().af_fft3_r2c( + c_pointer(output.arr), signal.arr, c_double_t(scale), c_dim_t(dim0), c_dim_t(dim1), c_dim_t(dim2))) return output + def _get_c2r_dim(dim, is_odd): - return 2 *(dim - 1) + int(is_odd) + return 2 * (dim - 1) + int(is_odd) -def fft_c2r(signal, is_odd = False, scale = None): + +def fft_c2r(signal, is_odd=False, scale=None): """ Real to Complex Fast Fourier Transform: 1D @@ -877,8 +888,6 @@ def fft_c2r(signal, is_odd = False, scale = None): A real af.Array containing the full output of the fft. """ - - if scale is None: dim0 = _get_c2r_dim(signal.dims()[0], is_odd) scale = 1.0/float(dim0) @@ -887,7 +896,8 @@ def fft_c2r(signal, is_odd = False, scale = None): safe_call(backend.get().af_fft_c2r(c_pointer(output.arr), signal.arr, c_double_t(scale), is_odd)) return output -def fft2_c2r(signal, is_odd = False, scale = None): + +def fft2_c2r(signal, is_odd=False, scale=None): """ Real to Complex Fast Fourier Transform: 2D @@ -922,7 +932,8 @@ def fft2_c2r(signal, is_odd = False, scale = None): safe_call(backend.get().af_fft2_c2r(c_pointer(output.arr), signal.arr, c_double_t(scale), is_odd)) return output -def fft3_c2r(signal, is_odd = False, scale = None): + +def fft3_c2r(signal, is_odd=False, scale=None): """ Real to Complex Fast Fourier Transform: 3D @@ -959,8 +970,7 @@ def fft3_c2r(signal, is_odd = False, scale = None): return output -def dft(signal, odims=(None, None, None, None), scale = None): - +def dft(signal, odims=(None, None, None, None), scale=None): """ Non batched Fourier transform. @@ -985,20 +995,21 @@ def dft(signal, odims=(None, None, None, None), scale = None): - A complex array that is the ouput of n-dimensional fourier transform. """ - + # FIXME: odims4 is assigned, but not used in function odims4 = dim4_to_tuple(odims, default=None) dims = signal.dims() ndims = len(dims) - if (ndims == 1): + if ndims == 1: return fft(signal, dims[0], scale) - elif (ndims == 2): + if ndims == 2: return fft2(signal, dims[0], dims[1], scale) - else: - return fft3(signal, dims[0], dims[1], dims[2], scale) -def idft(signal, scale = None, odims=(None, None, None, None)): + return fft3(signal, dims[0], dims[1], dims[2], scale) + + +def idft(signal, scale=None, odims=(None, None, None, None)): """ Non batched Inverse Fourier transform. @@ -1028,20 +1039,21 @@ def idft(signal, scale = None, odims=(None, None, None, None)): the output is always complex. """ - + # FIXME: odims4 is assigned, but not used in function odims4 = dim4_to_tuple(odims, default=None) dims = signal.dims() ndims = len(dims) - if (ndims == 1): + if ndims == 1: return ifft(signal, scale, dims[0]) - elif (ndims == 2): + if ndims == 2: return ifft2(signal, scale, dims[0], dims[1]) - else: - return ifft3(signal, scale, dims[0], dims[1], dims[2]) -def convolve1(signal, kernel, conv_mode = CONV_MODE.DEFAULT, conv_domain = CONV_DOMAIN.AUTO): + return ifft3(signal, scale, dims[0], dims[1], dims[2]) + + +def convolve1(signal, kernel, conv_mode=CONV_MODE.DEFAULT, conv_domain=CONV_DOMAIN.AUTO): """ Convolution: 1D @@ -1086,11 +1098,12 @@ def convolve1(signal, kernel, conv_mode = CONV_MODE.DEFAULT, conv_domain = CONV_ """ output = Array() - safe_call(backend.get().af_convolve1(c_pointer(output.arr), signal.arr, kernel.arr, - conv_mode.value, conv_domain.value)) + safe_call(backend.get().af_convolve1( + c_pointer(output.arr), signal.arr, kernel.arr, conv_mode.value, conv_domain.value)) return output -def convolve2(signal, kernel, conv_mode = CONV_MODE.DEFAULT, conv_domain = CONV_DOMAIN.AUTO): + +def convolve2(signal, kernel, conv_mode=CONV_MODE.DEFAULT, conv_domain=CONV_DOMAIN.AUTO): """ Convolution: 2D @@ -1134,8 +1147,8 @@ def convolve2(signal, kernel, conv_mode = CONV_MODE.DEFAULT, conv_domain = CONV_ """ output = Array() - safe_call(backend.get().af_convolve2(c_pointer(output.arr), signal.arr, kernel.arr, - conv_mode.value, conv_domain.value)) + safe_call(backend.get().af_convolve2( + c_pointer(output.arr), signal.arr, kernel.arr, conv_mode.value, conv_domain.value)) return output def convolve2NN(signal, kernel, stride = (1, 1), padding = (0, 0), dilation = (1, 1)): @@ -1214,12 +1227,12 @@ def convolve2_separable(col_kernel, row_kernel, signal, conv_mode = CONV_MODE.DE - Output of 2D sepearable convolution. """ output = Array() - safe_call(backend.get().af_convolve2_sep(c_pointer(output.arr), - col_kernel.arr, row_kernel.arr,signal.arr, - conv_mode.value)) + safe_call(backend.get().af_convolve2_sep( + c_pointer(output.arr), col_kernel.arr, row_kernel.arr, signal.arr, conv_mode.value)) return output -def convolve3(signal, kernel, conv_mode = CONV_MODE.DEFAULT, conv_domain = CONV_DOMAIN.AUTO): + +def convolve3(signal, kernel, conv_mode=CONV_MODE.DEFAULT, conv_domain=CONV_DOMAIN.AUTO): """ Convolution: 3D @@ -1261,11 +1274,12 @@ def convolve3(signal, kernel, conv_mode = CONV_MODE.DEFAULT, conv_domain = CONV_ """ output = Array() - safe_call(backend.get().af_convolve3(c_pointer(output.arr), signal.arr, kernel.arr, - conv_mode.value, conv_domain.value)) + safe_call(backend.get().af_convolve3( + c_pointer(output.arr), signal.arr, kernel.arr, conv_mode.value, conv_domain.value)) return output -def convolve(signal, kernel, conv_mode = CONV_MODE.DEFAULT, conv_domain = CONV_DOMAIN.AUTO): + +def convolve(signal, kernel, conv_mode=CONV_MODE.DEFAULT, conv_domain=CONV_DOMAIN.AUTO): """ Non batched Convolution. @@ -1296,18 +1310,18 @@ def convolve(signal, kernel, conv_mode = CONV_MODE.DEFAULT, conv_domain = CONV_D output: af.Array - Output of n-dimensional convolution. """ - dims = signal.dims() ndims = len(dims) - if (ndims == 1): + if ndims == 1: return convolve1(signal, kernel, conv_mode, conv_domain) - elif (ndims == 2): + if ndims == 2: return convolve2(signal, kernel, conv_mode, conv_domain) - else: - return convolve3(signal, kernel, conv_mode, conv_domain) -def fft_convolve1(signal, kernel, conv_mode = CONV_MODE.DEFAULT): + return convolve3(signal, kernel, conv_mode, conv_domain) + + +def fft_convolve1(signal, kernel, conv_mode=CONV_MODE.DEFAULT): """ FFT based Convolution: 1D @@ -1348,11 +1362,11 @@ def fft_convolve1(signal, kernel, conv_mode = CONV_MODE.DEFAULT): """ output = Array() - safe_call(backend.get().af_fft_convolve1(c_pointer(output.arr), signal.arr, kernel.arr, - conv_mode.value)) + safe_call(backend.get().af_fft_convolve1(c_pointer(output.arr), signal.arr, kernel.arr, conv_mode.value)) return output -def fft_convolve2(signal, kernel, conv_mode = CONV_MODE.DEFAULT): + +def fft_convolve2(signal, kernel, conv_mode=CONV_MODE.DEFAULT): """ FFT based Convolution: 2D @@ -1392,11 +1406,11 @@ def fft_convolve2(signal, kernel, conv_mode = CONV_MODE.DEFAULT): """ output = Array() - safe_call(backend.get().af_fft_convolve2(c_pointer(output.arr), signal.arr, kernel.arr, - conv_mode.value)) + safe_call(backend.get().af_fft_convolve2(c_pointer(output.arr), signal.arr, kernel.arr, conv_mode.value)) return output -def fft_convolve3(signal, kernel, conv_mode = CONV_MODE.DEFAULT): + +def fft_convolve3(signal, kernel, conv_mode=CONV_MODE.DEFAULT): """ FFT based Convolution: 3D @@ -1434,11 +1448,11 @@ def fft_convolve3(signal, kernel, conv_mode = CONV_MODE.DEFAULT): """ output = Array() - safe_call(backend.get().af_fft_convolve3(c_pointer(output.arr), signal.arr, kernel.arr, - conv_mode.value)) + safe_call(backend.get().af_fft_convolve3(c_pointer(output.arr), signal.arr, kernel.arr, conv_mode.value)) return output -def fft_convolve(signal, kernel, conv_mode = CONV_MODE.DEFAULT): + +def fft_convolve(signal, kernel, conv_mode=CONV_MODE.DEFAULT): """ Non batched FFT Convolution. @@ -1472,12 +1486,13 @@ def fft_convolve(signal, kernel, conv_mode = CONV_MODE.DEFAULT): dims = signal.dims() ndims = len(dims) - if (ndims == 1): + if ndims == 1: return fft_convolve1(signal, kernel, conv_mode) - elif (ndims == 2): + if ndims == 2: return fft_convolve2(signal, kernel, conv_mode) - else: - return fft_convolve3(signal, kernel, conv_mode) + + return fft_convolve3(signal, kernel, conv_mode) + def fir(B, X): """ @@ -1503,6 +1518,7 @@ def fir(B, X): safe_call(backend.get().af_fir(c_pointer(Y.arr), B.arr, X.arr)) return Y + def iir(B, A, X): """ Infinite impulse response filter. @@ -1530,7 +1546,8 @@ def iir(B, A, X): safe_call(backend.get().af_iir(c_pointer(Y.arr), B.arr, A.arr, X.arr)) return Y -def medfilt(signal, w0 = 3, w1 = 3, edge_pad = PAD.ZERO): + +def medfilt(signal, w0=3, w1=3, edge_pad=PAD.ZERO): """ Apply median filter for the signal. @@ -1557,12 +1574,11 @@ def medfilt(signal, w0 = 3, w1 = 3, edge_pad = PAD.ZERO): """ output = Array() - safe_call(backend.get().af_medfilt(c_pointer(output.arr), - signal.arr, c_dim_t(w0), - c_dim_t(w1), edge_pad.value)) + safe_call(backend.get().af_medfilt(c_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): + +def medfilt1(signal, length=3, edge_pad=PAD.ZERO): """ Apply median filter for the signal. @@ -1589,7 +1605,8 @@ def medfilt1(signal, length = 3, edge_pad = PAD.ZERO): safe_call(backend.get().af_medfilt1(c_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): + +def medfilt2(signal, w0=3, w1=3, edge_pad=PAD.ZERO): """ Apply median filter for the signal. @@ -1616,11 +1633,10 @@ def medfilt2(signal, w0 = 3, w1 = 3, edge_pad = PAD.ZERO): """ output = Array() - safe_call(backend.get().af_medfilt2(c_pointer(output.arr), - signal.arr, c_dim_t(w0), - c_dim_t(w1), edge_pad.value)) + safe_call(backend.get().af_medfilt2(c_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. diff --git a/arrayfire/sparse.py b/arrayfire/sparse.py index 91b8f7a23..4305988cf 100644 --- a/arrayfire/sparse.py +++ b/arrayfire/sparse.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,18 +11,18 @@ Functions to create and manipulate sparse matrices. """ -from .library import * -from .array import * -import numbers +from .array import Array +from .library import backend, safe_call, STORAGE, Dtype, c_dim_t, c_int_t, c_pointer from .interop import to_array -__to_sparse_enum = [STORAGE.DENSE, - STORAGE.CSR, - STORAGE.CSC, - STORAGE.COO] +__to_sparse_enum = [ + STORAGE.DENSE, + STORAGE.CSR, + STORAGE.CSC, + STORAGE.COO] -def create_sparse(values, row_idx, col_idx, nrows, ncols, storage = STORAGE.CSR): +def create_sparse(values, row_idx, col_idx, nrows, ncols, storage=STORAGE.CSR): """ Create a sparse matrix from it's constituent parts. @@ -52,15 +52,16 @@ def create_sparse(values, row_idx, col_idx, nrows, ncols, storage = STORAGE.CSR) A sparse matrix. """ - assert(isinstance(values, Array)) - assert(isinstance(row_idx, Array)) - assert(isinstance(col_idx, Array)) + assert isinstance(values, Array) + assert isinstance(row_idx, Array) + assert isinstance(col_idx, Array) out = Array() - safe_call(backend.get().af_create_sparse_array(c_pointer(out.arr), c_dim_t(nrows), c_dim_t(ncols), - values.arr, row_idx.arr, col_idx.arr, storage.value)) + safe_call(backend.get().af_create_sparse_array( + c_pointer(out.arr), c_dim_t(nrows), c_dim_t(ncols), values.arr, row_idx.arr, col_idx.arr, storage.value)) return out -def create_sparse_from_host(values, row_idx, col_idx, nrows, ncols, storage = STORAGE.CSR): + +def create_sparse_from_host(values, row_idx, col_idx, nrows, ncols, storage=STORAGE.CSR): """ Create a sparse matrix from it's constituent parts. @@ -90,12 +91,12 @@ def create_sparse_from_host(values, row_idx, col_idx, nrows, ncols, storage = ST A sparse matrix. """ - return create_sparse(to_array(values), - to_array(row_idx).as_type(Dtype.s32), - to_array(col_idx).as_type(Dtype.s32), - nrows, ncols, storage) + return create_sparse( + to_array(values), to_array(row_idx).as_type(Dtype.s32), to_array(col_idx).as_type(Dtype.s32), nrows, ncols, + storage) + -def create_sparse_from_dense(dense, storage = STORAGE.CSR): +def create_sparse_from_dense(dense, storage=STORAGE.CSR): """ Create a sparse matrix from a dense matrix. @@ -113,11 +114,12 @@ def create_sparse_from_dense(dense, storage = STORAGE.CSR): A sparse matrix. """ - assert(isinstance(dense, Array)) + assert isinstance(dense, Array) out = Array() safe_call(backend.get().af_create_sparse_array_from_dense(c_pointer(out.arr), dense.arr, storage.value)) return out + def convert_sparse_to_dense(sparse): """ Create a dense matrix from a sparse matrix. @@ -137,6 +139,7 @@ def convert_sparse_to_dense(sparse): safe_call(backend.get().af_sparse_to_dense(c_pointer(out.arr), sparse.arr)) return out + def sparse_get_info(sparse): """ Get the constituent arrays and storage info from a sparse matrix. @@ -159,11 +162,11 @@ def sparse_get_info(sparse): row_idx = Array() col_idx = Array() stype = c_int_t(0) - safe_call(backend.get().af_sparse_get_info(c_pointer(values.arr), c_pointer(row_idx.arr), - c_pointer(col_idx.arr), c_pointer(stype), - sparse.arr)) + safe_call(backend.get().af_sparse_get_info( + c_pointer(values.arr), c_pointer(row_idx.arr), c_pointer(col_idx.arr), c_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. @@ -183,6 +186,7 @@ def sparse_get_values(sparse): safe_call(backend.get().af_sparse_get_values(c_pointer(values.arr), sparse.arr)) return values + def sparse_get_row_idx(sparse): """ Get the row indices from sparse matrix. @@ -202,6 +206,7 @@ def sparse_get_row_idx(sparse): safe_call(backend.get().af_sparse_get_row_idx(c_pointer(row_idx.arr), sparse.arr)) return row_idx + def sparse_get_col_idx(sparse): """ Get the column indices from sparse matrix. @@ -221,6 +226,7 @@ def sparse_get_col_idx(sparse): safe_call(backend.get().af_sparse_get_col_idx(c_pointer(col_idx.arr), sparse.arr)) return col_idx + def sparse_get_nnz(sparse): """ Get the column indices from sparse matrix. @@ -240,6 +246,7 @@ def sparse_get_nnz(sparse): safe_call(backend.get().af_sparse_get_nnz(c_pointer(nnz), sparse.arr)) return nnz.value + def sparse_get_storage(sparse): """ Get the column indices from sparse matrix. @@ -259,6 +266,7 @@ def sparse_get_storage(sparse): safe_call(backend.get().af_sparse_get_storage(c_pointer(storage), sparse.arr)) return __to_sparse_enum[storage.value] + def convert_sparse(sparse, storage): """ Convert sparse matrix from one format to another. diff --git a/arrayfire/statistics.py b/arrayfire/statistics.py index f47f3a48d..bc51fcbad 100644 --- a/arrayfire/statistics.py +++ b/arrayfire/statistics.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,8 +11,9 @@ Statistical algorithms (mean, var, stdev, etc). """ -from .library import * -from .array import * +from .array import Array +from .library import TOPK, VARIANCE, c_double_t, c_int_t, c_pointer, backend, safe_call + def mean(a, weights=None, dim=None): """ @@ -45,19 +46,20 @@ def mean(a, weights=None, dim=None): safe_call(backend.get().af_mean_weighted(c_pointer(out.arr), a.arr, weights.arr, c_int_t(dim))) return out + + real = c_double_t(0) + imag = c_double_t(0) + + if weights is None: + safe_call(backend.get().af_mean_all(c_pointer(real), c_pointer(imag), a.arr)) else: - real = c_double_t(0) - imag = c_double_t(0) + safe_call(backend.get().af_mean_all_weighted(c_pointer(real), c_pointer(imag), a.arr, weights.arr)) - if weights is None: - safe_call(backend.get().af_mean_all(c_pointer(real), c_pointer(imag), a.arr)) - else: - safe_call(backend.get().af_mean_all_weighted(c_pointer(real), c_pointer(imag), a.arr, weights.arr)) + real = real.value + imag = imag.value - real = real.value - imag = imag.value + return real if imag == 0 else real + imag * 1j - return real if imag == 0 else real + imag * 1j def var(a, isbiased=False, weights=None, dim=None): """ @@ -94,19 +96,20 @@ def var(a, isbiased=False, weights=None, dim=None): safe_call(backend.get().af_var_weighted(c_pointer(out.arr), a.arr, weights.arr, c_int_t(dim))) return out + + real = c_double_t(0) + imag = c_double_t(0) + + if weights is None: + safe_call(backend.get().af_var_all(c_pointer(real), c_pointer(imag), a.arr, isbiased)) else: - real = c_double_t(0) - imag = c_double_t(0) + safe_call(backend.get().af_var_all_weighted(c_pointer(real), c_pointer(imag), a.arr, weights.arr)) - if weights is None: - safe_call(backend.get().af_var_all(c_pointer(real), c_pointer(imag), a.arr, isbiased)) - else: - safe_call(backend.get().af_var_all_weighted(c_pointer(real), c_pointer(imag), a.arr, weights.arr)) + real = real.value + imag = imag.value - real = real.value - imag = imag.value + return real if imag == 0 else real + imag * 1j - return real if imag == 0 else real + imag * 1j def meanvar(a, weights=None, bias=VARIANCE.DEFAULT, dim=-1): """ @@ -173,13 +176,14 @@ def stdev(a, dim=None): out = Array() safe_call(backend.get().af_stdev(c_pointer(out.arr), a.arr, c_int_t(dim))) return out - else: - real = c_double_t(0) - imag = c_double_t(0) - safe_call(backend.get().af_stdev_all(c_pointer(real), c_pointer(imag), a.arr)) - real = real.value - imag = imag.value - return real if imag == 0 else real + imag * 1j + + real = c_double_t(0) + imag = c_double_t(0) + safe_call(backend.get().af_stdev_all(c_pointer(real), c_pointer(imag), a.arr)) + real = real.value + imag = imag.value + return real if imag == 0 else real + imag * 1j + def cov(a, isbiased=False, dim=None): """ @@ -206,13 +210,14 @@ def cov(a, isbiased=False, dim=None): out = Array() safe_call(backend.get().af_cov(c_pointer(out.arr), a.arr, isbiased, c_int_t(dim))) return out - else: - real = c_double_t(0) - imag = c_double_t(0) - safe_call(backend.get().af_cov_all(c_pointer(real), c_pointer(imag), a.arr, isbiased)) - real = real.value - imag = imag.value - return real if imag == 0 else real + imag * 1j + + real = c_double_t(0) + imag = c_double_t(0) + safe_call(backend.get().af_cov_all(c_pointer(real), c_pointer(imag), a.arr, isbiased)) + real = real.value + imag = imag.value + return real if imag == 0 else real + imag * 1j + def median(a, dim=None): """ @@ -236,13 +241,14 @@ def median(a, dim=None): out = Array() safe_call(backend.get().af_median(c_pointer(out.arr), a.arr, c_int_t(dim))) return out - else: - real = c_double_t(0) - imag = c_double_t(0) - safe_call(backend.get().af_median_all(c_pointer(real), c_pointer(imag), a.arr)) - real = real.value - imag = imag.value - return real if imag == 0 else real + imag * 1j + + real = c_double_t(0) + imag = c_double_t(0) + safe_call(backend.get().af_median_all(c_pointer(real), c_pointer(imag), a.arr)) + real = real.value + imag = imag.value + return real if imag == 0 else real + imag * 1j + def corrcoef(x, y): """ @@ -268,6 +274,7 @@ def corrcoef(x, y): imag = imag.value return real if imag == 0 else real + imag * 1j + def topk(data, k, dim=0, order=TOPK.DEFAULT): """ Return top k elements along a single dimension. @@ -297,10 +304,10 @@ def topk(data, k, dim=0, order=TOPK.DEFAULT): indices: af.Array Corresponding index array to top k elements. """ - values = Array() indices = Array() - safe_call(backend.get().af_topk(c_pointer(values.arr), c_pointer(indices.arr), data.arr, k, c_int_t(dim), order.value)) + safe_call( + backend.get().af_topk(c_pointer(values.arr), c_pointer(indices.arr), data.arr, k, c_int_t(dim), order.value)) - return values,indices + return values, indices diff --git a/arrayfire/timer.py b/arrayfire/timer.py index d523fcd93..537aed09f 100644 --- a/arrayfire/timer.py +++ b/arrayfire/timer.py @@ -1,19 +1,21 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, 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 time arrayfire. """ -from .library import * -from .device import (sync, eval) -from time import time import math +from time import time + +from .device import eval, sync + def timeit(af_func, *args): """ @@ -31,25 +33,24 @@ def timeit(af_func, *args): t : Time in seconds """ - sample_trials = 3 sample_time = 1E20 - for i in range(sample_trials): + for _ in range(sample_trials): start = time() res = af_func(*args) eval(res) sync() sample_time = min(sample_time, time() - start) - if (sample_time >= 0.5): + if sample_time >= 0.5: return sample_time num_iters = max(math.ceil(1.0 / sample_time), 3.0) start = time() - for i in range(int(num_iters)): + for _ in range(int(num_iters)): res = af_func(*args) eval(res) sync() diff --git a/arrayfire/util.py b/arrayfire/util.py index 44af6000d..bf01639a0 100644 --- a/arrayfire/util.py +++ b/arrayfire/util.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,32 +11,41 @@ Utility functions to help with Array metadata. """ -from .library import * import numbers +from .library import ( + Dtype, c_char_t, c_dim_t, c_double_t, c_float_t, c_int_t, c_longlong_t, c_short_t, c_uchar_t, c_uint_t, + c_ulonglong_t, c_ushort_t) + + def dim4(d0=1, d1=1, d2=1, d3=1): c_dim4 = c_dim_t * 4 out = c_dim4(1, 1, 1, 1) for i, dim in enumerate((d0, d1, d2, d3)): - if (dim is not None): out[i] = c_dim_t(dim) + if dim is None: + continue + out[i] = c_dim_t(dim) return out + def _is_number(a): return isinstance(a, numbers.Number) + def number_dtype(a): if isinstance(a, bool): return Dtype.b8 if isinstance(a, int): return Dtype.s64 - elif isinstance(a, float): + if isinstance(a, float): return Dtype.f64 - elif isinstance(a, complex): + if isinstance(a, complex): return Dtype.c64 - else: - return to_dtype[a.dtype.char] + + return to_dtype[a.dtype.char] + def implicit_dtype(number, a_dtype): n_dtype = number_dtype(number) @@ -47,19 +56,20 @@ def implicit_dtype(number, a_dtype): c32v = Dtype.c32.value c64v = Dtype.c64.value - if n_value == f64v and (a_dtype == f32v or a_dtype == c32v): + if n_value == f64v and a_dtype in {f32v, c32v}: return Dtype.f32 - if n_value == c64v and (a_dtype == f32v or a_dtype == c32v): + if n_value == c64v and a_dtype in {f32v, c32v}: return Dtype.c32 return n_dtype + def dim4_to_tuple(dims, default=1): - assert(isinstance(dims, tuple)) + assert isinstance(dims, tuple) - if (default is not None): - assert(_is_number(default)) + if default is not None: + assert _is_number(default) out = [default]*4 @@ -68,15 +78,10 @@ def dim4_to_tuple(dims, default=1): return tuple(out) + def to_str(c_str): return str(c_str.value.decode('utf-8')) -def safe_call(af_error): - if (af_error != ERR.NONE.value): - err_str = c_char_ptr_t(0) - err_len = c_dim_t(0) - backend.get().af_get_last_error(c_pointer(err_str), c_pointer(err_len)) - raise RuntimeError(to_str(err_str)) def get_version(): """ @@ -88,6 +93,7 @@ def get_version(): safe_call(backend.get().af_get_version(c_pointer(major), c_pointer(minor), c_pointer(patch))) return major.value,minor.value,patch.value + def get_reversion(): """ Function to get the revision hash of the library. diff --git a/arrayfire/vision.py b/arrayfire/vision.py index 49cdc8fd8..0399fb696 100644 --- a/arrayfire/vision.py +++ b/arrayfire/vision.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -11,9 +11,10 @@ Computer vision functions (FAST, ORB, etc) """ -from .library import * -from .array import * -from .features import * +from .array import Array +from .library import backend, safe_call, HOMOGRAPHY, MATCH, Dtype, c_dim_t, c_float_t, c_int_t, c_pointer, c_uint_t +from .features import Features + def fast(image, threshold=20.0, arc_length=9, non_max=True, feature_ratio=0.05, edge=3): """ @@ -47,11 +48,12 @@ def fast(image, threshold=20.0, arc_length=9, non_max=True, feature_ratio=0.05, """ out = Features() - safe_call(backend.get().af_fast(c_pointer(out.feat), - image.arr, c_float_t(threshold), c_uint_t(arc_length), non_max, - c_float_t(feature_ratio), c_uint_t(edge))) + safe_call(backend.get().af_fast( + c_pointer(out.feat), image.arr, c_float_t(threshold), c_uint_t(arc_length), non_max, + c_float_t(feature_ratio), c_uint_t(edge))) return out + def harris(image, max_corners=500, min_response=1E5, sigma=1.0, block_size=0, k_thr=0.04): """ Harris corner detector. @@ -91,12 +93,13 @@ def harris(image, max_corners=500, min_response=1E5, sigma=1.0, block_size=0, k_ """ out = Features() - safe_call(backend.get().af_harris(c_pointer(out.feat), - image.arr, c_uint_t(max_corners), c_float_t(min_response), - c_float_t(sigma), c_uint_t(block_size), c_float_t(k_thr))) + safe_call(backend.get().af_harris( + c_pointer(out.feat), image.arr, c_uint_t(max_corners), c_float_t(min_response), c_float_t(sigma), + c_uint_t(block_size), c_float_t(k_thr))) return out -def orb(image, threshold=20.0, max_features=400, scale = 1.5, num_levels = 4, blur_image = False): + +def orb(image, threshold=20.0, max_features=400, scale=1.5, num_levels=4, blur_image=False): """ ORB Feature descriptor. @@ -131,12 +134,13 @@ def orb(image, threshold=20.0, max_features=400, scale = 1.5, num_levels = 4, bl """ feat = Features() desc = Array() - safe_call(backend.get().af_orb(c_pointer(feat.feat), c_pointer(desc.arr), image.arr, - c_float_t(threshold), c_uint_t(max_features), - c_float_t(scale), c_uint_t(num_levels), blur_image)) + safe_call(backend.get().af_orb( + c_pointer(feat.feat), c_pointer(desc.arr), image.arr, c_float_t(threshold), c_uint_t(max_features), + c_float_t(scale), c_uint_t(num_levels), blur_image)) return feat, desc -def hamming_matcher(query, database, dim = 0, num_nearest = 1): + +def hamming_matcher(query, database, dim=0, num_nearest=1): """ Hamming distance matcher. @@ -164,12 +168,12 @@ def hamming_matcher(query, database, dim = 0, num_nearest = 1): """ index = Array() dist = Array() - safe_call(backend.get().af_hamming_matcher(c_pointer(index.arr), c_pointer(dist.arr), - query.arr, database.arr, - c_dim_t(dim), c_dim_t(num_nearest))) + safe_call(backend.get().af_hamming_matcher( + c_pointer(index.arr), c_pointer(dist.arr), query.arr, database.arr, c_dim_t(dim), c_dim_t(num_nearest))) return index, dist -def nearest_neighbour(query, database, dim = 0, num_nearest = 1, match_type=MATCH.SSD): + +def nearest_neighbour(query, database, dim=0, num_nearest=1, match_type=MATCH.SSD): """ Nearest Neighbour matcher. @@ -200,13 +204,13 @@ def nearest_neighbour(query, database, dim = 0, num_nearest = 1, match_type=MATC """ index = Array() dist = Array() - safe_call(backend.get().af_nearest_neighbour(c_pointer(index.arr), c_pointer(dist.arr), - query.arr, database.arr, - c_dim_t(dim), c_dim_t(num_nearest), - match_type.value)) + safe_call(backend.get().af_nearest_neighbour( + c_pointer(index.arr), c_pointer(dist.arr), query.arr, database.arr, c_dim_t(dim), c_dim_t(num_nearest), + match_type.value)) return index, dist -def match_template(image, template, match_type = MATCH.SAD): + +def match_template(image, template, match_type=MATCH.SAD): """ Find the closest match of a template in an image. @@ -229,11 +233,10 @@ def match_template(image, template, match_type = MATCH.SAD): """ out = Array() - safe_call(backend.get().af_match_template(c_pointer(out.arr), - image.arr, template.arr, - match_type.value)) + safe_call(backend.get().af_match_template(c_pointer(out.arr), image.arr, template.arr, match_type.value)) return out + def susan(image, radius=3, diff_thr=32, geom_thr=10, feature_ratio=0.05, edge=3): """ SUSAN corner detector. @@ -266,12 +269,12 @@ def susan(image, radius=3, diff_thr=32, geom_thr=10, feature_ratio=0.05, edge=3) """ out = Features() - safe_call(backend.get().af_susan(c_pointer(out.feat), - image.arr, c_uint_t(radius), c_float_t(diff_thr), - c_float_t(geom_thr), c_float_t(feature_ratio), - c_uint_t(edge))) + safe_call(backend.get().af_susan( + c_pointer(out.feat), image.arr, c_uint_t(radius), c_float_t(diff_thr), c_float_t(geom_thr), + c_float_t(feature_ratio), c_uint_t(edge))) return out + def dog(image, radius1, radius2): """ Difference of gaussians. @@ -299,14 +302,13 @@ def dog(image, radius1, radius2): The sigma values are calculated to be 0.25 * radius. """ - out = Array() - safe_call(backend.get().af_dog(c_pointer(out.arr), - image.arr, radius1, radius2)) + safe_call(backend.get().af_dog(c_pointer(out.arr), image.arr, radius1, radius2)) return out -def sift(image, num_layers=3, contrast_threshold=0.04, edge_threshold=10.0, initial_sigma = 1.6, - double_input = True, intensity_scale = 0.00390625, feature_ratio = 0.05): + +def sift(image, num_layers=3, contrast_threshold=0.04, edge_threshold=10.0, initial_sigma=1.6, + double_input=True, intensity_scale=0.00390625, feature_ratio=0.05): """ SIFT feature detector and descriptor. @@ -342,17 +344,18 @@ def sift(image, num_layers=3, contrast_threshold=0.04, edge_threshold=10.0, init - descriptor is an af.Array of size N x 128 """ - feat = Features() desc = Array() - safe_call(backend.get().af_sift(c_pointer(feat.feat), c_pointer(desc.arr), - image.arr, num_layers, c_float_t(contrast_threshold), c_float_t(edge_threshold), - c_float_t(initial_sigma), double_input, c_float_t(intensity_scale), c_float_t(feature_ratio))) + safe_call(backend.get().af_sift( + c_pointer(feat.feat), c_pointer(desc.arr), image.arr, num_layers, c_float_t(contrast_threshold), + c_float_t(edge_threshold), c_float_t(initial_sigma), double_input, c_float_t(intensity_scale), + c_float_t(feature_ratio))) return (feat, desc) -def gloh(image, num_layers=3, contrast_threshold=0.04, edge_threshold=10.0, initial_sigma = 1.6, - double_input = True, intensity_scale = 0.00390625, feature_ratio = 0.05): + +def gloh(image, num_layers=3, contrast_threshold=0.04, edge_threshold=10.0, initial_sigma=1.6, + double_input=True, intensity_scale=0.00390625, feature_ratio=0.05): """ GLOH feature detector and descriptor. @@ -388,19 +391,18 @@ def gloh(image, num_layers=3, contrast_threshold=0.04, edge_threshold=10.0, init - descriptor is an af.Array of size N x 272 """ - feat = Features() desc = Array() - safe_call(backend.get().af_gloh(c_pointer(feat.feat), c_pointer(desc.arr), - image.arr, num_layers, c_float_t(contrast_threshold), - c_float_t(edge_threshold), c_float_t(initial_sigma), - double_input, c_float_t(intensity_scale), - c_float_t(feature_ratio))) + safe_call(backend.get().af_gloh( + c_pointer(feat.feat), c_pointer(desc.arr), image.arr, num_layers, c_float_t(contrast_threshold), + c_float_t(edge_threshold), c_float_t(initial_sigma), double_input, c_float_t(intensity_scale), + c_float_t(feature_ratio))) return (feat, desc) -def homography(x_src, y_src, x_dst, y_dst, htype = HOMOGRAPHY.RANSAC, - ransac_threshold = 3.0, iters = 1000, out_type = Dtype.f32): + +def homography(x_src, y_src, x_dst, y_dst, htype=HOMOGRAPHY.RANSAC, ransac_threshold=3.0, + iters=1000, out_type=Dtype.f32): """ Homography estimation @@ -433,10 +435,9 @@ def homography(x_src, y_src, x_dst, y_dst, htype = HOMOGRAPHY.RANSAC, ------- (H, inliers) : A tuple of (af.Array, integer) """ - H = Array() inliers = c_int_t(0) - safe_call(backend.get().af_homography(c_pointer(H), c_pointer(inliers), - x_src.arr, y_src.arr, x_dst.arr, y_dst.arr, - htype.value, ransac_threshold, iters, out_type.value)) + safe_call(backend.get().af_homography( + c_pointer(H), c_pointer(inliers), x_src.arr, y_src.arr, x_dst.arr, y_dst.arr, htype.value, ransac_threshold, + iters, out_type.value)) return (H, inliers) diff --git a/docs/conf.py b/docs/conf.py index 44374afb1..2575ef34a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python # -*- coding: utf-8 -*- # # ArrayFire documentation build configuration file, created by @@ -19,9 +19,11 @@ # import os import sys -sys.path.insert(0, os.path.abspath('..')) + from __af_version__ import full_version +sys.path.insert(0, os.path.abspath('..')) + # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -32,13 +34,13 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.mathjax', - 'sphinx.ext.viewcode', - 'numpydoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.doctest', - 'sphinx.ext.inheritance_diagram'] + 'sphinx.ext.autodoc', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', + 'numpydoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.doctest', + 'sphinx.ext.inheritance_diagram'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -247,21 +249,21 @@ # -- Options for LaTeX output --------------------------------------------- latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples diff --git a/examples/benchmarks/bench_blas.py b/examples/benchmarks/bench_blas.py index 21b776869..9cfe625f0 100644 --- a/examples/benchmarks/bench_blas.py +++ b/examples/benchmarks/bench_blas.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,9 +9,9 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## - import sys from time import time + import arrayfire as af try: @@ -26,6 +26,7 @@ def calc_arrayfire(n): def run(iters): for t in range(iters): + # FIXME: B is assigned, but not used in function B = af.matmul(A, A) af.sync() @@ -38,6 +39,7 @@ def calc_numpy(n): def run(iters): for t in range(iters): + # FIXME: B is assigned, but not used in function B = np.dot(A, A) return run @@ -57,8 +59,7 @@ def bench(calc, iters=100, upto=2048): if __name__ == "__main__": - - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() diff --git a/examples/benchmarks/bench_cg.py b/examples/benchmarks/bench_cg.py index 33c5b856c..9421f7af0 100644 --- a/examples/benchmarks/bench_cg.py +++ b/examples/benchmarks/bench_cg.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,9 +9,9 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## - import sys from time import time + import arrayfire as af try: @@ -34,13 +34,10 @@ def to_sparse(A): return af.sparse.create_sparse_from_dense(A) -def to_scipy_sparse(spA, fmt='csr'): - vals = np.asarray(af.sparse.sparse_get_values(spA).to_list(), - dtype = np.float32) - rows = np.asarray(af.sparse.sparse_get_row_idx(spA).to_list(), - dtype = np.int) - cols = np.asarray(af.sparse.sparse_get_col_idx(spA).to_list(), - dtype = np.int) +def to_scipy_sparse(spA, fmt="csr"): # BUG: 'fmt' argument is unused. + vals = np.asarray(af.sparse.sparse_get_values(spA).to_list(), dtype=np.float32) + rows = np.asarray(af.sparse.sparse_get_row_idx(spA).to_list(), dtype=np.int) + cols = np.asarray(af.sparse.sparse_get_col_idx(spA).to_list(), dtype=np.int) return sp.csr_matrix((vals, cols, rows), dtype=np.float32) @@ -57,11 +54,11 @@ def setup_input(n, sparsity=7): return A, b, x0 -def input_info(A, Asp): +def input_info(A, Asp): # BUG: 'Asp' argument is unused. m, n = A.dims() nnz = af.sum((A != 0)) - print(" matrix size: %i x %i" %(m, n)) - print(" matrix sparsity: %2.2f %%" %(100*nnz/n**2,)) + print(" matrix size: %i x %i" % (m, n)) + print(" matrix sparsity: %2.2f %%" % (100*nnz/n**2,)) print(" dense matrix memory usage: ") print(" sparse matrix memory usage: ") @@ -70,7 +67,7 @@ def calc_arrayfire(A, b, x0, maxiter=10): x = af.constant(0, b.dims()[0], dtype=af.Dtype.f32) r = b - af.matmul(A, x) p = r - for i in range(maxiter): + for _ in range(maxiter): Ap = af.matmul(A, p) alpha_num = af.dot(r, r) alpha_den = af.dot(p, Ap) @@ -89,7 +86,7 @@ def calc_numpy(A, b, x0, maxiter=10): x = np.zeros(len(b), dtype=np.float32) r = b - np.dot(A, x) p = r.copy() - for i in range(maxiter): + for _ in range(maxiter): Ap = np.dot(A, p) alpha_num = np.dot(r, r) alpha_den = np.dot(p, Ap) @@ -107,7 +104,7 @@ def calc_scipy_sparse(A, b, x0, maxiter=10): x = np.zeros(len(b), dtype=np.float32) r = b - A*x p = r.copy() - for i in range(maxiter): + for _ in range(maxiter): Ap = A*p alpha_num = np.dot(r, r) alpha_den = np.dot(p, Ap) @@ -130,7 +127,7 @@ def calc_scipy_sparse_linalg_cg(A, b, x0, maxiter=10): def timeit(calc, iters, args): t0 = time() - for i in range(iters): + for _ in range(iters): calc(*args) dt = time() - t0 return 1000*dt/iters # ms @@ -163,36 +160,36 @@ def test(): def bench(n=4*1024, sparsity=7, maxiter=10, iters=10): - # generate data - print("\nGenerating benchmark data for n = %i ..." %n) + print("\nGenerating benchmark data for n = %i ..." % n) A, b, x0 = setup_input(n, sparsity) # dense A Asp = to_sparse(A) # sparse A input_info(A, Asp) # make benchmarks - print("Benchmarking CG solver for n = %i ..." %n) + print("Benchmarking CG solver for n = %i ..." % n) t1 = timeit(calc_arrayfire, iters, args=(A, b, x0, maxiter)) - print(" arrayfire - dense: %f ms" %t1) + print(" arrayfire - dense: %f ms" % t1) t2 = timeit(calc_arrayfire, iters, args=(Asp, b, x0, maxiter)) - print(" arrayfire - sparse: %f ms" %t2) + print(" arrayfire - sparse: %f ms" % t2) if np: An = to_numpy(A) bn = to_numpy(b) x0n = to_numpy(x0) t3 = timeit(calc_numpy, iters, args=(An, bn, x0n, maxiter)) - print(" numpy - dense: %f ms" %t3) + print(" numpy - dense: %f ms" % t3) if sp: Asc = to_scipy_sparse(Asp) t4 = timeit(calc_scipy_sparse, iters, args=(Asc, bn, x0n, maxiter)) - print(" scipy - sparse: %f ms" %t4) + print(" scipy - sparse: %f ms" % t4) t5 = timeit(calc_scipy_sparse_linalg_cg, iters, args=(Asc, bn, x0n, maxiter)) - print(" scipy - sparse.linalg.cg: %f ms" %t5) + print(" scipy - sparse.linalg.cg: %f ms" % t5) + if __name__ == "__main__": - #af.set_backend('cpu', unsafe=True) + # af.set_backend("cpu", unsafe=True) - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() diff --git a/examples/benchmarks/bench_fft.py b/examples/benchmarks/bench_fft.py index 4d9a3d7b1..0df179b8d 100644 --- a/examples/benchmarks/bench_fft.py +++ b/examples/benchmarks/bench_fft.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,9 +9,9 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## - import sys from time import time + import arrayfire as af try: @@ -25,8 +25,8 @@ def calc_arrayfire(n): af.sync() def run(iters): - for t in range(iters): - B = af.fft2(A) + for _ in range(iters): + B = af.fft2(A) # FIXME: 'B' is assigned, but not used. af.sync() @@ -38,8 +38,8 @@ def calc_numpy(n): A = np.random.rand(n, n).astype(np.float32) def run(iters): - for t in range(iters): - B = np.fft.fft2(A) + for _ in range(iters): + B = np.fft.fft2(A) # FIXME: 'B' is assigned, but not used. return run @@ -59,8 +59,7 @@ def bench(calc, iters=100, upto=13): if __name__ == "__main__": - - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() diff --git a/examples/benchmarks/monte_carlo_pi.py b/examples/benchmarks/monte_carlo_pi.py index 440c01594..4e5f92b4b 100755 --- a/examples/benchmarks/monte_carlo_pi.py +++ b/examples/benchmarks/monte_carlo_pi.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,55 +9,62 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## +import sys from random import random from time import time + import arrayfire as af -import sys try: import numpy as np except ImportError: np = None -#alias range / xrange because xrange is faster than range in python2 +# alias range / xrange because xrange is faster than range in python2 try: - frange = xrange #Python2 + frange = xrange # Python2 except NameError: - frange = range #Python3 + frange = range # Python3 + -# Having the function outside is faster than the lambda inside def in_circle(x, y): + # Having the function outside is faster than the lambda inside return (x*x + y*y) < 1 + def calc_pi_device(samples): x = af.randu(samples) y = af.randu(samples) return 4 * af.sum(in_circle(x, y)) / samples + def calc_pi_numpy(samples): np.random.seed(1) x = np.random.rand(samples).astype(np.float32) y = np.random.rand(samples).astype(np.float32) return 4. * np.sum(in_circle(x, y)) / samples + def calc_pi_host(samples): count = sum(1 for k in frange(samples) if in_circle(random(), random())) return 4 * float(count) / samples + def bench(calc_pi, samples=1000000, iters=25): func_name = calc_pi.__name__[8:] - print("Monte carlo estimate of pi on %s with %d million samples: %f" % \ + print("Monte carlo estimate of pi on %s with %d million samples: %f" % (func_name, samples/1e6, calc_pi(samples))) start = time() - for k in frange(iters): + for _ in frange(iters): calc_pi(samples) end = time() print("Average time taken: %f ms" % (1000 * (end - start) / iters)) + if __name__ == "__main__": - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() diff --git a/examples/financial/black_scholes_options.py b/examples/financial/black_scholes_options.py index e53a4ab19..e2dd2714f 100644 --- a/examples/financial/black_scholes_options.py +++ b/examples/financial/black_scholes_options.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,17 +9,20 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## -import arrayfire as af -from time import time import math import sys +from time import time + +import arrayfire as af sqrt2 = math.sqrt(2.0) + def cnd(x): temp = (x > 0) return temp * (0.5 + af.erf(x/sqrt2)/2) + (1 - temp) * (0.5 - af.erf((-x)/sqrt2)/2) + def black_scholes(S, X, R, V, T): # S = Underlying stock price # X = Strike Price @@ -36,12 +39,13 @@ def black_scholes(S, X, R, V, T): cnd_d2 = cnd(d2) C = S * cnd_d1 - (X * af.exp((-R) * T) * cnd_d2) - P = X * af.exp((-R) * T) * (1 - cnd_d2) - (S * (1 -cnd_d1)) + P = X * af.exp((-R) * T) * (1 - cnd_d2) - (S * (1 - cnd_d1)) return (C, P) + if __name__ == "__main__": - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() @@ -53,7 +57,7 @@ def black_scholes(S, X, R, V, T): V = af.randu(M, 1) T = af.randu(M, 1) - (C, P) = black_scholes(S, X, R, V, T) + C, P = black_scholes(S, X, R, V, T) af.eval(C) af.eval(P) af.sync() @@ -71,7 +75,7 @@ def black_scholes(S, X, R, V, T): start = time() for i in range(num_iter): - (C, P) = black_scholes(S, X, R, V, T) + C, P = black_scholes(S, X, R, V, T) af.eval(C) af.eval(P) af.sync() diff --git a/examples/financial/heston_model.py b/examples/financial/heston_model.py index 640127eeb..c63dc6022 100644 --- a/examples/financial/heston_model.py +++ b/examples/financial/heston_model.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ############################################################################################## -# Copyright (c) 2015, Michael Nowotny +# Copyright (c) 2019, Michael Nowotny # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -31,12 +31,13 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ############################################################################################### -import arrayfire as af import math import time -def simulateHestonModel( T, N, R, mu, kappa, vBar, sigmaV, rho, x0, v0 ) : +import arrayfire as af + +def simulateHestonModel(T, N, R, mu, kappa, vBar, sigmaV, rho, x0, v0): deltaT = T / (float)(N - 1) x = [af.constant(x0, R, dtype=af.Dtype.f32), af.constant(0, R, dtype=af.Dtype.f32)] @@ -50,9 +51,9 @@ def simulateHestonModel( T, N, R, mu, kappa, vBar, sigmaV, rho, x0, v0 ) : m[1] = sqrtOneMinusRhoSquare zeroArray = af.constant(0, R, 1, dtype=af.Dtype.f32) - for t in range(1, N) : + for t in range(1, N): tPrevious = (t + 1) % 2 - tCurrent = t % 2 + tCurrent = t % 2 dBt = af.randn(R, 2, dtype=af.Dtype.f32) * sqrtDeltaT @@ -71,21 +72,21 @@ def main(): R_first = 1000 R = 5000000 - x0 = 0 # initial log stock price - v0 = 0.087**2 # initial volatility - r = math.log(1.0319) # risk-free rate - rho = -0.82 # instantaneous correlation between Brownian motions - sigmaV = 0.14 # variance of volatility - kappa = 3.46 # mean reversion speed - vBar = 0.008 # mean variance - k = math.log(0.95) # strike price + x0 = 0 # initial log stock price + v0 = 0.087**2 # initial volatility + r = math.log(1.0319) # risk-free rate + rho = -0.82 # instantaneous correlation between Brownian motions + sigmaV = 0.14 # variance of volatility + kappa = 3.46 # mean reversion speed + vBar = 0.008 # mean variance + k = math.log(0.95) # strike price # first run - ( x, v ) = simulateHestonModel( T, nT, R_first, r, kappa, vBar, sigmaV, rho, x0, v0 ) + x, v = simulateHestonModel(T, nT, R_first, r, kappa, vBar, sigmaV, rho, x0, v0) # Price plain vanilla call option tic = time.time() - ( x, v ) = simulateHestonModel( T, nT, R, r, kappa, vBar, sigmaV, rho, x0, v0 ) + x, v = simulateHestonModel(T, nT, R, r, kappa, vBar, sigmaV, rho, x0, v0) af.sync() toc = time.time() - tic K = math.exp(k) diff --git a/examples/financial/monte_carlo_options.py b/examples/financial/monte_carlo_options.py index 2c9bcc8ed..8c5f090d5 100644 --- a/examples/financial/monte_carlo_options.py +++ b/examples/financial/monte_carlo_options.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,29 +9,32 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## -import arrayfire as af -from time import time import math import sys +from time import time + +import arrayfire as af + -def monte_carlo_options(N, K, t, vol, r, strike, steps, use_barrier = True, B = None, ty = af.Dtype.f32): - payoff = af.constant(0, N, 1, dtype = ty) +def monte_carlo_options(N, K, t, vol, r, strike, steps, use_barrier=True, B=None, ty=af.Dtype.f32): + payoff = af.constant(0, N, 1, dtype=ty) dt = t / float(steps - 1) - s = af.constant(strike, N, 1, dtype = ty) + s = af.constant(strike, N, 1, dtype=ty) - randmat = af.randn(N, steps - 1, dtype = ty) - randmat = af.exp((r - (vol * vol * 0.5)) * dt + vol * math.sqrt(dt) * randmat); + randmat = af.randn(N, steps - 1, dtype=ty) + randmat = af.exp((r - (vol * vol * 0.5)) * dt + vol * math.sqrt(dt) * randmat) S = af.product(af.join(1, s, randmat), 1) - if (use_barrier): + if use_barrier: S = S * af.all_true(S < B, 1) payoff = af.maxof(0, S - K) return af.mean(payoff) * math.exp(-r * t) -def monte_carlo_simulate(N, use_barrier, num_iter = 10): + +def monte_carlo_simulate(N, use_barrier, num_iter=10): steps = 180 stock_price = 100.0 maturity = 0.5 @@ -41,19 +44,19 @@ def monte_carlo_simulate(N, use_barrier, num_iter = 10): barrier = 115.0 start = time() - for i in range(num_iter): - monte_carlo_options(N, stock_price, maturity, volatility, rate, strike, steps, - use_barrier, barrier) + for _ in range(num_iter): + monte_carlo_options(N, stock_price, maturity, volatility, rate, strike, steps, use_barrier, barrier) return (time() - start) / num_iter + if __name__ == "__main__": - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() - monte_carlo_simulate(1000, use_barrier = False) - monte_carlo_simulate(1000, use_barrier = True ) + monte_carlo_simulate(1000, use_barrier=False) + monte_carlo_simulate(1000, use_barrier=True) af.sync() for n in range(10000, 100001, 10000): diff --git a/examples/getting_started/convolve.py b/examples/getting_started/convolve.py index 6c9e2454d..5a2ccbb9e 100644 --- a/examples/getting_started/convolve.py +++ b/examples/getting_started/convolve.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,25 +9,27 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## -import arrayfire as af import sys from array import array +import arrayfire as af + + def af_assert(left, right, eps=1E-6): - if (af.max(af.abs(left -right)) > eps): + if af.max(af.abs(left - right)) > eps: raise ValueError("Arrays not within dictated precision") - return + if __name__ == "__main__": - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() - h_dx = array('f', (1.0/12, -8.0/12, 0, 8.0/12, 1.0/12)) - h_spread = array('f', (1.0/5, 1.0/5, 1.0/5, 1.0/5, 1.0/5)) + h_dx = array("f", (1.0/12, -8.0/12, 0, 8.0/12, 1.0/12)) + h_spread = array("f", (1.0/5, 1.0/5, 1.0/5, 1.0/5, 1.0/5)) img = af.randu(640, 480) - dx = af.Array(h_dx, (5,1)) + dx = af.Array(h_dx, (5, 1)) spread = af.Array(h_spread, (1, 5)) kernel = af.matmul(dx, spread) diff --git a/examples/getting_started/intro.py b/examples/getting_started/intro.py index 712343750..d03808738 100644 --- a/examples/getting_started/intro.py +++ b/examples/getting_started/intro.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,32 +9,33 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## -import arrayfire as af import sys from array import array +import arrayfire as af + if __name__ == "__main__": - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() print("\n---- Intro to ArrayFire using signed(s32) arrays ----\n") - h_A = array('i', ( 1, 2, 4, -1, 2, 0, 4, 2, 3)) - h_B = array('i', ( 2, 3, 5, 6, 0, 10,-12, 0, 1)) + h_A = array("i", (1, 2, 4, -1, 2, 0, 4, 2, 3)) + h_B = array("i", (2, 3, 5, 6, 0, 10, -12, 0, 1)) - A = af.Array(h_A, (3,3)) - B = af.Array(h_B, (3,3)) + A = af.Array(h_A, (3, 3)) + B = af.Array(h_B, (3, 3)) print("\n---- Sub referencing and sub assignment\n") af.display(A) - af.display(A[0,:]) - af.display(A[:,0]) - A[0,0] = 11 + af.display(A[0, :]) + af.display(A[:, 0]) + A[0, 0] = 11 A[1] = 100 af.display(A) af.display(B) - A[1,:] = B[2,:] + A[1, :] = B[2, :] af.display(A) print("\n---- Bitwise operations\n") @@ -61,6 +62,6 @@ af.display(af.max(A, 1)) print("\n---- Get minimum with index\n") - (min_val, min_idx) = af.imin(A, 0) + min_val, min_idx = af.imin(A, 0) af.display(min_val) af.display(min_idx) diff --git a/examples/graphics/conway.py b/examples/graphics/conway.py index 49ad43bb9..6e27b0472 100644 --- a/examples/graphics/conway.py +++ b/examples/graphics/conway.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,11 +9,12 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## -import arrayfire as af import array from time import time -h_kernel = array.array('f', (1, 1, 1, 1, 0, 1, 1, 1, 1)) +import arrayfire as af + +h_kernel = array.array("f", (1, 1, 1, 1, 0, 1, 1, 1, 1)) reset = 500 game_w = 128 game_h = 128 @@ -21,10 +22,10 @@ print("Example demonstrating conway's game of life using arrayfire") print("The conway_pretty example visualizes all the states in Conway") -print("Red : Cells that have died due to under population" ) -print("Yellow: Cells that continue to live from previous state" ) -print("Green : Cells that are new as a result of reproduction" ) -print("Blue : Cells that have died due to over population" ) +print("Red : Cells that have died due to under population") +print("Yellow: Cells that continue to live from previous state") +print("Green : Cells that are new as a result of reproduction") +print("Blue : Cells that have died due to over population") print("This examples is throttled to 30 FPS so as to be a better visualization") simple_win = af.Window(512, 512, "Conway's Game of Life - Current State") @@ -35,21 +36,23 @@ frame_count = 0 # Copy kernel that specifies neighborhood conditions -kernel = af.Array(h_kernel, dims=(3,3)) +kernel = af.Array(h_kernel, dims=(3, 3)) # Generate the initial state with 0s and 1s state = (af.randu(game_h, game_w) > 0.4).as_type(af.Dtype.f32) # tile 3 times to display color -display = af.tile(state, 1, 1, 3, 1) +display = af.tile(state, 1, 1, 3, 1) -while (not simple_win.close()) and (not pretty_win.close()): +while not (simple_win.close() or pretty_win.close()): delay = time() - if (not simple_win.close()): simple_win.image(state) - if (not pretty_win.close()): pretty_win.image(display) + if not simple_win.close(): + simple_win.image(state) + if not pretty_win.close(): + pretty_win.image(display) frame_count += 1 - if (frame_count % reset == 0): + if frame_count % reset == 0: state = (af.randu(game_h, game_w) > 0.4).as_type(af.Dtype.f32) neighborhood = af.convolve(state, kernel) @@ -70,5 +73,5 @@ state = state * C0 + C1 - while(time() - delay < (1.0 / fps)): + while time() - delay < (1.0 / fps): pass diff --git a/examples/graphics/fractal.py b/examples/graphics/fractal.py index 37b35a63f..d1c468088 100644 --- a/examples/graphics/fractal.py +++ b/examples/graphics/fractal.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,18 +9,21 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## -import arrayfire as af import sys from math import sqrt +import arrayfire as af + width = 400 height = 400 + def complex_grid(w, h, zoom, center): - x = (af.iota(d0 = 1, d1 = h, tile_dims = (w, 1)) - h/2) / zoom + center[0] - y = (af.iota(d0 = w, d1 = 1, tile_dims = (1, h)) - w/2) / zoom + center[1] + x = (af.iota(d0=1, d1=h, tile_dims=(w, 1)) - h/2) / zoom + center[0] + y = (af.iota(d0=w, d1=1, tile_dims=(1, h)) - w/2) / zoom + center[1] return af.cplx(x, y) + def mandelbrot(data, it, maxval): C = data Z = data @@ -42,13 +45,15 @@ def mandelbrot(data, it, maxval): return mag / maxval + def normalize(a): mx = af.max(a) mn = af.min(a) return (a - mn)/(mx - mn) + if __name__ == "__main__": - if (len(sys.argv) > 1): + if len(sys.argv) > 1: af.set_device(int(sys.argv[1])) af.info() @@ -62,13 +67,14 @@ def normalize(a): for i in range(10, 400): zoom = i * i - if not (i % 10): + if not i % 10: print("Iteration: %d zoom: %d" % (i, zoom)) c = complex_grid(width, height, zoom, center) it = sqrt(2*sqrt(abs(1-sqrt(5*zoom))))*100 - if (win.close()): break + if win.close(): + break mag = mandelbrot(c, int(it), 1000) win.image(normalize(mag)) diff --git a/examples/graphics/histogram.py b/examples/graphics/histogram.py index 9a15dcf30..ee9c0db1e 100644 --- a/examples/graphics/histogram.py +++ b/examples/graphics/histogram.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,29 +9,29 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## -import arrayfire as af -import sys import os +import sys -if __name__ == "__main__": +import arrayfire as af - if (len(sys.argv) == 1): +if __name__ == "__main__": + if len(sys.argv) == 1: raise RuntimeError("Expected to the image as the first argument") if not os.path.isfile(sys.argv[1]): raise RuntimeError("File %s not found" % sys.argv[1]) - if (len(sys.argv) > 2): + if len(sys.argv) > 2: af.set_device(int(sys.argv[2])) af.info() hist_win = af.Window(512, 512, "3D Plot example using ArrayFire") - img_win = af.Window(480, 640, "Input Image") + img_win = af.Window(480, 640, "Input Image") img = af.load_image(sys.argv[1]).as_type(af.Dtype.u8) hist = af.histogram(img, 256, 0, 255) - while (not hist_win.close()) and (not img_win.close()): + while not (hist_win.close() or img_win.close()): hist_win.hist(hist, 0, 255) img_win.image(img) diff --git a/examples/graphics/plot2d.py b/examples/graphics/plot2d.py index a7f7f8164..8115771bf 100755 --- a/examples/graphics/plot2d.py +++ b/examples/graphics/plot2d.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -9,9 +9,10 @@ # http://arrayfire.com/licenses/BSD-3-Clause ######################################################## -import arrayfire as af import math +import arrayfire as af + POINTS = 10000 PRECISION = 1.0 / float(POINTS) @@ -28,7 +29,7 @@ X += PRECISION * sign val += PRECISION * sign - if (val > math.pi): + if val > math.pi: sign = -1.0 - elif (val < -math.pi): + elif val < -math.pi: sign = 1.0 diff --git a/examples/graphics/plot3.py b/examples/graphics/plot3.py index 4957326a6..86565b432 100644 --- a/examples/graphics/plot3.py +++ b/examples/graphics/plot3.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/examples/graphics/surface.py b/examples/graphics/surface.py index 1af980e22..a51bf6161 100644 --- a/examples/graphics/surface.py +++ b/examples/graphics/surface.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -16,13 +16,13 @@ POINTS = 30 N = 2 * POINTS -x = (af.iota(d0 = N, d1 = 1, tile_dims = (1, N)) - POINTS) / POINTS -y = (af.iota(d0 = 1, d1 = N, tile_dims = (N, 1)) - POINTS) / POINTS +x = (af.iota(d0=N, d1=1, tile_dims=(1, N)) - POINTS) / POINTS +y = (af.iota(d0=1, d1=N, tile_dims=(N, 1)) - POINTS) / POINTS win = af.Window(800, 800, "3D Surface example using ArrayFire") t = 0 while not win.close(): t = t + 0.07 - z = 10*x*-af.abs(y) * af.cos(x*x*(y+t))+af.sin(y*(x+t))-1.5; + z = 10*x*-af.abs(y) * af.cos(x*x*(y+t))+af.sin(y*(x+t))-1.5 win.surface(x, y, z) diff --git a/examples/helloworld/helloworld.py b/examples/helloworld/helloworld.py index 2d76cf3ea..61b5f859c 100755 --- a/examples/helloworld/helloworld.py +++ b/examples/helloworld/helloworld.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -27,33 +27,33 @@ B[0:3, 1] = B[0:3, 1] * -1 af.display(B) - print("Fourier transform the result\n"); - C = af.fft(B); - af.display(C); + print("Fourier transform the result\n") + C = af.fft(B) + af.display(C) - print("Grab last row\n"); - c = C[-1,:]; - af.display(c); + print("Grab last row\n") + c = C[-1, :] + af.display(c) - print("Scan Test\n"); - r = af.constant(2, 16, 4, 1, 1); - af.display(r); + print("Scan Test\n") + r = af.constant(2, 16, 4, 1, 1) + af.display(r) - print("Scan\n"); - S = af.scan(r, 0, af.BINARYOP.MUL); - af.display(S); + print("Scan\n") + S = af.scan(r, 0, af.BINARYOP.MUL) + af.display(S) - print("Create 2-by-3 matrix from host data\n"); - d = [ 1, 2, 3, 4, 5, 6 ] + print("Create 2-by-3 matrix from host data\n") + d = [1, 2, 3, 4, 5, 6] D = af.Array(d, (2, 3)) af.display(D) - print("Copy last column onto first\n"); - D[:,0] = D[:, -1] - af.display(D); + print("Copy last column onto first\n") + D[:, 0] = D[:, -1] + af.display(D) - print("Sort A and print sorted array and corresponding indices\n"); - [sorted_vals, sorted_idxs] = af.sort_index(A); + print("Sort A and print sorted array and corresponding indices\n") + sorted_vals, sorted_idxs = af.sort_index(A) af.display(A) af.display(sorted_vals) af.display(sorted_idxs) diff --git a/setup.py b/setup.py index e4d485c30..5bc5472ca 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/__init__.py b/tests/__init__.py index 24e9ac759..0c6d787de 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/__main__.py b/tests/__main__.py index 6bed94278..190c5c8f8 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/__init__.py b/tests/simple/__init__.py index 4950136e3..abedbc4ba 100644 --- a/tests/simple/__init__.py +++ b/tests/simple/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/_util.py b/tests/simple/_util.py index 2275cf2fc..339bdd382 100644 --- a/tests/simple/_util.py +++ b/tests/simple/_util.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/algorithm.py b/tests/simple/algorithm.py index b9e42f138..d46b6d8cc 100644 --- a/tests/simple/algorithm.py +++ b/tests/simple/algorithm.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/arith.py b/tests/simple/arith.py index 5d4d83d00..05c5dd47a 100644 --- a/tests/simple/arith.py +++ b/tests/simple/arith.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -78,27 +78,25 @@ def simple_arith(verbose=False): display_func(a < b) display_func(a < 0.5) - display_func(0.5 < a) + display_func(a > 0.5) display_func(a <= b) display_func(a <= 0.5) - display_func(0.5 <= a) + display_func(a >= 0.5) display_func(a > b) display_func(a > 0.5) - display_func(0.5 > a) + display_func(a < 0.5) display_func(a >= b) display_func(a >= 0.5) - display_func(0.5 >= a) + display_func(a <= 0.5) display_func(a != b) display_func(a != 0.5) - display_func(0.5 != a) display_func(a == b) display_func(a == 0.5) - display_func(0.5 == a) a = af.randu(3, 3, dtype=af.Dtype.u32) b = af.constant(4, 3, 3, dtype=af.Dtype.u32) diff --git a/tests/simple/array_test.py b/tests/simple/array_test.py index b2a787940..b1d9d1b18 100644 --- a/tests/simple/array_test.py +++ b/tests/simple/array_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -20,7 +20,7 @@ def simple_array(verbose=False): display_func = _util.display_func(verbose) print_func = _util.print_func(verbose) - a = af.Array([1, 2, 3]) + a = af.array.Array([1, 2, 3]) display_func(a) display_func(a.T) display_func(a.H) @@ -34,14 +34,14 @@ def simple_array(verbose=False): print_func(a.is_complex(), a.is_real(), a.is_double(), a.is_single()) print_func(a.is_real_floating(), a.is_floating(), a.is_integer(), a.is_bool()) - a = af.Array(host.array("i", [4, 5, 6])) + a = af.array.Array(host.array("i", [4, 5, 6])) display_func(a) print_func(a.elements(), a.type(), a.dims(), a.numdims()) print_func(a.is_empty(), a.is_scalar(), a.is_column(), a.is_row()) print_func(a.is_complex(), a.is_real(), a.is_double(), a.is_single()) print_func(a.is_real_floating(), a.is_floating(), a.is_integer(), a.is_bool()) - a = af.Array(host.array("I", [7, 8, 9] * 3), (3, 3)) + a = af.array.Array(host.array("I", [7, 8, 9] * 3), (3, 3)) display_func(a) print_func(a.elements(), a.type(), a.dims(), a.numdims()) print_func(a.is_empty(), a.is_scalar(), a.is_column(), a.is_row()) diff --git a/tests/simple/blas.py b/tests/simple/blas.py index f04049a93..ac4aa6166 100644 --- a/tests/simple/blas.py +++ b/tests/simple/blas.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/data.py b/tests/simple/data.py index d091497eb..3120aec09 100644 --- a/tests/simple/data.py +++ b/tests/simple/data.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/device.py b/tests/simple/device.py index f677c5e2a..f125ab862 100644 --- a/tests/simple/device.py +++ b/tests/simple/device.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -27,7 +27,7 @@ def simple_device(verbose=False): for k in range(af.get_device_count()): af.set_device(k) dev = af.get_device() - assert(k == dev) + assert k == dev print_func(af.is_dbl_supported(k)) @@ -38,8 +38,8 @@ def simple_device(verbose=False): a = af.randu(100, 100) af.sync(dev) mem_info = af.device_mem_info() - assert(mem_info["alloc"]["buffers"] == 1 + mem_info_old["alloc"]["buffers"]) - assert(mem_info["lock"]["buffers"] == 1 + mem_info_old["lock"]["buffers"]) + assert mem_info["alloc"]["buffers"] == 1 + mem_info_old["alloc"]["buffers"] + assert mem_info["lock"]["buffers"] == 1 + mem_info_old["lock"]["buffers"] af.set_device(curr_dev) @@ -67,9 +67,9 @@ def simple_device(verbose=False): print_func(d) print_func(af.set_manual_eval_flag(True)) - assert(af.get_manual_eval_flag()) + assert af.get_manual_eval_flag() print_func(af.set_manual_eval_flag(False)) - assert(not af.get_manual_eval_flag()) + assert not af.get_manual_eval_flag() display_func(af.is_locked_array(a)) diff --git a/tests/simple/image.py b/tests/simple/image.py index 6f2e12186..c3bb48142 100644 --- a/tests/simple/image.py +++ b/tests/simple/image.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -86,7 +86,8 @@ def simple_image(verbose=False): a = af.randu(10, 10) b = af.canny(a, low_threshold=0.2, high_threshold=0.8) - display_func(af.anisotropic_diffusion(a, 0.125, 1.0, 64, af.FLUX.QUADRATIC, af.DIFFUSION.GRAD)) + # FIXME: OpenCL Error (-11): Build Program Failure when calling clBuildProgram + # display_func(af.anisotropic_diffusion(a, 0.125, 1.0, 64, af.FLUX.QUADRATIC, af.DIFFUSION.GRAD)) a = af.randu(10, 10) psf = af.gaussian_kernel(3, 3) diff --git a/tests/simple/index.py b/tests/simple/index.py index 8bb4b571a..1cd6229f2 100644 --- a/tests/simple/index.py +++ b/tests/simple/index.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -12,7 +12,6 @@ import array as host import arrayfire as af -from arrayfire import ParallelRange from . import _util @@ -57,12 +56,12 @@ def simple_index(verbose=False): b = af.randu(5, 1) display_func(a) display_func(b) - for ii in ParallelRange(1, 3): + for ii in af.ParallelRange(1, 3): a[ii] = b[ii] display_func(a) - for ii in ParallelRange(2, 5): + for ii in af.ParallelRange(2, 5): b[ii] = 2 display_func(b) diff --git a/tests/simple/interop.py b/tests/simple/interop.py index f07e6a770..75515f611 100644 --- a/tests/simple/interop.py +++ b/tests/simple/interop.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -13,41 +13,43 @@ from . import _util +# BUG: module 'arrayfire' has no 'to_array' member. -def simple_interop(verbose=False): + +def simple_interop(*args): if af.AF_NUMPY_FOUND: import numpy as np n = np.random.random((5,)) a = af.to_array(n) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n2[:] = 0 a.to_ndarray(n2) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3)) a = af.to_array(n) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n2[:] = 0 a.to_ndarray(n2) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3, 2)) a = af.to_array(n) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n2[:] = 0 a.to_ndarray(n2) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3, 2, 2)) a = af.to_array(n) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n2[:] = 0 a.to_ndarray(n2) - assert((n == n2).all()) + assert (n == n2).all() if af.AF_PYCUDA_FOUND and af.get_active_backend() == "cuda": import pycuda.gpuarray as cudaArray @@ -55,28 +57,28 @@ def simple_interop(verbose=False): c = cudaArray.to_gpu(n) a = af.to_array(c) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3)) c = cudaArray.to_gpu(n) a = af.to_array(c) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3, 2)) c = cudaArray.to_gpu(n) a = af.to_array(c) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3, 2, 2)) c = cudaArray.to_gpu(n) a = af.to_array(c) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() if af.AF_PYOPENCL_FOUND and af.backend.name() == "opencl": - # TODO: This needs fixing upstream + # FIXME: This needs fixing upstream # https://github.com/arrayfire/arrayfire/issues/1728 # import pyopencl as cl @@ -88,25 +90,25 @@ def simple_interop(verbose=False): # c = cl.array.to_device(queue, n) # a = af.to_array(c) # n2 = np.array(a) - # assert((n==n2).all()) + # assert (n==n2).all() # n = np.random.random((5,3)) # c = cl.array.to_device(queue, n) # a = af.to_array(c) # n2 = np.array(a) - # assert((n==n2).all()) + # assert (n==n2).all() # n = np.random.random((5,3,2)) # c = cl.array.to_device(queue, n) # a = af.to_array(c) # n2 = np.array(a) - # assert((n==n2).all()) + # assert (n==n2).all() # n = np.random.random((5,3,2,2)) # c = cl.array.to_device(queue, n) # a = af.to_array(c) # n2 = np.array(a) - # assert((n==n2).all()) + # assert (n==n2).all() pass if af.AF_NUMBA_FOUND and af.get_active_backend() == "cuda": @@ -116,25 +118,25 @@ def simple_interop(verbose=False): c = cuda.to_device(n) a = af.to_array(c) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3)) c = cuda.to_device(n) a = af.to_array(c) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3, 2)) c = cuda.to_device(n) a = af.to_array(c) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() n = np.random.random((5, 3, 2, 2)) c = cuda.to_device(n) a = af.to_array(c) n2 = np.array(a) - assert((n == n2).all()) + assert (n == n2).all() _util.tests["interop"] = simple_interop diff --git a/tests/simple/lapack.py b/tests/simple/lapack.py index 8cd3e9ac3..600e22605 100644 --- a/tests/simple/lapack.py +++ b/tests/simple/lapack.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/random.py b/tests/simple/random.py index 5152cb4e0..dcf7fbca6 100644 --- a/tests/simple/random.py +++ b/tests/simple/random.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -25,7 +25,7 @@ def simple_random(verbose=False): display_func(af.randn(3, 3, dtype=af.Dtype.c32)) af.set_seed(1024) - assert(af.get_seed() == 1024) + assert af.get_seed() == 1024 engine = af.Random_Engine(af.RANDOM_ENGINE.MERSENNE_GP11213, 100) @@ -35,7 +35,7 @@ def simple_random(verbose=False): display_func(af.randn(3, 3, engine=engine)) engine.set_seed(100) - assert(engine.get_seed() == 100) + assert engine.get_seed() == 100 _util.tests["random"] = simple_random diff --git a/tests/simple/signal.py b/tests/simple/signal.py index 0e3e8da9d..b2a337ed5 100644 --- a/tests/simple/signal.py +++ b/tests/simple/signal.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/sparse.py b/tests/simple/sparse.py index bda87dfb7..49253d97d 100644 --- a/tests/simple/sparse.py +++ b/tests/simple/sparse.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. diff --git a/tests/simple/statistics.py b/tests/simple/statistics.py index 174af0a5b..0da72cb0c 100644 --- a/tests/simple/statistics.py +++ b/tests/simple/statistics.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ####################################################### -# Copyright (c) 2015, ArrayFire +# Copyright (c) 2019, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -58,7 +58,7 @@ def simple_statistics(verbose=False): k = 3 dim = 0 order = af.TOPK.DEFAULT # defaults to af.TOPK.MAX - assert(dim == 0) # topk currently supports first dim only + assert dim == 0 # topk currently supports first dim only values, indices = af.topk(data, k, dim, order) display_func(values) display_func(indices) From 220a4ad0d9f32ef2d554c586cb80f74959de34f1 Mon Sep 17 00:00:00 2001 From: Anton Chernyatevich Date: Fri, 13 Nov 2020 23:12:48 +0200 Subject: [PATCH 2/3] Fix refactor init module --- arrayfire/__init__.py | 544 +++++++++++++++++++++++++++++++----------- arrayfire/image.py | 5 +- arrayfire/ml.py | 21 +- 3 files changed, 411 insertions(+), 159 deletions(-) diff --git a/arrayfire/__init__.py b/arrayfire/__init__.py index 5708805f3..595d9615c 100644 --- a/arrayfire/__init__.py +++ b/arrayfire/__init__.py @@ -1,5 +1,5 @@ ####################################################### -# Copyright (c) 2019, ArrayFire +# Copyright (c) 2020, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -48,150 +48,408 @@ """ -from .algorithm import ( - accum, all_true, allTrueByKey, any_true, anyTrueByKey, count, countByKey, diff1, diff2, imax, imin, max, maxByKey, min, minByKey, product, productByKey, scan, scan_by_key, set_intersect, - set_union, set_unique, sort, sort_by_key, sort_index, sum, sumByKey, where) -from .arith import ( - abs, acos, acosh, arg, asin, asinh, atan, atan2, atanh, cast, cbrt, ceil, clamp, conjg, cos, cosh, cplx, erf, erfc, exp, - expm1, factorial, floor, hypot, imag, isinf, isnan, iszero, lgamma, log, log1p, log2, log10, maxof, minof, - mod, pow, - pow2, real, rem, root, round, rsqrt, sigmoid, sign, sin, sinh, sqrt, tan, tanh, tgamma, trunc) -from .array import ( - Array, constant_array, display, get_display_dims_limit, read_array, save_array, - set_display_dims_limit, transpose, transpose_inplace) -from .base import BaseArray -from .bcast import broadcast -from .blas import dot, matmul, matmulNT, matmulTN, matmulTT, gemm -from .cuda import get_native_id, get_stream, set_native_id -from .data import ( - constant, diag, flat, flip, identity, iota, join, lookup, lower, moddims, pad, range, reorder, replace, select, shift, - tile, upper) -from .library import ( - BACKEND, BINARYOP, CANNY_THRESHOLD, COLORMAP, CONNECTIVITY, CONV_DOMAIN, CONV_GRADIENT, CONV_MODE, CSPACE, DIFFUSION, ERR, FLUX, - HOMOGRAPHY, IMAGE_FORMAT, INTERP, ITERATIVE_DECONV, INVERSE_DECONV, MARKER, MATCH, MATPROP, MOMENT, NORM, PAD, RANDOM_ENGINE, STORAGE, TOPK, VARIANCE, YCC_STD, Dtype, Source, AF_VER_MAJOR, FORGE_VER_MAJOR) -from .device import ( - alloc_device, alloc_host, alloc_pinned, device_gc, device_info, device_mem_info, eval, free_device, free_host, - free_pinned, get_device, get_device_count, get_device_ptr, get_manual_eval_flag, info, - info_str, init, is_dbl_supported, is_half_supported, is_locked_array, lock_array, lock_device_ptr, print_mem_info, set_device, - set_manual_eval_flag, sync, unlock_array, unlock_device_ptr) -from .graphics import Window -from .image import ( - anisotropic_diffusion, bilateral, canny, color_space, confidenceCC, dilate, dilate3, erode, erode3, gaussian_kernel, gradient, - gray2rgb, hist_equal, histogram, hsv2rgb, is_image_io_available, iterativeDeconv, inverseDeconv, load_image, load_image_native, maxfilt, - mean_shift, minfilt, moments, regions, resize, rgb2gray, rgb2hsv, rgb2ycbcr, rotate, sat, save_image, - save_image_native, scale, skew, sobel_derivatives, sobel_filter, transform, translate, unwrap, wrap, ycbcr2rgb) -from .index import Index, ParallelRange, Seq -from .interop import AF_NUMBA_FOUND, AF_NUMPY_FOUND, AF_PYCUDA_FOUND, AF_PYOPENCL_FOUND, to_array -from .lapack import ( - cholesky, cholesky_inplace, det, inverse, is_lapack_available, lu, lu_inplace, norm, pinverse, qr, qr_inplace, rank, solve, - solve_lu, svd, svd_inplace) -from .library import ( - get_active_backend, get_available_backends, get_backend, get_backend_count, get_backend_id, get_device_id, - get_size_of, safe_call, set_backend) -from .ml import convolve2GradientNN -from .random import ( - Random_Engine, get_default_random_engine, get_seed, randn, randu, set_default_random_engine_type, - set_seed) -from .signal import ( - approx1, approx1_uniform, approx2, approx2_uniform, convolve, convolve1, convolve2, convolve2NN, convolve2_separable, convolve3, dft, fft, fft2, fft2_c2r, - fft2_inplace, fft2_r2c, fft3, fft3_c2r, fft3_inplace, fft3_r2c, fft_c2r, fft_convolve, fft_convolve1, - fft_convolve2, fft_convolve3, fft_inplace, fft_r2c, fir, idft, ifft, ifft2, ifft2_inplace, ifft3, ifft3_inplace, - ifft_inplace, iir, medfilt, medfilt1, medfilt2, set_fft_plan_cache_size) -from .sparse import ( - convert_sparse, convert_sparse_to_dense, create_sparse, create_sparse_from_dense, create_sparse_from_host, - sparse_get_col_idx, sparse_get_info, sparse_get_nnz, sparse_get_row_idx, sparse_get_storage, sparse_get_values) -from .statistics import corrcoef, cov, mean, meanvar, median, stdev, topk, var -from .timer import timeit -from .util import dim4, dim4_to_tuple, implicit_dtype, number_dtype, to_str, get_reversion, get_version, to_dtype, to_typecode, to_c_type +# ============================================================================= +# Algorithm module +# ============================================================================= +from .algorithm import accum # noqa : E401 +from .algorithm import all_true # noqa : E401 +from .algorithm import allTrueByKey # noqa : E401 +from .algorithm import any_true # noqa : E401 +from .algorithm import anyTrueByKey # noqa : E401 +from .algorithm import count # noqa : E401 +from .algorithm import countByKey # noqa : E401 +from .algorithm import diff1 # noqa : E401 +from .algorithm import diff2 # noqa : E401 +from .algorithm import imax # noqa : E401 +from .algorithm import imin # noqa : E401 +from .algorithm import max # noqa : E401 # FIXME: do not use python reserved variable names +from .algorithm import maxByKey # noqa : E401 +from .algorithm import min # noqa : E401 # FIXME: do not use python reserved variable names +from .algorithm import minByKey # noqa : E401 +from .algorithm import product # noqa : E401 +from .algorithm import productByKey # noqa : E401 +from .algorithm import scan # noqa : E401 +from .algorithm import scan_by_key # noqa : E401 +from .algorithm import set_intersect # noqa : E401 +from .algorithm import set_union # noqa : E401 +from .algorithm import set_unique # noqa : E401 +from .algorithm import sort # noqa : E401 +from .algorithm import sort_by_key # noqa : E401 +from .algorithm import sort_index # noqa : E401 +from .algorithm import sum # noqa : E401 # FIXME: do not use python reserved variable names +from .algorithm import sumByKey # noqa : E401 +from .algorithm import where # noqa : E401 +# ============================================================================= +# Arith module +# ============================================================================= +from .arith import abs # noqa : E401 # FIXME: do not use python reserved variable names +from .arith import acos # noqa : E401 +from .arith import acosh # noqa : E401 +from .arith import arg # noqa : E401 +from .arith import asin # noqa : E401 +from .arith import asinh # noqa : E401 +from .arith import atan # noqa : E401 +from .arith import atan2 # noqa : E401 +from .arith import atanh # noqa : E401 +from .arith import cast # noqa : E401 +from .arith import cbrt # noqa : E401 +from .arith import ceil # noqa : E401 +from .arith import clamp # noqa : E401 +from .arith import conjg # noqa : E401 +from .arith import cos # noqa : E401 +from .arith import cosh # noqa : E401 +from .arith import cplx # noqa : E401 +from .arith import erf # noqa : E401 +from .arith import erfc # noqa : E401 +from .arith import exp # noqa : E401 +from .arith import expm1 # noqa : E401 +from .arith import factorial # noqa : E401 +from .arith import floor # noqa : E401 +from .arith import hypot # noqa : E401 +from .arith import imag # noqa : E401 +from .arith import isinf # noqa : E401 +from .arith import isnan # noqa : E401 +from .arith import iszero # noqa : E401 +from .arith import lgamma # noqa : E401 +from .arith import log # noqa : E401 +from .arith import log1p # noqa : E401 +from .arith import log2 # noqa : E401 +from .arith import log10 # noqa : E401 +from .arith import maxof # noqa : E401 +from .arith import minof # noqa : E401 +from .arith import mod # noqa : E401 +from .arith import pow # noqa : E401 # FIXME: do not use python reserved variable names +from .arith import pow2 # noqa : E401 +from .arith import real # noqa : E401 +from .arith import rem # noqa : E401 +from .arith import root # noqa : E401 +from .arith import round # noqa : E401 # FIXME: do not use python reserved variable names +from .arith import rsqrt # noqa : E401 +from .arith import sigmoid # noqa : E401 +from .arith import sign # noqa : E401 +from .arith import sin # noqa : E401 +from .arith import sinh # noqa : E401 +from .arith import sqrt # noqa : E401 +from .arith import tan # noqa : E401 +from .arith import tanh # noqa : E401 +from .arith import tgamma # noqa : E401 +from .arith import trunc # noqa : E401 +# ============================================================================= +# Array module +# ============================================================================= +from .array import Array # noqa : E401 +from .array import constant_array # noqa : E401 +from .array import display # noqa : E401 +from .array import get_display_dims_limit # noqa : E401 +from .array import read_array # noqa : E401 +from .array import save_array # noqa : E401 +from .array import set_display_dims_limit # noqa : E401 +from .array import transpose # noqa : E401 +from .array import transpose_inplace # noqa : E401 +# ============================================================================= +# Base module +# ============================================================================= +from .base import BaseArray # noqa : E401 +# ============================================================================= +# Bcast module +# ============================================================================= +from .bcast import broadcast # noqa : E401 +# ============================================================================= +# Blas module +# ============================================================================= +from .blas import dot # noqa : E401 +from .blas import gemm # noqa : E401 +from .blas import matmul # noqa : E401 +from .blas import matmulNT # noqa : E401 +from .blas import matmulTN # noqa : E401 +from .blas import matmulTT # noqa : E401 +# ============================================================================= +# Cuda module +# ============================================================================= +from .cuda import get_native_id # noqa : E401 +from .cuda import get_stream # noqa : E401 +from .cuda import set_native_id # noqa : E401 +# ============================================================================= +# Data module +# ============================================================================= +from .data import constant # noqa : E401 +from .data import diag # noqa : E401 +from .data import flat # noqa : E401 +from .data import flip # noqa : E401 +from .data import identity # noqa : E401 +from .data import iota # noqa : E401 +from .data import join # noqa : E401 +from .data import lookup # noqa : E401 +from .data import lower # noqa : E401 +from .data import moddims # noqa : E401 +from .data import pad # noqa : E401 +from .data import range # noqa : E401 # FIXME: do not use python reserved variable names +from .data import reorder # noqa : E401 +from .data import replace # noqa : E401 +from .data import select # noqa : E401 +from .data import shift # noqa : E401 +from .data import tile # noqa : E401 +from .data import upper # noqa : E401 +# ============================================================================= +# Device module +# ============================================================================= +from .device import alloc_device # noqa : E401 +from .device import alloc_host # noqa : E401 +from .device import alloc_pinned # noqa : E401 +from .device import device_gc # noqa : E401 +from .device import device_info # noqa : E401 +from .device import device_mem_info # noqa : E401 +from .device import eval # noqa : E401 # FIXME: do not use python reserved variable names +from .device import free_device # noqa : E401 +from .device import free_host # noqa : E401 +from .device import free_pinned # noqa : E401 +from .device import get_device # noqa : E401 +from .device import get_device_count # noqa : E401 +from .device import get_device_ptr # noqa : E401 +from .device import get_manual_eval_flag # noqa : E401 +from .device import info # noqa : E401 +from .device import info_str # noqa : E401 +from .device import init # noqa : E401 +from .device import is_dbl_supported # noqa : E401 +from .device import is_half_supported # noqa : E401 +from .device import is_locked_array # noqa : E401 +from .device import lock_array # noqa : E401 +from .device import lock_device_ptr # noqa : E401 +from .device import print_mem_info # noqa : E401 +from .device import set_device # noqa : E401 +from .device import set_manual_eval_flag # noqa : E401 +from .device import sync # noqa : E401 +from .device import unlock_array # noqa : E401 +from .device import unlock_device_ptr # noqa : E401 +# ============================================================================= +# Graphics module +# ============================================================================= +from .graphics import Window # noqa : E401 +# ============================================================================= +# Image module +# ============================================================================= +from .image import ITERATIVE_DECONV # noqa : E401 +from .image import anisotropic_diffusion # noqa : E401 +from .image import bilateral # noqa : E401 +from .image import canny # noqa : E401 +from .image import color_space # noqa : E401 +from .image import confidenceCC # noqa : E401 +from .image import dilate # noqa : E401 +from .image import dilate3 # noqa : E401 +from .image import erode # noqa : E401 +from .image import erode3 # noqa : E401 +from .image import gaussian_kernel # noqa : E401 +from .image import gradient # noqa : E401 +from .image import gray2rgb # noqa : E401 +from .image import hist_equal # noqa : E401 +from .image import histogram # noqa : E401 +from .image import hsv2rgb # noqa : E401 +from .image import is_image_io_available # noqa : E401 +from .image import inverseDeconv # noqa : E401 +from .image import iterativeDeconv # noqa : E401 +from .image import load_image # noqa : E401 +from .image import load_image_native # noqa : E401 +from .image import maxfilt # noqa : E401 +from .image import mean_shift # noqa : E401 +from .image import minfilt # noqa : E401 +from .image import moments # noqa : E401 +from .image import regions # noqa : E401 +from .image import resize # noqa : E401 +from .image import rgb2gray # noqa : E401 +from .image import rgb2hsv # noqa : E401 +from .image import rgb2ycbcr # noqa : E401 +from .image import rotate # noqa : E401 +from .image import sat # noqa : E401 +from .image import save_image # noqa : E401 +from .image import save_image_native # noqa : E401 +from .image import scale # noqa : E401 +from .image import skew # noqa : E401 +from .image import sobel_derivatives # noqa : E401 +from .image import sobel_filter # noqa : E401 +from .image import transform # noqa : E401 +from .image import translate # noqa : E401 +from .image import unwrap # noqa : E401 +from .image import wrap # noqa : E401 +from .image import ycbcr2rgb # noqa : E401 +# ============================================================================= +# Index module +# ============================================================================= +from .index import Index # noqa : E401 +from .index import ParallelRange # noqa : E401 +from .index import Seq # noqa : E401 +# ============================================================================= +# Interop module +# ============================================================================= +from .interop import AF_NUMBA_FOUND # noqa : E401 +from .interop import AF_NUMPY_FOUND # noqa : E401 +from .interop import AF_PYCUDA_FOUND # noqa : E401 +from .interop import AF_PYOPENCL_FOUND # noqa : E401 +from .interop import to_array # noqa : E401 +# ============================================================================= +# Lapack module +# ============================================================================= +from .lapack import cholesky # noqa : E401 +from .lapack import cholesky_inplace # noqa : E401 +from .lapack import det # noqa : E401 +from .lapack import inverse # noqa : E401 +from .lapack import is_lapack_available # noqa : E401 +from .lapack import lu # noqa : E401 +from .lapack import lu_inplace # noqa : E401 +from .lapack import norm # noqa : E401 +from .lapack import pinverse # noqa : E401 +from .lapack import qr # noqa : E401 +from .lapack import qr_inplace # noqa : E401 +from .lapack import rank # noqa : E401 +from .lapack import solve # noqa : E401 +from .lapack import solve_lu # noqa : E401 +from .lapack import svd # noqa : E401 +from .lapack import svd_inplace # noqa : E401 +# ============================================================================= +# Library module +# ============================================================================= +from .library import AF_VER_MAJOR # noqa : E401 +from .library import BACKEND # noqa : E401 +from .library import BINARYOP # noqa : E401 +from .library import CANNY_THRESHOLD # noqa : E401 +from .library import COLORMAP # noqa : E401 +from .library import CONNECTIVITY # noqa : E401 +from .library import CONV_DOMAIN # noqa : E401 +from .library import CONV_GRADIENT # noqa : E401 +from .library import CONV_MODE # noqa : E401 +from .library import CSPACE # noqa : E401 +from .library import DIFFUSION # noqa : E401 +from .library import ERR # noqa : E401 +from .library import FLUX # noqa : E401 +from .library import FORGE_VER_MAJOR # noqa : E401 +from .library import HOMOGRAPHY # noqa : E401 +from .library import IMAGE_FORMAT # noqa : E401 +from .library import INTERP # noqa : E401 +from .library import INVERSE_DECONV # noqa : E401 +from .library import ITERATIVE_DECONV # noqa : E401 +from .library import MARKER # noqa : E401 +from .library import MATCH # noqa : E401 +from .library import MATPROP # noqa : E401 +from .library import MOMENT # noqa : E401 +from .library import NORM # noqa : E401 +from .library import PAD # noqa : E401 +from .library import RANDOM_ENGINE # noqa : E401 +from .library import STORAGE # noqa : E401 +from .library import TOPK # noqa : E401 +from .library import VARIANCE # noqa : E401 +from .library import YCC_STD # noqa : E401 +from .library import Dtype # noqa : E401 +from .library import Source # noqa : E401 +from .library import get_active_backend # noqa : E401 +from .library import get_available_backends # noqa : E401 +from .library import get_backend # noqa : E401 +from .library import get_backend_count # noqa : E401 +from .library import get_backend_id # noqa : E401 +from .library import get_device_id # noqa : E401 +from .library import get_size_of # noqa : E401 +from .library import safe_call # noqa : E401 +from .library import set_backend # noqa : E401 +# ============================================================================= +# Machine Learning (ML) module +# ============================================================================= +from .ml import convolve2GradientNN # noqa : E401 +# ============================================================================= +# Random module +# ============================================================================= +from .random import Random_Engine # noqa : E401 +from .random import get_default_random_engine # noqa : E401 +from .random import get_seed # noqa : E401 +from .random import randn # noqa : E401 +from .random import randu # noqa : E401 +from .random import set_default_random_engine_type # noqa : E401 +from .random import set_seed # noqa : E401 +# ============================================================================= +# Signal module +# ============================================================================= +from .signal import approx1 # noqa : E401 +from .signal import approx1_uniform # noqa : E401 +from .signal import approx2 # noqa : E401 +from .signal import approx2_uniform # noqa : E401 +from .signal import convolve # noqa : E401 +from .signal import convolve1 # noqa : E401 +from .signal import convolve2 # noqa : E401 +from .signal import convolve2_separable # noqa : E401 +from .signal import convolve2NN # noqa : E401 +from .signal import convolve3 # noqa : E401 +from .signal import dft # noqa : E401 +from .signal import fft # noqa : E401 +from .signal import fft2 # noqa : E401 +from .signal import fft2_c2r # noqa : E401 +from .signal import fft2_inplace # noqa : E401 +from .signal import fft2_r2c # noqa : E401 +from .signal import fft3 # noqa : E401 +from .signal import fft3_c2r # noqa : E401 +from .signal import fft3_inplace # noqa : E401 +from .signal import fft3_r2c # noqa : E401 +from .signal import fft_c2r # noqa : E401 +from .signal import fft_convolve # noqa : E401 +from .signal import fft_convolve1 # noqa : E401 +from .signal import fft_convolve2 # noqa : E401 +from .signal import fft_convolve3 # noqa : E401 +from .signal import fft_inplace # noqa : E401 +from .signal import fft_r2c # noqa : E401 +from .signal import fir # noqa : E401 +from .signal import idft # noqa : E401 +from .signal import ifft # noqa : E401 +from .signal import ifft2 # noqa : E401 +from .signal import ifft2_inplace # noqa : E401 +from .signal import ifft3 # noqa : E401 +from .signal import ifft3_inplace # noqa : E401 +from .signal import ifft_inplace # noqa : E401 +from .signal import iir # noqa : E401 +from .signal import medfilt # noqa : E401 +from .signal import medfilt1 # noqa : E401 +from .signal import medfilt2 # noqa : E401 +from .signal import set_fft_plan_cache_size # noqa : E401 +# ============================================================================= +# Sparse module +# ============================================================================= +from .sparse import convert_sparse # noqa : E401 +from .sparse import convert_sparse_to_dense # noqa : E401 +from .sparse import create_sparse # noqa : E401 +from .sparse import create_sparse_from_dense # noqa : E401 +from .sparse import create_sparse_from_host # noqa : E401 +from .sparse import sparse_get_col_idx # noqa : E401 +from .sparse import sparse_get_info # noqa : E401 +from .sparse import sparse_get_nnz # noqa : E401 +from .sparse import sparse_get_row_idx # noqa : E401 +from .sparse import sparse_get_storage # noqa : E401 +from .sparse import sparse_get_values # noqa : E401 +# ============================================================================= +# Statistics module +# ============================================================================= +from .statistics import corrcoef # noqa : E401 +from .statistics import cov # noqa : E401 +from .statistics import mean # noqa : E401 +from .statistics import meanvar # noqa : E401 +from .statistics import median # noqa : E401 +from .statistics import stdev # noqa : E401 +from .statistics import topk # noqa : E401 +from .statistics import var # noqa : E401 +# ============================================================================= +# Timer module +# ============================================================================= +from .timer import timeit # noqa : E401 +# ============================================================================= +# Utils module +# ============================================================================= +from .util import dim4 # noqa : E401 +from .util import dim4_to_tuple # noqa : E401 +from .util import get_reversion # noqa : E401 +from .util import get_version # noqa : E401 +from .util import implicit_dtype # noqa : E401 +from .util import number_dtype # noqa : E401 +from .util import to_c_type # noqa : E401 +from .util import to_dtype # noqa : E401 +from .util import to_str # noqa : E401 +from .util import to_typecode # noqa : E401 try: # FIXME: pycuda imported but unused - import pycuda.autoinit + import pycuda.autoinit # noqa : E401 except ImportError: pass - - -__all__ = [ - # algorithm - "accum", "all_true", "allTrueByKey", "any_true", "anyTrueByKey", "count", "countByKey", - "diff1", "diff2", "imax", "imin", "max", "maxByKey", "min", "minByKey", "product", - "productByKey", "scan", "scan_by_key", "set_intersect", "set_union", "set_unique", - "sort", "sort_by_key", "sort_index", "sum", "sumByKey", "where", - # arith - "abs", "acos", "acosh", "arg", "asin", "asinh", "atan", "atan2", "atanh", - "cast", "cbrt", "ceil", "clamp", "conjg", "cos", "cosh", "cplx", "erf", - "erfc", "exp", "expm1", "factorial", "floor", "hypot", "imag", "isinf", - "isnan", "iszero", "lgamma", "log", "log1p", "log2", "log10", "maxof", - "minof", "mod", "pow", "pow2", "real", "rem", "root", "round", "rsqrt", - "sigmoid", "sign", "sin", "sinh", "sqrt", "tan", "tanh", "tgamma", "trunc", - # array - "Array", "constant_array", "display", "get_display_dims_limit", "read_array", - "save_array", "set_display_dims_limit", "transpose", "transpose_inplace", - # base - "BaseArray", - # bcast - "broadcast", - # blas - "dot", "matmul", "matmulNT", "matmulTN", "matmulTT", "gemm", - #cuda - "get_native_id", "get_stream", "set_native_id", - # data - "constant", "diag", "flat", "flip", "identity", "iota", "join", "lookup", - "lower", "moddims", "pad", "range", "reorder", "replace", "select", - "shift", "tile", "upper", - # library - "BACKEND", "BINARYOP", "CANNY_THRESHOLD", "COLORMAP", "CONNECTIVITY", "CONV_DOMAIN", - "CONV_GRADIENT", "CONV_MODE", "CSPACE", "DIFFUSION", "ERR", "FLUX", "HOMOGRAPHY", - "IMAGE_FORMAT", "INTERP", "ITERATIVE_DECONV", "INVERSE_DECONV", "MARKER", "MATCH", - "MATPROP", "MOMENT", "NORM", "PAD", "RANDOM_ENGINE", "STORAGE", "TOPK", "VARIANCE", - "YCC_STD", "Dtype", "Source", "AF_VER_MAJOR", "FORGE_VER_MAJOR", - # device - "alloc_device", "alloc_host", "alloc_pinned", "device_gc", "device_info", "device_mem_info", - "eval", "free_device", "free_host", "free_pinned", "get_device", "get_device_count", - "get_device_ptr", "get_manual_eval_flag", "info", "info_str", "init", "is_dbl_supported", - "is_half_supported", "is_locked_array", "lock_array", "lock_device_ptr", "print_mem_info", - "set_device", "set_manual_eval_flag", "sync", "unlock_array", "unlock_device_ptr", - # graphics - "Window", - # image - "anisotropic_diffusion", "bilateral", "canny", "color_space", "confidenceCC", "dilate", "dilate3", - "erode", "erode3", "gaussian_kernel", "gradient", "gray2rgb", "hist_equal", "histogram", "hsv2rgb", - "is_image_io_available", "iterativeDeconv", "inverseDeconv", "load_image", "load_image_native", - "maxfilt", "mean_shift", "minfilt", "moments", "regions", "resize", "rgb2gray", "rgb2hsv", "rgb2ycbcr", - "rotate", "sat", "save_image", "save_image_native", "scale", "skew", "sobel_derivatives", "sobel_filter", - "transform", "translate", "unwrap", "wrap", "ycbcr2rgb", - # index - "Index", "ParallelRange", "Seq", - # interop - "AF_NUMBA_FOUND", "AF_NUMPY_FOUND", "AF_PYCUDA_FOUND", "AF_PYOPENCL_FOUND", "to_array", - # lapack - "cholesky", "cholesky_inplace", "det", "inverse", "is_lapack_available", "lu", "lu_inplace", - "norm", "pinverse", "qr", "qr_inplace", "rank", "solve", "solve_lu", "svd", "svd_inplace", - # library - "get_active_backend", "get_available_backends", "get_backend", "get_backend_count", - "get_backend_id", "get_device_id", "get_size_of", "safe_call", "set_backend", - # ml - "convolve2GradientNN", - # random - "Random_Engine", "get_default_random_engine", "get_seed", "randn", "randu", - "set_default_random_engine_type", "set_seed", - # signal - "approx1", "approx1_uniform", "approx2", "approx2_uniform", "convolve", "convolve1", - "convolve2", "convolve2NN", "convolve2_separable", "convolve3", "dft", "fft", - "fft2", "fft2_c2r", "fft2_inplace", "fft2_r2c", "fft3", "fft3_c2r", "fft3_inplace", - "fft3_r2c", "fft_c2r", "fft_convolve", "fft_convolve1", "fft_convolve2", "fft_convolve3", - "fft_inplace", "fft_r2c", "fir", "idft", "ifft", "ifft2", "ifft2_inplace", "ifft3", - "ifft3_inplace", "ifft_inplace", "iir", "medfilt", "medfilt1", "medfilt2", - "set_fft_plan_cache_size", - # sparse - "convert_sparse", "convert_sparse_to_dense", "create_sparse", "create_sparse_from_dense", - "create_sparse_from_host", "sparse_get_col_idx", "sparse_get_info", "sparse_get_nnz", - "sparse_get_row_idx", "sparse_get_storage", "sparse_get_values", - # statistics - "corrcoef", "cov", "mean", "meanvar", "median", "stdev", "topk", "var", - # timer - "timeit", - # util - "dim4", "dim4_to_tuple", "implicit_dtype", "number_dtype", "to_str", "get_reversion", - "get_version", "to_dtype", "to_typecode", "to_c_type" -] diff --git a/arrayfire/image.py b/arrayfire/image.py index 325ee909b..9e4de7fe0 100644 --- a/arrayfire/image.py +++ b/arrayfire/image.py @@ -1368,9 +1368,8 @@ def iterativeDeconv(image, psf, iterations, relax_factor, algo = ITERATIVE_DECON """ out = Array() - safe_call(backend.get(). - af_iterative_deconv(c_pointer(out.arr), image.arr, psf.arr, - c_uint_t(iterations), c_float_t(relax_factor), algo.value)) + safe_call(backend.get().af_iterative_deconv( + c_pointer(out.arr), image.arr, psf.arr, c_uint_t(iterations), c_float_t(relax_factor), algo.value)) return out def inverseDeconv(image, psf, gamma, algo = ITERATIVE_DECONV.DEFAULT): diff --git a/arrayfire/ml.py b/arrayfire/ml.py index 5f612ca59..d8249c1f8 100644 --- a/arrayfire/ml.py +++ b/arrayfire/ml.py @@ -17,7 +17,10 @@ from .library import backend, safe_call, c_pointer, CONV_GRADIENT from .util import dim4 -def convolve2GradientNN(incoming_gradient, original_signal, original_kernel, convolved_output, stride = (1, 1), padding = (0, 0), dilation = (1, 1), gradType = CONV_GRADIENT.DEFAULT): + +def convolve2GradientNN( + incoming_gradient, original_signal, original_kernel, convolved_output, stride=(1, 1), padding=(0, 0), + dilation=(1, 1), gradType=CONV_GRADIENT.DEFAULT): """ Function for calculating backward pass gradient of 2D convolution. @@ -66,19 +69,11 @@ def convolve2GradientNN(incoming_gradient, original_signal, original_kernel, con """ output = Array() - stride_dim = dim4(stride[0], stride[1]) - padding_dim = dim4(padding[0], padding[1]) + stride_dim = dim4(stride[0], stride[1]) + padding_dim = dim4(padding[0], padding[1]) dilation_dim = dim4(dilation[0], dilation[1]) safe_call(backend.get().af_convolve2_gradient_nn( - c_pointer(output.arr), - incoming_gradient.arr, - original_signal.arr, - original_kernel.arr, - convolved_output.arr, - 2, c_pointer(stride_dim), - 2, c_pointer(padding_dim), - 2, c_pointer(dilation_dim), - gradType.value)) + c_pointer(output.arr), incoming_gradient.arr, original_signal.arr, original_kernel.arr, convolved_output.arr, + 2, c_pointer(stride_dim), 2, c_pointer(padding_dim), 2, c_pointer(dilation_dim), gradType.value)) return output - From 28a0f610c5329ebc718ce4d924f870c3651bfb3e Mon Sep 17 00:00:00 2001 From: Anton Chernyatevich Date: Fri, 13 Nov 2020 04:43:28 +0200 Subject: [PATCH 3/3] Fix minimal required python version --- .gitignore | 39 +++++++-------------------------------- __af_version__.py | 14 -------------- docs/conf.py | 6 +++++- setup.cfg | 6 ++++-- 4 files changed, 16 insertions(+), 49 deletions(-) delete mode 100644 __af_version__.py diff --git a/.gitignore b/.gitignore index aa7bb5f1d..8d944a440 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ __pycache__/ *.so # Distribution / packaging -.Python env/ build/ develop-eggs/ @@ -23,39 +22,15 @@ var/ .installed.cfg *.egg -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*,cover - -# Translations -*.mo -*.pot - -# Django stuff: -*.log - # Sphinx documentation docs/_build/ -# PyBuilder -target/ +# Environments +env +venv +.env +.venv -# IDE -.idea +# IDEs .vscode +.idea diff --git a/__af_version__.py b/__af_version__.py deleted file mode 100644 index c8d51d332..000000000 --- a/__af_version__.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python - -####################################################### -# Copyright (c) 2019, 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 -######################################################## - -version = "3.7" -release = "20200213" -full_version = version + "." + release diff --git a/docs/conf.py b/docs/conf.py index 2575ef34a..b68eb8e81 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,8 +19,12 @@ # import os import sys +from configparser import ConfigParser -from __af_version__ import full_version + +config = ConfigParser() +config.read(os.path.abspath("setup.cfg")) +full_version = config.get("metadata", "version") sys.path.insert(0, os.path.abspath('..')) diff --git a/setup.cfg b/setup.cfg index 831f2063b..5f6ccf0ed 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = arrayfire -version = 3.7.20200213 +version = 3.7.20201113 description = Python bindings for ArrayFire licence = BSD long_description = file: README.md @@ -9,12 +9,14 @@ maintainer_email = technical@arrayfire.com url = http://arrayfire.com classifiers = Programming Language :: Python - Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] packages = find: +python_requires = >=3.6.0 [options.packages.find] include = arrayfire pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy