use crate::fixed::Fixed;
use crate::fixed::BNUM_DIGIT_WIDTH;

use arrayvec::ArrayVec;
use std::cmp::Ordering;
macro_rules! impl_zeroes{
	($n:expr)=>{
		impl Fixed<{$n/BNUM_DIGIT_WIDTH},{$n>>1}>{
			#[inline]
			pub fn zeroes2(a0:Self,a1:Self,a2:Self)->ArrayVec<<Self as core::ops::Div>::Output,2>{
				let a2pos=match a2.cmp(&Self::ZERO){
					Ordering::Greater=>true,
					Ordering::Equal=>return ArrayVec::from_iter(Self::zeroes1(a0,a1)),
					Ordering::Less=>false,
				};
				let radicand=a1*a1-((a2*a0)<<2);
				match radicand.cmp(&<Self as core::ops::Mul>::Output::ZERO){
					Ordering::Greater=>{
						// using wrap because sqrt always halves the number of leading digits.
						// clamp would be more defensive, but is slower.
						paste::item!{
						let planar_radicand=radicand.sqrt().[<wrap_ $n>]();
						}
						//sort roots ascending and avoid taking the difference of large numbers
						let zeroes=match (a2pos,a1.is_positive()){
							(true, true )=>[(-a1-planar_radicand)/(a2<<1),(a0<<1)/(-a1-planar_radicand)],
							(true, false)=>[(a0<<1)/(-a1+planar_radicand),(-a1+planar_radicand)/(a2<<1)],
							(false,true )=>[(a0<<1)/(-a1-planar_radicand),(-a1-planar_radicand)/(a2<<1)],
							(false,false)=>[(-a1+planar_radicand)/(a2<<1),(a0<<1)/(-a1+planar_radicand)],
						};
						ArrayVec::from_iter(zeroes)
					},
					Ordering::Equal=>ArrayVec::from_iter([(a1)/(-a2<<1)]),
					Ordering::Less=>ArrayVec::new_const(),
				}
			}
			#[inline]
			pub fn zeroes1(a0:Self,a1:Self)->ArrayVec<<Self as core::ops::Div>::Output,1>{
				if a1.is_zero(){
					ArrayVec::new_const()
				}else{
					ArrayVec::from_iter([(-a0)/(a1)])
				}
			}
		}
	};
}
impl_zeroes!(64);
impl_zeroes!(128);
impl_zeroes!(192);
impl_zeroes!(256);
//sqrt doubles twice!
//impl_zeroes!(5);
//impl_zeroes!(6);
//impl_zeroes!(7);
//impl_zeroes!(8);
