use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
const LOWER_LIMIT: usize = 16 ;
fn main() {
let limit = if cfg!(feature="limit_2048" ) {
2048
} else if cfg!(feature="limit_1024" ) {
1024
} else if cfg!(feature="limit_512" ) {
512
} else if cfg!(feature="limit_256" ) {
256
} else if cfg!(feature="limit_128" ) {
128
} else {
64
};
let out_dir = env::var("OUT_DIR" ).unwrap();
let dest_path = Path::new(&out_dir).join("lib.rs" );
let mut f = File::create(&dest_path).unwrap();
let mut output = String::new();
output.push_str(r#"
/// Unroll the given for loop
///
/// Example:
///
/// ```ignore
/// unroll! {
/// for i in 0..5 {
/// println!("Iteration {}", i);
/// }
/// }
/// ```
///
/// will expand into:
///
/// ```ignore
/// { println!("Iteration {}", 0); }
/// { println!("Iteration {}", 1); }
/// { println!("Iteration {}", 2); }
/// { println!("Iteration {}", 3); }
/// { println!("Iteration {}", 4); }
/// ```
#[ macro_export]
macro_rules! unroll {
(for $v:ident in 0 ..0 $c:block) => {};
(for $v:ident < $max:tt in ($start:tt..$end:tt).step_by($val:expr) {$($c:tt)*}) => {
{
let step = $val;
let start = $start;
let end = start + ($end - start) / step;
unroll! {
for val < $max in start..end {
let $v: usize = ((val - start) * step) + start;
$($c)*
}
}
}
};
(for $v:ident in ($start:tt..$end:tt).step_by($val:expr) {$($c:tt)*}) => {
unroll! {
for $v < $end in ($start..$end).step_by($val) {$($c)*}
}
};
(for $v:ident in ($start:tt..$end:tt) {$($c:tt)*}) => {
unroll!{
for $v in $start..$end {$($c)*}
}
};
(for $v:ident in $start:tt..$end:tt {$($c:tt)*}) => {
#[ allow(non_upper_case_globals)]
#[ allow(unused_comparisons)]
{
unroll!(@$v, 0 , $end, {
if $v >= $start {$($c)*}
}
);
}
};
(for $v:ident < $max:tt in $start:tt..$end:tt $c:block) => {
#[ allow(non_upper_case_globals)]
{
let range = $start..$end;
assert!(
$max >= range.end,
"`{}` out of range `{:?}`" ,
stringify!($max),
range,
);
unroll!(
@$v,
0 ,
$max,
{
if $v >= range.start && $v < range.end {
$c
}
}
);
}
};
(for $v:ident in 0 ..$end:tt {$($statement:tt)*}) => {
#[ allow(non_upper_case_globals)]
{ unroll!(@$v, 0 , $end, {$($statement)*}); }
};
"#);
for i in 0 ..limit + 1 {
output.push_str(format!(" (@$v:ident, $a:expr, {}, $c:block) => {{\n" , i).as_str());
if i <= LOWER_LIMIT {
output.push_str(format!(" {{ const $v: usize = $a; $c }}\n" ).as_str());
for a in 1 ..i {
output.push_str(format!(" {{ const $v: usize = $a + {}; $c }}\n" , a).as_str());
}
} else {
let half = i / 2 ;
if i % 2 == 0 {
output.push_str(format!(" unroll!(@$v, $a, {0}, $c);\n" , half).as_str());
output.push_str(format!(" unroll!(@$v, $a + {0}, {0}, $c);\n" , half).as_str());
} else {
if half > 1 {
output.push_str(format!(" unroll!(@$v, $a, {}, $c);\n" , i - 1 ).as_str())
}
output.push_str(format!(" {{ const $v: usize = $a + {}; $c }}\n" , i - 1 ).as_str());
}
}
output.push_str(" };\n\n" );
}
output.push_str("}\n\n" );
output.push_str(format!(r#"
#[ cfg(all(test, feature = "std" ))]
mod tests {{
#[ test]
fn invalid_range() {{
let mut a: Vec<usize> = vec![];
unroll! {{
for i in (5 ..4 ) {{
a.push(i);
}}
}}
assert_eq!(a, vec![]);
}}
#[ test]
fn start_at_one_with_step() {{
let mut a: Vec<usize> = vec![];
unroll! {{
for i in (2 ..4 ).step_by(1 ) {{
a.push(i);
}}
}}
assert_eq!(a, vec![2 , 3 ]);
}}
#[ test]
fn start_at_one() {{
let mut a: Vec<usize> = vec![];
unroll! {{
for i in 1 ..4 {{
a.push(i);
}}
}}
assert_eq!(a, vec![1 , 2 , 3 ]);
}}
#[ test]
fn test_all() {{
{{
let a: Vec<usize> = vec![];
unroll! {{
for i in 0 ..0 {{
a.push(i);
}}
}}
assert_eq!(a, (0 ..0 ).collect::<Vec<usize>>());
}}
{{
let mut a: Vec<usize> = vec![];
unroll! {{
for i in 0 ..1 {{
a.push(i);
}}
}}
assert_eq!(a, (0 ..1 ).collect::<Vec<usize>>());
}}
{{
let mut a: Vec<usize> = vec![];
unroll! {{
for i in 0 ..{0 } {{
a.push(i);
}}
}}
assert_eq!(a, (0 ..{0 }).collect::<Vec<usize>>());
}}
{{
let mut a: Vec<usize> = vec![];
let start = {0 } / 4 ;
let end = start * 3 ;
unroll! {{
for i < {0 } in start..end {{
a.push(i);
}}
}}
assert_eq!(a, (start..end).collect::<Vec<usize>>());
}}
{{
let mut a: Vec<usize> = vec![];
unroll! {{
for i in (0 ..{0 }).step_by(2 ) {{
a.push(i);
}}
}}
assert_eq!(a, (0 ..{0 } / 2 ).map(|x| x * 2 ).collect::<Vec<usize>>());
}}
{{
let mut a: Vec<usize> = vec![];
let start = {0 } / 4 ;
let end = start * 3 ;
unroll! {{
for i < {0 } in (start..end).step_by(2 ) {{
a.push(i);
}}
}}
assert_eq!(a, (start..end).filter(|x| x % 2 == 0 ).collect::<Vec<usize>>());
}}
}}
}}
"#, limit).as_str());
f.write_all(output.as_bytes()).unwrap();
}
Messung V0.5 in Prozent C=96 H=98 G=96
¤ Dauer der Verarbeitung: 0.3 Sekunden
¤
*© Formatika GbR, Deutschland