Skip to content

Commit cf4f658

Browse files
Volodymyr OrlovVolodymyr Orlov
authored andcommitted
feat: adds 3 more SVM kernels, linalg refactoring
1 parent 1773ed0 commit cf4f658

File tree

6 files changed

+568
-9
lines changed

6 files changed

+568
-9
lines changed

src/linalg/mod.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,76 @@ pub trait BaseVector<T: RealNumber>: Clone + Debug {
9191

9292
/// Returns True if matrices are element-wise equal within a tolerance `error`.
9393
fn approximate_eq(&self, other: &Self, error: T) -> bool;
94+
95+
/// Returns [L2 norm] of the vector(https://en.wikipedia.org/wiki/Matrix_norm).
96+
fn norm2(&self) -> T;
97+
98+
/// Returns [vectors norm](https://en.wikipedia.org/wiki/Matrix_norm) of order `p`.
99+
fn norm(&self, p: T) -> T;
100+
101+
/// Divide single element of the vector by `x`, write result to original vector.
102+
fn div_element_mut(&mut self, pos: usize, x: T);
103+
104+
/// Multiply single element of the vector by `x`, write result to original vector.
105+
fn mul_element_mut(&mut self, pos: usize, x: T);
106+
107+
/// Add single element of the vector to `x`, write result to original vector.
108+
fn add_element_mut(&mut self, pos: usize, x: T);
109+
110+
/// Subtract `x` from single element of the vector, write result to original vector.
111+
fn sub_element_mut(&mut self, pos: usize, x: T);
112+
113+
/// Add vectors, element-wise, overriding original vector with result.
114+
fn add_mut(&mut self, other: &Self) -> &Self;
115+
116+
/// Subtract vectors, element-wise, overriding original vector with result.
117+
fn sub_mut(&mut self, other: &Self) -> &Self;
118+
119+
/// Multiply vectors, element-wise, overriding original vector with result.
120+
fn mul_mut(&mut self, other: &Self) -> &Self;
121+
122+
/// Divide vectors, element-wise, overriding original vector with result.
123+
fn div_mut(&mut self, other: &Self) -> &Self;
124+
125+
/// Add vectors, element-wise
126+
fn add(&self, other: &Self) -> Self {
127+
let mut r = self.clone();
128+
r.add_mut(other);
129+
r
130+
}
131+
132+
/// Subtract vectors, element-wise
133+
fn sub(&self, other: &Self) -> Self {
134+
let mut r = self.clone();
135+
r.sub_mut(other);
136+
r
137+
}
138+
139+
/// Multiply vectors, element-wise
140+
fn mul(&self, other: &Self) -> Self {
141+
let mut r = self.clone();
142+
r.mul_mut(other);
143+
r
144+
}
145+
146+
/// Divide vectors, element-wise
147+
fn div(&self, other: &Self) -> Self {
148+
let mut r = self.clone();
149+
r.div_mut(other);
150+
r
151+
}
152+
153+
/// Calculates sum of all elements of the vector.
154+
fn sum(&self) -> T;
155+
156+
/// Returns unique values from the vector.
157+
/// ```
158+
/// use smartcore::linalg::naive::dense_matrix::*;
159+
/// let a = vec!(1., 2., 2., -2., -6., -7., 2., 3., 4.);
160+
///
161+
///assert_eq!(a.unique(), vec![-7., -6., -2., 1., 2., 3., 4.]);
162+
/// ```
163+
fn unique(&self) -> Vec<T>;
94164
}
95165

96166
/// Generic matrix type.

src/linalg/naive/dense_matrix.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,96 @@ impl<T: RealNumber> BaseVector<T> for Vec<T> {
5858
result
5959
}
6060

61+
fn norm2(&self) -> T {
62+
let mut norm = T::zero();
63+
64+
for xi in self.iter() {
65+
norm = norm + *xi * *xi;
66+
}
67+
68+
norm.sqrt()
69+
}
70+
71+
fn norm(&self, p: T) -> T {
72+
if p.is_infinite() && p.is_sign_positive() {
73+
self.iter()
74+
.map(|x| x.abs())
75+
.fold(T::neg_infinity(), |a, b| a.max(b))
76+
} else if p.is_infinite() && p.is_sign_negative() {
77+
self.iter()
78+
.map(|x| x.abs())
79+
.fold(T::infinity(), |a, b| a.min(b))
80+
} else {
81+
let mut norm = T::zero();
82+
83+
for xi in self.iter() {
84+
norm = norm + xi.abs().powf(p);
85+
}
86+
87+
norm.powf(T::one() / p)
88+
}
89+
}
90+
91+
fn div_element_mut(&mut self, pos: usize, x: T) {
92+
self[pos] = self[pos] / x;
93+
}
94+
95+
fn mul_element_mut(&mut self, pos: usize, x: T) {
96+
self[pos] = self[pos] * x;
97+
}
98+
99+
fn add_element_mut(&mut self, pos: usize, x: T) {
100+
self[pos] = self[pos] + x
101+
}
102+
103+
fn sub_element_mut(&mut self, pos: usize, x: T) {
104+
self[pos] = self[pos] - x;
105+
}
106+
107+
fn add_mut(&mut self, other: &Self) -> &Self {
108+
if self.len() != other.len() {
109+
panic!("A and B should have the same shape");
110+
}
111+
for i in 0..self.len() {
112+
self.add_element_mut(i, other.get(i));
113+
}
114+
115+
self
116+
}
117+
118+
fn sub_mut(&mut self, other: &Self) -> &Self {
119+
if self.len() != other.len() {
120+
panic!("A and B should have the same shape");
121+
}
122+
for i in 0..self.len() {
123+
self.sub_element_mut(i, other.get(i));
124+
}
125+
126+
self
127+
}
128+
129+
fn mul_mut(&mut self, other: &Self) -> &Self {
130+
if self.len() != other.len() {
131+
panic!("A and B should have the same shape");
132+
}
133+
for i in 0..self.len() {
134+
self.mul_element_mut(i, other.get(i));
135+
}
136+
137+
self
138+
}
139+
140+
fn div_mut(&mut self, other: &Self) -> &Self {
141+
if self.len() != other.len() {
142+
panic!("A and B should have the same shape");
143+
}
144+
for i in 0..self.len() {
145+
self.div_element_mut(i, other.get(i));
146+
}
147+
148+
self
149+
}
150+
61151
fn approximate_eq(&self, other: &Self, error: T) -> bool {
62152
if self.len() != other.len() {
63153
false
@@ -70,6 +160,21 @@ impl<T: RealNumber> BaseVector<T> for Vec<T> {
70160
true
71161
}
72162
}
163+
164+
fn sum(&self) -> T {
165+
let mut sum = T::zero();
166+
for i in 0..self.len() {
167+
sum = sum + self[i];
168+
}
169+
sum
170+
}
171+
172+
fn unique(&self) -> Vec<T> {
173+
let mut result = self.clone();
174+
result.sort_by(|a, b| a.partial_cmp(b).unwrap());
175+
result.dedup();
176+
result
177+
}
73178
}
74179

75180
/// Column-major, dense matrix. See [Simple Dense Matrix](../index.html).

src/linalg/nalgebra_bindings.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,76 @@ impl<T: RealNumber + 'static> BaseVector<T> for MatrixMN<T, U1, Dynamic> {
8484
self.dot(other)
8585
}
8686

87+
fn norm2(&self) -> T {
88+
self.iter().map(|x| *x * *x).sum::<T>().sqrt()
89+
}
90+
91+
fn norm(&self, p: T) -> T {
92+
if p.is_infinite() && p.is_sign_positive() {
93+
self.iter().fold(T::neg_infinity(), |f, &val| {
94+
let v = val.abs();
95+
if f > v {
96+
f
97+
} else {
98+
v
99+
}
100+
})
101+
} else if p.is_infinite() && p.is_sign_negative() {
102+
self.iter().fold(T::infinity(), |f, &val| {
103+
let v = val.abs();
104+
if f < v {
105+
f
106+
} else {
107+
v
108+
}
109+
})
110+
} else {
111+
let mut norm = T::zero();
112+
113+
for xi in self.iter() {
114+
norm = norm + xi.abs().powf(p);
115+
}
116+
117+
norm.powf(T::one() / p)
118+
}
119+
}
120+
121+
fn div_element_mut(&mut self, pos: usize, x: T) {
122+
*self.get_mut(pos).unwrap() = *self.get(pos).unwrap() / x;
123+
}
124+
125+
fn mul_element_mut(&mut self, pos: usize, x: T) {
126+
*self.get_mut(pos).unwrap() = *self.get(pos).unwrap() * x;
127+
}
128+
129+
fn add_element_mut(&mut self, pos: usize, x: T) {
130+
*self.get_mut(pos).unwrap() = *self.get(pos).unwrap() + x;
131+
}
132+
133+
fn sub_element_mut(&mut self, pos: usize, x: T) {
134+
*self.get_mut(pos).unwrap() = *self.get(pos).unwrap() - x;
135+
}
136+
137+
fn add_mut(&mut self, other: &Self) -> &Self {
138+
*self += other;
139+
self
140+
}
141+
142+
fn sub_mut(&mut self, other: &Self) -> &Self {
143+
*self -= other;
144+
self
145+
}
146+
147+
fn mul_mut(&mut self, other: &Self) -> &Self {
148+
self.component_mul_assign(other);
149+
self
150+
}
151+
152+
fn div_mut(&mut self, other: &Self) -> &Self {
153+
self.component_div_assign(other);
154+
self
155+
}
156+
87157
fn approximate_eq(&self, other: &Self, error: T) -> bool {
88158
if self.shape() != other.shape() {
89159
false
@@ -93,6 +163,21 @@ impl<T: RealNumber + 'static> BaseVector<T> for MatrixMN<T, U1, Dynamic> {
93163
.all(|(a, b)| (*a - *b).abs() <= error)
94164
}
95165
}
166+
167+
fn sum(&self) -> T {
168+
let mut sum = T::zero();
169+
for v in self.iter() {
170+
sum += *v;
171+
}
172+
sum
173+
}
174+
175+
fn unique(&self) -> Vec<T> {
176+
let mut result: Vec<T> = self.iter().map(|v| *v).collect();
177+
result.sort_by(|a, b| a.partial_cmp(b).unwrap());
178+
result.dedup();
179+
result
180+
}
96181
}
97182

98183
impl<T: RealNumber + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static>

src/linalg/ndarray_bindings.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,90 @@ impl<T: RealNumber + ScalarOperand> BaseVector<T> for ArrayBase<OwnedRepr<T>, Ix
8989
self.dot(other)
9090
}
9191

92+
fn norm2(&self) -> T {
93+
self.iter().map(|x| *x * *x).sum::<T>().sqrt()
94+
}
95+
96+
fn norm(&self, p: T) -> T {
97+
if p.is_infinite() && p.is_sign_positive() {
98+
self.iter().fold(T::neg_infinity(), |f, &val| {
99+
let v = val.abs();
100+
if f > v {
101+
f
102+
} else {
103+
v
104+
}
105+
})
106+
} else if p.is_infinite() && p.is_sign_negative() {
107+
self.iter().fold(T::infinity(), |f, &val| {
108+
let v = val.abs();
109+
if f < v {
110+
f
111+
} else {
112+
v
113+
}
114+
})
115+
} else {
116+
let mut norm = T::zero();
117+
118+
for xi in self.iter() {
119+
norm = norm + xi.abs().powf(p);
120+
}
121+
122+
norm.powf(T::one() / p)
123+
}
124+
}
125+
126+
fn div_element_mut(&mut self, pos: usize, x: T) {
127+
self[pos] = self[pos] / x;
128+
}
129+
130+
fn mul_element_mut(&mut self, pos: usize, x: T) {
131+
self[pos] = self[pos] * x;
132+
}
133+
134+
fn add_element_mut(&mut self, pos: usize, x: T) {
135+
self[pos] = self[pos] + x;
136+
}
137+
138+
fn sub_element_mut(&mut self, pos: usize, x: T) {
139+
self[pos] = self[pos] - x;
140+
}
141+
92142
fn approximate_eq(&self, other: &Self, error: T) -> bool {
93143
(self - other).iter().all(|v| v.abs() <= error)
94144
}
145+
146+
fn add_mut(&mut self, other: &Self) -> &Self {
147+
*self += other;
148+
self
149+
}
150+
151+
fn sub_mut(&mut self, other: &Self) -> &Self {
152+
*self -= other;
153+
self
154+
}
155+
156+
fn mul_mut(&mut self, other: &Self) -> &Self {
157+
*self *= other;
158+
self
159+
}
160+
161+
fn div_mut(&mut self, other: &Self) -> &Self {
162+
*self /= other;
163+
self
164+
}
165+
166+
fn sum(&self) -> T {
167+
self.sum()
168+
}
169+
170+
fn unique(&self) -> Vec<T> {
171+
let mut result = self.clone().into_raw_vec();
172+
result.sort_by(|a, b| a.partial_cmp(b).unwrap());
173+
result.dedup();
174+
result
175+
}
95176
}
96177

97178
impl<T: RealNumber + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum>

0 commit comments

Comments
 (0)