// 保留直接 Rust 参照,分别观察值参数、借用参数和 Result 对循环优化的影响。 fn generated(values: &[Option]) -> Result { let mut total = 0i64; for value in values { total += GENERATED_FLOAT(value)?; } Ok(total) } fn reference(values: &[Option]) -> Result { 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]) -> Result { GENERATED_FLOAT_TOTAL(values) } fn reference_batch(values: &[Option]) -> Result { 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) -> 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) -> Result { Ok(classify(value)) } fn classify_borrowed(value: &Option) -> 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]) -> Result { let mut total = 0i64; for value in values { total += classify(*value); } Ok(total) } fn result_helper(values: &[Option]) -> Result { let mut total = 0i64; for value in values { total += classify_result(*value)?; } Ok(total) } fn borrowed_helper(values: &[Option]) -> Result { 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::>(); 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::>(); let references = [ ( "direct", reference as fn(&[Option]) -> Result, ), ("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]) -> Result ) ); } 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]) -> Result, ), ("float_mixed_result_helper", result_helper), ("float_mixed_borrowed_helper", borrowed_helper), ] { compare(name, &mixed, 10000, generated, operation, |value| { *value as u64 }); } }