extern crate libc;
use array::Array;
use defines::{AfError, MatProp, NormType};
use error::HANDLE_ERROR;
use util::{AfArray, MutAfArray, MutDouble, to_u32};
use self::libc::{uint8_t, c_int, c_uint, c_double};
#[allow(dead_code)]
extern {
fn af_svd(u: MutAfArray, s: MutAfArray, vt: MutAfArray, input: AfArray) -> c_int;
fn af_svd_inplace(u: MutAfArray, s: MutAfArray, vt: MutAfArray, input: AfArray) -> c_int;
fn af_lu(lower: MutAfArray, upper: MutAfArray, pivot: MutAfArray, input: AfArray) -> c_int;
fn af_lu_inplace(pivot: MutAfArray, input: AfArray, is_lapack_piv: c_int) -> c_int;
fn af_qr(q: MutAfArray, r: MutAfArray, tau: MutAfArray, input: AfArray) -> c_int;
fn af_qr_inplace(tau: MutAfArray, input: AfArray) -> c_int;
fn af_cholesky(out: MutAfArray, info: *mut c_int, input: AfArray, is_upper: c_int) -> c_int;
fn af_cholesky_inplace(info: *mut c_int, input: AfArray, is_upper: c_int) -> c_int;
fn af_solve(x: MutAfArray, a: AfArray, b: AfArray, options: c_uint) -> c_int;
fn af_solve_lu(x: MutAfArray, a: AfArray, piv: AfArray, b: AfArray, options: c_uint) -> c_int;
fn af_inverse(out: MutAfArray, input: AfArray, options: c_uint) -> c_int;
fn af_rank(rank: *mut c_uint, input: AfArray, tol: c_double) -> c_int;
fn af_det(det_real: MutDouble, det_imag: MutDouble, input: AfArray) -> c_int;
fn af_norm(out: MutDouble, input: AfArray, ntype: uint8_t, p: c_double, q: c_double) -> c_int;
fn af_is_lapack_available(out: *mut c_int) -> c_int;
}
#[allow(unused_mut)]
pub fn svd(input: &Array) -> (Array, Array, Array) {
unsafe {
let mut u: i64 = 0;
let mut s: i64 = 0;
let mut vt: i64 = 0;
let err_val = af_svd(&mut u as MutAfArray, &mut s as MutAfArray, &mut vt as MutAfArray,
input.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
(Array::from(u), Array::from(s), Array::from(vt))
}
}
#[allow(unused_mut)]
pub fn svd_inplace(input: &mut Array) -> (Array, Array, Array) {
unsafe {
let mut u: i64 = 0;
let mut s: i64 = 0;
let mut vt: i64 = 0;
let err_val = af_svd_inplace(&mut u as MutAfArray, &mut s as MutAfArray,
&mut vt as MutAfArray, input.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
(Array::from(u), Array::from(s), Array::from(vt))
}
}
#[allow(unused_mut)]
pub fn lu(input: &Array) -> (Array, Array, Array) {
unsafe {
let mut lower: i64 = 0;
let mut upper: i64 = 0;
let mut pivot: i64 = 0;
let err_val = af_lu(&mut lower as MutAfArray, &mut upper as MutAfArray,
&mut pivot as MutAfArray, input.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
(Array::from(lower), Array::from(upper), Array::from(pivot))
}
}
#[allow(unused_mut)]
pub fn lu_inplace(input: &mut Array, is_lapack_piv: bool) -> Array {
unsafe {
let mut pivot: i64 = 0;
let err_val = af_lu_inplace(&mut pivot as MutAfArray, input.get() as AfArray,
is_lapack_piv as c_int);
HANDLE_ERROR(AfError::from(err_val));
Array::from(pivot)
}
}
#[allow(unused_mut)]
pub fn qr(input: &Array) -> (Array, Array, Array) {
unsafe {
let mut q: i64 = 0;
let mut r: i64 = 0;
let mut tau: i64 = 0;
let err_val = af_qr(&mut q as MutAfArray, &mut r as MutAfArray,
&mut tau as MutAfArray, input.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
(Array::from(q), Array::from(r), Array::from(tau))
}
}
#[allow(unused_mut)]
pub fn qr_inplace(input: &mut Array) -> Array {
unsafe {
let mut tau: i64 = 0;
let err_val = af_qr_inplace(&mut tau as MutAfArray, input.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
Array::from(tau)
}
}
#[allow(unused_mut)]
pub fn cholesky(input: &Array, is_upper: bool) -> (Array, i32) {
unsafe {
let mut temp: i64 = 0;
let mut info: i32 = 0;
let err_val = af_cholesky(&mut temp as MutAfArray, &mut info as *mut c_int,
input.get() as AfArray, is_upper as c_int);
HANDLE_ERROR(AfError::from(err_val));
(Array::from(temp), info)
}
}
#[allow(unused_mut)]
pub fn cholesky_inplace(input: &mut Array, is_upper: bool) -> i32 {
unsafe {
let mut info: i32 = 0;
let err_val = af_cholesky_inplace(&mut info as *mut c_int, input.get() as AfArray,
is_upper as c_int);
HANDLE_ERROR(AfError::from(err_val));
info
}
}
#[allow(unused_mut)]
pub fn solve(a: &Array, b: &Array, options: MatProp) -> Array {
unsafe {
let mut temp: i64 = 0;
let err_val = af_solve(&mut temp as MutAfArray, a.get() as AfArray,
b.get() as AfArray, to_u32(options) as c_uint);
HANDLE_ERROR(AfError::from(err_val));
Array::from(temp)
}
}
#[allow(unused_mut)]
pub fn solve_lu(a: &Array, piv: &Array, b: &Array,
options: MatProp) -> Array {
unsafe {
let mut temp: i64 = 0;
let err_val = af_solve_lu(&mut temp as MutAfArray, a.get() as AfArray, piv.get() as AfArray,
b.get() as AfArray, to_u32(options) as c_uint);
HANDLE_ERROR(AfError::from(err_val));
Array::from(temp)
}
}
#[allow(unused_mut)]
pub fn inverse(input: &Array, options: MatProp) -> Array {
unsafe {
let mut temp: i64 = 0;
let err_val = af_inverse(&mut temp as MutAfArray, input.get() as AfArray, to_u32(options) as c_uint);
HANDLE_ERROR(AfError::from(err_val));
Array::from(temp)
}
}
#[allow(unused_mut)]
pub fn rank(input: &Array, tol: f64) -> u32 {
unsafe {
let mut temp: u32 = 0;
let err_val = af_rank(&mut temp as *mut c_uint, input.get() as AfArray, tol as c_double);
HANDLE_ERROR(AfError::from(err_val));
temp
}
}
#[allow(unused_mut)]
pub fn det(input: &Array) -> (f64, f64) {
unsafe {
let mut real: f64 = 0.0;
let mut imag: f64 = 0.0;
let err_val = af_det(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
(real, imag)
}
}
#[allow(unused_mut)]
pub fn norm(input: &Array, ntype: NormType, p: f64, q: f64) -> f64 {
unsafe {
let mut out: f64 = 0.0;
let err_val = af_norm(&mut out as MutDouble, input.get() as AfArray, ntype as uint8_t,
p as c_double, q as c_double);
HANDLE_ERROR(AfError::from(err_val));
out
}
}
pub fn is_lapack_available() -> bool {
unsafe {
let mut temp: i32 = 0;
af_is_lapack_available(&mut temp as *mut c_int);
temp > 0 }
}