Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+256
View File
@@ -0,0 +1,256 @@
// 标准库入口来自实际 Dever 源码;参照只使用 dec,不调用 Dever 运行库。
use dec::{Context, Decimal128};
use std::sync::LazyLock;
static NATIVE_CONTEXT: LazyLock<Context<Decimal128>> = LazyLock::new(Context::default);
struct DecimalInput {
text: String,
value: Decimal,
native: Decimal128,
places: i64,
}
fn native_parse(text: &str) -> Option<Decimal128> {
let mut context = NATIVE_CONTEXT.clone();
let value = context.parse(text).ok()?;
(value.is_finite() && !context.status().inexact()).then_some(value)
}
fn parsed<const NATIVE: bool>(values: &[String]) -> Result<Vec<Option<[u8; 16]>>, Fault> {
values
.iter()
.map(|text| {
Ok(if NATIVE {
native_parse(text).map(|value| value.to_be_bytes())
} else {
DECIMAL_PARSE(text)?.map(Decimal::to_be_bytes)
})
})
.collect()
}
struct NativeDisplay(Decimal128);
impl std::fmt::Display for NativeDisplay {
fn fmt(&self, output: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let value = Context::<Decimal128>::default().reduce(self.0);
if value.is_zero() {
output.write_str("0")
} else {
write!(output, "{value}")
}
}
}
fn formatted<const NATIVE: bool>(values: &[DecimalInput]) -> Result<Vec<String>, Fault> {
values
.iter()
.map(|input| {
if NATIVE {
Ok(NativeDisplay(input.native).to_string())
} else {
DECIMAL_TEXT(input.value)
}
})
.collect()
}
fn native_round(value: Decimal128, places: i64) -> Option<Decimal128> {
let exponent = i32::try_from(places.checked_neg()?).ok()?;
if !(-6176..=6111).contains(&exponent) {
return None;
}
let mut context = NATIVE_CONTEXT.clone();
let mut quantum = Decimal128::ONE;
context.set_exponent(&mut quantum, exponent);
let value = context.quantize(value, quantum);
(value.is_finite() && !context.status().underflow() && !context.status().invalid_context())
.then_some(value)
}
fn rounded<const NATIVE: bool>(values: &[DecimalInput]) -> Result<Vec<Option<[u8; 16]>>, Fault> {
Ok(values
.iter()
.map(|input| {
if NATIVE {
native_round(input.native, input.places).map(|value| value.to_be_bytes())
} else {
DECIMAL_ROUND(input.value, input.places)
.ok()
.map(Decimal::to_be_bytes)
}
})
.collect())
}
fn negated<const NATIVE: bool>(values: &[DecimalInput]) -> Result<Vec<[u8; 16]>, Fault> {
Ok(values
.iter()
.map(|input| {
if NATIVE {
(-input.native).to_be_bytes()
} else {
(-input.value).to_be_bytes()
}
})
.collect())
}
fn compared<const NATIVE: bool>(
values: &[DecimalInput],
) -> Result<Vec<(bool, Option<std::cmp::Ordering>)>, Fault> {
Ok(values
.windows(2)
.map(|pair| {
if NATIVE {
(
pair[0].native == pair[1].native,
pair[0].native.partial_cmp(&pair[1].native),
)
} else {
(
pair[0].value == pair[1].value,
pair[0].value.partial_cmp(&pair[1].value),
)
}
})
.collect())
}
fn byte_score(values: &[Option<[u8; 16]>]) -> u64 {
values
.iter()
.flatten()
.flat_map(|value| value.iter())
.map(|value| u64::from(*value))
.sum()
}
fn text_score(values: &[String]) -> u64 {
values
.iter()
.flat_map(|value| value.bytes())
.map(u64::from)
.sum()
}
fn main() {
println!("case,sample,implementation,nanoseconds,checksum");
let spellings = [
"0",
"-0",
"1.2300",
"-12.345",
"1E-6176",
"1E6111",
"9.999999999999999999999999999999999E6144",
"1234567890123456789012345678901234",
"1.25",
"1.35",
"-250",
"+.125",
"1e-34",
"1.000000000000000000000000000000000",
];
let texts = spellings
.iter()
.cycle()
.take(112)
.map(|text| (*text).to_owned())
.collect::<Vec<_>>();
let inputs = texts
.iter()
.enumerate()
.map(|(index, text)| DecimalInput {
text: text.clone(),
value: Decimal::parse(text).unwrap(),
native: native_parse(text).unwrap(),
places: [0, 1, 2, -2, 6176, -6111][index % 6],
})
.collect::<Vec<_>>();
compare(
"decimal_parse_valid",
&texts,
1000,
parsed::<false>,
parsed::<true>,
|value| byte_score(value),
);
let invalid = [
"",
"+",
"NaN",
"-sNaN",
"Infinity",
"nan123",
" 1",
"1 ",
"1_000",
"1e",
"1\0",
"雪",
"1e9999",
"1e-9999",
"12345678901234567890123456789012345",
]
.iter()
.cycle()
.take(120)
.map(|value| (*value).to_owned())
.collect::<Vec<_>>();
assert!(
parsed::<false>(&invalid)
.unwrap()
.iter()
.all(Option::is_none)
);
compare(
"decimal_parse_invalid",
&invalid,
1000,
parsed::<false>,
parsed::<true>,
|value| byte_score(value),
);
compare(
"decimal_format",
&inputs,
1000,
formatted::<false>,
formatted::<true>,
|value| text_score(value),
);
compare(
"decimal_round",
&inputs,
1000,
rounded::<false>,
rounded::<true>,
|value| byte_score(value),
);
compare(
"decimal_negate",
&inputs,
1000,
negated::<false>,
negated::<true>,
|value| value.iter().flatten().map(|value| u64::from(*value)).sum(),
);
compare(
"decimal_compare",
&inputs,
1000,
compared::<false>,
compared::<true>,
|value| {
value
.iter()
.map(|(equal, order)| {
u64::from(*equal) + u64::from(order == &Some(std::cmp::Ordering::Less))
})
.sum()
},
);
wire_cases(&inputs);
storage_cases();
}