use ::af;
use super::{Vector};
use ::norm::{Norm};
impl Vector {
pub fn new<T>(data: T) -> Vector where T: Into<Vec<f64>> {
let data: Vec<f64> = data.into();
let size = data.len();
let backend = af::Array::new(&data, af::Dim4::new(&[size as u64, 1, 1, 1]));
Vector {size, backend, data}
}
pub fn from_fn<F>(size: usize, f: F) -> Vector where F: Fn(f64) -> f64 {
let data: Vec<f64> = (0..size).into_iter().map(|x| f(x as f64)).collect();
let backend = af::Array::new(&data, af::Dim4::new(&[size as u64,1, 1, 1]));
Vector {size, backend, data}
}
pub fn zeros(size: usize) -> Vector {
let data = vec![0f64; size];
Vector::new(data)
}
pub fn ones(size: usize) -> Vector {
let data = vec![1f64; size];
Vector::new(data)
}
pub fn size(&self) -> usize {
self.size
}
pub fn data(&self) -> Vec<f64> {
self.data.clone()
}
pub fn into_vec(self) -> Vec<f64> {
self.data
}
pub fn get(&self, index: usize) -> Option<f64> {
self.data.get(index).cloned()
}
pub fn apply<F>(self, f: F) -> Vector where F: Fn(f64) -> f64 {
let mut data = Vec::with_capacity(self.size());
for val in self {
data.push(f(val));
}
Vector::new(data)
}
pub fn apply_self<F>(&mut self, f: F) where F: Fn(f64) -> f64 {
let mut data = self.data();
for val in &mut data {
*val = f(*val);
}
*self = Vector::new(data);
}
pub fn max(&self) -> f64 {
af::max_all(&self.backend).0
}
pub fn min(&self) -> f64 {
af::min_all(&self.backend).0
}
pub fn select(&self, idxs: &[usize]) -> Result<Vector, String> {
let mut data: Vec<f64> = Vec::with_capacity(idxs.len());
for idx in idxs {
let o = self.get(*idx);
match o {
Some(x) => data.push(x),
None => return Err(format!("Tried to access index: {} but length was: {}", idx, self.size()))
}
}
Ok(Vector::new(data))
}
pub fn dot(&self, rhs: &Vector) -> Result<f64, String> {
if let Err(s) = Vector::check_size(self, rhs) {
return Err(s);
}
let result = af::dot(&self.backend, &rhs.backend, af::MatProp::NONE, af::MatProp::NONE);
Ok(af::max_all(&result).0)
}
pub fn sum(&self) -> f64 {
af::sum_all(&self.backend).0
}
pub fn norm(&self, norm_type: Norm) -> f64 {
match norm_type {
Norm::Taxicab => af::norm(&self.backend, af::NormType::VECTOR_1, 0.0, 0.0),
Norm::Euclidean => af::norm(&self.backend, af::NormType::VECTOR_2, 0.0, 0.0),
Norm::Infinity => af::norm(&self.backend, af::NormType::VECTOR_INF, 0.0, 0.0),
Norm::LP(p) => af::norm(&self.backend, af::NormType::VECTOR_P, p, 0.0),
}
}
pub fn metric(&self, rhs: &Vector) -> Result<f64, String> {
if let Err(s) = Vector::check_size(self, rhs) {
return Err(s);
}
let diff: Vector = Vector::from(&self.backend - &rhs.backend);
Ok(diff.norm(Norm::Euclidean))
}
pub fn mean(&self) -> f64 {
af::mean_all(&self.backend).0
}
pub fn variance(&self) -> f64 {
let mean = self.mean();
let mut var = 0f64;
for x in self {
var += (x - mean).powf(2.0);
}
var
}
fn check_size(lhs: &Vector, rhs: &Vector) -> Result<(), String> {
if lhs.size() == rhs.size() {
Ok(())
} else {
Err(format!("The two Vectors must have the same size. The left Vector has size: {} and the right Vector has size: {}",
lhs.size(), rhs.size()))
}
}
}
use std::fmt;
impl fmt::Display for Vector {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[");
for (i, v) in self.data().into_iter().enumerate() {
write!(f, "{}", v);
if i != self.size()-1 {
write!(f, ", ");
}
}
write!(f, "]")
}
}
impl<'a> From<&'a Vector> for Vector {
fn from(vector: &Vector) -> Vector {
vector.clone()
}
}
impl From<af::Array> for Vector {
fn from(array: af::Array) -> Vector {
let dims = array.dims();
let max = ::std::usize::MAX;
assert!(dims.get()[0] < max as u64, "Internal array representation contained more than `usize` rows: {} > {}", dims.get()[0], max);
assert!(dims.get()[1] == 1, "Internal array representation contained data in 2D space");
assert!(dims.get()[2] == 1, "Internal array representation contained data in 3D space");
assert!(dims.get()[3] == 1, "Internal array representation contained data in 4D space");
let size: u64 = array.dims().get().into_iter().fold(1, |acc, &d| acc * d);
let mut data: Vec<f64> = vec![0.; size as usize];
array.host(&mut data);
Vector::new(data)
}
}
impl From<f64> for Vector {
fn from(value: f64) -> Vector {
Vector::new(vec![value])
}
}
impl<'a> From<&'a f64> for Vector {
fn from(value: &f64) -> Vector {
Vector::new(vec![*value])
}
}
use std::iter::{IntoIterator};
impl IntoIterator for Vector {
type Item = f64;
type IntoIter = ::std::vec::IntoIter<f64>;
fn into_iter(self) -> Self::IntoIter {
self.data().into_iter()
}
}
impl<'a> IntoIterator for &'a Vector {
type Item = f64;
type IntoIter = ::std::vec::IntoIter<f64>;
fn into_iter(self) -> Self::IntoIter {
self.data().into_iter()
}
}
use std::cmp::{PartialEq, Eq};
impl PartialEq for Vector {
fn eq(&self, other: &Vector) -> bool {
self.size() == other.size() && self.data == other.data
}
}
impl Eq for Vector {}