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

80 lines
2.8 KiB
Rust

// 独立 Rust 参照直接使用相同版本的 dec,逐项清理和检查状态。
// 两侧使用同一输入、Decimal128 精度、舍入和顺序,不用二进制浮点代替。
fn generated(values: &[Decimal]) -> Result<Decimal, Fault> {
GENERATED_DECIMAL_SUM(values)
}
fn reference(values: &[Decimal]) -> Result<Decimal, Fault> {
let mut context = dec::Context::<dec::Decimal128>::default();
let mut total = dec::Decimal128::ZERO;
for value in values {
context.clear_status();
total = context.add(total, dec::Decimal128::from_be_bytes(value.to_be_bytes()));
if !total.is_finite() || context.status().overflow() || context.status().invalid_operation()
{
return Err(&FaultInfo {
message: "Decimal fault",
source: "Rust reference",
line: 0,
column: 0,
});
}
}
Ok(Decimal::from_be_bytes(total.to_be_bytes()))
}
fn score(value: &Decimal) -> u64 {
u64::from_be_bytes(value.to_be_bytes()[8..].try_into().unwrap())
}
fn main() {
let maximum = Decimal::parse("9.999999999999999999999999999999999E+6144").unwrap();
let zero = Decimal::from_int(0);
for values in [
vec![maximum, maximum, -maximum],
vec![-maximum, -maximum, maximum],
vec![zero],
Vec::new(),
] {
let actual = generated(&values);
let expected = reference(&values);
assert_eq!(actual.is_err(), expected.is_err());
if let (Ok(actual), Ok(expected)) = (actual, expected) {
assert_eq!(actual.to_be_bytes(), expected.to_be_bytes());
}
}
let short = [
"0.1", "0.2", "-0.05", "1.25", "-0.00", "10", "-2.50", "0.001",
]
.map(|text| Decimal::parse(text).unwrap());
let integers = (0..256).map(Decimal::from_int).collect::<Vec<_>>();
let palette = [
"-1234567890123456789012345678901234",
"1.000000000000000000000000000000001",
"-0.001",
"-1E-6176",
"-0.00",
"0E+100",
"1E-6176",
"0.9999999999999999999999999999999999",
"1234567890123456789012345678901234",
]
.map(|text| Decimal::parse(text).unwrap());
let mixed = (0..256)
.map(|index| palette[index % palette.len()])
.collect::<Vec<_>>();
println!("case,sample,implementation,elapsed_ns,checksum");
for (name, values, count) in [
("decimal_sum_short", short.as_slice(), 10000),
("decimal_sum_integers", integers.as_slice(), 1000),
("decimal_sum_mixed", mixed.as_slice(), 1000),
] {
assert_eq!(
generated(values).unwrap().to_be_bytes(),
reference(values).unwrap().to_be_bytes()
);
compare(name, values, count, generated, reference, score);
}
}