openalgebra 0.0.1

Rust linear algebra library for OpenCL
use vector::Vector;
use norm::Norm;

#[test]
fn creation() {
    let v1 = Vector::new(vec![0.0, 1.0, 2.0, 3.0]);
    let v2 = Vector::from_fn(4, |x| x);
    assert!(v1 == v2, "Creation of a Vector differs between `new` and `from_fn`:\nVector New: {}\nvs\nVector From_fn: {}", v1, v2);
}

#[test]
fn zero() {
    let size: usize = 4;
    let v1 = Vector::new(vec![0.; size]);
    let v2 = Vector::zeros(size);
    assert!(v1 == v2, "Creation of a Zeros Vector differs between `new` and `zeros`:\nVector New: {}\nvs\nVector Zeros: {}", v1, v2);
}

#[test]
fn one() {
    let size: usize = 4;
    let v1 = Vector::new(vec![1.; size]);
    let v2 = Vector::ones(size);
    assert!(v1 == v2, "Creation of a Ones Vector differs between `new` and `ones`:\nVector New: {}\nvs\nVector Ones: {}", v1, v2);
}

#[test]
fn size() {
    let size: usize = 4;
    let v = Vector::new(vec![0.; size]);
    assert!(size == v.size(), "Size of a Vector does not match creation length:\nVector Size: {} == {}\nvs\nCreation: {}", v, v.size(), size);
}

#[test]
fn data() {
    let v = Vector::new(vec![5.; 4]);
    assert!(vec![5.; 4] == v.data(), "Data of a Vector does not match creation data:\nVector: {:?}\nvs\nCreation: {:?}", v.data(), vec![5.; 4]);
}

#[test]
fn get() {
    let data: Vec<f64> = vec![0., 1., 2., 3.];
    let v = Vector::new(data.clone());
    for i in 0..4 {
        let eq = data.get(i).cloned() == v.get(i);
        assert!(eq, "Getting individual values from a Vector does not match creation data at index {}:\nVector: {:?}\nvs\nCreation: {:?}", i, v.get(i), data.get(i).cloned());
    }
}

#[test]
fn apply() {
    let mut v1 = Vector::new(vec![0., 1., 2., 3.]);
    let v2 = Vector::new(vec![0., 2., 4., 6.]);
    v1 = v1.apply(|x| x * 2.0);
    assert!(v1 == v2, "Applying a function to a Vector does not match expected result:\nVector: {}\nvs\nExpected: {}", v1, v2);
}

#[test]
fn apply_self() {
    let mut v1 = Vector::new(vec![0., 1., 2., 3.]);
    let v2 = Vector::new(vec![0., 2., 4., 6.]);
    v1.apply_self(|x| x * 2.0);
    assert!(v1 == v2, "Applying a function on a Vector does not match expected result:\nVector: {}\nvs\nExpected: {}", v1, v2);
}

#[test]
fn argmax() {
    let max_val: f64 = 3.;
    let v1 = Vector::new(vec![0., max_val, 2., 1.]);
    let max = v1.max();
    assert!(max == max_val, "The max value of a Vector does not match the expected result:\nVector: {}\nvs\nExpected: {}", max_val, max);
}

#[test]
fn argmin() {
    let min_val: f64 = 0.;
    let v1 = Vector::new(vec![min_val, 3., 2., 1.]);
    let min = v1.min();
    assert!(min == min_val, "The min value of a Vector does not match the expected result:\nVector: {}\nvs\nExpected: {}", min_val, min);
}

#[test]
fn select() {
    let v = Vector::new(vec![0., 1., 2., 3.]);
    let indexes = &[0, 2, 1];
    let results = v.select(indexes).unwrap();
    let expected = Vector::new(vec![0., 2., 1.]);
    assert!(results == expected, "The selected values of a Vector do not match the expected result:\nVector: {}\nvs\nExpected: {}", results, expected);
}

#[test]
fn dot() {
    let v = Vector::new(vec![1., 2., 3., 4.]);
    let v2 = Vector::new(vec![2., 4., 6., 8.]);
    let dot_result = v.dot(&v2).unwrap();
    let manual_result: f64 = 60.;
    assert!(dot_result == manual_result,
    "The calculated dot product of two Vectors does not match the expected result\nVector1: {} `dot` Vector2: {} == {}\nvs\nExpected: {}",
    v, v2, dot_result, manual_result);
}

#[test]
fn sum() {
    let v = Vector::new(vec![0., 1., 2., 3.]);
    let sum = v.sum();
    let expected = 0. + 1. + 2. + 3.;
    assert!(sum == expected, "The sum of a Vector does not match the expected result:\nVector Sum: {}\nvs\nExpected: {}", sum, expected);
}

#[test]
fn norm() {
    let v = Vector::new(vec![0., 1., 2., 3., 4.]);
    let norm = v.norm(Norm::Euclidean);
    let dot: f64 = 30.;
    let expected: f64 = dot.sqrt();
    assert!(norm == expected, "The Euclidean norm of a Vector does not match the expected result:\nNorm: {}\nvs\nExpected: {}", norm, expected);
}

#[test]
fn metric() {
    let v1 = Vector::new(vec![0., 1., 2., 3.]);
    let v2 = Vector::new(vec![1., 2., 3., 4.]);
    let diff = vec![0.0 - 1.0, 1.0 - 2.0, 2.0 - 3.0, 3.0 - 4.0];
    let square: Vec<f64> = diff.iter().map(|x| x * x).collect();
    let sum: f64 = square.iter().fold(0., |acc, &d| acc + d);
    let expected = sum.sqrt();
    let metric = v1.metric(&v2).unwrap();
    assert!(metric == expected, "The metric of two Vectors does not match the expected result:\nVector1: {} `metric` Vector2: {} == {}\nvs\nExpected: {}",
    v1, v2, metric, expected);
}

#[test]
fn mean() {
    let v = Vector::new(vec![0., 1., 2., 3.]);
    let mean = v.mean();
    let expected = vec![0., 1., 2., 3.].iter().fold(0., |acc, &d| acc + d) / (vec![0., 1., 2., 3.].len() as f64);
    assert!(mean == expected, "The mean of a Vector does not match the expected value:\nVector Mean: {} == {}\nvs\nEXpected: {}",
    v, mean, expected);
}

#[test]
fn variance() {
    let v = Vector::new(vec![0., 1., 2., 3.]);
    let mean = vec![0., 1., 2., 3.].iter().fold(0., |acc, &d| acc + d) / (vec![0., 1., 2., 3.].len() as f64);
    let expected = vec![0., 1., 2., 3.].iter().fold(0., |acc, &d| acc + (d - mean).powf(2.0));
    let variance = v.variance();
    assert!(variance == expected, "The variance of a Vector does not match the expected result:\nVector Variance: {} == {}\nvs\nExpected: {}",
    v, variance, expected);
}

#[test]
fn add() {
    let v1 = Vector::new(vec![0., 1., 2., 3.]);
    let v2 = Vector::new(vec![1., 2., 3., 4.]);
    let sum = &v1 + &v2;
    let expected = Vector::new(vec![0. + 1., 1. + 2., 2. + 3., 3. + 4.]);
    assert!(sum == expected, "The sum of two Vectors does not match the expected result:\nVector1: {} + Vector2: {} == {}\nvs\nExpected: {}",
    v1, v2, sum, expected);
    let sum = &v1 + &1.0;
    let expected = Vector::new(vec![0. + 1., 1. + 1., 2. + 1., 3. + 1.]);
    assert!(sum == expected, "The sum of a Vector and a number does not match the expected result:\nVector: {} + {} == {}\nvs\nExpected: {}",
    v1, 1.0, sum, expected);
}

#[test]
fn subtract() {
    let v1 = Vector::new(vec![0., 1., 2., 3.]);
    let v2 = Vector::new(vec![1., 2., 3., 4.]);
    let subtract = &v1 - &v2;
    let expected = Vector::new(vec![0. - 1., 1. - 2., 2. - 3., 3. - 4.]);
    assert!(subtract == expected, "The subtraction of two Vectors does not match the expected result:\nVector1: {} - Vector2: {} == {}\nvs\nExpected: {}",
    v1, v2, subtract, expected);
    let subtract = &v1 - &1.0;
    let expected = Vector::new(vec![0. - 1., 1. - 1., 2. - 1., 3. - 1.]);
    assert!(subtract == expected, "The subtraction of a Vector and a number does not match the expected result:\nVector: {} - {} == {}\nvs\nExpected: {}",
    v1, 1.0, subtract, expected);
}

#[test]
fn divide() {
    let v1 = Vector::new(vec![0., 1., 2., 3.]);
    let v2 = Vector::new(vec![1., 2., 3., 4.]);
    let div = &v1 / &v2;
    let expected = Vector::new(vec![0. / 1., 1. / 2., 2. / 3., 3. / 4.]);
    assert!(div == expected, "The division of two Vectors does not match the expected result:\nVector1: {} / Vector2: {} == {}\nvs\nExpected: {}",
    v1, v2, div, expected);
    let div = &v1 / &2.0;
    let expected = Vector::new(vec![0. / 2., 1. / 2., 2. / 2., 3. / 2.]);
    assert!(div == expected, "The division of a Vector and a number does not match the expected result:\nVector: {} / {} == {}\nvs\nExpected: {}",
    v1, 2.0, div, expected);
}

#[test]
fn multiply() {
    let v1 = Vector::new(vec![0., 1., 2., 3.]);
    let v2 = Vector::new(vec![1., 2., 3., 4.]);
    let mul = &v1 * &v2;
    let expected = Vector::new(vec![0. * 1., 1. * 2., 2. * 3., 3. * 4.]);
    assert!(mul == expected, "The multiplication of two Vectors does not match the expected result:\nVector1: {} * Vector2: {} == {}\nvs\nExpected: {}",
    v1, v2, mul, expected);
    let mul = &v1 * &2.0;
    let expected = Vector::new(vec![0. * 2., 1. * 2., 2. * 2., 3. * 2.]);
    assert!(mul == expected, "The multiplication of a Vector and a number does not match the expected result:\nVector: {} * {} == {}\nvs\nExpected: {}",
    v1, 2.0, mul, expected);
}

#[test]
fn remainder() {
    let v1 = Vector::new(vec![0., 1., 2., 3.]);
    let v2 = Vector::new(vec![1., 2., 3., 4.]);
    let rem = &v1 % &v2;
    let expected = Vector::new(vec![0.%1., 1.%2., 2.%3., 3.%4.]);
    assert!(rem == expected, "The remainder of two Vectors does not match the expected result:\nVector1: {} % Vector2: {} == {}\nvs\nExpected: {}",
    v1, v2, rem, expected);
}