File: mod.rs

package info (click to toggle)
rustc 1.85.0%2Bdfsg3-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie, trixie-backports, trixie-proposed-updates
  • size: 893,396 kB
  • sloc: xml: 158,127; python: 35,830; javascript: 19,497; cpp: 19,002; sh: 17,245; ansic: 13,127; asm: 4,376; makefile: 1,051; perl: 29; lisp: 29; ruby: 19; sql: 11
file content (99 lines) | stat: -rw-r--r-- 3,258 bytes parent folder | download | duplicates (3)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use rand::Rng;
use test::{Bencher, black_box};

const ITERATIONS: usize = 128; // Uses an ITERATIONS * 20 Byte stack allocation
type IntType = i128; // Hardest native type to multiply
const EXPONENT_MAX: u32 = 31;
const MAX_BASE: IntType = 17; // +-17 ** 31 <= IntType::MAX

macro_rules! pow_bench_template {
    ($name:ident, $inner_macro:ident, $base_macro:ident) => {
        #[bench]
        fn $name(bench: &mut Bencher) {
            // Frequent black_box calls can add latency and prevent optimizations, so for
            // variable parameters we premake an array and pass the
            // reference through black_box outside of the loop.
            let mut rng = crate::bench_rng();
            let base_array: [IntType; ITERATIONS] =
                core::array::from_fn(|_| rng.gen_range((-MAX_BASE..=MAX_BASE)));
            let exp_array: [u32; ITERATIONS] =
                core::array::from_fn(|_| rng.gen_range((0..=EXPONENT_MAX)));

            bench.iter(|| {
                #[allow(unused, unused_mut)]
                let mut base_iter = black_box(&base_array).into_iter();
                let mut exp_iter = black_box(&exp_array).into_iter();

                (0..ITERATIONS).fold((0 as IntType, false), |acc, _| {
                    // Sometimes constants don't propagate all the way to the
                    // inside of the loop, so we call a custom expression every cycle
                    // rather than iter::repeat(CONST)
                    let base: IntType = $base_macro!(base_iter);
                    let exp: u32 = *exp_iter.next().unwrap();

                    let r: (IntType, bool) = $inner_macro!(base, exp);
                    (acc.0 ^ r.0, acc.1 ^ r.1)
                })
            });
        }
    };
}

// This may panic if it overflows.
macro_rules! inner_pow {
    ($base:ident, $exp:ident) => {
        ($base.pow($exp), false)
    };
}

macro_rules! inner_wrapping {
    ($base:ident, $exp:ident) => {
        ($base.wrapping_pow($exp), false)
    };
}

macro_rules! inner_overflowing {
    ($base:ident, $exp:ident) => {
        $base.overflowing_pow($exp)
    };
}

// This will panic if it overflows.
macro_rules! inner_checked_unwrapped {
    ($base:ident, $exp:ident) => {
        ($base.checked_pow($exp).unwrap(), false)
    };
}

macro_rules! inner_saturating {
    ($base:ident, $exp:ident) => {
        ($base.saturating_pow($exp), false)
    };
}

macro_rules! make_const_base {
    ($name:ident, $x:literal) => {
        macro_rules! $name {
            ($iter:ident) => {
                $x
            };
        }
    };
}

make_const_base!(const_base_m7, -7);
make_const_base!(const_base_m8, -8);

macro_rules! variable_base {
    ($iter:ident) => {
        *$iter.next().unwrap()
    };
}

pow_bench_template!(pow_variable, inner_pow, variable_base);
pow_bench_template!(wrapping_pow_variable, inner_wrapping, variable_base);
pow_bench_template!(overflowing_pow_variable, inner_overflowing, variable_base);
pow_bench_template!(checked_pow_variable, inner_checked_unwrapped, variable_base);
pow_bench_template!(saturating_pow_variable, inner_saturating, variable_base);
pow_bench_template!(pow_m7, inner_pow, const_base_m7);
pow_bench_template!(pow_m8, inner_pow, const_base_m8);