mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-24 02:46:51 -06:00
Fall back to decimal for huge architectural/fractional distances (#1762)
Found while testing crates/engine/src/units.rs:27-31 and 44-46 Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
f686a595e6
commit
1428174159
@@ -2,6 +2,10 @@
|
||||
|
||||
use std::f64::consts::PI;
|
||||
|
||||
/// Largest scaled value (below `i64::MAX`) that the integer feet/inch splitting handles; larger
|
||||
/// distances fall back to decimal.
|
||||
const I64_SAFE_MAX: f64 = 9.0e18;
|
||||
|
||||
/// Format a distance per LUNITS (1 scientific, 2 decimal, 3 engineering, 4 architectural,
|
||||
/// 5 fractional) and LUPREC.
|
||||
pub fn format_distance(v: f64, lunits: i64, luprec: i64) -> String {
|
||||
@@ -25,7 +29,11 @@ pub fn format_distance(v: f64, lunits: i64, luprec: i64) -> String {
|
||||
let neg = v < 0.0;
|
||||
let a = v.abs();
|
||||
let denom = 1i64 << prec.min(8);
|
||||
let total = (a * denom as f64).round() as i64;
|
||||
let scaled = (a * denom as f64).round();
|
||||
if scaled >= I64_SAFE_MAX {
|
||||
return format!("{:.*}", prec, v);
|
||||
}
|
||||
let total = scaled as i64;
|
||||
let ft = total / (12 * denom);
|
||||
let rem = total - ft * 12 * denom;
|
||||
let inch = rem / denom;
|
||||
@@ -42,7 +50,11 @@ pub fn format_distance(v: f64, lunits: i64, luprec: i64) -> String {
|
||||
let neg = v < 0.0;
|
||||
let a = v.abs();
|
||||
let denom = 1i64 << prec.min(8);
|
||||
let total = (a * denom as f64).round() as i64;
|
||||
let scaled = (a * denom as f64).round();
|
||||
if scaled >= I64_SAFE_MAX {
|
||||
return format!("{:.*}", prec, v);
|
||||
}
|
||||
let total = scaled as i64;
|
||||
let whole = total / denom;
|
||||
let frac = total % denom;
|
||||
let fs = if frac == 0 {
|
||||
@@ -335,6 +347,17 @@ pub const DEG: f64 = PI / 180.0;
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn huge_architectural_and_fractional_distances_do_not_saturate() {
|
||||
for lunits in [4, 5] {
|
||||
for v in [1e30, -1e30] {
|
||||
assert_eq!(format_distance(v, lunits, 4), format!("{:.4}", v), "lunits {lunits}");
|
||||
}
|
||||
}
|
||||
assert_eq!(format_distance(1e15, 5, 4), "1000000000000000");
|
||||
assert_eq!(format_distance(12.5, 4, 4), "1'-0 1/2\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn directions_show_from_angbase_in_the_angdir_sense() {
|
||||
let north_clockwise = AngleSettings { aunits: 0, angbase: 90f64.to_radians(), clockwise: true };
|
||||
|
||||
Reference in New Issue
Block a user