further sqrt improvements

This commit is contained in:
Quaternions 2024-08-29 13:15:17 -07:00
parent e684fb421e
commit 6ea9eff844

View File

@ -18,6 +18,15 @@ impl<const CHUNKS:usize,Frac:Unsigned> Fixed<CHUNKS,Frac>{
pub const NEG_ONE:Self=Self{bits:BInt::<CHUNKS>::NEG_ONE.shl(Frac::U32),frac:PhantomData}; pub const NEG_ONE:Self=Self{bits:BInt::<CHUNKS>::NEG_ONE.shl(Frac::U32),frac:PhantomData};
pub const NEG_TWO:Self=Self{bits:BInt::<CHUNKS>::NEG_TWO.shl(Frac::U32),frac:PhantomData}; pub const NEG_TWO:Self=Self{bits:BInt::<CHUNKS>::NEG_TWO.shl(Frac::U32),frac:PhantomData};
pub const NEG_HALF:Self=Self{bits:BInt::<CHUNKS>::NEG_ONE.shl(Frac::U32-1),frac:PhantomData}; pub const NEG_HALF:Self=Self{bits:BInt::<CHUNKS>::NEG_ONE.shl(Frac::U32-1),frac:PhantomData};
pub const fn from_bits(bits:BInt::<CHUNKS>)->Self{
Self{
bits,
frac:PhantomData,
}
}
pub const fn to_bits(self)->BInt<CHUNKS>{
self.bits
}
} }
impl<const CHUNKS:usize,Frac:Unsigned,T> From<T> for Fixed<CHUNKS,Frac> impl<const CHUNKS:usize,Frac:Unsigned,T> From<T> for Fixed<CHUNKS,Frac>
@ -290,6 +299,13 @@ impl<const CHUNKS:usize,Frac:Unsigned> Fixed<CHUNKS,Frac>
{ {
pub fn sqrt_unchecked(self)->Self{ pub fn sqrt_unchecked(self)->Self{
//pow2 must be the minimum power of two which when squared is greater than 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<u8,4> //0001.0000 Fixed<u8,4>
//sqrt //sqrt
//0110.0000 //0110.0000
@ -300,14 +316,21 @@ impl<const CHUNKS:usize,Frac:Unsigned> Fixed<CHUNKS,Frac>
}; };
let mut result=pow2>>1; let mut result=pow2>>1;
while pow2!=Self::ZERO{ loop{
pow2>>=1; 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; let new_result=result+pow2;
if new_result*new_result<=self{ //note that the implicit truncation in the multiply
result=new_result; //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{ pub fn sqrt(self)->Self{
if self<Self::ZERO{ if self<Self::ZERO{