further sqrt improvements
This commit is contained in:
parent
e684fb421e
commit
6ea9eff844
@ -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_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 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>
|
||||
@ -290,6 +299,13 @@ impl<const CHUNKS:usize,Frac:Unsigned> Fixed<CHUNKS,Frac>
|
||||
{
|
||||
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<u8,4>
|
||||
//sqrt
|
||||
//0110.0000
|
||||
@ -300,14 +316,21 @@ impl<const CHUNKS:usize,Frac:Unsigned> Fixed<CHUNKS,Frac>
|
||||
};
|
||||
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<Self::ZERO{
|
||||
|
Loading…
Reference in New Issue
Block a user