Files
core/test/rust/performance/numeric/float.rs
T
2026-11-03 03:32:07 +00:00

204 lines
5.1 KiB
Rust

// 保留直接 Rust 参照,分别观察值参数、借用参数和 Result 对循环优化的影响。
fn generated(values: &[Option<f64>]) -> Result<i64, Fault> {
let mut total = 0i64;
for value in values {
total += GENERATED_FLOAT(value)?;
}
Ok(total)
}
fn reference(values: &[Option<f64>]) -> Result<i64, Fault> {
let mut total = 0i64;
for value in values {
total += match value {
None => -1,
Some(value) if *value == 1.0 => 1,
Some(value) if *value == 0.0 => 0,
Some(_) => 2,
};
}
Ok(total)
}
fn generated_batch(values: &[Option<f64>]) -> Result<i64, Fault> {
GENERATED_FLOAT_TOTAL(values)
}
fn reference_batch(values: &[Option<f64>]) -> Result<i64, Fault> {
let mut total = 0i64;
for value in values {
let projected = match value {
None => -1,
Some(value) if *value == 1.0 => 1,
Some(value) if *value == 0.0 => 0,
Some(_) => 2,
};
total = total.checked_add(projected).ok_or(&FaultInfo {
message: "integer overflow",
source: "Rust reference",
line: 0,
column: 0,
})?;
}
Ok(total)
}
fn classify(value: Option<f64>) -> i64 {
match value {
None => -1,
Some(value) if value == 1.0 => 1,
Some(value) if value == 0.0 => 0,
Some(_) => 2,
}
}
fn classify_result(value: Option<f64>) -> Result<i64, Fault> {
Ok(classify(value))
}
fn classify_borrowed(value: &Option<f64>) -> i64 {
match value {
None => -1,
Some(value) if *value == 1.0 => 1,
Some(value) if *value == 0.0 => 0,
Some(_) => 2,
}
}
fn value_helper(values: &[Option<f64>]) -> Result<i64, Fault> {
let mut total = 0i64;
for value in values {
total += classify(*value);
}
Ok(total)
}
fn result_helper(values: &[Option<f64>]) -> Result<i64, Fault> {
let mut total = 0i64;
for value in values {
total += classify_result(*value)?;
}
Ok(total)
}
fn borrowed_helper(values: &[Option<f64>]) -> Result<i64, Fault> {
let mut total = 0i64;
for value in values {
total += classify_borrowed(value);
}
Ok(total)
}
fn main() {
let special = [
None,
Some(0.0),
Some(-0.0),
Some(1.0),
Some(-1.0),
Some(f64::NAN),
Some(f64::INFINITY),
Some(f64::NEG_INFINITY),
];
let values = (0..256)
.map(|index| special[index % special.len()])
.collect::<Vec<_>>();
let mut state = 0x123456789abcdef0u64;
let mixed = (0..256)
.map(|index| {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
if index % 3 == 0 {
Some(f64::from_bits(state))
} else {
special[((state >> 32) as usize) % special.len()]
}
})
.collect::<Vec<_>>();
let references = [
(
"direct",
reference as fn(&[Option<f64>]) -> Result<i64, Fault>,
),
("value", value_helper),
("result", result_helper),
("borrowed", borrowed_helper),
];
for (name, operation) in references {
for value in values.iter().chain(&mixed) {
assert_eq!(generated(&[*value]).unwrap(), operation(&[*value]).unwrap());
}
eprintln!(
"{name}_equals_generated={}",
std::ptr::fn_addr_eq(
operation,
generated as fn(&[Option<f64>]) -> Result<i64, Fault>
)
);
}
println!("case,sample,implementation,elapsed_ns,checksum");
for (name, values) in [("float_batch", &values), ("float_batch_mixed", &mixed)] {
compare(
name,
values,
10000,
generated_batch,
reference_batch,
|value| *value as u64,
);
}
compare(
"float_direct",
&values,
10000,
generated,
reference,
|value| *value as u64,
);
compare(
"float_mixed",
&mixed,
10000,
generated,
reference,
|value| *value as u64,
);
compare(
"float_value_helper",
&values,
10000,
generated,
value_helper,
|value| *value as u64,
);
compare(
"float_result_helper",
&values,
10000,
generated,
result_helper,
|value| *value as u64,
);
compare(
"float_borrowed_helper",
&values,
10000,
generated,
borrowed_helper,
|value| *value as u64,
);
// 同一混合序列也经过各参照,避免把函数边界或布局差异归给 Dever。
for (name, operation) in [
(
"float_mixed_value_helper",
value_helper as fn(&[Option<f64>]) -> Result<i64, Fault>,
),
("float_mixed_result_helper", result_helper),
("float_mixed_borrowed_helper", borrowed_helper),
] {
compare(name, &mixed, 10000, generated, operation, |value| {
*value as u64
});
}
}