use crate::fixed::Fixed; use arrayvec::ArrayVec; use std::cmp::Ordering; macro_rules! impl_zeroes{ ($n:expr)=>{ impl Fixed<$n,{$n*32}>{ #[inline] pub fn zeroes2(a0:Self,a1:Self,a2:Self)->ArrayVec<::Output,2>{ let a2pos=match a2.cmp(&Self::ZERO){ Ordering::Greater=>true, Ordering::Equal=>return ArrayVec::from_iter(Self::zeroes1(a0,a1).into_iter()), Ordering::Less=>true, }; paste::item!{ let radicand=a1*a1-a2*a0*4; } match radicand.cmp(&::Output::ZERO){ Ordering::Greater=>{ //TODO: use resize method let planar_radicand:Self=radicand.sqrt().halve_precision(); //sort roots ascending and avoid taking the difference of large numbers let zeroes=match (a2pos,Self::ZERO[(-a1-planar_radicand)/(a2*2),(a0*2)/(-a1-planar_radicand)], (true, false)=>[(a0*2)/(-a1+planar_radicand),(-a1+planar_radicand)/(a2*2)], (false,true )=>[(a0*2)/(-a1-planar_radicand),(-a1-planar_radicand)/(a2*2)], (false,false)=>[(-a1+planar_radicand)/(a2*2),(a0*2)/(-a1+planar_radicand)], }; ArrayVec::from_iter(zeroes) }, Ordering::Equal=>ArrayVec::from_iter([(a1)/(a2*-2)]), Ordering::Less=>ArrayVec::new_const(), } } #[inline] pub fn zeroes1(a0:Self,a1:Self)->ArrayVec<::Output,1>{ if a1==Self::ZERO{ ArrayVec::new_const() }else{ ArrayVec::from_iter([(-a0)/(a1)]) } } } }; } impl_zeroes!(1); impl_zeroes!(2); impl_zeroes!(3); impl_zeroes!(4); //sqrt doubles twice! //impl_zeroes!(5); //impl_zeroes!(6); //impl_zeroes!(7); //impl_zeroes!(8);