162 lines
4.0 KiB
Rust
162 lines
4.0 KiB
Rust
fn fault() -> Fault {
|
|
&FaultInfo {
|
|
message: "integer arithmetic fault",
|
|
source: "reference.dever",
|
|
line: 1,
|
|
column: 1,
|
|
}
|
|
}
|
|
|
|
fn map_reference(values: &[i64]) -> Result<Vec<i64>, Fault> {
|
|
let mut output = Vec::with_capacity(values.len());
|
|
for value in values {
|
|
output.push(value.checked_mul(2).ok_or_else(fault)?);
|
|
}
|
|
Ok(output)
|
|
}
|
|
|
|
fn filter_reference(values: &[i64]) -> Result<Vec<i64>, Fault> {
|
|
let mut output = Vec::new();
|
|
for value in values {
|
|
if *value > 0 {
|
|
output.push(*value);
|
|
}
|
|
}
|
|
Ok(output)
|
|
}
|
|
|
|
fn find_reference(values: &[i64]) -> Result<Option<i64>, Fault> {
|
|
Ok(values.iter().find(|value| **value > 997).copied())
|
|
}
|
|
|
|
fn find_generated(values: &[i64]) -> Result<Option<i64>, Fault> {
|
|
GENERATED_FIND(values, 997)
|
|
}
|
|
|
|
fn sum_reference(values: &[i64]) -> Result<i64, Fault> {
|
|
let mut total = 0i64;
|
|
for value in values {
|
|
let projected = value.checked_mul(2).ok_or_else(fault)?;
|
|
total = total.checked_add(projected).ok_or_else(fault)?;
|
|
}
|
|
Ok(total)
|
|
}
|
|
|
|
fn fold_reference(values: &[i64]) -> Result<i64, Fault> {
|
|
let mut state = 0i64;
|
|
for value in values {
|
|
state = state.checked_add(*value).ok_or_else(fault)?;
|
|
}
|
|
Ok(state)
|
|
}
|
|
|
|
fn stop_reference(values: &[i64]) -> Result<i64, Fault> {
|
|
let mut state = 0i64;
|
|
for value in values {
|
|
state = state.checked_add(*value).ok_or_else(fault)?;
|
|
if state >= 3 {
|
|
break;
|
|
}
|
|
}
|
|
Ok(state)
|
|
}
|
|
|
|
fn rows_reference(values: &[ROW_TYPE]) -> Result<Vec<ROW_TYPE>, Fault> {
|
|
let mut output = Vec::with_capacity(values.len());
|
|
for value in values {
|
|
let mut name = String::with_capacity(value.field0.len() + "新".len());
|
|
name.push_str(&value.field0);
|
|
name.push_str("新");
|
|
output.push(ROW_TYPE {
|
|
field0: name,
|
|
field1: value.field1.checked_add(1).ok_or_else(fault)?,
|
|
});
|
|
}
|
|
Ok(output)
|
|
}
|
|
|
|
fn main() {
|
|
let values: Vec<i64> = (0..1024).map(|value| (value * 17) % 1000 - 1).collect();
|
|
let rows: Vec<_> = (0..64)
|
|
.map(|index| ROW_TYPE {
|
|
field0: "雪山树林".repeat(4),
|
|
field1: index,
|
|
})
|
|
.collect();
|
|
for values in [&[i64::MAX][..], &[i64::MAX / 2, 3][..], &[i64::MIN, -1][..]] {
|
|
assert_eq!(
|
|
GENERATED_MAP(values).map_err(|_| ()),
|
|
map_reference(values).map_err(|_| ())
|
|
);
|
|
assert_eq!(
|
|
GENERATED_SUM(values).map_err(|_| ()),
|
|
sum_reference(values).map_err(|_| ())
|
|
);
|
|
assert_eq!(
|
|
GENERATED_FOLD(values).map_err(|_| ()),
|
|
fold_reference(values).map_err(|_| ())
|
|
);
|
|
assert_eq!(
|
|
GENERATED_STOP(values).map_err(|_| ()),
|
|
stop_reference(values).map_err(|_| ())
|
|
);
|
|
}
|
|
println!("case,sample,implementation,elapsed_ns,checksum");
|
|
compare(
|
|
"each_int",
|
|
&values,
|
|
20000,
|
|
GENERATED_MAP,
|
|
map_reference,
|
|
|value| value.len() as u64,
|
|
);
|
|
compare(
|
|
"filter_int",
|
|
&values,
|
|
20000,
|
|
GENERATED_FILTER,
|
|
filter_reference,
|
|
|value| value.len() as u64,
|
|
);
|
|
compare(
|
|
"find_int",
|
|
&values,
|
|
50000,
|
|
find_generated,
|
|
find_reference,
|
|
|value| value.unwrap_or(0) as u64,
|
|
);
|
|
compare(
|
|
"project_sum",
|
|
&values,
|
|
30000,
|
|
GENERATED_SUM,
|
|
sum_reference,
|
|
|value| *value as u64,
|
|
);
|
|
compare(
|
|
"reduce_int",
|
|
&values,
|
|
30000,
|
|
GENERATED_FOLD,
|
|
fold_reference,
|
|
|value| *value as u64,
|
|
);
|
|
compare(
|
|
"reduce_until_int",
|
|
&values,
|
|
500000,
|
|
GENERATED_STOP,
|
|
stop_reference,
|
|
|value| *value as u64,
|
|
);
|
|
compare(
|
|
"each_record",
|
|
&rows,
|
|
5000,
|
|
GENERATED_ROWS,
|
|
rows_reference,
|
|
|value| value.len() as u64,
|
|
);
|
|
}
|