extern crate libc;
use array::Array;
use defines::{AfError, MatProp, NormType};
use error::HANDLE_ERROR;
use util::{AfArray, MutAfArray, MutDouble, to_u32};
use util::{FloatingPoint, HasAfEnum};
use self::libc::{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: c_uint, 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<T>(input: &Array<T>) -> (Array<T>, Array< T::BaseType >, Array<T>)
where T: HasAfEnum + FloatingPoint,
T::BaseType: HasAfEnum
{
let mut u: i64 = 0;
let mut s: i64 = 0;
let mut vt: i64 = 0;
unsafe {
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));
}
(u.into(), s.into(), vt.into())
}
#[allow(unused_mut)]
pub fn svd_inplace<T>(input: &mut Array<T>) -> (Array<T>, Array< T::BaseType >, Array<T>)
where T: HasAfEnum + FloatingPoint,
T::BaseType: HasAfEnum
{
let mut u: i64 = 0;
let mut s: i64 = 0;
let mut vt: i64 = 0;
unsafe {
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));
}
(u.into(), s.into(), vt.into())
}
#[allow(unused_mut)]
pub fn lu<T>(input: &Array<T>) -> (Array<T>, Array<T>, Array<i32>)
where T: HasAfEnum + FloatingPoint
{
let mut lower: i64 = 0;
let mut upper: i64 = 0;
let mut pivot: i64 = 0;
unsafe {
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));
}
(lower.into(), upper.into(), pivot.into())
}
#[allow(unused_mut)]
pub fn lu_inplace<T>(input: &mut Array<T>, is_lapack_piv: bool) -> Array<i32>
where T: HasAfEnum + FloatingPoint
{
let mut pivot: i64 = 0;
unsafe {
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));
}
pivot.into()
}
#[allow(unused_mut)]
pub fn qr<T>(input: &Array<T>) -> (Array<T>, Array<T>, Array<T>)
where T: HasAfEnum + FloatingPoint
{
let mut q: i64 = 0;
let mut r: i64 = 0;
let mut tau: i64 = 0;
unsafe {
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));
}
(q.into(), r.into(), tau.into())
}
#[allow(unused_mut)]
pub fn qr_inplace<T>(input: &mut Array<T>) -> Array<T>
where T: HasAfEnum + FloatingPoint
{
let mut tau: i64 = 0;
unsafe {
let err_val = af_qr_inplace(&mut tau as MutAfArray, input.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
}
tau.into()
}
#[allow(unused_mut)]
pub fn cholesky<T>(input: &Array<T>, is_upper: bool) -> (Array<T>, i32)
where T: HasAfEnum + FloatingPoint
{
let mut temp: i64 = 0;
let mut info: i32 = 0;
unsafe {
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));
}
(temp.into(), info)
}
#[allow(unused_mut)]
pub fn cholesky_inplace<T>(input: &mut Array<T>, is_upper: bool) -> i32
where T: HasAfEnum + FloatingPoint
{
let mut info: i32 = 0;
unsafe {
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<T>(a: &Array<T>, b: &Array<T>, options: MatProp) -> Array<T>
where T: HasAfEnum + FloatingPoint
{
let mut temp: i64 = 0;
unsafe {
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));
}
temp.into()
}
#[allow(unused_mut)]
pub fn solve_lu<T>(a: &Array<T>, piv: &Array<i32>, b: &Array<T>,
options: MatProp) -> Array<T>
where T: HasAfEnum + FloatingPoint
{
let mut temp: i64 = 0;
unsafe {
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));
}
temp.into()
}
#[allow(unused_mut)]
pub fn inverse<T>(input: &Array<T>, options: MatProp) -> Array<T>
where T: HasAfEnum + FloatingPoint
{
let mut temp: i64 = 0;
unsafe {
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));
}
temp.into()
}
#[allow(unused_mut)]
pub fn rank<T>(input: &Array<T>, tol: f64) -> u32
where T: HasAfEnum + FloatingPoint
{
let mut temp: u32 = 0;
unsafe {
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<T>(input: &Array<T>) -> (f64, f64)
where T: HasAfEnum + FloatingPoint
{
let mut real: f64 = 0.0;
let mut imag: f64 = 0.0;
unsafe {
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<T>(input: &Array<T>, ntype: NormType, p: f64, q: f64) -> f64
where T: HasAfEnum + FloatingPoint
{
let mut out: f64 = 0.0;
unsafe {
let err_val = af_norm(&mut out as MutDouble, input.get() as AfArray,
ntype as c_uint,
p as c_double, q as c_double);
HANDLE_ERROR(AfError::from(err_val));
}
out
}
pub fn is_lapack_available() -> bool {
let mut temp: i32 = 0;
unsafe {
af_is_lapack_available(&mut temp as *mut c_int);
}
temp > 0 }