describe algorithm
This commit is contained in:
parent
70a79a8d25
commit
3c5f01da89
@ -57,24 +57,19 @@ impl<const CHUNKS:usize,Frac:Unsigned> Fixed<CHUNKS,Frac>
|
|||||||
<Fixed::<CHUNKS,Frac> as WideMul>::Output:Ord,
|
<Fixed::<CHUNKS,Frac> as WideMul>::Output:Ord,
|
||||||
{
|
{
|
||||||
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
|
//1<<max_shift must be the minimum power of two which when squared is greater than self
|
||||||
//the algorithm:
|
//calculating max_shift:
|
||||||
//1. count "used" bits to the left of the decimal
|
//1. count "used" bits to the left of the decimal, not including the sign bit (so -1)
|
||||||
//2. add one
|
//2. divide by 2 via >>1 (sqrt-ish)
|
||||||
//This is the power of two which is greater than self.
|
//3. add on fractional offset
|
||||||
//3. divide by 2 via >>1
|
|
||||||
//4. add on fractional offset
|
|
||||||
//Voila
|
//Voila
|
||||||
//0001.0000 Fixed<u8,4>
|
|
||||||
//sqrt
|
|
||||||
//0110.0000
|
|
||||||
//pow2 = 0100.0000
|
|
||||||
let used_bits=CHUNKS as i32*64-1-Frac::I32-self.bits.leading_zeros() as i32;
|
let used_bits=CHUNKS as i32*64-1-Frac::I32-self.bits.leading_zeros() as i32;
|
||||||
let max_shift=((used_bits>>1)+Frac::I32) as u32;
|
let max_shift=((used_bits>>1)+Frac::I32) as u32;
|
||||||
let mut result=Self::ZERO;
|
let mut result=Self::ZERO;
|
||||||
|
|
||||||
//cheat to make the types match
|
//multiply by one to make the types match (hack)
|
||||||
let wide_self=self.wide_mul(Fixed::<CHUNKS,Frac>::ONE);
|
let wide_self=self.wide_mul(Fixed::<CHUNKS,Frac>::ONE);
|
||||||
|
//descend down the bits and check if flipping each bit would push the square over the input value
|
||||||
for shift in (0..=max_shift).rev(){
|
for shift in (0..=max_shift).rev(){
|
||||||
let new_result=result|Fixed::<CHUNKS,Frac>::from_bits(BInt::from_bits(bnum::BUint::power_of_two(shift)));
|
let new_result=result|Fixed::<CHUNKS,Frac>::from_bits(BInt::from_bits(bnum::BUint::power_of_two(shift)));
|
||||||
if new_result.wide_mul(new_result)<=wide_self{
|
if new_result.wide_mul(new_result)<=wide_self{
|
||||||
|
Loading…
Reference in New Issue
Block a user