1use std::iter;
4use std::mem;
5use std::ops;
6
7use rand::prelude::*;
8use rand::distributions::Uniform;
9
10pub trait Dot<B: ?Sized> {
12 type Output;
13 fn dot(&self, other: &B) -> Self::Output;
14}
15
16impl<T> Dot<[T]> for [T]
17 where T: ops::Mul + Clone,
18 T::Output: iter::Sum
19{
20 type Output = T::Output;
21
22 fn dot(&self, other: &[T]) -> Self::Output {
23 assert_eq!(self.len(), other.len());
24 self.iter().zip(other.iter()).map(|(a, b)| a.clone() * b.clone()).sum()
25 }
26}
27
28impl<T> Dot<[T]> for Vec<T>
29 where T: ops::Mul + Clone,
30 T::Output: iter::Sum
31{
32 type Output = T::Output;
33
34 fn dot(&self, other: &[T]) -> Self::Output {
35 assert_eq!(self.len(), other.len());
36 self.iter().zip(other.iter()).map(|(a, b)| a.clone() * b.clone()).sum()
37 }
38}
39
40macro_rules! impl_dot_array_for_array {
41 ( $( $size:expr ),* ) => {
42 $(
43 impl<T> Dot<[T; $size]> for [T; $size]
44 where T: ops::Mul + Clone,
45 T::Output: iter::Sum
46 {
47 type Output = T::Output;
48 fn dot(&self, other: &Self) -> Self::Output {
49 self.iter().zip(other.iter()).map(|(a, b)| a.clone() * b.clone()).sum()
50 }
51 }
52 )*
53 };
54}
55
56impl_dot_array_for_array!{ 1, 2, 3, 4, 5, 6, 7, 8}
57impl_dot_array_for_array!{ 9, 10, 11, 12, 13, 14, 15, 16}
58impl_dot_array_for_array!{17, 18, 19, 20, 21, 22, 23, 24}
59impl_dot_array_for_array!{25, 26, 27, 28, 29, 30, 31, 32}
60
61macro_rules! impl_dot_slice_for_array {
62 ( $( $size:expr ),* ) => {
63 $(
64 impl<T> Dot<[T]> for [T; $size]
65 where T: ops::Mul + Clone,
66 T::Output: iter::Sum
67 {
68 type Output = T::Output;
69 fn dot(&self, other: &[T]) -> Self::Output {
70 assert_eq!($size, other.len());
71 self.iter().zip(other.iter()).map(|(a, b)| a.clone() * b.clone()).sum()
72 }
73 }
74 )*
75 };
76}
77
78impl_dot_slice_for_array!{ 1, 2, 3, 4, 5, 6, 7, 8}
79impl_dot_slice_for_array!{ 9, 10, 11, 12, 13, 14, 15, 16}
80impl_dot_slice_for_array!{17, 18, 19, 20, 21, 22, 23, 24}
81impl_dot_slice_for_array!{25, 26, 27, 28, 29, 30, 31, 32}
82
83macro_rules! impl_dot_array_for_slice {
84 ( $( $size:expr ),* ) => {
85 $(
86 impl<T> Dot<[T; $size]> for [T]
87 where T: ops::Mul + Clone,
88 T::Output: iter::Sum
89 {
90 type Output = T::Output;
91 fn dot(&self, other: &[T; $size]) -> Self::Output {
92 assert_eq!($size, self.len());
93 self.iter().zip(other.iter()).map(|(a, b)| a.clone() * b.clone()).sum()
94 }
95 }
96 )*
97 };
98}
99
100impl_dot_array_for_slice!{ 1, 2, 3, 4, 5, 6, 7, 8}
101impl_dot_array_for_slice!{ 9, 10, 11, 12, 13, 14, 15, 16}
102impl_dot_array_for_slice!{17, 18, 19, 20, 21, 22, 23, 24}
103impl_dot_array_for_slice!{25, 26, 27, 28, 29, 30, 31, 32}
104
105pub trait Partition<T> {
107 fn partition<F: FnMut(&T) -> bool>(&mut self, predicate: F) -> usize;
110}
111
112impl<T> Partition<T> for [T]
113{
114 fn partition<F: FnMut(&T) -> bool>(&mut self, mut predicate: F) -> usize {
116 unsafe {
118 let start = &mut self[0] as *mut T;
119 let end = start.offset(self.len() as isize);
120 let mut target = &mut self[0] as *mut T;
121 let mut current = target;
122 let mut count = 0;
123 while current < end {
124 if predicate(&*current) {
125 mem::swap(&mut *target, &mut *current);
126 target = target.offset(1);
127 count += 1;
128 }
129 current = current.offset(1);
130 }
131 count
132 }
133 }
134}
135
136pub fn resample<T: Clone, R: Rng>(x: &[T], n: usize, rng: &mut R) -> Vec<T> {
137 rng.sample_iter(&Uniform::new(0, x.len()))
138 .take(n)
139 .map(|i| x[i].clone())
140 .collect()
141}
142
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn dot_vec() {
150 let a = vec!(1.0, 2.0, 3.0);
151 let b = vec!(2.0, 1.0, 1.0);
152 assert_eq!(a.dot(&b), 7.0);
153
154 let a = vec!(1, 2, 1);
155 let b = vec!(2, 0, -3);
156 assert_eq!(a.dot(&b), -1);
157
158 let a = vec!(1, 2, -1);
159 let b = vec!(2, 1, 4);
160 assert_eq!(a.dot(&b), 0);
161 }
162
163 #[test]
164 fn dot_array() {
165 let a = [1.0, 2.0, 3.0];
166 let b = [2.0, 1.0, 1.0];
167 assert_eq!(a.dot(&b), 7.0);
168
169 let a = [1, 2, 1];
170 let b = [2, 0, -3];
171 assert_eq!(a.dot(&b), -1);
172
173 let a = [1, 2, -1];
174 let b = [2, 1, 4];
175 assert_eq!(a.dot(&b), 0);
176 }
177
178 #[test]
179 fn dot_slice() {
180 let a: &[_] = &[1.0, 2.0, 3.0];
181 let b: &[_] = &[2.0, 1.0, 1.0];
182 assert_eq!(a.dot(b), 7.0);
183
184 let a: &[_] = &[1, 2, 1];
185 let b: &[_] = &[2, 0, -3];
186 assert_eq!(a.dot(b), -1);
187
188 let a: &[_] = &[1, 2, -1];
189 let b: &[_] = &[2, 1, 4];
190 assert_eq!(a.dot(b), 0);
191 }
192
193 #[test]
194 fn partition() {
195 let mut x = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
196 let i = x.partition(|&xi| xi < 5);
197 assert_eq!(i, 5);
198 assert!(x[..i].iter().all(|&xi| xi < 5));
199 assert!(x[i..].iter().all(|&xi| xi >= 5));
200
201 let mut x = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
203 let i = x.partition(|&xi| xi <= 3);
204 assert_eq!(i, 4);
205 assert_eq!(x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
206 }
207
208 #[test]
209 fn bootstrap() {
210 let x: Vec<_> = (1..=3).collect();
211 let y = resample(&x, 1_000_000, &mut thread_rng());
212
213 let (mut a, mut b, mut c) = (0.0, 0.0, 0.0);
214
215 for z in &y {
216 match z {
217 1 => a += 1.0,
218 2 => b += 1.0,
219 3 => c += 1.0,
220 _ => panic!("Value {} was not in original array", z)
221 }
222 }
223
224 let expected = y.len() as f64 / 3.0;
225
226 let chi_square = (a - expected) * (a - expected) / expected
227 + (b - expected) * (b - expected) / expected
228 + (c - expected) * (c - expected) / expected;
229
230 assert!(chi_square < 9.21);
235 }
236}