[python-arrayfire] 84/250: Adding runtime selection of arrayfire backends using af.backend.set(name)

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Mon Mar 28 22:59:34 UTC 2016


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/master
in repository python-arrayfire.

commit a5394feb022cc29e6823ec9fde505a4fd74411b7
Author: Pavan Yalamanchili <pavan at arrayfire.com>
Date:   Mon Aug 31 09:06:20 2015 -0400

    Adding runtime selection of arrayfire backends using af.backend.set(name)
    
    - Backend is locked after array creation
    - Backend can be unlocked in an unsafe manner by passing unsafe=True flag
---
 arrayfire/__init__.py   |   1 -
 arrayfire/algorithm.py  |  56 +++++++++----------
 arrayfire/arith.py      |  98 ++++++++++++++++-----------------
 arrayfire/array.py      | 142 ++++++++++++++++++++++++------------------------
 arrayfire/blas.py       |  10 ++--
 arrayfire/data.py       |  38 ++++++-------
 arrayfire/device.py     |  16 +++---
 arrayfire/features.py   |  14 ++---
 arrayfire/graphics.py   |  18 +++---
 arrayfire/image.py      |  54 +++++++++---------
 arrayfire/lapack.py     |  24 ++++----
 arrayfire/library.py    |  93 +++++++++++++++++++------------
 arrayfire/signal.py     |  32 +++++------
 arrayfire/statistics.py |  30 +++++-----
 arrayfire/util.py       |   4 +-
 arrayfire/vision.py     |   8 +--
 16 files changed, 332 insertions(+), 306 deletions(-)

diff --git a/arrayfire/__init__.py b/arrayfire/__init__.py
index b1876cb..9ac5a67 100644
--- a/arrayfire/__init__.py
+++ b/arrayfire/__init__.py
@@ -49,7 +49,6 @@ del reduce_all
 del arith_unary_func
 del arith_binary_func
 del brange
-del load_backend
 del dim4_tuple
 del is_number
 del to_str
diff --git a/arrayfire/algorithm.py b/arrayfire/algorithm.py
index 62e6188..fbe3e20 100644
--- a/arrayfire/algorithm.py
+++ b/arrayfire/algorithm.py
@@ -25,57 +25,57 @@ def reduce_all(a, c_func):
 
 def sum(a, dim=None):
     if dim is not None:
-        return parallel_dim(a, dim, clib.af_sum)
+        return parallel_dim(a, dim, backend.get().af_sum)
     else:
-        return reduce_all(a, clib.af_sum_all)
+        return reduce_all(a, backend.get().af_sum_all)
 
 def product(a, dim=None):
     if dim is not None:
-        return parallel_dim(a, dim, clib.af_product)
+        return parallel_dim(a, dim, backend.get().af_product)
     else:
-        return reduce_all(a, clib.af_product_all)
+        return reduce_all(a, backend.get().af_product_all)
 
 def min(a, dim=None):
     if dim is not None:
-        return parallel_dim(a, dim, clib.af_min)
+        return parallel_dim(a, dim, backend.get().af_min)
     else:
-        return reduce_all(a, clib.af_min_all)
+        return reduce_all(a, backend.get().af_min_all)
 
 def max(a, dim=None):
     if dim is not None:
-        return parallel_dim(a, dim, clib.af_max)
+        return parallel_dim(a, dim, backend.get().af_max)
     else:
-        return reduce_all(a, clib.af_max_all)
+        return reduce_all(a, backend.get().af_max_all)
 
 def all_true(a, dim=None):
     if dim is not None:
-        return parallel_dim(a, dim, clib.af_all_true)
+        return parallel_dim(a, dim, backend.get().af_all_true)
     else:
-        return reduce_all(a, clib.af_all_true_all)
+        return reduce_all(a, backend.get().af_all_true_all)
 
 def any_true(a, dim=None):
     if dim is not None:
-        return parallel_dim(a, dim, clib.af_any_true)
+        return parallel_dim(a, dim, backend.get().af_any_true)
     else:
-        return reduce_all(a, clib.af_any_true_all)
+        return reduce_all(a, backend.get().af_any_true_all)
 
 def count(a, dim=None):
     if dim is not None:
-        return parallel_dim(a, dim, clib.af_count)
+        return parallel_dim(a, dim, backend.get().af_count)
     else:
-        return reduce_all(a, clib.af_count_all)
+        return reduce_all(a, backend.get().af_count_all)
 
 def imin(a, dim=None):
     if dim is not None:
         out = Array()
         idx = Array()
-        safe_call(clib.af_imin(ct.pointer(out.arr), ct.pointer(idx.arr), a.arr, ct.c_int(dim)))
+        safe_call(backend.get().af_imin(ct.pointer(out.arr), ct.pointer(idx.arr), a.arr, ct.c_int(dim)))
         return out,idx
     else:
         real = ct.c_double(0)
         imag = ct.c_double(0)
         idx  = ct.c_uint(0)
-        safe_call(clib.af_imin_all(ct.pointer(real), ct.pointer(imag), ct.pointer(idx), a.arr))
+        safe_call(backend.get().af_imin_all(ct.pointer(real), ct.pointer(imag), ct.pointer(idx), a.arr))
         real = real.value
         imag = imag.value
         val = real if imag == 0 else real + imag * 1j
@@ -85,13 +85,13 @@ def imax(a, dim=None):
     if dim is not None:
         out = Array()
         idx = Array()
-        safe_call(clib.af_imax(ct.pointer(out.arr), ct.pointer(idx.arr), a.arr, ct.c_int(dim)))
+        safe_call(backend.get().af_imax(ct.pointer(out.arr), ct.pointer(idx.arr), a.arr, ct.c_int(dim)))
         return out,idx
     else:
         real = ct.c_double(0)
         imag = ct.c_double(0)
         idx  = ct.c_uint(0)
-        safe_call(clib.af_imax_all(ct.pointer(real), ct.pointer(imag), ct.pointer(idx), a.arr))
+        safe_call(backend.get().af_imax_all(ct.pointer(real), ct.pointer(imag), ct.pointer(idx), a.arr))
         real = real.value
         imag = imag.value
         val = real if imag == 0 else real + imag * 1j
@@ -99,49 +99,49 @@ def imax(a, dim=None):
 
 
 def accum(a, dim=0):
-    return parallel_dim(a, dim, clib.af_accum)
+    return parallel_dim(a, dim, backend.get().af_accum)
 
 def where(a):
     out = Array()
-    safe_call(clib.af_where(ct.pointer(out.arr), a.arr))
+    safe_call(backend.get().af_where(ct.pointer(out.arr), a.arr))
     return out
 
 def diff1(a, dim=0):
-    return parallel_dim(a, dim, clib.af_diff1)
+    return parallel_dim(a, dim, backend.get().af_diff1)
 
 def diff2(a, dim=0):
-    return parallel_dim(a, dim, clib.af_diff2)
+    return parallel_dim(a, dim, backend.get().af_diff2)
 
 def sort(a, dim=0, is_ascending=True):
     out = Array()
-    safe_call(clib.af_sort(ct.pointer(out.arr), a.arr, ct.c_uint(dim), ct.c_bool(is_ascending)))
+    safe_call(backend.get().af_sort(ct.pointer(out.arr), a.arr, ct.c_uint(dim), ct.c_bool(is_ascending)))
     return out
 
 def sort_index(a, dim=0, is_ascending=True):
     out = Array()
     idx = Array()
-    safe_call(clib.af_sort_index(ct.pointer(out.arr), ct.pointer(idx.arr), a.arr,
+    safe_call(backend.get().af_sort_index(ct.pointer(out.arr), ct.pointer(idx.arr), a.arr,
                                  ct.c_uint(dim), ct.c_bool(is_ascending)))
     return out,idx
 
 def sort_by_key(iv, ik, dim=0, is_ascending=True):
     ov = Array()
     ok = Array()
-    safe_call(clib.af_sort_by_key(ct.pointer(ov.arr), ct.pointer(ok.arr),
+    safe_call(backend.get().af_sort_by_key(ct.pointer(ov.arr), ct.pointer(ok.arr),
                                   iv.arr, ik.arr, ct.c_uint(dim), ct.c_bool(is_ascending)))
     return ov,ok
 
 def set_unique(a, is_sorted=False):
     out = Array()
-    safe_call(clib.af_set_unique(ct.pointer(out.arr), a.arr, ct.c_bool(is_sorted)))
+    safe_call(backend.get().af_set_unique(ct.pointer(out.arr), a.arr, ct.c_bool(is_sorted)))
     return out
 
 def set_union(a, b, is_unique=False):
     out = Array()
-    safe_call(clib.af_set_union(ct.pointer(out.arr), a.arr, b.arr, ct.c_bool(is_unique)))
+    safe_call(backend.get().af_set_union(ct.pointer(out.arr), a.arr, b.arr, ct.c_bool(is_unique)))
     return out
 
 def set_intersect(a, b, is_unique=False):
     out = Array()
-    safe_call(clib.af_set_intersect(ct.pointer(out.arr), a.arr, b.arr, ct.c_bool(is_unique)))
+    safe_call(backend.get().af_set_intersect(ct.pointer(out.arr), a.arr, b.arr, ct.c_bool(is_unique)))
     return out
diff --git a/arrayfire/arith.py b/arrayfire/arith.py
index 9f8b3e4..2e88f77 100644
--- a/arrayfire/arith.py
+++ b/arrayfire/arith.py
@@ -46,149 +46,149 @@ def arith_unary_func(a, c_func):
 
 def cast(a, dtype=f32):
     out=Array()
-    safe_call(clib.af_cast(ct.pointer(out.arr), a.arr, dtype))
+    safe_call(backend.get().af_cast(ct.pointer(out.arr), a.arr, dtype))
     return out
 
 def minof(lhs, rhs):
-    return arith_binary_func(lhs, rhs, clib.af_minof)
+    return arith_binary_func(lhs, rhs, backend.get().af_minof)
 
 def maxof(lhs, rhs):
-    return arith_binary_func(lhs, rhs, clib.af_maxof)
+    return arith_binary_func(lhs, rhs, backend.get().af_maxof)
 
 def rem(lhs, rhs):
-    return arith_binary_func(lhs, rhs, clib.af_rem)
+    return arith_binary_func(lhs, rhs, backend.get().af_rem)
 
 def abs(a):
-    return arith_unary_func(a, clib.af_abs)
+    return arith_unary_func(a, backend.get().af_abs)
 
 def arg(a):
-    return arith_unary_func(a, clib.af_arg)
+    return arith_unary_func(a, backend.get().af_arg)
 
 def sign(a):
-    return arith_unary_func(a, clib.af_sign)
+    return arith_unary_func(a, backend.get().af_sign)
 
 def round(a):
-    return arith_unary_func(a, clib.af_round)
+    return arith_unary_func(a, backend.get().af_round)
 
 def trunc(a):
-    return arith_unary_func(a, clib.af_trunc)
+    return arith_unary_func(a, backend.get().af_trunc)
 
 def floor(a):
-    return arith_unary_func(a, clib.af_floor)
+    return arith_unary_func(a, backend.get().af_floor)
 
 def ceil(a):
-    return arith_unary_func(a, clib.af_ceil)
+    return arith_unary_func(a, backend.get().af_ceil)
 
 def hypot(lhs, rhs):
-    return arith_binary_func(lhs, rhs, clib.af_hypot)
+    return arith_binary_func(lhs, rhs, backend.get().af_hypot)
 
 def sin(a):
-    return arith_unary_func(a, clib.af_sin)
+    return arith_unary_func(a, backend.get().af_sin)
 
 def cos(a):
-    return arith_unary_func(a, clib.af_cos)
+    return arith_unary_func(a, backend.get().af_cos)
 
 def tan(a):
-    return arith_unary_func(a, clib.af_tan)
+    return arith_unary_func(a, backend.get().af_tan)
 
 def asin(a):
-    return arith_unary_func(a, clib.af_asin)
+    return arith_unary_func(a, backend.get().af_asin)
 
 def acos(a):
-    return arith_unary_func(a, clib.af_acos)
+    return arith_unary_func(a, backend.get().af_acos)
 
 def atan(a):
-    return arith_unary_func(a, clib.af_atan)
+    return arith_unary_func(a, backend.get().af_atan)
 
 def atan2(lhs, rhs):
-    return arith_binary_func(lhs, rhs, clib.af_atan2)
+    return arith_binary_func(lhs, rhs, backend.get().af_atan2)
 
 def cplx(lhs, rhs=None):
     if rhs is None:
-        return arith_unary_func(lhs, clib.af_cplx)
+        return arith_unary_func(lhs, backend.get().af_cplx)
     else:
-        return arith_binary_func(lhs, rhs, clib.af_cplx2)
+        return arith_binary_func(lhs, rhs, backend.get().af_cplx2)
 
 def real(lhs):
-    return arith_unary_func(lhs, clib.af_real)
+    return arith_unary_func(lhs, backend.get().af_real)
 
 def imag(lhs):
-    return arith_unary_func(lhs, clib.af_imag)
+    return arith_unary_func(lhs, backend.get().af_imag)
 
 def conjg(lhs):
-    return arith_unary_func(lhs, clib.af_conjg)
+    return arith_unary_func(lhs, backend.get().af_conjg)
 
 def sinh(a):
-    return arith_unary_func(a, clib.af_sinh)
+    return arith_unary_func(a, backend.get().af_sinh)
 
 def cosh(a):
-    return arith_unary_func(a, clib.af_cosh)
+    return arith_unary_func(a, backend.get().af_cosh)
 
 def tanh(a):
-    return arith_unary_func(a, clib.af_tanh)
+    return arith_unary_func(a, backend.get().af_tanh)
 
 def asinh(a):
-    return arith_unary_func(a, clib.af_asinh)
+    return arith_unary_func(a, backend.get().af_asinh)
 
 def acosh(a):
-    return arith_unary_func(a, clib.af_acosh)
+    return arith_unary_func(a, backend.get().af_acosh)
 
 def atanh(a):
-    return arith_unary_func(a, clib.af_atanh)
+    return arith_unary_func(a, backend.get().af_atanh)
 
 def root(lhs, rhs):
-    return arith_binary_func(lhs, rhs, clib.af_root)
+    return arith_binary_func(lhs, rhs, backend.get().af_root)
 
 def pow(lhs, rhs):
-    return arith_binary_func(lhs, rhs, clib.af_pow)
+    return arith_binary_func(lhs, rhs, backend.get().af_pow)
 
 def pow2(a):
-    return arith_unary_func(a, clib.af_pow2)
+    return arith_unary_func(a, backend.get().af_pow2)
 
 def exp(a):
-    return arith_unary_func(a, clib.af_exp)
+    return arith_unary_func(a, backend.get().af_exp)
 
 def expm1(a):
-    return arith_unary_func(a, clib.af_expm1)
+    return arith_unary_func(a, backend.get().af_expm1)
 
 def erf(a):
-    return arith_unary_func(a, clib.af_erf)
+    return arith_unary_func(a, backend.get().af_erf)
 
 def erfc(a):
-    return arith_unary_func(a, clib.af_erfc)
+    return arith_unary_func(a, backend.get().af_erfc)
 
 def log(a):
-    return arith_unary_func(a, clib.af_log)
+    return arith_unary_func(a, backend.get().af_log)
 
 def log1p(a):
-    return arith_unary_func(a, clib.af_log1p)
+    return arith_unary_func(a, backend.get().af_log1p)
 
 def log10(a):
-    return arith_unary_func(a, clib.af_log10)
+    return arith_unary_func(a, backend.get().af_log10)
 
 def log2(a):
-    return arith_unary_func(a, clib.af_log2)
+    return arith_unary_func(a, backend.get().af_log2)
 
 def sqrt(a):
-    return arith_unary_func(a, clib.af_sqrt)
+    return arith_unary_func(a, backend.get().af_sqrt)
 
 def cbrt(a):
-    return arith_unary_func(a, clib.af_cbrt)
+    return arith_unary_func(a, backend.get().af_cbrt)
 
 def factorial(a):
-    return arith_unary_func(a, clib.af_factorial)
+    return arith_unary_func(a, backend.get().af_factorial)
 
 def tgamma(a):
-    return arith_unary_func(a, clib.af_tgamma)
+    return arith_unary_func(a, backend.get().af_tgamma)
 
 def lgamma(a):
-    return arith_unary_func(a, clib.af_lgamma)
+    return arith_unary_func(a, backend.get().af_lgamma)
 
 def iszero(a):
-    return arith_unary_func(a, clib.af_iszero)
+    return arith_unary_func(a, backend.get().af_iszero)
 
 def isinf(a):
-    return arith_unary_func(a, clib.af_isinf)
+    return arith_unary_func(a, backend.get().af_isinf)
 
 def isnan(a):
-    return arith_unary_func(a, clib.af_isnan)
+    return arith_unary_func(a, backend.get().af_isnan)
diff --git a/arrayfire/array.py b/arrayfire/array.py
index 9657e72..132e6e6 100644
--- a/arrayfire/array.py
+++ b/arrayfire/array.py
@@ -17,7 +17,7 @@ from .index import *
 def create_array(buf, numdims, idims, dtype):
     out_arr = ct.c_void_p(0)
     c_dims = dim4(idims[0], idims[1], idims[2], idims[3])
-    safe_call(clib.af_create_array(ct.pointer(out_arr), ct.c_void_p(buf),
+    safe_call(backend.get().af_create_array(ct.pointer(out_arr), ct.c_void_p(buf),
                                    numdims, ct.pointer(c_dims), dtype))
     return out_arr
 
@@ -39,17 +39,17 @@ def constant_array(val, d0, d1=None, d2=None, d3=None, dtype=f32):
         if (dtype != c32 and dtype != c64):
             dtype = c32
 
-        safe_call(clib.af_constant_complex(ct.pointer(out), c_real, c_imag,
+        safe_call(backend.get().af_constant_complex(ct.pointer(out), c_real, c_imag,
                                            4, ct.pointer(dims), dtype))
     elif dtype == s64:
         c_val = ct.c_longlong(val.real)
-        safe_call(clib.af_constant_long(ct.pointer(out), c_val, 4, ct.pointer(dims)))
+        safe_call(backend.get().af_constant_long(ct.pointer(out), c_val, 4, ct.pointer(dims)))
     elif dtype == u64:
         c_val = ct.c_ulonglong(val.real)
-        safe_call(clib.af_constant_ulong(ct.pointer(out), c_val, 4, ct.pointer(dims)))
+        safe_call(backend.get().af_constant_ulong(ct.pointer(out), c_val, 4, ct.pointer(dims)))
     else:
         c_val = ct.c_double(val)
-        safe_call(clib.af_constant(ct.pointer(out), c_val, 4, ct.pointer(dims), dtype))
+        safe_call(backend.get().af_constant(ct.pointer(out), c_val, 4, ct.pointer(dims), dtype))
 
     return out
 
@@ -88,11 +88,11 @@ def binary_funcr(lhs, rhs, c_func):
 
 def transpose(a, conj=False):
     out = Array()
-    safe_call(clib.af_transpose(ct.pointer(out.arr), a.arr, conj))
+    safe_call(backend.get().af_transpose(ct.pointer(out.arr), a.arr, conj))
     return out
 
 def transpose_inplace(a, conj=False):
-    safe_call(clib.af_transpose_inplace(a.arr, conj))
+    safe_call(backend.get().af_transpose_inplace(a.arr, conj))
 
 def ctype_to_lists(ctype_arr, dim, shape, offset=0):
     if (dim == 0):
@@ -135,10 +135,12 @@ class Array(BaseArray):
         _type_char='f'
         dtype = f32
 
+        backend.lock()
+
         if src is not None:
 
             if (isinstance(src, Array)):
-                safe_call(clib.af_retain_array(ct.pointer(self.arr), src.arr))
+                safe_call(backend.get().af_retain_array(ct.pointer(self.arr), src.arr))
                 return
 
             host = __import__("array")
@@ -179,26 +181,26 @@ class Array(BaseArray):
 
     def copy(self):
         out = Array()
-        safe_call(clib.af_copy_array(ct.pointer(out.arr), self.arr))
+        safe_call(backend.get().af_copy_array(ct.pointer(out.arr), self.arr))
         return out
 
     def __del__(self):
         if self.arr.value:
-            clib.af_release_array(self.arr)
+            backend.get().af_release_array(self.arr)
 
     def device_ptr(self):
         ptr = ct.c_void_p(0)
-        clib.af_get_device_ptr(ct.pointer(ptr), self.arr)
+        backend.get().af_get_device_ptr(ct.pointer(ptr), self.arr)
         return ptr.value
 
     def elements(self):
         num = ct.c_ulonglong(0)
-        safe_call(clib.af_get_elements(ct.pointer(num), self.arr))
+        safe_call(backend.get().af_get_elements(ct.pointer(num), self.arr))
         return num.value
 
     def dtype(self):
         dty = ct.c_int(f32.value)
-        safe_call(clib.af_get_type(ct.pointer(dty), self.arr))
+        safe_call(backend.get().af_get_type(ct.pointer(dty), self.arr))
         return dty
 
     def type(self):
@@ -209,204 +211,204 @@ class Array(BaseArray):
         d1 = ct.c_longlong(0)
         d2 = ct.c_longlong(0)
         d3 = ct.c_longlong(0)
-        safe_call(clib.af_get_dims(ct.pointer(d0), ct.pointer(d1),
+        safe_call(backend.get().af_get_dims(ct.pointer(d0), ct.pointer(d1),
                                    ct.pointer(d2), ct.pointer(d3), self.arr))
         dims = (d0.value,d1.value,d2.value,d3.value)
         return dims[:self.numdims()]
 
     def numdims(self):
         nd = ct.c_uint(0)
-        safe_call(clib.af_get_numdims(ct.pointer(nd), self.arr))
+        safe_call(backend.get().af_get_numdims(ct.pointer(nd), self.arr))
         return nd.value
 
     def is_empty(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_empty(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_empty(ct.pointer(res), self.arr))
         return res.value
 
     def is_scalar(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_scalar(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_scalar(ct.pointer(res), self.arr))
         return res.value
 
     def is_row(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_row(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_row(ct.pointer(res), self.arr))
         return res.value
 
     def is_column(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_column(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_column(ct.pointer(res), self.arr))
         return res.value
 
     def is_vector(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_vector(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_vector(ct.pointer(res), self.arr))
         return res.value
 
     def is_complex(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_complex(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_complex(ct.pointer(res), self.arr))
         return res.value
 
     def is_real(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_real(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_real(ct.pointer(res), self.arr))
         return res.value
 
     def is_double(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_double(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_double(ct.pointer(res), self.arr))
         return res.value
 
     def is_single(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_single(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_single(ct.pointer(res), self.arr))
         return res.value
 
     def is_real_floating(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_realfloating(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_realfloating(ct.pointer(res), self.arr))
         return res.value
 
     def is_floating(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_floating(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_floating(ct.pointer(res), self.arr))
         return res.value
 
     def is_integer(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_integer(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_integer(ct.pointer(res), self.arr))
         return res.value
 
     def is_bool(self):
         res = ct.c_bool(False)
-        safe_call(clib.af_is_bool(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_is_bool(ct.pointer(res), self.arr))
         return res.value
 
     def __add__(self, other):
-        return binary_func(self, other, clib.af_add)
+        return binary_func(self, other, backend.get().af_add)
 
     def __iadd__(self, other):
-        self = binary_func(self, other, clib.af_add)
+        self = binary_func(self, other, backend.get().af_add)
         return self
 
     def __radd__(self, other):
-        return binary_funcr(other, self, clib.af_add)
+        return binary_funcr(other, self, backend.get().af_add)
 
     def __sub__(self, other):
-        return binary_func(self, other, clib.af_sub)
+        return binary_func(self, other, backend.get().af_sub)
 
     def __isub__(self, other):
-        self = binary_func(self, other, clib.af_sub)
+        self = binary_func(self, other, backend.get().af_sub)
         return self
 
     def __rsub__(self, other):
-        return binary_funcr(other, self, clib.af_sub)
+        return binary_funcr(other, self, backend.get().af_sub)
 
     def __mul__(self, other):
-        return binary_func(self, other, clib.af_mul)
+        return binary_func(self, other, backend.get().af_mul)
 
     def __imul__(self, other):
-        self = binary_func(self, other, clib.af_mul)
+        self = binary_func(self, other, backend.get().af_mul)
         return self
 
     def __rmul__(self, other):
-        return binary_funcr(other, self, clib.af_mul)
+        return binary_funcr(other, self, backend.get().af_mul)
 
     # Necessary for python3
     def __truediv__(self, other):
-        return binary_func(self, other, clib.af_div)
+        return binary_func(self, other, backend.get().af_div)
 
     def __itruediv__(self, other):
-        self =  binary_func(self, other, clib.af_div)
+        self =  binary_func(self, other, backend.get().af_div)
         return self
 
     def __rtruediv__(self, other):
-        return binary_funcr(other, self, clib.af_div)
+        return binary_funcr(other, self, backend.get().af_div)
 
     # Necessary for python2
     def __div__(self, other):
-        return binary_func(self, other, clib.af_div)
+        return binary_func(self, other, backend.get().af_div)
 
     def __idiv__(self, other):
-        self =  binary_func(self, other, clib.af_div)
+        self =  binary_func(self, other, backend.get().af_div)
         return self
 
     def __rdiv__(self, other):
-        return binary_funcr(other, self, clib.af_div)
+        return binary_funcr(other, self, backend.get().af_div)
 
     def __mod__(self, other):
-        return binary_func(self, other, clib.af_mod)
+        return binary_func(self, other, backend.get().af_mod)
 
     def __imod__(self, other):
-        self =  binary_func(self, other, clib.af_mod)
+        self =  binary_func(self, other, backend.get().af_mod)
         return self
 
     def __rmod__(self, other):
-        return binary_funcr(other, self, clib.af_mod)
+        return binary_funcr(other, self, backend.get().af_mod)
 
     def __pow__(self, other):
-        return binary_func(self, other, clib.af_pow)
+        return binary_func(self, other, backend.get().af_pow)
 
     def __ipow__(self, other):
-        self =  binary_func(self, other, clib.af_pow)
+        self =  binary_func(self, other, backend.get().af_pow)
         return self
 
     def __rpow__(self, other):
-        return binary_funcr(other, self, clib.af_pow)
+        return binary_funcr(other, self, backend.get().af_pow)
 
     def __lt__(self, other):
-        return binary_func(self, other, clib.af_lt)
+        return binary_func(self, other, backend.get().af_lt)
 
     def __gt__(self, other):
-        return binary_func(self, other, clib.af_gt)
+        return binary_func(self, other, backend.get().af_gt)
 
     def __le__(self, other):
-        return binary_func(self, other, clib.af_le)
+        return binary_func(self, other, backend.get().af_le)
 
     def __ge__(self, other):
-        return binary_func(self, other, clib.af_ge)
+        return binary_func(self, other, backend.get().af_ge)
 
     def __eq__(self, other):
-        return binary_func(self, other, clib.af_eq)
+        return binary_func(self, other, backend.get().af_eq)
 
     def __ne__(self, other):
-        return binary_func(self, other, clib.af_neq)
+        return binary_func(self, other, backend.get().af_neq)
 
     def __and__(self, other):
-        return binary_func(self, other, clib.af_bitand)
+        return binary_func(self, other, backend.get().af_bitand)
 
     def __iand__(self, other):
-        self = binary_func(self, other, clib.af_bitand)
+        self = binary_func(self, other, backend.get().af_bitand)
         return self
 
     def __or__(self, other):
-        return binary_func(self, other, clib.af_bitor)
+        return binary_func(self, other, backend.get().af_bitor)
 
     def __ior__(self, other):
-        self = binary_func(self, other, clib.af_bitor)
+        self = binary_func(self, other, backend.get().af_bitor)
         return self
 
     def __xor__(self, other):
-        return binary_func(self, other, clib.af_bitxor)
+        return binary_func(self, other, backend.get().af_bitxor)
 
     def __ixor__(self, other):
-        self = binary_func(self, other, clib.af_bitxor)
+        self = binary_func(self, other, backend.get().af_bitxor)
         return self
 
     def __lshift__(self, other):
-        return binary_func(self, other, clib.af_bitshiftl)
+        return binary_func(self, other, backend.get().af_bitshiftl)
 
     def __ilshift__(self, other):
-        self = binary_func(self, other, clib.af_bitshiftl)
+        self = binary_func(self, other, backend.get().af_bitshiftl)
         return self
 
     def __rshift__(self, other):
-        return binary_func(self, other, clib.af_bitshiftr)
+        return binary_func(self, other, backend.get().af_bitshiftr)
 
     def __irshift__(self, other):
-        self = binary_func(self, other, clib.af_bitshiftr)
+        self = binary_func(self, other, backend.get().af_bitshiftr)
         return self
 
     def __neg__(self):
@@ -431,7 +433,7 @@ class Array(BaseArray):
             n_dims = self.numdims()
             inds = get_indices(key)
 
-            safe_call(clib.af_index_gen(ct.pointer(out.arr),
+            safe_call(backend.get().af_index_gen(ct.pointer(out.arr),
                                         self.arr, ct.c_longlong(n_dims), ct.pointer(inds)))
             return out
         except RuntimeError as e:
@@ -451,10 +453,10 @@ class Array(BaseArray):
             out_arr = ct.c_void_p(0)
             inds  = get_indices(key)
 
-            safe_call(clib.af_assign_gen(ct.pointer(out_arr),
+            safe_call(backend.get().af_assign_gen(ct.pointer(out_arr),
                                          self.arr, ct.c_longlong(n_dims), ct.pointer(inds),
                                          other_arr))
-            safe_call(clib.af_release_array(self.arr))
+            safe_call(backend.get().af_release_array(self.arr))
             self.arr = out_arr
 
         except RuntimeError as e:
@@ -468,7 +470,7 @@ class Array(BaseArray):
         tmp = transpose(self) if row_major else self
         ctype_type = to_c_type[self.type()] * self.elements()
         res = ctype_type()
-        safe_call(clib.af_get_data_ptr(ct.pointer(res), self.arr))
+        safe_call(backend.get().af_get_data_ptr(ct.pointer(res), self.arr))
         if (return_shape):
             return res, self.dims()
         else:
@@ -497,4 +499,4 @@ def display(a):
     expr = inspect.stack()[1][-2]
     if (expr is not None):
         print('%s' % expr[0].split('display(')[1][:-2])
-    safe_call(clib.af_print_array(a.arr))
+    safe_call(backend.get().af_print_array(a.arr))
diff --git a/arrayfire/blas.py b/arrayfire/blas.py
index c31f176..d51fa12 100644
--- a/arrayfire/blas.py
+++ b/arrayfire/blas.py
@@ -12,30 +12,30 @@ from .array import *
 
 def matmul(lhs, rhs, lhs_opts=AF_MAT_NONE, rhs_opts=AF_MAT_NONE):
     out = Array()
-    safe_call(clib.af_matmul(ct.pointer(out.arr), lhs.arr, rhs.arr,
+    safe_call(backend.get().af_matmul(ct.pointer(out.arr), lhs.arr, rhs.arr,
                              lhs_opts, rhs_opts))
     return out
 
 def matmulTN(lhs, rhs):
     out = Array()
-    safe_call(clib.af_matmul(ct.pointer(out.arr), lhs.arr, rhs.arr,
+    safe_call(backend.get().af_matmul(ct.pointer(out.arr), lhs.arr, rhs.arr,
                              AF_MAT_TRANS, AF_MAT_NONE))
     return out
 
 def matmulNT(lhs, rhs):
     out = Array()
-    safe_call(clib.af_matmul(ct.pointer(out.arr), lhs.arr, rhs.arr,
+    safe_call(backend.get().af_matmul(ct.pointer(out.arr), lhs.arr, rhs.arr,
                              AF_MAT_NONE, AF_MAT_TRANS))
     return out
 
 def matmulTT(lhs, rhs):
     out = Array()
-    safe_call(clib.af_matmul(ct.pointer(out.arr), lhs.arr, rhs.arr,
+    safe_call(backend.get().af_matmul(ct.pointer(out.arr), lhs.arr, rhs.arr,
                              AF_MAT_TRANS, AF_MAT_TRANS))
     return out
 
 def dot(lhs, rhs, lhs_opts=AF_MAT_NONE, rhs_opts=AF_MAT_NONE):
     out = Array()
-    safe_call(clib.af_dot(ct.pointer(out.arr), lhs.arr, rhs.arr,
+    safe_call(backend.get().af_dot(ct.pointer(out.arr), lhs.arr, rhs.arr,
                           lhs_opts, rhs_opts))
     return out
diff --git a/arrayfire/data.py b/arrayfire/data.py
index be04bc4..94f88a2 100644
--- a/arrayfire/data.py
+++ b/arrayfire/data.py
@@ -31,7 +31,7 @@ def range(d0, d1=None, d2=None, d3=None, dim=-1, dtype=f32):
     out = Array()
     dims = dim4(d0, d1, d2, d3)
 
-    safe_call(clib.af_range(ct.pointer(out.arr), 4, ct.pointer(dims), dim, dtype))
+    safe_call(backend.get().af_range(ct.pointer(out.arr), 4, ct.pointer(dims), dim, dtype))
     return out
 
 
@@ -52,7 +52,7 @@ def iota(d0, d1=None, d2=None, d3=None, dim=-1, tile_dims=None, dtype=f32):
 
     tdims = dim4(td[0], td[1], td[2], td[3])
 
-    safe_call(clib.af_iota(ct.pointer(out.arr), 4, ct.pointer(dims), 4, ct.pointer(tdims), dtype))
+    safe_call(backend.get().af_iota(ct.pointer(out.arr), 4, ct.pointer(dims), 4, ct.pointer(tdims), dtype))
     return out
 
 def randu(d0, d1=None, d2=None, d3=None, dtype=f32):
@@ -66,7 +66,7 @@ def randu(d0, d1=None, d2=None, d3=None, dtype=f32):
     out = Array()
     dims = dim4(d0, d1, d2, d3)
 
-    safe_call(clib.af_randu(ct.pointer(out.arr), 4, ct.pointer(dims), dtype))
+    safe_call(backend.get().af_randu(ct.pointer(out.arr), 4, ct.pointer(dims), dtype))
     return out
 
 def randn(d0, d1=None, d2=None, d3=None, dtype=f32):
@@ -80,15 +80,15 @@ def randn(d0, d1=None, d2=None, d3=None, dtype=f32):
     out = Array()
     dims = dim4(d0, d1, d2, d3)
 
-    safe_call(clib.af_randn(ct.pointer(out.arr), 4, ct.pointer(dims), dtype))
+    safe_call(backend.get().af_randn(ct.pointer(out.arr), 4, ct.pointer(dims), dtype))
     return out
 
 def set_seed(seed=0):
-    safe_call(clib.af_set_seed(ct.c_ulonglong(seed)))
+    safe_call(backend.get().af_set_seed(ct.c_ulonglong(seed)))
 
 def get_seed():
     seed = ct.c_ulonglong(0)
-    safe_call(clib.af_get_seed(ct.pointer(seed)))
+    safe_call(backend.get().af_get_seed(ct.pointer(seed)))
     return seed.value
 
 def identity(d0, d1=None, d2=None, d3=None, dtype=f32):
@@ -102,21 +102,21 @@ def identity(d0, d1=None, d2=None, d3=None, dtype=f32):
     out = Array()
     dims = dim4(d0, d1, d2, d3)
 
-    safe_call(clib.af_identity(ct.pointer(out.arr), 4, ct.pointer(dims), dtype))
+    safe_call(backend.get().af_identity(ct.pointer(out.arr), 4, ct.pointer(dims), dtype))
     return out
 
 def diag(a, num=0, extract=True):
     out = Array()
     if extract:
-        safe_call(clib.af_diag_extract(ct.pointer(out.arr), a.arr, ct.c_int(num)))
+        safe_call(backend.get().af_diag_extract(ct.pointer(out.arr), a.arr, ct.c_int(num)))
     else:
-        safe_call(clib.af_diag_create(ct.pointer(out.arr), a.arr, ct.c_int(num)))
+        safe_call(backend.get().af_diag_create(ct.pointer(out.arr), a.arr, ct.c_int(num)))
     return out
 
 def join(dim, first, second, third=None, fourth=None):
     out = Array()
     if (third is None and fourth is None):
-        safe_call(clib.af_join(ct.pointer(out.arr), dim, first.arr, second.arr))
+        safe_call(backend.get().af_join(ct.pointer(out.arr), dim, first.arr, second.arr))
     else:
         c_void_p_4 = ct.c_void_p * 4
         c_array_vec = c_void_p_4(first.arr, second.arr, 0, 0)
@@ -128,48 +128,48 @@ def join(dim, first, second, third=None, fourth=None):
             c_array_vec[num] = fourth.arr
             num+=1
 
-        safe_call(clib.af_join_many(ct.pointer(out.arr), dim, num, ct.pointer(c_array_vec)))
+        safe_call(backend.get().af_join_many(ct.pointer(out.arr), dim, num, ct.pointer(c_array_vec)))
     return out
 
 
 def tile(a, d0, d1=1, d2=1, d3=1):
     out = Array()
-    safe_call(clib.af_tile(ct.pointer(out.arr), a.arr, d0, d1, d2, d3))
+    safe_call(backend.get().af_tile(ct.pointer(out.arr), a.arr, d0, d1, d2, d3))
     return out
 
 
 def reorder(a, d0=1, d1=0, d2=2, d3=3):
     out = Array()
-    safe_call(clib.af_reorder(ct.pointer(out.arr), a.arr, d0, d1, d2, d3))
+    safe_call(backend.get().af_reorder(ct.pointer(out.arr), a.arr, d0, d1, d2, d3))
     return out
 
 def shift(a, d0, d1=0, d2=0, d3=0):
     out = Array()
-    safe_call(clib.af_shift(ct.pointer(out.arr), a.arr, d0, d1, d2, d3))
+    safe_call(backend.get().af_shift(ct.pointer(out.arr), a.arr, d0, d1, d2, d3))
     return out
 
 def moddims(a, d0, d1=1, d2=1, d3=1):
     out = Array()
     dims = dim4(d0, d1, d2, d3)
-    safe_call(clib.af_moddims(ct.pointer(out.arr), a.arr, 4, ct.pointer(dims)))
+    safe_call(backend.get().af_moddims(ct.pointer(out.arr), a.arr, 4, ct.pointer(dims)))
     return out
 
 def flat(a):
     out = Array()
-    safe_call(clib.af_flat(ct.pointer(out.arr), a.arr))
+    safe_call(backend.get().af_flat(ct.pointer(out.arr), a.arr))
     return out
 
 def flip(a, dim=0):
     out = Array()
-    safe_call(clib.af_flip(ct.pointer(out.arr), a.arr, ct.c_int(dim)))
+    safe_call(backend.get().af_flip(ct.pointer(out.arr), a.arr, ct.c_int(dim)))
     return out
 
 def lower(a, is_unit_diag=False):
     out = Array()
-    safe_call(clib.af_lower(ct.pointer(out.arr), a.arr, is_unit_diag))
+    safe_call(backend.get().af_lower(ct.pointer(out.arr), a.arr, is_unit_diag))
     return out
 
 def upper(a, is_unit_diag=False):
     out = Array()
-    safe_call(clib.af_upper(ct.pointer(out.arr), a.arr, is_unit_diag))
+    safe_call(backend.get().af_upper(ct.pointer(out.arr), a.arr, is_unit_diag))
     return out
diff --git a/arrayfire/device.py b/arrayfire/device.py
index d630696..4072236 100644
--- a/arrayfire/device.py
+++ b/arrayfire/device.py
@@ -11,7 +11,7 @@ from .library import *
 from .util import (safe_call, to_str)
 
 def info():
-    safe_call(clib.af_info())
+    safe_call(backend.get().af_info())
 
 def device_info():
     c_char_256 = ct.c_char * 256
@@ -20,7 +20,7 @@ def device_info():
     toolkit = c_char_256()
     compute = c_char_256()
 
-    safe_call(clib.af_device_info(ct.pointer(device_name), ct.pointer(backend_name),
+    safe_call(backend.get().af_device_info(ct.pointer(device_name), ct.pointer(backend_name),
                                   ct.pointer(toolkit), ct.pointer(compute)))
     dev_info = {}
     dev_info['device'] = to_str(device_name)
@@ -32,33 +32,33 @@ def device_info():
 
 def get_device_count():
     c_num = ct.c_int(0)
-    safe_call(clib.af_get_device_count(ct.pointer(c_num)))
+    safe_call(backend.get().af_get_device_count(ct.pointer(c_num)))
     return c_num.value
 
 def get_device():
     c_dev = ct.c_int(0)
-    safe_call(clib.af_get_device(ct.pointer(c_dev)))
+    safe_call(backend.get().af_get_device(ct.pointer(c_dev)))
     return c_dev.value
 
 def set_device(num):
-    safe_call(clib.af_set_device(num))
+    safe_call(backend.get().af_set_device(num))
 
 def is_dbl_supported(device=None):
     dev = device if device is not None else get_device()
     res = ct.c_bool(False)
-    safe_call(clib.af_get_dbl_support(ct.pointer(res), dev))
+    safe_call(backend.get().af_get_dbl_support(ct.pointer(res), dev))
     return res.value
 
 def sync(device=None):
     dev = device if device is not None else get_device()
-    safe_call(clib.af_sync(dev))
+    safe_call(backend.get().af_sync(dev))
 
 def device_mem_info():
     alloc_bytes = ct.c_size_t(0)
     alloc_buffers = ct.c_size_t(0)
     lock_bytes = ct.c_size_t(0)
     lock_buffers = ct.c_size_t(0)
-    safe_call(clib.af_device_mem_info(ct.pointer(alloc_bytes), ct.pointer(alloc_buffers),
+    safe_call(backend.get().af_device_mem_info(ct.pointer(alloc_bytes), ct.pointer(alloc_buffers),
                                       ct.pointer(lock_bytes), ct.pointer(lock_buffers)))
     mem_info = {}
     mem_info['alloc'] = {'buffers' : alloc_buffers.value, 'bytes' : alloc_bytes.value}
diff --git a/arrayfire/features.py b/arrayfire/features.py
index dbcc601..a293ebb 100644
--- a/arrayfire/features.py
+++ b/arrayfire/features.py
@@ -16,34 +16,34 @@ class Features(object):
         self.feat = ct.c_void_p(0)
         if num is not None:
             assert(isinstance(num, numbers.Number))
-            safe_call(clib.af_create_features(ct.pointer(self.feat), ct.c_longlong(num)))
+            safe_call(backend.get().af_create_features(ct.pointer(self.feat), ct.c_longlong(num)))
 
     def num_features():
         num = ct.c_longlong(0)
-        safe_call(clib.af_get_features_num(ct.pointer(num), self.feat))
+        safe_call(backend.get().af_get_features_num(ct.pointer(num), self.feat))
         return num
 
     def get_xpos():
         out = Array()
-        safe_call(clib.af_get_features_xpos(ct.pointer(out.arr), self.feat))
+        safe_call(backend.get().af_get_features_xpos(ct.pointer(out.arr), self.feat))
         return out
 
     def get_ypos():
         out = Array()
-        safe_call(clib.af_get_features_ypos(ct.pointer(out.arr), self.feat))
+        safe_call(backend.get().af_get_features_ypos(ct.pointer(out.arr), self.feat))
         return out
 
     def get_score():
         out = Array()
-        safe_call(clib.af_get_features_score(ct.pointer(out.arr), self.feat))
+        safe_call(backend.get().af_get_features_score(ct.pointer(out.arr), self.feat))
         return out
 
     def get_orientation():
         out = Array()
-        safe_call(clib.af_get_features_orientation(ct.pointer(out.arr), self.feat))
+        safe_call(backend.get().af_get_features_orientation(ct.pointer(out.arr), self.feat))
         return out
 
     def get_size():
         out = Array()
-        safe_call(clib.af_get_features_size(ct.pointer(out.arr), self.feat))
+        safe_call(backend.get().af_get_features_size(ct.pointer(out.arr), self.feat))
         return out
diff --git a/arrayfire/graphics.py b/arrayfire/graphics.py
index 3266f3e..2777311 100644
--- a/arrayfire/graphics.py
+++ b/arrayfire/graphics.py
@@ -36,32 +36,32 @@ class window(object):
 
         _title = _title.encode("ascii")
 
-        safe_call(clib.af_create_window(ct.pointer(self._wnd),
+        safe_call(backend.get().af_create_window(ct.pointer(self._wnd),
                                         ct.c_int(_width), ct.c_int(_height), ct.c_char_p(_title)))
 
     def __del__(self):
-        safe_call(clib.af_destroy_window(self._wnd))
+        safe_call(backend.get().af_destroy_window(self._wnd))
 
     def set_pos(self, x, y):
-        safe_call(clib.af_set_position(self._wnd, ct.c_int(x), ct.c_int(y)))
+        safe_call(backend.get().af_set_position(self._wnd, ct.c_int(x), ct.c_int(y)))
 
     def set_title(self, title):
-        safe_call(clib.af_set_title(self._wnd, title))
+        safe_call(backend.get().af_set_title(self._wnd, title))
 
     def set_colormap(self, cmap):
         self._cmap = cmap
 
     def image(self, img, title=None):
         _cell = Cell(self._r, self._c, title, self._cmap)
-        safe_call(clib.af_draw_image(self._wnd, img.arr, ct.pointer(_cell)))
+        safe_call(backend.get().af_draw_image(self._wnd, img.arr, ct.pointer(_cell)))
 
     def plot(self, X, Y, title=None):
         _cell = Cell(self._r, self._c, title, self._cmap)
-        safe_call(clib.af_draw_plot(self._wnd, X.arr, Y.arr, ct.pointer(_cell)))
+        safe_call(backend.get().af_draw_plot(self._wnd, X.arr, Y.arr, ct.pointer(_cell)))
 
     def hist(self, X, min_val, max_val, title=None):
         _cell = Cell(self._r, self._c, title, self._cmap)
-        safe_call(clib.af_draw_hist(self._wnd, X.arr,
+        safe_call(backend.get().af_draw_hist(self._wnd, X.arr,
                                     ct.c_double(max_val), ct.c_double(min_val),
                                     ct.pointer(_cell)))
 
@@ -69,11 +69,11 @@ class window(object):
         safe_call(af_grid(self._wnd, ct.c_int(rows), ct.c_int(cols)))
 
     def show(self):
-        safe_call(clib.af_show(self._wnd))
+        safe_call(backend.get().af_show(self._wnd))
 
     def close(self):
         tmp = ct.c_bool(True)
-        safe_call(clib.af_is_window_closed(ct.pointer(tmp), self._wnd))
+        safe_call(backend.get().af_is_window_closed(ct.pointer(tmp), self._wnd))
         return tmp
 
     def __getitem__(self, keys):
diff --git a/arrayfire/image.py b/arrayfire/image.py
index e00fca3..0d4a327 100644
--- a/arrayfire/image.py
+++ b/arrayfire/image.py
@@ -15,19 +15,19 @@ import os
 def gradient(image):
     dx = Array()
     dy = Array()
-    safe_call(clib.af_gradient(ct.pointer(dx.arr), ct.pointer(dy.arr), image.arr))
+    safe_call(backend.get().af_gradient(ct.pointer(dx.arr), ct.pointer(dy.arr), image.arr))
     return dx, dy
 
 def load_image(file_name, is_color=False):
     assert(os.path.isfile(file_name))
     image = Array()
-    safe_call(clib.af_load_image(ct.pointer(image.arr),
+    safe_call(backend.get().af_load_image(ct.pointer(image.arr),
                                  ct.c_char_p(file_name.encode('ascii')), is_color))
     return image
 
 def save_image(image, file_name):
     assert(isinstance(file_name, str))
-    safe_call(clib.af_save_image(ct.c_char_p(file_name.encode('ascii')), image.arr))
+    safe_call(backend.get().af_save_image(ct.c_char_p(file_name.encode('ascii')), image.arr))
     return image
 
 def resize(image, scale=None, odim0=None, odim1=None, method=AF_INTERP_NEAREST):
@@ -41,39 +41,39 @@ def resize(image, scale=None, odim0=None, odim1=None, method=AF_INTERP_NEAREST):
         odim1 = int(scale * idims[1])
 
     output = Array()
-    safe_call(clib.af_resize(ct.pointer(output.arr),
+    safe_call(backend.get().af_resize(ct.pointer(output.arr),
                              image.arr, ct.c_longlong(odim0), ct.c_longlong(odim1), method))
 
     return output
 
 def transform(image, transform, odim0 = 0, odim1 = 0, method=AF_INTERP_NEAREST, is_inverse=True):
     output = Array()
-    safe_call(clib.af_transform(ct.pointer(output.arr),
+    safe_call(backend.get().af_transform(ct.pointer(output.arr),
                                 image.arr, transform.arr,
                                 ct.c_longlong(odim0), ct.c_longlong(odim1), method, is_inverse))
     return output
 
 def rotate(image, theta, is_crop = True, method = AF_INTERP_NEAREST):
     output = Array()
-    safe_call(clib.af_rotate(ct.pointer(output.arr), image.arr, ct.c_double(theta), is_crop, method))
+    safe_call(backend.get().af_rotate(ct.pointer(output.arr), image.arr, ct.c_double(theta), is_crop, method))
     return output
 
 def translate(image, trans0, trans1, odim0 = 0, odim1 = 0, method = AF_INTERP_NEAREST):
     output = Array()
-    safe_call(clib.af_translate(ct.pointer(output.arr),
+    safe_call(backend.get().af_translate(ct.pointer(output.arr),
                                 image.arr, trans0, trans1, ct.c_longlong(odim0), ct.c_longlong(odim1), method))
     return output
 
 def scale(image, scale0, scale1, odim0 = 0, odim1 = 0, method = AF_INTERP_NEAREST):
     output = Array()
-    safe_call(clib.af_scale(ct.pointer(output.arr),
+    safe_call(backend.get().af_scale(ct.pointer(output.arr),
                             image.arr, ct.c_double(scale0), ct.c_double(scale1),
                             ct.c_longlong(odim0), ct.c_longlong(odim1), method))
     return output
 
 def skew(image, skew0, skew1, odim0 = 0, odim1 = 0, method = AF_INTERP_NEAREST, is_inverse=True):
     output = Array()
-    safe_call(clib.af_skew(ct.pointer(output.arr),
+    safe_call(backend.get().af_skew(ct.pointer(output.arr),
                            image.arr, ct.c_double(skew0), ct.c_double(skew1),
                            ct.c_longlong(odim0), ct.c_longlong(odim1), method, is_inverse))
 
@@ -90,13 +90,13 @@ def histogram(image, nbins, min_val = None, max_val = None):
         max_val = af_max(image)
 
     output = Array()
-    safe_call(clib.af_histogram(ct.pointer(output.arr),
+    safe_call(backend.get().af_histogram(ct.pointer(output.arr),
                                 image.arr, ct.c_uint(nbins), ct.c_double(min_val), ct.c_double(max_val)))
     return output
 
 def hist_equal(image, hist):
     output = Array()
-    safe_call(clib.af_hist_equal(ct.pointer(output.arr), image.arr, hist.arr))
+    safe_call(backend.get().af_hist_equal(ct.pointer(output.arr), image.arr, hist.arr))
     return output
 
 def dilate(image, mask = None):
@@ -105,7 +105,7 @@ def dilate(image, mask = None):
         mask = constant(1, 3, 3, dtype=f32)
 
     output = Array()
-    safe_call(clib.af_dilate(ct.pointer(output.arr), image.arr, mask.arr))
+    safe_call(backend.get().af_dilate(ct.pointer(output.arr), image.arr, mask.arr))
 
     return output
 
@@ -115,7 +115,7 @@ def dilate3(image, mask = None):
         mask = constant(1, 3, 3, 3, dtype=f32)
 
     output = Array()
-    safe_call(clib.af_dilate3(ct.pointer(output.arr), image.arr, mask.arr))
+    safe_call(backend.get().af_dilate3(ct.pointer(output.arr), image.arr, mask.arr))
 
     return output
 
@@ -125,7 +125,7 @@ def erode(image, mask = None):
         mask = constant(1, 3, 3, dtype=f32)
 
     output = Array()
-    safe_call(clib.af_erode(ct.pointer(output.arr), image.arr, mask.arr))
+    safe_call(backend.get().af_erode(ct.pointer(output.arr), image.arr, mask.arr))
 
     return output
 
@@ -135,50 +135,50 @@ def erode3(image, mask = None):
         mask = constant(1, 3, 3, 3, dtype=f32)
 
     output = Array()
-    safe_call(clib.af_erode3(ct.pointer(output.arr), image.arr, mask.arr))
+    safe_call(backend.get().af_erode3(ct.pointer(output.arr), image.arr, mask.arr))
 
     return output
 
 def bilateral(image, s_sigma, c_sigma, is_color = False):
     output = Array()
-    safe_call(clib.af_bilateral(ct.pointer(output.arr),
+    safe_call(backend.get().af_bilateral(ct.pointer(output.arr),
                                 image.arr, ct.c_double(s_sigma), ct.c_double(c_sigma), is_color))
     return output
 
 def mean_shift(image, s_sigma, c_sigma, n_iter, is_color = False):
     output = Array()
-    safe_call(clib.af_mean_shift(ct.pointer(output.arr),
+    safe_call(backend.get().af_mean_shift(ct.pointer(output.arr),
                                  image.arr, ct.c_double(s_sigma), ct.c_double(c_sigma),
                                  ct.c_uint(n_iter), is_color))
     return output
 
 def medfilt(image, w_len = 3, w_wid = 3, edge_pad = AF_PAD_ZERO):
     output = Array()
-    safe_call(clib.af_medfilt(ct.pointer(output.arr),
+    safe_call(backend.get().af_medfilt(ct.pointer(output.arr),
                               image.arr, ct.c_longlong(w_len), ct.c_longlong(w_wid), edge_pad))
     return output
 
 def minfilt(image, w_len = 3, w_wid = 3, edge_pad = AF_PAD_ZERO):
     output = Array()
-    safe_call(clib.af_minfilt(ct.pointer(output.arr),
+    safe_call(backend.get().af_minfilt(ct.pointer(output.arr),
                               image.arr, ct.c_longlong(w_len), ct.c_longlong(w_wid), edge_pad))
     return output
 
 def maxfilt(image, w_len = 3, w_wid = 3, edge_pad = AF_PAD_ZERO):
     output = Array()
-    safe_call(clib.af_maxfilt(ct.pointer(output.arr),
+    safe_call(backend.get().af_maxfilt(ct.pointer(output.arr),
                               image.arr, ct.c_longlong(w_len), ct.c_longlong(w_wid), edge_pad))
     return output
 
 def regions(image, connectivity = AF_CONNECTIVITY_4, out_type = f32):
     output = Array()
-    safe_call(clib.af_regions(ct.pointer(output.arr), image.arr, connectivity, out_type))
+    safe_call(backend.get().af_regions(ct.pointer(output.arr), image.arr, connectivity, out_type))
     return output
 
 def sobel_derivatives(image, w_len=3):
     dx = Array()
     dy = Array()
-    safe_call(clib.af_sobel_operator(ct.pointer(dx.arr), ct.pointer(dy.arr),
+    safe_call(backend.get().af_sobel_operator(ct.pointer(dx.arr), ct.pointer(dy.arr),
                                      image.arr, ct.c_uint(w_len)))
     return dx,dy
 
@@ -194,27 +194,27 @@ def sobel_filter(image, w_len = 3, is_fast = False):
 
 def rgb2gray(image, r_factor = 0.2126, g_factor = 0.7152, b_factor = 0.0722):
     output=Array()
-    safe_call(clib.af_rgb2gray(ct.pointer(output.arr),
+    safe_call(backend.get().af_rgb2gray(ct.pointer(output.arr),
                                image.arr, ct.c_float(r_factor), ct.c_float(g_factor), ct.c_float(b_factor)))
     return output
 
 def gray2rgb(image, r_factor = 1.0, g_factor = 1.0, b_factor = 1.0):
     output=Array()
-    safe_call(clib.af_gray2rgb(ct.pointer(output.arr),
+    safe_call(backend.get().af_gray2rgb(ct.pointer(output.arr),
                                image.arr, ct.c_float(r_factor), ct.c_float(g_factor), ct.c_float(b_factor)))
     return output
 
 def hsv2rgb(image):
     output = Array()
-    safe_call(clib.af_hsv2rgb(ct.pointer(output.arr), image.arr))
+    safe_call(backend.get().af_hsv2rgb(ct.pointer(output.arr), image.arr))
     return output
 
 def rgb2hsv(image):
     output = Array()
-    safe_call(clib.af_rgb2hsv(ct.pointer(output.arr), image.arr))
+    safe_call(backend.get().af_rgb2hsv(ct.pointer(output.arr), image.arr))
     return output
 
 def color_space(image, to_type, from_type):
     output = Array()
-    safe_call(clib.af_color_space(ct.pointer(output.arr), image.arr, to_type, from_type))
+    safe_call(backend.get().af_color_space(ct.pointer(output.arr), image.arr, to_type, from_type))
     return output
diff --git a/arrayfire/lapack.py b/arrayfire/lapack.py
index 6540fc4..f324daf 100644
--- a/arrayfire/lapack.py
+++ b/arrayfire/lapack.py
@@ -14,67 +14,67 @@ def lu(A):
     L = Array()
     U = Array()
     P = Array()
-    safe_call(clib.af_lu(ct.pointer(L.arr), ct.pointer(U.arr), ct.pointer(P.arr), A.arr))
+    safe_call(backend.get().af_lu(ct.pointer(L.arr), ct.pointer(U.arr), ct.pointer(P.arr), A.arr))
     return L,U,P
 
 def lu_inplace(A, pivot="lapack"):
     P = Array()
     is_pivot_lapack = False if (pivot == "full") else True
-    safe_call(clib.af_lu_inplace(ct.pointer(P.arr), A.arr, is_pivot_lapack))
+    safe_call(backend.get().af_lu_inplace(ct.pointer(P.arr), A.arr, is_pivot_lapack))
     return P
 
 def qr(A):
     Q = Array()
     R = Array()
     T = Array()
-    safe_call(clib.af_lu(ct.pointer(Q.arr), ct.pointer(R.arr), ct.pointer(T.arr), A.arr))
+    safe_call(backend.get().af_lu(ct.pointer(Q.arr), ct.pointer(R.arr), ct.pointer(T.arr), A.arr))
     return Q,R,T
 
 def qr_inplace(A):
     T = Array()
-    safe_call(clib.af_qr_inplace(ct.pointer(T.arr), A.arr))
+    safe_call(backend.get().af_qr_inplace(ct.pointer(T.arr), A.arr))
     return T
 
 def cholesky(A, is_upper=True):
     R = Array()
     info = ct.c_int(0)
-    safe_call(clib.af_cholesky(ct.pointer(R.arr), ct.pointer(info), A.arr, is_upper))
+    safe_call(backend.get().af_cholesky(ct.pointer(R.arr), ct.pointer(info), A.arr, is_upper))
     return R, info.value
 
 def cholesky_inplace(A, is_upper=True):
     info = ct.c_int(0)
-    safe_call(clib.af_cholesky_inplace(ct.pointer(info), A.arr, is_upper))
+    safe_call(backend.get().af_cholesky_inplace(ct.pointer(info), A.arr, is_upper))
     return info.value
 
 def solve(A, B, options=AF_MAT_NONE):
     X = Array()
-    safe_call(clib.af_solve(ct.pointer(X.arr), A.arr, B.arr, options))
+    safe_call(backend.get().af_solve(ct.pointer(X.arr), A.arr, B.arr, options))
     return X
 
 def solve_lu(A, P, B, options=AF_MAT_NONE):
     X = Array()
-    safe_call(clib.af_solve_lu(ct.pointer(X.arr), A.arr, P.arr, B.arr, options))
+    safe_call(backend.get().af_solve_lu(ct.pointer(X.arr), A.arr, P.arr, B.arr, options))
     return X
 
 def inverse(A, options=AF_MAT_NONE):
     I = Array()
-    safe_call(clib.af_inverse(ct.pointer(I.arr), A.arr, options))
+    safe_call(backend.get().af_inverse(ct.pointer(I.arr), A.arr, options))
     return I
 
 def rank(A, tol=1E-5):
     r = ct.c_uint(0)
-    safe_call(clib.af_rank(ct.pointer(r), A.arr, ct.c_double(tol)))
+    safe_call(backend.get().af_rank(ct.pointer(r), A.arr, ct.c_double(tol)))
     return r.value
 
 def det(A):
     re = ct.c_double(0)
     im = ct.c_double(0)
-    safe_call(clib.af_det(ct.pointer(re), ct.pointer(im), A.arr))
+    safe_call(backend.get().af_det(ct.pointer(re), ct.pointer(im), A.arr))
     re = re.value
     im = im.value
     return re if (im == 0) else re + im * 1j
 
 def norm(A, norm_type=AF_NORM_EUCLID, p=1.0, q=1.0):
     res = ct.c_double(0)
-    safe_call(clib.af_norm(ct.pointer(res), A.arr, norm_type, ct.c_double(p), ct.c_double(q)))
+    safe_call(backend.get().af_norm(ct.pointer(res), A.arr, norm_type, ct.c_double(p), ct.c_double(q)))
     return res.value
diff --git a/arrayfire/library.py b/arrayfire/library.py
index dec76b1..d3b18b4 100644
--- a/arrayfire/library.py
+++ b/arrayfire/library.py
@@ -10,40 +10,65 @@
 import platform
 import ctypes as ct
 
-def load_backend(name):
-    platform_name = platform.system()
-    assert(len(platform_name) >= 3)
-
-    libname = 'libaf' + name
-    if platform_name == 'Linux':
-        libname += '.so'
-    elif platform_name == 'Darwin':
-        libname += '.dylib'
-    elif platform_name == "Windows" or platform_name[:3] == "CYG":
-        libname += '.dll'
-        libname = libname[3:] # remove 'lib'
-        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);
-    else:
-        raise OSError(platform_name + ' not supported')
-
-    ct.cdll.LoadLibrary(libname)
-    clib = ct.CDLL(libname)
-    return clib, name
-
-try:
-    clib, backend = load_backend('cuda')
-except:
-    try:
-        clib, backend = load_backend('opencl')
-    except:
-        clib, backend = load_backend('cpu')
-
+class clibrary(object):
+
+    def __libname(self, name):
+        platform_name = platform.system()
+        assert(len(platform_name) >= 3)
+
+        libname = 'libaf' + name
+        if platform_name == 'Linux':
+            libname += '.so'
+        elif platform_name == 'Darwin':
+            libname += '.dylib'
+        elif platform_name == "Windows" or platform_name[:3] == "CYG":
+            libname += '.dll'
+            libname = libname[3:] # remove 'lib'
+            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);
+        else:
+            raise OSError(platform_name + ' not supported')
+
+        return libname
+
+    def set(self, name, unsafe=False):
+        if (not unsafe and self.__lock):
+            raise RuntimeError("Can not change backend after creating an Array")
+        if (self.clibs[name] is None):
+            raise RuntimeError("Could not load any ArrayFire %s backend" % name)
+        self.name = name
+        return
+
+    def __init__(self):
+        self.clibs = {}
+        self.name = None
+        self.__lock = False
+        # Iterate in reverse order of preference
+        for name in ('cpu', 'opencl', 'cuda'):
+            try:
+                libname = self.__libname(name)
+                ct.cdll.LoadLibrary(libname)
+                self.clibs[name] = ct.CDLL(libname)
+                self.name = name
+            except:
+                self.clibs[name] = None
+
+        if (self.name is None):
+            raise RuntimeError("Could not load any ArrayFire libraries")
+
+    def get(self):
+        return self.clibs[self.name]
+
+    def lock(self):
+        self.__lock = True
+
+backend = clibrary()
+del clibrary
 
 AF_SUCCESS            =   ct.c_int(0)
 
diff --git a/arrayfire/signal.py b/arrayfire/signal.py
index bad70ad..2b8c955 100644
--- a/arrayfire/signal.py
+++ b/arrayfire/signal.py
@@ -12,13 +12,13 @@ from .array import *
 
 def approx1(signal, pos0, method=AF_INTERP_LINEAR, off_grid=0.0):
     output = Array()
-    safe_call(clib.af_approx1(ct.pointer(output.arr), signal.arr, pos0.arr,
+    safe_call(backend.get().af_approx1(ct.pointer(output.arr), signal.arr, pos0.arr,
                               method, ct.c_double(off_grid)))
     return output
 
 def approx2(signal, pos0, pos1, method=AF_INTERP_LINEAR, off_grid=0.0):
     output = Array()
-    safe_call(clib.af_approx2(ct.pointer(output.arr), signal.arr,
+    safe_call(backend.get().af_approx2(ct.pointer(output.arr), signal.arr,
                               pos0.arr, pos1.arr, method, ct.c_double(off_grid)))
     return output
 
@@ -31,7 +31,7 @@ def fft(signal, dim0 = None , scale = None):
         scale = 1.0
 
     output = Array()
-    safe_call(clib.af_fft(ct.pointer(output.arr), signal.arr, ct.c_double(scale), ct.c_longlong(dim0)))
+    safe_call(backend.get().af_fft(ct.pointer(output.arr), signal.arr, ct.c_double(scale), ct.c_longlong(dim0)))
     return output
 
 def fft2(signal, dim0 = None, dim1 = None , scale = None):
@@ -46,7 +46,7 @@ def fft2(signal, dim0 = None, dim1 = None , scale = None):
         scale = 1.0
 
     output = Array()
-    safe_call(clib.af_fft2(ct.pointer(output.arr), signal.arr, ct.c_double(scale),
+    safe_call(backend.get().af_fft2(ct.pointer(output.arr), signal.arr, ct.c_double(scale),
                            ct.c_longlong(dim0), ct.c_longlong(dim1)))
     return output
 
@@ -65,7 +65,7 @@ def fft3(signal, dim0 = None, dim1 = None , dim2 = None, scale = None):
         scale = 1.0
 
     output = Array()
-    safe_call(clib.af_fft3(ct.pointer(output.arr), signal.arr, ct.c_double(scale),
+    safe_call(backend.get().af_fft3(ct.pointer(output.arr), signal.arr, ct.c_double(scale),
                            ct.c_longlong(dim0), ct.c_longlong(dim1), ct.c_longlong(dim2)))
     return output
 
@@ -78,7 +78,7 @@ def ifft(signal, dim0 = None , scale = None):
         scale = 1.0/float(dim0)
 
     output = Array()
-    safe_call(clib.af_ifft(ct.pointer(output.arr), signal.arr, ct.c_double(scale), ct.c_longlong(dim0)))
+    safe_call(backend.get().af_ifft(ct.pointer(output.arr), signal.arr, ct.c_double(scale), ct.c_longlong(dim0)))
     return output
 
 def ifft2(signal, dim0 = None, dim1 = None , scale = None):
@@ -98,7 +98,7 @@ def ifft2(signal, dim0 = None, dim1 = None , scale = None):
         scale = 1.0/float(dim0 * dim1)
 
     output = Array()
-    safe_call(clib.af_ifft2(ct.pointer(output.arr), signal.arr, ct.c_double(scale),
+    safe_call(backend.get().af_ifft2(ct.pointer(output.arr), signal.arr, ct.c_double(scale),
                             ct.c_longlong(dim0), ct.c_longlong(dim1)))
     return output
 
@@ -122,7 +122,7 @@ def ifft3(signal, dim0 = None, dim1 = None , dim2 = None, scale = None):
         scale = 1.0 / float(dim0 * dim1 * dim2)
 
     output = Array()
-    safe_call(clib.af_ifft3(ct.pointer(output.arr), signal.arr, ct.c_double(scale),
+    safe_call(backend.get().af_ifft3(ct.pointer(output.arr), signal.arr, ct.c_double(scale),
                             ct.c_longlong(dim0), ct.c_longlong(dim1), ct.c_longlong(dim2)))
     return output
 
@@ -156,17 +156,17 @@ def idft(signal, scale = None, odims=(None, None, None, None)):
 
 def convolve1(signal, kernel, conv_mode = AF_CONV_DEFAULT, conv_domain = AF_CONV_AUTO):
     output = Array()
-    safe_call(clib.af_convolve1(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode, conv_domain))
+    safe_call(backend.get().af_convolve1(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode, conv_domain))
     return output
 
 def convolve2(signal, kernel, conv_mode = AF_CONV_DEFAULT, conv_domain = AF_CONV_AUTO):
     output = Array()
-    safe_call(clib.af_convolve2(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode, conv_domain))
+    safe_call(backend.get().af_convolve2(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode, conv_domain))
     return output
 
 def convolve3(signal, kernel, conv_mode = AF_CONV_DEFAULT, conv_domain = AF_CONV_AUTO):
     output = Array()
-    safe_call(clib.af_convolve3(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode, conv_domain))
+    safe_call(backend.get().af_convolve3(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode, conv_domain))
     return output
 
 def convolve(signal, kernel, conv_mode = AF_CONV_DEFAULT, conv_domain = AF_CONV_AUTO):
@@ -182,17 +182,17 @@ def convolve(signal, kernel, conv_mode = AF_CONV_DEFAULT, conv_domain = AF_CONV_
 
 def fft_convolve1(signal, kernel, conv_mode = AF_CONV_DEFAULT):
     output = Array()
-    safe_call(clib.af_fft_convolve1(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode))
+    safe_call(backend.get().af_fft_convolve1(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode))
     return output
 
 def fft_convolve2(signal, kernel, conv_mode = AF_CONV_DEFAULT):
     output = Array()
-    safe_call(clib.af_fft_convolve2(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode))
+    safe_call(backend.get().af_fft_convolve2(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode))
     return output
 
 def fft_convolve3(signal, kernel, conv_mode = AF_CONV_DEFAULT):
     output = Array()
-    safe_call(clib.af_fft_convolve3(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode))
+    safe_call(backend.get().af_fft_convolve3(ct.pointer(output.arr), signal.arr, kernel.arr, conv_mode))
     return output
 
 def fft_convolve(signal, kernel, conv_mode = AF_CONV_DEFAULT):
@@ -208,10 +208,10 @@ def fft_convolve(signal, kernel, conv_mode = AF_CONV_DEFAULT):
 
 def fir(B, X):
     Y = Array()
-    safe_call(clib.af_fir(ct.pointer(Y.arr), B.arr, X.arr))
+    safe_call(backend.get().af_fir(ct.pointer(Y.arr), B.arr, X.arr))
     return Y
 
 def iir(B, A, X):
     Y = Array()
-    safe_call(clib.af_iir(ct.pointer(Y.arr), B.arr, A.arr, X.arr))
+    safe_call(backend.get().af_iir(ct.pointer(Y.arr), B.arr, A.arr, X.arr))
     return Y
diff --git a/arrayfire/statistics.py b/arrayfire/statistics.py
index 30aedda..597dc68 100644
--- a/arrayfire/statistics.py
+++ b/arrayfire/statistics.py
@@ -15,9 +15,9 @@ def mean(a, weights=None, dim=None):
         out = Array()
 
         if weights is None:
-            safe_call(clib.af_mean(ct.pointer(out.arr), a.arr, ct.c_int(dim)))
+            safe_call(backend.get().af_mean(ct.pointer(out.arr), a.arr, ct.c_int(dim)))
         else:
-            safe_call(clib.af_mean_weighted(ct.pointer(out.arr), a.arr, weights.arr, ct.c_int(dim)))
+            safe_call(backend.get().af_mean_weighted(ct.pointer(out.arr), a.arr, weights.arr, ct.c_int(dim)))
 
         return out
     else:
@@ -25,9 +25,9 @@ def mean(a, weights=None, dim=None):
         imag = ct.c_double(0)
 
         if weights is None:
-            safe_call(clib.af_mean_all(ct.pointer(real), ct.pointer(imag), a.arr))
+            safe_call(backend.get().af_mean_all(ct.pointer(real), ct.pointer(imag), a.arr))
         else:
-            safe_call(clib.af_mean_all_weighted(ct.pointer(real), ct.pointer(imag), a.arr, weights.arr))
+            safe_call(backend.get().af_mean_all_weighted(ct.pointer(real), ct.pointer(imag), a.arr, weights.arr))
 
         real = real.value
         imag = imag.value
@@ -39,9 +39,9 @@ def var(a, isbiased=False, weights=None, dim=None):
         out = Array()
 
         if weights is None:
-            safe_call(clib.af_var(ct.pointer(out.arr), a.arr, isbiased, ct.c_int(dim)))
+            safe_call(backend.get().af_var(ct.pointer(out.arr), a.arr, isbiased, ct.c_int(dim)))
         else:
-            safe_call(clib.af_var_weighted(ct.pointer(out.arr), a.arr, weights.arr, ct.c_int(dim)))
+            safe_call(backend.get().af_var_weighted(ct.pointer(out.arr), a.arr, weights.arr, ct.c_int(dim)))
 
         return out
     else:
@@ -49,9 +49,9 @@ def var(a, isbiased=False, weights=None, dim=None):
         imag = ct.c_double(0)
 
         if weights is None:
-            safe_call(clib.af_var_all(ct.pointer(real), ct.pointer(imag), a.arr, isbiased))
+            safe_call(backend.get().af_var_all(ct.pointer(real), ct.pointer(imag), a.arr, isbiased))
         else:
-            safe_call(clib.af_var_all_weighted(ct.pointer(real), ct.pointer(imag), a.arr, weights.arr))
+            safe_call(backend.get().af_var_all_weighted(ct.pointer(real), ct.pointer(imag), a.arr, weights.arr))
 
         real = real.value
         imag = imag.value
@@ -61,12 +61,12 @@ def var(a, isbiased=False, weights=None, dim=None):
 def stdev(a, dim=None):
     if dim is not None:
         out = Array()
-        safe_call(clib.af_stdev(ct.pointer(out.arr), a.arr, ct.c_int(dim)))
+        safe_call(backend.get().af_stdev(ct.pointer(out.arr), a.arr, ct.c_int(dim)))
         return out
     else:
         real = ct.c_double(0)
         imag = ct.c_double(0)
-        safe_call(clib.af_stdev_all(ct.pointer(real), ct.pointer(imag), a.arr))
+        safe_call(backend.get().af_stdev_all(ct.pointer(real), ct.pointer(imag), a.arr))
         real = real.value
         imag = imag.value
         return real if imag == 0 else real + imag * 1j
@@ -74,12 +74,12 @@ def stdev(a, dim=None):
 def cov(a, isbiased=False, dim=None):
     if dim is not None:
         out = Array()
-        safe_call(clib.af_cov(ct.pointer(out.arr), a.arr, isbiased, ct.c_int(dim)))
+        safe_call(backend.get().af_cov(ct.pointer(out.arr), a.arr, isbiased, ct.c_int(dim)))
         return out
     else:
         real = ct.c_double(0)
         imag = ct.c_double(0)
-        safe_call(clib.af_cov_all(ct.pointer(real), ct.pointer(imag), a.arr, isbiased))
+        safe_call(backend.get().af_cov_all(ct.pointer(real), ct.pointer(imag), a.arr, isbiased))
         real = real.value
         imag = imag.value
         return real if imag == 0 else real + imag * 1j
@@ -87,12 +87,12 @@ def cov(a, isbiased=False, dim=None):
 def median(a, dim=None):
     if dim is not None:
         out = Array()
-        safe_call(clib.af_median(ct.pointer(out.arr), a.arr, ct.c_int(dim)))
+        safe_call(backend.get().af_median(ct.pointer(out.arr), a.arr, ct.c_int(dim)))
         return out
     else:
         real = ct.c_double(0)
         imag = ct.c_double(0)
-        safe_call(clib.af_median_all(ct.pointer(real), ct.pointer(imag), a.arr))
+        safe_call(backend.get().af_median_all(ct.pointer(real), ct.pointer(imag), a.arr))
         real = real.value
         imag = imag.value
         return real if imag == 0 else real + imag * 1j
@@ -100,7 +100,7 @@ def median(a, dim=None):
 def corrcoef(x, y):
     real = ct.c_double(0)
     imag = ct.c_double(0)
-    safe_call(clib.af_corrcoef(ct.pointer(real), ct.pointer(imag), x.arr, y.arr))
+    safe_call(backend.get().af_corrcoef(ct.pointer(real), ct.pointer(imag), x.arr, y.arr))
     real = real.value
     imag = imag.value
     return real if imag == 0 else real + imag * 1j
diff --git a/arrayfire/util.py b/arrayfire/util.py
index 04ac95d..1cca212 100644
--- a/arrayfire/util.py
+++ b/arrayfire/util.py
@@ -71,14 +71,14 @@ def safe_call(af_error):
     if (af_error != AF_SUCCESS.value):
         err_str = ct.c_char_p(0)
         err_len = ct.c_longlong(0)
-        clib.af_get_last_error(ct.pointer(err_str), ct.pointer(err_len))
+        backend.get().af_get_last_error(ct.pointer(err_str), ct.pointer(err_len))
         raise RuntimeError(to_str(err_str), af_error)
 
 def get_version():
     major=ct.c_int(0)
     minor=ct.c_int(0)
     patch=ct.c_int(0)
-    safe_call(clib.af_get_version(ct.pointer(major), ct.pointer(minor), ct.pointer(patch)))
+    safe_call(backend.get().af_get_version(ct.pointer(major), ct.pointer(minor), ct.pointer(patch)))
     return major,minor,patch
 
 to_dtype = {'f' : f32,
diff --git a/arrayfire/vision.py b/arrayfire/vision.py
index 4de067b..79a3269 100644
--- a/arrayfire/vision.py
+++ b/arrayfire/vision.py
@@ -12,7 +12,7 @@ from .features import *
 
 def fast(image, threshold=20.0, arc_length=9, non_max=True, feature_ratio=0.05, edge=3):
     out = Features()
-    safe_call(clib.af_fast(ct.pointer(out.feat),
+    safe_call(backend.get().af_fast(ct.pointer(out.feat),
                            image.arr, ct.c_float(threshold), ct.c_uint(arc_length), non_max,
                            ct.c_float(feature_ratio), ct.c_uint(edge)))
     return out
@@ -20,7 +20,7 @@ def fast(image, threshold=20.0, arc_length=9, non_max=True, feature_ratio=0.05,
 def orb(image, threshold=20.0, max_features=400, scale = 1.5, num_levels = 4, blur_image = False):
     feat = Features()
     desc = Array()
-    safe_call(clib.af_orb(ct.pointer(feat.feat), ct.pointer(desc.arr),
+    safe_call(backend.get().af_orb(ct.pointer(feat.feat), ct.pointer(desc.arr),
                           ct.c_float(threshold), ct.c_uint(max_features),
                           ct.c_float(scale), ct.c_uint(num_levels), blur_image))
     return feat, desc
@@ -28,12 +28,12 @@ def orb(image, threshold=20.0, max_features=400, scale = 1.5, num_levels = 4, bl
 def hamming_matcher(query, database, dim = 0, num_nearest = 1):
     index = Array()
     dist = Array()
-    safe_call(clib.af_hamming_matcher(ct.pointer(idx.arr), ct.pointer(dist.arr),
+    safe_call(backend.get().af_hamming_matcher(ct.pointer(idx.arr), ct.pointer(dist.arr),
                                       query.arr, database.arr,
                                       ct.c_longlong(dim), ct.c_longlong(num_nearest)))
     return index, dist
 
 def match_template(image, template, match_type = AF_SAD):
     out = Array()
-    safe_call(clib.af_match_template(ct.pointer(out.arr), image.arr, template.arr, match_type))
+    safe_call(backend.get().af_match_template(ct.pointer(out.arr), image.arr, template.arr, match_type))
     return out

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/python-arrayfire.git



More information about the debian-science-commits mailing list