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
/// Compile time for loops with a `const` variable for testing.
///
/// Repeats a block of code with different values assigned to a constant.
///
/// ```rust
/// # use ruint::{const_for, nlimbs, Uint};
/// const_for!(BITS in [0, 10, 100] {
///     const LIMBS: usize = nlimbs(BITS);
///     println!("{:?}", Uint::<BITS, LIMBS>::MAX);
/// });
/// ```
///
/// is equivalent to
///
/// ```rust
/// # use ruint::{const_for, Uint};
/// println!("{:?}", Uint::<0, 0>::MAX);
/// println!("{:?}", Uint::<10, 1>::MAX);
/// println!("{:?}", Uint::<100, 2>::MAX);
/// ```
///
/// It comes with two build-in lists: `NON_ZERO` which is equivalent to
///
/// ```text
/// [1, 2, 63, 64, 65, 127, 128, 129, 256, 384, 512, 4096]
/// ```
///
/// and `SIZES` which is the same but also has `0` as a value.
///
/// In combination with [`proptest!`][proptest::proptest] this allows for
/// testing over a large range of [`Uint`][crate::Uint] types and values:
///
/// ```rust
/// # use proptest::prelude::*;
/// # use ruint::{const_for, nlimbs, Uint};
/// const_for!(BITS in SIZES {
///    const LIMBS: usize = nlimbs(BITS);
///    proptest!(|(value: Uint<BITS, LIMBS>)| {
///         // ... test code
///     });
/// });
/// ```
#[macro_export]
macro_rules! const_for {
    ($C:ident in [ $( $n:literal ),* ] $x:block) => {
        $({
            const $C: usize = $n;
            $x
        })*
    };
    ($C:ident in SIZES $x:block) => {
        const_for!($C in [0] $x);
        const_for!($C in NON_ZERO $x);
    };
    ($C:ident in NON_ZERO $x:block) => {
        const_for!($C in [1, 2, 63, 64, 65, 127, 128, 129, 256, 384, 512, 4096] $x);
    };
    ($C:ident in BENCH $x:block) => {
        const_for!($C in [0, 64, 160, 256, 384, 512, 4096] $x);
    };
    ($C:ident in $S:ident if ( $c:expr ) $x:block) => {
        const_for!($C in $S {
            if $c {
                $x
            }
        });
    };
}