From 385fa57f0a5d7e9d09b93b40c5afd7d5e9a135f1 Mon Sep 17 00:00:00 2001 From: Rhys Lloyd Date: Tue, 24 Feb 2026 08:49:59 -0800 Subject: [PATCH] ratio --- wasm-module/src/lib.rs | 7 ++++-- wasm-module/src/ratio.rs | 48 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 wasm-module/src/ratio.rs diff --git a/wasm-module/src/lib.rs b/wasm-module/src/lib.rs index e901229..4fb1eb0 100644 --- a/wasm-module/src/lib.rs +++ b/wasm-module/src/lib.rs @@ -5,6 +5,8 @@ use strafesnet_roblox_bot_player::{bot,head,time,graphics}; use strafesnet_graphics::setup; use strafesnet_common::physics::Time as PhysicsTime; +mod ratio; + // Hack to keep the code compiling, // SurfaceTarget::Canvas is not available in IDE for whatever reason. struct ToSurfaceTarget(web_sys::HtmlCanvasElement); @@ -141,9 +143,10 @@ impl PlaybackHead{ self.head.set_paused(time,paused); } #[wasm_bindgen] - pub fn set_scale(&mut self,time:f64,scale_num:i64,scale_den:u64){ + pub fn set_scale(&mut self,time:f64,scale:f64){ let time=time::from_float(time).unwrap(); - self.head.set_scale(time,strafesnet_common::integer::Ratio64::new(scale_num,scale_den).unwrap()); + let scale=crate::ratio::ratio_from_float(scale).unwrap(); + self.head.set_scale(time,scale); } #[wasm_bindgen] pub fn seek_to(&mut self,time:f64,new_time:f64){ diff --git a/wasm-module/src/ratio.rs b/wasm-module/src/ratio.rs new file mode 100644 index 0000000..de06e9f --- /dev/null +++ b/wasm-module/src/ratio.rs @@ -0,0 +1,48 @@ +use strafesnet_common::integer::Ratio64; + +#[derive(Debug)] +pub enum RatioFromFloatError{ + Nan, + Overflow, + Underflow, +} + +fn f64_into_parts(f: f64) -> (u64, i16, i8) { + let bits: u64 = f.to_bits(); + let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; + let mantissa = if exponent == 0 { + (bits & 0xfffffffffffff) << 1 + } else { + (bits & 0xfffffffffffff) | 0x10000000000000 + }; + // Exponent bias + mantissa shift + exponent -= 1023 + 52; + (mantissa, exponent, sign) +} + +pub fn ratio_from_float(value:f64)->Result{ + // Handle special values first + match value.classify() { + core::num::FpCategory::Nan=>return Err(RatioFromFloatError::Nan), + core::num::FpCategory::Zero=>return Ok(Ratio64::ZERO), + core::num::FpCategory::Subnormal + |core::num::FpCategory::Normal + |core::num::FpCategory::Infinite=>{ + if value < i64::MIN as f64 { + return Err(RatioFromFloatError::Underflow); + } + if (i64::MAX as f64) < value { + return Err(RatioFromFloatError::Overflow); + } + } + } + + // value = sign * mantissa * 2 ^ exponent + let (mantissa, exponent, sign) = f64_into_parts(value); + + // the idea: create exact float num/den ratio, and compute continued fraction if it doesn't fit + + + return Ok(()) +}