diff --git a/fixed_wide/src/fixed.rs b/fixed_wide/src/fixed.rs index 0030361..4fa36fa 100644 --- a/fixed_wide/src/fixed.rs +++ b/fixed_wide/src/fixed.rs @@ -18,6 +18,15 @@ impl Fixed{ pub const NEG_ONE:Self=Self{bits:BInt::::NEG_ONE.shl(Frac::U32),frac:PhantomData}; pub const NEG_TWO:Self=Self{bits:BInt::::NEG_TWO.shl(Frac::U32),frac:PhantomData}; pub const NEG_HALF:Self=Self{bits:BInt::::NEG_ONE.shl(Frac::U32-1),frac:PhantomData}; + pub const fn from_bits(bits:BInt::)->Self{ + Self{ + bits, + frac:PhantomData, + } + } + pub const fn to_bits(self)->BInt{ + self.bits + } } impl From for Fixed @@ -290,6 +299,13 @@ impl Fixed { pub fn sqrt_unchecked(self)->Self{ //pow2 must be the minimum power of two which when squared is greater than self + //the algorithm: + //1. count "used" bits to the left of the decimal + //2. add one + //This is the power of two which is greater than self. + //3. divide by 2 via >>1 + //4. add on fractional offset + //Voila //0001.0000 Fixed //sqrt //0110.0000 @@ -300,14 +316,21 @@ impl Fixed }; let mut result=pow2>>1; - while pow2!=Self::ZERO{ + loop{ pow2>>=1; + if pow2==Self::ZERO{ + break result; + } + //TODO: flip a single bit instead of adding a power of 2 let new_result=result+pow2; - if new_result*new_result<=self{ - result=new_result; + //note that the implicit truncation in the multiply + //means that the algorithm can return a result which squares to a number greater than the input. + match self.cmp(&(new_result*new_result)){ + core::cmp::Ordering::Less=>continue, + core::cmp::Ordering::Equal=>break new_result, + core::cmp::Ordering::Greater=>result=new_result, } } - result } pub fn sqrt(self)->Self{ if self