Source code for arrayfire.library
#######################################################
# 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
# 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 = ct.c_longlong
# 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 = ct.c_int
try:
from enum import Enum as _Enum
def _Enum_Type(v):
return v
except:
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)
# 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)
[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)
[docs]class PAD(_Enum):
"""
Edge padding types
"""
ZERO = _Enum_Type(0)
SYM = _Enum_Type(1)
[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 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)
def _setup():
import platform
import os
platform_name = platform.system()
try:
AF_PATH = os.environ['AF_PATH']
except:
AF_PATH = None
pass
AF_SEARCH_PATH = AF_PATH
try:
CUDA_PATH = os.environ['CUDA_PATH']
except:
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/v3/"
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 = '.3.dylib'
if AF_SEARCH_PATH is None:
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.3'
if AF_SEARCH_PATH is None:
AF_SEARCH_PATH='/opt/arrayfire-3/'
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')
if AF_PATH is None:
os.environ['AF_PATH'] = AF_SEARCH_PATH
return pre, post, AF_SEARCH_PATH, CUDA_FOUND
class _clibrary(object):
def __libname(self, name, head='af'):
libname = self.__pre + head + name + self.__post
libname_full = self.AF_PATH + '/lib/' + libname
return (libname, libname_full)
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, CUDA_FOUND = _setup()
self.__pre = pre
self.__post = post
self.AF_PATH = AF_PATH
self.CUDA_FOUND = CUDA_FOUND
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 = self.__libname('forge', '')
for libname in libnames:
try:
ct.cdll.LoadLibrary(libname)
except:
pass
# Iterate in reverse order of preference
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
self.__clibs[__name] = ct.CDLL(libname)
self.__name = __name
break;
except:
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 = ct.c_int(BACKEND.CPU.value)
safe_call(backend.get().af_get_backend_id(ct.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 = ct.c_int(0)
safe_call(backend.get().af_get_backend_count(ct.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 = ct.c_int(0)
safe_call(backend.get().af_get_available_backends(ct.pointer(available)))
return backend.parse(int(available.value))
[docs]def get_active_backend():
"""
Get the current active backend
name : str.
Backend name
"""
backend_id = ct.c_int(BACKEND.CPU.value)
safe_call(backend.get().af_get_active_backend(ct.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 = ct.c_int(0)
safe_call(backend.get().af_get_device_id(ct.pointer(device_id), A.arr))
return device_id
from .util import safe_call