argmin_math/vec/
random.rs

1// Copyright 2018-2024 argmin developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::ArgminRandom;
9use rand::Rng;
10
11macro_rules! make_random {
12    ($t:ty) => {
13        impl ArgminRandom for Vec<$t> {
14            fn rand_from_range<R: Rng>(min: &Self, max: &Self, rng: &mut R) -> Vec<$t> {
15                assert!(!min.is_empty());
16                assert_eq!(min.len(), max.len());
17
18                min.iter()
19                    .zip(max.iter())
20                    .map(|(a, b)| {
21                        // Do not require a < b:
22
23                        // We do want to know if a and b are *exactly* the same.
24                        #[allow(clippy::float_cmp)]
25                        if a == b {
26                            a.clone()
27                        } else if a < b {
28                            rng.gen_range(a.clone()..b.clone())
29                        } else {
30                            rng.gen_range(b.clone()..a.clone())
31                        }
32                    })
33                    .collect()
34            }
35        }
36
37        impl ArgminRandom for Vec<Vec<$t>> {
38            fn rand_from_range<R: Rng>(min: &Self, max: &Self, rng: &mut R) -> Vec<Vec<$t>> {
39                assert!(!min.is_empty());
40                assert_eq!(min.len(), max.len());
41                min.iter()
42                    .zip(max.iter())
43                    .map(|(a, b)| Vec::<$t>::rand_from_range(a, b, rng))
44                    .collect()
45            }
46        }
47    };
48}
49
50make_random!(f32);
51make_random!(f64);
52make_random!(i8);
53make_random!(i16);
54make_random!(i32);
55make_random!(i64);
56make_random!(u8);
57make_random!(u16);
58make_random!(u32);
59make_random!(u64);
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64    use paste::item;
65    use rand::SeedableRng;
66
67    macro_rules! make_test {
68        ($t:ty) => {
69            item! {
70                #[test]
71                fn [<test_random_vec_ $t>]() {
72                    let a = vec![1 as $t, 2 as $t, 4 as $t];
73                    let b = vec![2 as $t, 3 as $t, 5 as $t];
74                    let mut rng = rand::rngs::StdRng::seed_from_u64(42);
75                    let random = Vec::<$t>::rand_from_range(&a, &b, &mut rng);
76                    for i in 0..3usize {
77                        assert!(random[i] >= a[i]);
78                        assert!(random[i] <= b[i]);
79                    }
80                }
81            }
82
83            item! {
84                #[test]
85                fn [<test_random_mat_ $t>]() {
86                    let a = vec![
87                        vec![1 as $t, 2 as $t, 4 as $t],
88                        vec![2 as $t, 3 as $t, 5 as $t]
89                    ];
90                    let b = vec![
91                        vec![2 as $t, 3 as $t, 5 as $t],
92                        vec![3 as $t, 4 as $t, 6 as $t]
93                    ];
94                    let mut rng = rand::rngs::StdRng::seed_from_u64(42);
95                    let random = Vec::<Vec<$t>>::rand_from_range(&a, &b, &mut rng);
96                    for i in 0..3 {
97                        for j in 0..2 {
98                            assert!(random[j][i] >= a[j][i]);
99                            assert!(random[j][i] <= b[j][i]);
100                        }
101                    }
102                }
103            }
104        };
105    }
106
107    make_test!(i8);
108    make_test!(u8);
109    make_test!(i16);
110    make_test!(u16);
111    make_test!(i32);
112    make_test!(u32);
113    make_test!(i64);
114    make_test!(u64);
115    make_test!(f32);
116    make_test!(f64);
117}