1pub trait LbfgsMath<T> {
8 fn vecadd(&mut self, x: &[T], c: T);
10
11 fn vecdot(&self, other: &[T]) -> f64;
14
15 fn veccpy(&mut self, x: &[T]);
17
18 fn vecncpy(&mut self, x: &[T]);
20
21 fn vecdiff(&mut self, x: &[T], y: &[T]);
23
24 fn vecscale(&mut self, c: T);
26
27 fn vec2norm(&self) -> T;
29
30 fn vec2norminv(&self) -> T;
32}
33
34impl LbfgsMath<f64> for [f64] {
35 fn vecadd(&mut self, x: &[f64], c: f64) {
37 for (y, x) in self.iter_mut().zip(x) {
38 *y += c * x;
39 }
40 }
41
42 fn vecdot(&self, other: &[f64]) -> f64 {
44 self.iter().zip(other).map(|(x, y)| x * y).sum()
45 }
46
47 fn vecscale(&mut self, c: f64) {
49 for y in self.iter_mut() {
50 *y *= c;
51 }
52 }
53
54 fn veccpy(&mut self, x: &[f64]) {
56 for (v, x) in self.iter_mut().zip(x) {
57 *v = *x;
58 }
59 }
60
61 fn vecncpy(&mut self, x: &[f64]) {
63 for (v, x) in self.iter_mut().zip(x) {
64 *v = -x;
65 }
66 }
67
68 fn vecdiff(&mut self, x: &[f64], y: &[f64]) {
70 for ((z, x), y) in self.iter_mut().zip(x).zip(y) {
71 *z = x - y;
72 }
73 }
74
75 fn vec2norm(&self) -> f64 {
77 let n2 = self.vecdot(&self);
78 n2.sqrt()
79 }
80
81 fn vec2norminv(&self) -> f64 {
83 1.0 / self.vec2norm()
84 }
85}
86
87#[test]
88fn test_lbfgs_math() {
89 let x = [1.0, 1.0, 1.0];
91 let c = 2.;
92
93 let mut y = [1.0, 2.0, 3.0];
94 y.vecadd(&x, c);
95
96 assert_eq!(3.0, y[0]);
97 assert_eq!(4.0, y[1]);
98 assert_eq!(5.0, y[2]);
99
100 let v = y.vecdot(&x);
102 assert_eq!(12.0, v);
103
104 y.vecscale(2.0);
106 assert_eq!(6.0, y[0]);
107 assert_eq!(8.0, y[1]);
108 assert_eq!(10.0, y[2]);
109
110 let mut z = y.clone();
112 z.vecdiff(&x, &y);
113 assert_eq!(-5.0, z[0]);
114 assert_eq!(-7.0, z[1]);
115 assert_eq!(-9.0, z[2]);
116
117 y.veccpy(&x);
119
120 y.vecncpy(&x);
122 assert_eq!(-1.0, y[0]);
123 assert_eq!(-1.0, y[1]);
124 assert_eq!(-1.0, y[2]);
125}
126