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
use std::ops::{Mul, Add, Sub};

use crate::numlib::Zero;

use super::Vector;

impl<T: Copy> Vector<T> {
    pub fn apply<F: Fn(&T) -> T>(&mut self, f: F) {
        for val in &mut self.data {
            *val = f(val);
        }
    }
}

impl<T: Copy + Mul<T, Output = T>> Vector<T> {
    pub fn scale(&self, scalar: T) -> Vector<T> {
        let mut res = self.data.to_vec();

        for val in &mut res {
            *val = (*val) * scalar;
        }

        Vector::new(res)
    }
}

impl<T: Copy + Add<T, Output = T>> Vector<T> {
    pub fn add(&self, other: &Vector<T>) -> Result<Vector<T>, &'static str> {
        let to_add = other.as_vec();
        if other.size != self.size {
            return Err("Vectors don't match in size");
        }
        let mut res = self.data.to_vec();
        for index in 0..self.size {
            if let Some(elem) = res.get_mut(index) {
                // Unreachable since they have the same size and thus all indexes we loop through are
                // Also present in to_add
                *elem = *elem
                    + match to_add.get(index) {
                        Some(value) => *value,
                        None => unreachable!(),
                    };
            }
        }

        Ok(Vector::new(res))
    }
}

impl<T: Copy + Sub<T, Output = T>> Vector<T> {
    pub fn sub(&self, other: &Vector<T>) -> Result<Vector<T>, &'static str> {
        let to_add = other.as_vec();
        if other.size != self.size {
            return Err("Vectors don't match in size");
        }
        let mut res = self.data.to_vec();
        for index in 0..self.size {
            if let Some(elem) = res.get_mut(index) {
                // None is unreachable since they have the same size and thus all indexes we loop through are
                // Also present in to_add
                *elem = *elem
                    - match to_add.get(index) {
                        Some(value) => *value,
                        None => unreachable!(),
                    };
            }
        }

        Ok(Vector::new(res))
    }
}

impl<T: Copy + Zero + Add<T, Output = T> + Mul<T, Output = T>> Vector<T> {
    pub fn dot(&self, other: &Vector<T>) -> Result<T, &'static str> {
        if self.size != other.size {
            return Err("Vectors don't match in size");
        }

        let mut res = T::zero();

        if self.size == 0 {
            return Ok(res);
        }

        for index in 0..self.size {
            if let Some(elem) = self.data.get(index) {
                // None is unreachable since they have the same size and thus all indexes we loop through are
                // Also present in to_add
                res = res
                    + (*elem
                        * match other.data.get(index) {
                            Some(value) => *value,
                            None => unreachable!(),
                        });
            }
        }

        Ok(res)
    }
}

impl Vector<f64> {
    pub fn abs(&self) -> f64 {
        self.dot(&self).unwrap().sqrt()
    }
}