Skip to main content

ark_std/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(not(feature = "std"))]
4#[doc(hidden)]
5extern crate alloc;
6
7#[cfg(not(feature = "std"))]
8pub use alloc::*;
9
10#[cfg(not(feature = "std"))]
11pub use core::*;
12
13#[cfg(not(feature = "std"))]
14pub mod fmt {
15    pub use alloc::fmt::*;
16    pub use core::fmt::*;
17}
18
19#[cfg(not(feature = "std"))]
20pub mod borrow {
21    pub use alloc::borrow::*;
22    pub use core::borrow::*;
23}
24
25#[cfg(not(feature = "std"))]
26pub mod slice {
27    pub use alloc::slice::*;
28    pub use core::slice::*;
29}
30
31#[cfg(not(feature = "std"))]
32pub mod str {
33    pub use alloc::str::*;
34    pub use core::str::*;
35}
36
37#[cfg(not(feature = "std"))]
38pub mod io;
39
40#[cfg(feature = "std")]
41#[doc(hidden)]
42pub use std::*;
43
44#[cfg(target_has_atomic = "ptr")]
45#[doc(hidden)]
46pub mod sync {
47    #[cfg(not(feature = "std"))]
48    pub use alloc::sync::*;
49    #[cfg(feature = "std")]
50    pub use std::sync::*;
51}
52
53mod rand_helper;
54pub use rand_helper::*;
55
56pub mod perf_trace;
57
58pub mod iterable;
59
60pub use num_traits::{One, Zero};
61
62/// Returns the ceiling of the base-2 logarithm of `x`.
63///
64/// ```
65/// use ark_std::log2;
66///
67/// assert_eq!(log2(16), 4);
68/// assert_eq!(log2(17), 5);
69/// assert_eq!(log2(1), 0);
70/// assert_eq!(log2(0), 0);
71/// assert_eq!(log2(usize::MAX), (core::mem::size_of::<usize>() * 8) as u32);
72/// assert_eq!(log2(1 << 15), 15);
73/// assert_eq!(log2(2usize.pow(18)), 18);
74/// ```
75#[inline(always)]
76pub const fn log2(x: usize) -> u32 {
77    if x == 0 {
78        0
79    } else if x.is_power_of_two() {
80        1usize.leading_zeros() - x.leading_zeros()
81    } else {
82        0usize.leading_zeros() - x.leading_zeros()
83    }
84}
85
86/// Creates parallel iterator over refs if `parallel` feature is enabled.
87/// Additionally, if the object being iterated implements
88/// `IndexedParallelIterator`, then one can specify a minimum size for
89/// iteration.
90#[macro_export]
91macro_rules! cfg_iter {
92    ($e: expr, $min_len: expr) => {{
93        #[cfg(feature = "parallel")]
94        let result = $e.par_iter().with_min_len($min_len);
95
96        #[cfg(not(feature = "parallel"))]
97        let result = $e.iter();
98
99        result
100    }};
101    ($e: expr) => {{
102        #[cfg(feature = "parallel")]
103        let result = $e.par_iter();
104
105        #[cfg(not(feature = "parallel"))]
106        let result = $e.iter();
107
108        result
109    }};
110}
111
112/// Creates parallel iterator over mut refs if `parallel` feature is enabled.
113/// Additionally, if the object being iterated implements
114/// `IndexedParallelIterator`, then one can specify a minimum size for
115/// iteration.
116#[macro_export]
117macro_rules! cfg_iter_mut {
118    ($e: expr, $min_len: expr) => {{
119        #[cfg(feature = "parallel")]
120        let result = $e.par_iter_mut().with_min_len($min_len);
121
122        #[cfg(not(feature = "parallel"))]
123        let result = $e.iter_mut();
124
125        result
126    }};
127    ($e: expr) => {{
128        #[cfg(feature = "parallel")]
129        let result = $e.par_iter_mut();
130
131        #[cfg(not(feature = "parallel"))]
132        let result = $e.iter_mut();
133
134        result
135    }};
136}
137
138/// Creates parallel iterator if `parallel` feature is enabled.
139/// Additionally, if the object being iterated implements
140/// `IndexedParallelIterator`, then one can specify a minimum size for
141/// iteration.
142#[macro_export]
143macro_rules! cfg_into_iter {
144    ($e: expr, $min_len: expr) => {{
145        #[cfg(feature = "parallel")]
146        let result = $e.into_par_iter().with_min_len($min_len);
147
148        #[cfg(not(feature = "parallel"))]
149        let result = $e.into_iter();
150
151        result
152    }};
153    ($e: expr) => {{
154        #[cfg(feature = "parallel")]
155        let result = $e.into_par_iter();
156
157        #[cfg(not(feature = "parallel"))]
158        let result = $e.into_iter();
159
160        result
161    }};
162}
163
164/// Returns an iterator over `chunk_size` elements of the slice at a
165/// time.
166#[macro_export]
167macro_rules! cfg_chunks {
168    ($e: expr, $size: expr) => {{
169        #[cfg(feature = "parallel")]
170        let result = $e.par_chunks($size);
171
172        #[cfg(not(feature = "parallel"))]
173        let result = $e.chunks($size);
174
175        result
176    }};
177}
178
179/// Returns an iterator over `chunk_size` mutable elements of the slice at a
180/// time.
181#[macro_export]
182macro_rules! cfg_chunks_mut {
183    ($e: expr, $size: expr) => {{
184        #[cfg(feature = "parallel")]
185        let result = $e.par_chunks_mut($size);
186
187        #[cfg(not(feature = "parallel"))]
188        let result = $e.chunks_mut($size);
189
190        result
191    }};
192}
193
194/// Executes two closures. If `parallel` feature is enabled, the closures
195/// are executed in parallel using `rayon::join`. Otherwise, they are
196/// executed sequentially. The result is returned as a tuple.
197///
198/// ```rust
199/// # use ark_std::cfg_join;
200/// let (two, five) = cfg_join!(|| { 1 + 1 }, || { 2 + 3 });
201/// # assert_eq!(two, 2);
202/// # assert_eq!(five, 5);
203/// ```
204///
205/// The macro can also be nested to join more than two closures:
206/// ```
207/// # use ark_std::cfg_join;
208///
209/// let (two, (five, seven)) =
210///     cfg_join!(|| { 1 + 1 }, || cfg_join!(|| { 2 + 3 }, || { 1 + 6 }));
211/// # assert_eq!(two, 2);
212/// # assert_eq!(five, 5);
213/// # assert_eq!(seven, 7);
214/// ```
215#[macro_export]
216macro_rules! cfg_join {
217    ($e1: expr, $e2: expr) => {{
218        #[cfg(feature = "parallel")]
219        let result = rayon::join($e1, $e2);
220
221        #[cfg(not(feature = "parallel"))]
222        let result = ($e1(), $e2());
223
224        result
225    }};
226}
227
228#[cfg(test)]
229mod test {
230    use super::*;
231    #[cfg(feature = "parallel")]
232    use rayon::prelude::*;
233
234    #[test]
235    fn test_cfg_macros() {
236        #[cfg(feature = "parallel")]
237        println!("In parallel mode");
238
239        let mut thing = crate::vec![1, 2, 3, 4, 5u64];
240        println!("Iterating");
241        cfg_iter!(&thing).for_each(|i| println!("{:?}", i));
242        println!("Iterating Mut");
243        cfg_iter_mut!(&mut thing).for_each(|i| *i += 1);
244        println!("Iterating By Value");
245        cfg_into_iter!(thing.clone()).for_each(|i| println!("{:?}", i));
246        println!("Chunks");
247        cfg_chunks!(&thing, 2).for_each(|chunk| println!("{:?}", chunk));
248        println!("Chunks Mut");
249        cfg_chunks_mut!(&mut thing, 2).for_each(|chunk| println!("{:?}", chunk));
250
251        println!("Iterating");
252        cfg_iter!(&thing, 3).for_each(|i| println!("{:?}", i));
253        println!("Iterating Mut");
254        cfg_iter_mut!(&mut thing, 3).for_each(|i| *i += 1);
255        println!("Iterating By Value");
256        cfg_into_iter!(thing, 3).for_each(|i| println!("{:?}", i));
257
258        println!("Joining");
259        cfg_join!(
260            || {
261                println!("In first");
262            },
263            || {
264                println!("In second");
265            }
266        );
267    }
268}