zeroes: branch instead of heap allocation
This commit is contained in:
parent
9563290454
commit
62e9397c98
@ -1,40 +1,96 @@
|
|||||||
//find roots of polynomials
|
//find roots of polynomials
|
||||||
use crate::integer::Planar64;
|
use crate::integer::Planar64;
|
||||||
|
|
||||||
|
pub enum Zeroes{
|
||||||
|
Two([Planar64;2]),
|
||||||
|
One([Planar64;1]),
|
||||||
|
Zero,
|
||||||
|
}
|
||||||
|
impl Zeroes{
|
||||||
|
pub fn len(&self)->usize{
|
||||||
|
match self{
|
||||||
|
Zeroes::Two(z)=>z.len(),
|
||||||
|
Zeroes::One(z)=>z.len(),
|
||||||
|
Zeroes::Zero=>0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<[Planar64;0]> for Zeroes{
|
||||||
|
fn from(_value:[Planar64;0])->Self{
|
||||||
|
Zeroes::Zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<[Planar64;1]> for Zeroes{
|
||||||
|
fn from(value:[Planar64;1])->Self{
|
||||||
|
Zeroes::One(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<[Planar64;2]> for Zeroes{
|
||||||
|
fn from(value:[Planar64;2])->Self{
|
||||||
|
Zeroes::Two(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub struct ZeroesIter{
|
||||||
|
zeroes:Zeroes,
|
||||||
|
index:usize,
|
||||||
|
}
|
||||||
|
impl Iterator for ZeroesIter{
|
||||||
|
type Item=Planar64;
|
||||||
|
fn next(&mut self)->Option<Self::Item>{
|
||||||
|
let ret=match self.zeroes{
|
||||||
|
Zeroes::Two(z)=>z.get(self.index).copied(),
|
||||||
|
Zeroes::One(z)=>z.get(self.index).copied(),
|
||||||
|
Zeroes::Zero=>None,
|
||||||
|
};
|
||||||
|
self.index+=1;
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl IntoIterator for Zeroes{
|
||||||
|
type Item=Planar64;
|
||||||
|
type IntoIter=ZeroesIter;
|
||||||
|
fn into_iter(self)->Self::IntoIter{
|
||||||
|
ZeroesIter{
|
||||||
|
zeroes:self,
|
||||||
|
index:0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zeroes2(a0:Planar64,a1:Planar64,a2:Planar64) -> Vec<Planar64>{
|
pub fn zeroes2(a0:Planar64,a1:Planar64,a2:Planar64)->Zeroes{
|
||||||
if a2==Planar64::ZERO{
|
if a2==Planar64::ZERO{
|
||||||
return zeroes1(a0, a1);
|
return zeroes1(a0,a1);
|
||||||
}
|
}
|
||||||
let radicand=a1.get() as i128*a1.get() as i128-a2.get() as i128*a0.get() as i128*4;
|
let radicand=a1.get() as i128*a1.get() as i128-a2.get() as i128*a0.get() as i128*4;
|
||||||
if 0<radicand {
|
if 0<radicand{
|
||||||
//start with f64 sqrt
|
//start with f64 sqrt
|
||||||
//failure case: 2^63 < sqrt(2^127)
|
//failure case: 2^63 < sqrt(2^127)
|
||||||
let planar_radicand=Planar64::raw(unsafe{(radicand as f64).sqrt().to_int_unchecked()});
|
let planar_radicand=Planar64::raw(unsafe{(radicand as f64).sqrt().to_int_unchecked()});
|
||||||
//TODO: one or two newtons
|
//TODO: one or two newtons
|
||||||
//sort roots ascending and avoid taking the difference of large numbers
|
//sort roots ascending and avoid taking the difference of large numbers
|
||||||
match (Planar64::ZERO<a2,Planar64::ZERO<a1){
|
match (Planar64::ZERO<a2,Planar64::ZERO<a1){
|
||||||
(true, true )=>vec![(-a1-planar_radicand)/(a2*2),(a0*2)/(-a1-planar_radicand)],
|
(true, true )=>[(-a1-planar_radicand)/(a2*2),(a0*2)/(-a1-planar_radicand)].into(),
|
||||||
(true, false)=>vec![(a0*2)/(-a1+planar_radicand),(-a1+planar_radicand)/(a2*2)],
|
(true, false)=>[(a0*2)/(-a1+planar_radicand),(-a1+planar_radicand)/(a2*2)].into(),
|
||||||
(false,true )=>vec![(a0*2)/(-a1-planar_radicand),(-a1-planar_radicand)/(a2*2)],
|
(false,true )=>[(a0*2)/(-a1-planar_radicand),(-a1-planar_radicand)/(a2*2)].into(),
|
||||||
(false,false)=>vec![(-a1+planar_radicand)/(a2*2),(a0*2)/(-a1+planar_radicand)],
|
(false,false)=>[(-a1+planar_radicand)/(a2*2),(a0*2)/(-a1+planar_radicand)].into(),
|
||||||
}
|
}
|
||||||
} else if radicand==0 {
|
}else if radicand==0{
|
||||||
return vec![a1/(a2*-2)];
|
return [a1/(a2*-2)].into();
|
||||||
} else {
|
}else{
|
||||||
return vec![];
|
return [].into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zeroes1(a0:Planar64,a1:Planar64) -> Vec<Planar64> {
|
pub fn zeroes1(a0:Planar64,a1:Planar64)->Zeroes{
|
||||||
if a1==Planar64::ZERO{
|
if a1==Planar64::ZERO{
|
||||||
return vec![];
|
return [].into();
|
||||||
}else{
|
}else{
|
||||||
let q=((-a0.get() as i128)<<32)/(a1.get() as i128);
|
let q=((-a0.get() as i128)<<32)/(a1.get() as i128);
|
||||||
if i64::MIN as i128<=q&&q<=i64::MAX as i128{
|
if i64::MIN as i128<=q&&q<=i64::MAX as i128{
|
||||||
return vec![Planar64::raw(q as i64)];
|
return [Planar64::raw(q as i64)].into();
|
||||||
}else{
|
}else{
|
||||||
return vec![];
|
return [].into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user