#######################################################
# Copyright (c) 2015, ArrayFire
# All rights reserved.
#
# This file is distributed under 3-clause BSD license.
# The complete license agreement can be obtained at:
# http://arrayfire.com/licenses/BSD-3-Clause
########################################################
"""
Module containing enums and other constants.
"""
import platform
import ctypes as ct
import traceback
import os
import sys
c_float_t = ct.c_float
c_double_t = ct.c_double
c_int_t = ct.c_int
c_uint_t = ct.c_uint
c_longlong_t = ct.c_longlong
c_ulonglong_t = ct.c_ulonglong
c_char_t = ct.c_char
c_bool_t = ct.c_bool
c_uchar_t = ct.c_ubyte
c_short_t = ct.c_short
c_ushort_t = ct.c_ushort
c_pointer = ct.pointer
c_void_ptr_t = ct.c_void_p
c_char_ptr_t = ct.c_char_p
c_size_t = ct.c_size_t
c_cast = ct.cast
[docs]class af_cfloat_t(ct.Structure):
_fields_ = [("real", ct.c_float), ("imag", ct.c_float)]
[docs]class af_cdouble_t(ct.Structure):
_fields_ = [("real", ct.c_double), ("imag", ct.c_double)]
AF_VER_MAJOR = '3'
FORGE_VER_MAJOR = '1'
# Work around for unexpected architectures
if 'c_dim_t_forced' in globals():
global c_dim_t_forced
c_dim_t = c_dim_t_forced
else:
# dim_t is long long by default
c_dim_t = c_longlong_t
# Change to int for 32 bit x86 and amr architectures
if (platform.architecture()[0][0:2] == '32' and
(platform.machine()[-2:] == '86' or
platform.machine()[0:3] == 'arm')):
c_dim_t = c_int_t
try:
from enum import Enum as _Enum
def _Enum_Type(v):
return v
except ImportError:
class _MetaEnum(type):
def __init__(cls, name, bases, attrs):
for attrname, attrvalue in attrs.iteritems():
if name != '_Enum' and isinstance(attrvalue, _Enum_Type):
attrvalue.__class__ = cls
attrs[attrname] = attrvalue
class _Enum(object):
__metaclass__ = _MetaEnum
class _Enum_Type(object):
def __init__(self, v):
self.value = v
[docs]class ERR(_Enum):
"""
Error values. For internal use only.
"""
NONE = _Enum_Type(0)
#100-199 Errors in environment
NO_MEM = _Enum_Type(101)
DRIVER = _Enum_Type(102)
RUNTIME = _Enum_Type(103)
# 200-299 Errors in input parameters
INVALID_ARRAY = _Enum_Type(201)
ARG = _Enum_Type(202)
SIZE = _Enum_Type(203)
TYPE = _Enum_Type(204)
DIFF_TYPE = _Enum_Type(205)
BATCH = _Enum_Type(207)
DEVICE = _Enum_Type(208)
# 300-399 Errors for missing software features
NOT_SUPPORTED = _Enum_Type(301)
NOT_CONFIGURED = _Enum_Type(302)
NONFREE = _Enum_Type(303)
# 400-499 Errors for missing hardware features
NO_DBL = _Enum_Type(401)
NO_GFX = _Enum_Type(402)
NO_HALF = _Enum_Type(403)
# 500-599 Errors specific to the heterogeneous API
LOAD_LIB = _Enum_Type(501)
LOAD_SYM = _Enum_Type(502)
ARR_BKND_MISMATCH = _Enum_Type(503)
# 900-999 Errors from upstream libraries and runtimes
INTERNAL = _Enum_Type(998)
UNKNOWN = _Enum_Type(999)
[docs]class Dtype(_Enum):
"""
Error values. For internal use only.
"""
f32 = _Enum_Type(0)
c32 = _Enum_Type(1)
f64 = _Enum_Type(2)
c64 = _Enum_Type(3)
b8 = _Enum_Type(4)
s32 = _Enum_Type(5)
u32 = _Enum_Type(6)
u8 = _Enum_Type(7)
s64 = _Enum_Type(8)
u64 = _Enum_Type(9)
s16 = _Enum_Type(10)
u16 = _Enum_Type(11)
f16 = _Enum_Type(12)
[docs]class Source(_Enum):
"""
Source of the pointer
"""
device = _Enum_Type(0)
host = _Enum_Type(1)
[docs]class INTERP(_Enum):
"""
Interpolation method
"""
NEAREST = _Enum_Type(0)
LINEAR = _Enum_Type(1)
BILINEAR = _Enum_Type(2)
CUBIC = _Enum_Type(3)
LOWER = _Enum_Type(4)
LINEAR_COSINE = _Enum_Type(5)
BILINEAR_COSINE = _Enum_Type(6)
BICUBIC = _Enum_Type(7)
CUBIC_SPLINE = _Enum_Type(8)
BICUBIC_SPLINE = _Enum_Type(9)
[docs]class PAD(_Enum):
"""
Edge padding types
"""
ZERO = _Enum_Type(0)
SYM = _Enum_Type(1)
CLAMP_TO_EDGE = _Enum_Type(2)
PERIODIC = _Enum_Type(3)
[docs]class CONNECTIVITY(_Enum):
"""
Neighborhood connectivity
"""
FOUR = _Enum_Type(4)
EIGHT = _Enum_Type(8)
[docs]class CONV_MODE(_Enum):
"""
Convolution mode
"""
DEFAULT = _Enum_Type(0)
EXPAND = _Enum_Type(1)
[docs]class CONV_DOMAIN(_Enum):
"""
Convolution domain
"""
AUTO = _Enum_Type(0)
SPATIAL = _Enum_Type(1)
FREQ = _Enum_Type(2)
[docs]class CONV_GRADIENT(_Enum):
"""
Convolution gradient type
"""
DEFAULT = _Enum_Type(0)
FILTER = _Enum_Type(1)
DATA = _Enum_Type(2)
BIAS = _Enum_Type(3)
[docs]class MATCH(_Enum):
"""
Match type
"""
"""
Sum of absolute differences
"""
SAD = _Enum_Type(0)
"""
Zero mean SAD
"""
ZSAD = _Enum_Type(1)
"""
Locally scaled SAD
"""
LSAD = _Enum_Type(2)
"""
Sum of squared differences
"""
SSD = _Enum_Type(3)
"""
Zero mean SSD
"""
ZSSD = _Enum_Type(4)
"""
Locally scaled SSD
"""
LSSD = _Enum_Type(5)
"""
Normalized cross correlation
"""
NCC = _Enum_Type(6)
"""
Zero mean NCC
"""
ZNCC = _Enum_Type(7)
"""
Sum of hamming distances
"""
SHD = _Enum_Type(8)
[docs]class YCC_STD(_Enum):
"""
YCC Standard formats
"""
BT_601 = _Enum_Type(601)
BT_709 = _Enum_Type(709)
BT_2020 = _Enum_Type(2020)
[docs]class CSPACE(_Enum):
"""
Colorspace formats
"""
GRAY = _Enum_Type(0)
RGB = _Enum_Type(1)
HSV = _Enum_Type(2)
YCbCr= _Enum_Type(3)
[docs]class MATPROP(_Enum):
"""
Matrix properties
"""
"""
None, general.
"""
NONE = _Enum_Type(0)
"""
Transposed.
"""
TRANS = _Enum_Type(1)
"""
Conjugate transposed.
"""
CTRANS = _Enum_Type(2)
"""
Upper triangular matrix.
"""
UPPER = _Enum_Type(32)
"""
Lower triangular matrix.
"""
LOWER = _Enum_Type(64)
"""
Treat diagonal as units.
"""
DIAG_UNIT = _Enum_Type(128)
"""
Symmetric matrix.
"""
SYM = _Enum_Type(512)
"""
Positive definite matrix.
"""
POSDEF = _Enum_Type(1024)
"""
Orthogonal matrix.
"""
ORTHOG = _Enum_Type(2048)
"""
Tri diagonal matrix.
"""
TRI_DIAG = _Enum_Type(4096)
"""
Block diagonal matrix.
"""
BLOCK_DIAG = _Enum_Type(8192)
[docs]class NORM(_Enum):
"""
Norm types
"""
VECTOR_1 = _Enum_Type(0)
VECTOR_INF = _Enum_Type(1)
VECTOR_2 = _Enum_Type(2)
VECTOR_P = _Enum_Type(3)
MATRIX_1 = _Enum_Type(4)
MATRIX_INF = _Enum_Type(5)
MATRIX_2 = _Enum_Type(6)
MATRIX_L_PQ = _Enum_Type(7)
EUCLID = VECTOR_2
[docs]class COLORMAP(_Enum):
"""
Colormaps
"""
DEFAULT = _Enum_Type(0)
SPECTRUM = _Enum_Type(1)
COLORS = _Enum_Type(2)
RED = _Enum_Type(3)
MOOD = _Enum_Type(4)
HEAT = _Enum_Type(5)
BLUE = _Enum_Type(6)
[docs]class HOMOGRAPHY(_Enum):
"""
Homography Types
"""
RANSAC = _Enum_Type(0)
LMEDS = _Enum_Type(1)
[docs]class BACKEND(_Enum):
"""
Backend libraries
"""
DEFAULT = _Enum_Type(0)
CPU = _Enum_Type(1)
CUDA = _Enum_Type(2)
OPENCL = _Enum_Type(4)
[docs]class MARKER(_Enum):
"""
Markers used for different points in graphics plots
"""
NONE = _Enum_Type(0)
POINT = _Enum_Type(1)
CIRCLE = _Enum_Type(2)
SQUARE = _Enum_Type(3)
TRIANGE = _Enum_Type(4)
CROSS = _Enum_Type(5)
PLUS = _Enum_Type(6)
STAR = _Enum_Type(7)
[docs]class MOMENT(_Enum):
"""
Image Moments types
"""
M00 = _Enum_Type(1)
M01 = _Enum_Type(2)
M10 = _Enum_Type(4)
M11 = _Enum_Type(8)
FIRST_ORDER = _Enum_Type(15)
[docs]class BINARYOP(_Enum):
"""
Binary Operators
"""
ADD = _Enum_Type(0)
MUL = _Enum_Type(1)
MIN = _Enum_Type(2)
MAX = _Enum_Type(3)
[docs]class RANDOM_ENGINE(_Enum):
"""
Random engine types
"""
PHILOX_4X32_10 = _Enum_Type(100)
THREEFRY_2X32_16 = _Enum_Type(200)
MERSENNE_GP11213 = _Enum_Type(300)
PHILOX = PHILOX_4X32_10
THREEFRY = THREEFRY_2X32_16
DEFAULT = PHILOX
[docs]class STORAGE(_Enum):
"""
Matrix Storage types
"""
DENSE = _Enum_Type(0)
CSR = _Enum_Type(1)
CSC = _Enum_Type(2)
COO = _Enum_Type(3)
[docs]class CANNY_THRESHOLD(_Enum):
"""
Canny Edge Threshold types
"""
MANUAL = _Enum_Type(0)
AUTO_OTSU = _Enum_Type(1)
[docs]class FLUX(_Enum):
"""
Flux functions
"""
DEFAULT = _Enum_Type(0)
QUADRATIC = _Enum_Type(1)
EXPONENTIAL = _Enum_Type(2)
[docs]class DIFFUSION(_Enum):
"""
Diffusion equations
"""
DEFAULT = _Enum_Type(0)
GRAD = _Enum_Type(1)
MCDE = _Enum_Type(2)
[docs]class TOPK(_Enum):
"""
Top-K ordering
"""
DEFAULT = _Enum_Type(0)
MIN = _Enum_Type(1)
MAX = _Enum_Type(2)
[docs]class ITERATIVE_DECONV(_Enum):
"""
Iterative deconvolution algorithm
"""
DEFAULT = _Enum_Type(0)
LANDWEBER = _Enum_Type(1)
RICHARDSONLUCY = _Enum_Type(2)
[docs]class INVERSE_DECONV(_Enum):
"""
Inverse deconvolution algorithm
"""
DEFAULT = _Enum_Type(0)
TIKHONOV = _Enum_Type(1)
[docs]class VARIANCE(_Enum):
"""
Variance bias type
"""
DEFAULT = _Enum_Type(0)
SAMPLE = _Enum_Type(1)
POPULATION = _Enum_Type(2)
_VER_MAJOR_PLACEHOLDER = "__VER_MAJOR__"
def _setup():
platform_name = platform.system()
try:
AF_PATH = os.environ['AF_PATH']
except KeyError:
AF_PATH = None
pass
AF_SEARCH_PATH = AF_PATH
try:
CUDA_PATH = os.environ['CUDA_PATH']
except KeyError:
CUDA_PATH= None
pass
CUDA_FOUND = False
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
'''
ct.windll.kernel32.SetErrorMode(0x0001 | 0x0002)
if AF_SEARCH_PATH is None:
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':
## OSX specific setup
pre = 'lib'
post = '.' + _VER_MAJOR_PLACEHOLDER + '.dylib'
if AF_SEARCH_PATH is None:
if os.path.exists('/opt/arrayfire'):
AF_SEARCH_PATH = '/opt/arrayfire/'
else:
AF_SEARCH_PATH = '/usr/local/'
if CUDA_PATH is None:
CUDA_PATH='/usr/local/cuda/'
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
if AF_SEARCH_PATH is None:
if os.path.exists('/opt/arrayfire-' + AF_VER_MAJOR + '/'):
AF_SEARCH_PATH = '/opt/arrayfire-' + AF_VER_MAJOR + '/'
elif os.path.exists('/opt/arrayfire/'):
AF_SEARCH_PATH = '/opt/arrayfire/'
else:
AF_SEARCH_PATH = '/usr/local/'
if CUDA_PATH is None:
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')
else:
CUDA_FOUND = os.path.isdir(CUDA_PATH + '/lib') and os.path.isdir(CUDA_PATH + '/nvvm/lib')
else:
raise OSError(platform_name + ' not supported')
return pre, post, AF_PATH, AF_SEARCH_PATH, CUDA_FOUND
class _clibrary(object):
def __find_nvrtc_builtins_libname(self, search_path):
filelist = os.listdir(search_path)
for f in filelist:
if 'nvrtc-builtins' in f:
return f
return None
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 self.AF_PATH:
if os.path.isdir(self.AF_PATH + '/lib64'):
path_search = self.AF_PATH + '/lib64/'
else:
path_search = self.AF_PATH + '/lib/'
else:
if os.path.isdir(self.AF_SEARCH_PATH + '/lib64'):
path_search = self.AF_SEARCH_PATH + '/lib64/'
else:
path_search = self.AF_SEARCH_PATH + '/lib/'
if platform.architecture()[0][:2] == '64':
path_site = sys.prefix + '/lib64/'
else:
path_site = sys.prefix + '/lib/'
path_local = self.AF_PYMODULE_PATH
libpaths = [('', libname),
(path_site, libname),
(path_local,libname)]
if self.AF_PATH: #prefer specified AF_PATH if exists
libpaths.append((path_search, libname))
else:
libpaths.insert(2, (path_search, libname))
return libpaths
def set_unsafe(self, name):
lib = self.__clibs[name]
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, AF_SEARCH_PATH, CUDA_FOUND = _setup()
self.__pre = pre
self.__post = post
self.AF_PATH = AF_PATH
self.AF_SEARCH_PATH = AF_SEARCH_PATH
self.CUDA_FOUND = CUDA_FOUND
# prefer locally packaged arrayfire libraries if they exist
af_module = __import__(__name__)
self.AF_PYMODULE_PATH = af_module.__path__[0] + '/' if af_module.__path__ else None
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}
# Try to pre-load forge library if it exists
libnames = reversed(self.__libname('forge', head='', ver_major=FORGE_VER_MAJOR))
try:
VERBOSE_LOADS = os.environ['AF_VERBOSE_LOADS'] == '1'
except KeyError:
VERBOSE_LOADS = False
pass
for libname in libnames:
try:
full_libname = libname[0] + libname[1]
ct.cdll.LoadLibrary(full_libname)
if VERBOSE_LOADS:
print('Loaded ' + full_libname)
break
except OSError:
if VERBOSE_LOADS:
traceback.print_exc()
print('Unable to load ' + full_libname)
pass
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', ''):
libnames = reversed(self.__libname(name))
for libname in libnames:
try:
full_libname = libname[0] + libname[1]
ct.cdll.LoadLibrary(full_libname)
__name = 'unified' if name == '' else name
clib = ct.CDLL(full_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 ' + full_libname)
# load nvrtc-builtins library if using cuda
if name == 'cuda':
nvrtc_name = self.__find_nvrtc_builtins_libname(libname[0])
if nvrtc_name:
ct.cdll.LoadLibrary(libname[0] + nvrtc_name)
if VERBOSE_LOADS:
print('Loaded ' + libname[0] + nvrtc_name)
else:
if VERBOSE_LOADS:
print('Could not find local nvrtc-builtins libarary')
break;
except OSError:
if VERBOSE_LOADS:
traceback.print_exc()
print('Unable to load ' + full_libname)
pass
if (self.__name is None):
raise RuntimeError("Could not load any ArrayFire libraries.\n" + more_info_str)
def get_id(self, name):
return self.__backend_name_map[name]
def get_name(self, bk_id):
return self.__backend_map[bk_id]
def get(self):
return self.__clibs[self.__name]
def name(self):
return self.__name
def is_unified(self):
return self.__name == 'unified'
def parse(self, res):
lst = []
for key,value in self.__backend_name_map.items():
if (value & res):
lst.append(key)
return tuple(lst)
backend = _clibrary()
[docs]def set_backend(name, unsafe=False):
"""
Set a specific backend by name
Parameters
----------
name : str.
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):
raise RuntimeError("Can not change backend to %s after loading %s" % (name, backend.name()))
if (backend.is_unified()):
safe_call(backend.get().af_set_backend(backend.get_id(name)))
else:
backend.set_unsafe(name)
return
[docs]def get_backend():
"""
Return the name of the backend
"""
return backend.name()
[docs]def get_backend_id(A):
"""
Get backend name of an array
Parameters
----------
A : af.Array
Returns
----------
name : str.
Backend name
"""
backend_id = c_int_t(BACKEND.CPU.value)
safe_call(backend.get().af_get_backend_id(c_pointer(backend_id), A.arr))
return backend.get_name(backend_id.value)
[docs]def get_backend_count():
"""
Get number of available backends
Returns
----------
count : int
Number of available backends
"""
count = c_int_t(0)
safe_call(backend.get().af_get_backend_count(c_pointer(count)))
return count.value
[docs]def get_available_backends():
"""
Get names of available backends
Returns
----------
names : tuple of strings
Names of available backends
"""
available = c_int_t(0)
safe_call(backend.get().af_get_available_backends(c_pointer(available)))
return backend.parse(int(available.value))
[docs]def get_active_backend():
"""
Get the current active backend
name : str.
Backend name
"""
backend_id = c_int_t(BACKEND.CPU.value)
safe_call(backend.get().af_get_active_backend(c_pointer(backend_id)))
return backend.get_name(backend_id.value)
[docs]def get_device_id(A):
"""
Get the device id of the array
Parameters
----------
A : af.Array
Returns
----------
dev : Integer
id of the device array was created on
"""
device_id = c_int_t(0)
safe_call(backend.get().af_get_device_id(c_pointer(device_id), A.arr))
return device_id
[docs]def get_size_of(dtype):
"""
Get the size of the type represented by arrayfire.Dtype
"""
size = c_size_t(0)
safe_call(backend.get().af_get_size_of(c_pointer(size), dtype.value))
return size.value
from .util import safe_call