59 lines
1.9 KiB
Rust
59 lines
1.9 KiB
Rust
|
use crate::fixed::Fixed;
|
||
|
use crate::ratio::Ratio;
|
||
|
|
||
|
use typenum::{Sum,Unsigned};
|
||
|
use arrayvec::ArrayVec;
|
||
|
use std::cmp::Ordering;
|
||
|
macro_rules! impl_zeroes{
|
||
|
($n:expr)=>{
|
||
|
impl<F> Fixed<$n,F>
|
||
|
where
|
||
|
F:Unsigned+std::ops::Add,
|
||
|
<F as std::ops::Add>::Output:Unsigned,
|
||
|
{
|
||
|
#[inline]
|
||
|
pub fn zeroes2(a0:Self,a1:Self,a2:Self)->ArrayVec<Ratio<Self,Self>,2>{
|
||
|
let a2pos=match a2.cmp(&Self::ZERO){
|
||
|
Ordering::Greater=>true,
|
||
|
Ordering::Equal=>return ArrayVec::from_iter($crate::zeroes::zeroes1(a0,a1).into_iter()),
|
||
|
Ordering::Less=>true,
|
||
|
};
|
||
|
let radicand=$crate::traits::WideMul::wide_mul(a1,a1)-$crate::traits::WideMul::wide_mul(a2,a0)*4;
|
||
|
match radicand.cmp(&Fixed::<{$n*2},Sum<F,F>>::ZERO){
|
||
|
Ordering::Greater=>{
|
||
|
//start with f64 sqrt
|
||
|
//failure case: 2^63 < sqrt(2^127)
|
||
|
let planar_radicand=radicand.sqrt();
|
||
|
//TODO: one or two newtons
|
||
|
//sort roots ascending and avoid taking the difference of large numbers
|
||
|
match (a2pos,Self::ZERO<a1){
|
||
|
(true, true )=>[Ratio::new(-a1-planar_radicand,a2*2),Ratio::new(a0*2,-a1-planar_radicand)].into(),
|
||
|
(true, false)=>[Ratio::new(a0*2,-a1+planar_radicand),Ratio::new(-a1+planar_radicand,a2*2)].into(),
|
||
|
(false,true )=>[Ratio::new(a0*2,-a1-planar_radicand),Ratio::new(-a1-planar_radicand,a2*2)].into(),
|
||
|
(false,false)=>[Ratio::new(-a1+planar_radicand,a2*2),Ratio::new(a0*2,-a1+planar_radicand)].into(),
|
||
|
}
|
||
|
},
|
||
|
Ordering::Equal=>ArrayVec::from_iter([Ratio::new(a1,a2*-2)]),
|
||
|
Ordering::Less=>ArrayVec::new_const(),
|
||
|
}
|
||
|
}
|
||
|
#[inline]
|
||
|
pub fn zeroes1(a0:Self,a1:Self)->ArrayVec<Ratio<Self,Self>,1>{
|
||
|
if a1==Self::ZERO{
|
||
|
ArrayVec::new_const()
|
||
|
}else{
|
||
|
ArrayVec::from_iter([Ratio::new(-a0,a1)])
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
impl_zeroes!(1);
|
||
|
impl_zeroes!(2);
|
||
|
impl_zeroes!(3);
|
||
|
impl_zeroes!(4);
|
||
|
impl_zeroes!(5);
|
||
|
impl_zeroes!(6);
|
||
|
impl_zeroes!(7);
|
||
|
impl_zeroes!(8);
|