1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
extern crate libc;
extern crate num;

use defines::{AfError, ColorMap, ConvDomain, ConvMode, DType, InterpType, MatProp, MatchType};
use defines::{SparseFormat, BinaryOp, RandomEngineType};
use error::HANDLE_ERROR;
use std::mem;
use self::num::Complex;
use self::libc::{uint8_t, c_int, size_t, c_void};

pub type AfArray       = self::libc::c_longlong;
pub type AfIndex       = self::libc::c_longlong;
pub type CellPtr       = *const self::libc::c_void;
pub type Complex32     = Complex<f32>;
pub type Complex64     = Complex<f64>;
pub type DimT          = self::libc::c_longlong;
pub type Feat          = *const self::libc::c_void;
pub type Intl          = self::libc::c_longlong;
pub type MutAfArray    = *mut self::libc::c_longlong;
pub type MutAfIndex    = *mut self::libc::c_longlong;
pub type MutDimT       = *mut self::libc::c_longlong;
pub type MutDouble     = *mut self::libc::c_double;
pub type MutFeat       = *mut *mut self::libc::c_void;
pub type MutRandEngine = *mut self::libc::c_longlong;
pub type MutUint       = *mut self::libc::c_uint;
pub type MutVoidPtr    = *mut self::libc::c_ulonglong;
pub type MutWndHandle  = *mut self::libc::c_ulonglong;
pub type RandEngine    = self::libc::c_longlong;
pub type Uintl         = self::libc::c_ulonglong;
pub type WndHandle     = self::libc::c_ulonglong;

#[allow(dead_code)]
extern {
    fn af_get_size_of(size: *mut size_t, aftype: uint8_t) -> c_int;

    fn af_alloc_host(ptr: *mut *const c_void, bytes: DimT) -> c_int;
    fn af_free_host(ptr: *mut c_void) -> c_int;
}

/// Get size, in bytes, of the arrayfire native type
pub fn get_size(value: DType) -> usize {
    unsafe {
        let mut ret_val: usize = 0;
        let err_val = af_get_size_of(&mut ret_val as *mut size_t, value as uint8_t);
        HANDLE_ERROR(AfError::from(err_val));
        ret_val
    }
}

/// Allocates space using Arrayfire allocator in host memory
#[allow(dead_code)]
pub fn alloc_host<T>(elements: usize, _type: DType) -> *const T {
    let ptr: *const T = ::std::ptr::null();
    let bytes = (elements * get_size(_type)) as DimT;
    unsafe {
        let err_val = af_alloc_host(&mut (ptr as *const c_void), bytes);
        HANDLE_ERROR(AfError::from(err_val));
    }
    ptr
}

/// Frees memory allocated by Arrayfire allocator in host memory
pub fn free_host<T>(ptr: *mut T) {
    unsafe {
        let err_val = af_free_host(ptr as *mut c_void);
        HANDLE_ERROR(AfError::from(err_val));
    }
}

impl From<i32> for AfError {
    fn from(t: i32) -> AfError {
        assert!(AfError::SUCCESS as i32 <= t && t <= AfError::ERR_UNKNOWN as i32);
        unsafe { mem::transmute(t) }
    }
}

impl From<i32> for DType {
    fn from(t: i32) -> DType {
        assert!(DType::F32 as i32 <= t && t <= DType::U64 as i32);
        unsafe { mem::transmute(t) }
    }
}

impl From<i32> for InterpType {
    fn from(t: i32) -> InterpType {
        assert!(InterpType::NEAREST as i32 <= t && t <= InterpType::BICUBIC_SPLINE as i32);
        unsafe { mem::transmute(t) }
    }
}

impl From<i32> for ConvMode {
    fn from(t: i32) -> ConvMode {
        assert!(ConvMode::DEFAULT as i32 <= t && t <= ConvMode::EXPAND as i32);
        unsafe { mem::transmute(t) }
    }
}

impl From<i32> for ConvDomain {
    fn from(t: i32) -> ConvDomain {
        assert!(ConvDomain::AUTO as i32 <= t && t <= ConvDomain::FREQUENCY as i32);
        unsafe { mem::transmute(t) }
    }
}

impl From<i32> for MatchType {
    fn from(t: i32) -> MatchType {
        assert!(MatchType::SAD as i32 <= t && t <= MatchType::SHD as i32);
        unsafe { mem::transmute(t) }
    }
}

pub fn to_u32(t: MatProp) -> u32 {
    match t {
        MatProp::NONE       =>  0,
        MatProp::TRANS      =>  1,
        MatProp::CTRANS     =>  2,
        MatProp::UPPER      =>  32,
        MatProp::LOWER      =>  64,
        MatProp::DIAGUNIT  =>  128,
        MatProp::SYM        =>  512,
        MatProp::POSDEF     =>  1024,
        MatProp::ORTHOG     =>  2048,
        MatProp::TRIDIAG   =>  4096,
        MatProp::BLOCKDIAG =>  8192,
    }
}

impl From<i32> for ColorMap {
    fn from(t: i32) -> ColorMap {
        assert!(ColorMap::DEFAULT as i32 <= t && t <= ColorMap::BLUE as i32);
        unsafe { mem::transmute(t) }
    }
}

/// Types of the data that can be generated using ArrayFire data generation functions.
///
/// The trait HasAfEnum has been defined internally for the following types. We strongly suggest
/// not to implement this trait in your program for user defined types because ArrayFire functions
/// will only work for the following data types currently. Any such trait implementation for types
/// other than the ones listed below will result in undefined behavior.
///
/// - f32
/// - f64
/// - num::Complex\<f32\>
/// - num::Complex\<f64\>
/// - bool
/// - i32
/// - u32
/// - u8
/// - i64
/// - u64
/// - i16
/// - u16
///
pub trait HasAfEnum {
    /// Return trait implmentors corresponding [DType](./enum.DType.html)
    fn get_af_dtype() -> DType;
}

macro_rules! impl_has_af_enum {
    ($rust_t: ty, $af_dtype: expr) => (
        impl HasAfEnum for $rust_t {
            fn get_af_dtype() -> DType {
                $af_dtype
            }
        }
    )
}

impl_has_af_enum!(f32, DType::F32);
impl_has_af_enum!(Complex<f32>, DType::C32);
impl_has_af_enum!(f64, DType::F64);
impl_has_af_enum!(Complex<f64>, DType::C64);
// FIXME: Rust bool may become incompatible in memory layout with C-ABI
// Currently, it is of size 1-byte
impl_has_af_enum!(bool, DType::B8);
impl_has_af_enum!(i32, DType::S32);
impl_has_af_enum!(u32, DType::U32);
impl_has_af_enum!(u8, DType::U8);
impl_has_af_enum!(i64, DType::S64);
impl_has_af_enum!(u64, DType::U64);
impl_has_af_enum!(i16, DType::S16);
impl_has_af_enum!(u16, DType::U16);

impl From<i32> for SparseFormat {
    fn from(t: i32) -> SparseFormat {
        assert!(SparseFormat::DENSE as i32 <= t && t <= SparseFormat::COO as i32);
        unsafe { mem::transmute(t) }
    }
}

impl From<i32> for BinaryOp {
    fn from(t: i32) -> BinaryOp {
        assert!(BinaryOp::ADD as i32 <= t && t <= BinaryOp::MAX as i32);
        unsafe { mem::transmute(t) }
    }
}

impl From<i32> for RandomEngineType {
    fn from(t: i32) -> RandomEngineType {
        assert!(RandomEngineType::PHILOX_4X32_10 as i32 <= t && t <= RandomEngineType::MERSENNE_GP11213 as i32);
        unsafe { mem::transmute(t) }
    }
}