// No Unsigned constraint because this also works on positive integers and is called
// like that, see above
No Unsigned constraint because this also works on positive integers and is called
like that, see above
No Unsigned constraint because this also works on positive integers and is called like that see above
fn approximate_float_unsigned<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>>
where
    T: Integer + Bounded + NumCast + Clone,
    F: FloatCore + NumCast,
{
    // Continued fractions algorithm
    // http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac
    if val < F::zero() || val.is_nan() {
        return None;
    }
    let mut q = val;
    let mut n0 = T::zero();
    let mut d0 = T::one();
    let mut n1 = T::one();
    let mut d1 = T::zero();
    let t_max = T::max_value();
    let t_max_f = <F as NumCast>::from(t_max.clone())?;
    // 1/epsilon > T::MAX
    let epsilon = t_max_f.recip();
    // Overflow
    if q > t_max_f {
        return None;
    }
    for _ in 0..max_iterations {
        let a = match <T as NumCast>::from(q) {
            None => break,
            Some(a) => a,
        };
        let a_f = match <F as NumCast>::from(a.clone()) {
            None => break,
            Some(a_f) => a_f,
        };
        let f = q - a_f;
        // Prevent overflow
        if !a.is_zero()
            && (n1 > t_max.clone() / a.clone()
                || d1 > t_max.clone() / a.clone()
                || a.clone() * n1.clone() > t_max.clone() - n0.clone()
                || a.clone() * d1.clone() > t_max.clone() - d0.clone())
        {
            break;
        }
        let n = a.clone() * n1.clone() + n0.clone();
        let d = a.clone() * d1.clone() + d0.clone();
        n0 = n1;
        d0 = d1;
        n1 = n.clone();
        d1 = d.clone();
        // Simplify fraction. Doing so here instead of at the end
        // allows us to get closer to the target value without overflows
        let g = Integer::gcd(&n1, &d1);
        if !g.is_zero() {
            n1 = n1 / g.clone();
            d1 = d1 / g.clone();
        }
        // Close enough?
        let (n_f, d_f) = match (<F as NumCast>::from(n), <F as NumCast>::from(d)) {
            (Some(n_f), Some(d_f)) => (n_f, d_f),
            _ => break,
        };
        if (n_f / d_f - val).abs() < max_error {
            break;
        }
        // Prevent division by ~0
        if f < epsilon {
            break;
        }
        q = f.recip();
    }
    // Overflow
    if d1.is_zero() {
        return None;
    }
    Some(Ratio::new(n1, d1))
}
fn approximate_float_unsigned < T , F > ( val : F , max_error : F , max_iterations : usize ) -> Option < Ratio < T > > where T : Integer + Bounded + NumCast + Clone , F : FloatCore + NumCast , { // Continued fractions algorithm // http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac if val < F :: zero ( ) || val . is_nan ( ) { return None ; } let mut q = val ; let mut n0 = T :: zero ( ) ; let mut d0 = T :: one ( ) ; let mut n1 = T :: one ( ) ; let mut d1 = T :: zero ( ) ; let t_max = T :: max_value ( ) ; let t_max_f = < F as NumCast > :: from ( t_max . clone ( ) ) ? ; // 1/epsilon > T::MAX let epsilon = t_max_f . recip ( ) ; // Overflow if q > t_max_f { return None ; } for _ in 0 .. max_iterations { let a = match < T as NumCast > :: from ( q ) { None => break , Some ( a ) => a , } ; let a_f = match < F as NumCast > :: from ( a . clone ( ) ) { None => break , Some ( a_f ) => a_f , } ; let f = q - a_f ; // Prevent overflow if ! a . is_zero ( ) && ( n1 > t_max . clone ( ) / a . clone ( ) || d1 > t_max . clone ( ) / a . clone ( ) || a . clone ( ) * n1 . clone ( ) > t_max . clone ( ) - n0 . clone ( ) || a . clone ( ) * d1 . clone ( ) > t_max . clone ( ) - d0 . clone ( ) ) { break ; } let n = a . clone ( ) * n1 . clone ( ) + n0 . clone ( ) ; let d = a . clone ( ) * d1 . clone ( ) + d0 . clone ( ) ; n0 = n1 ; d0 = d1 ; n1 = n . clone ( ) ; d1 = d . clone ( ) ; // Simplify fraction. Doing so here instead of at the end // allows us to get closer to the target value without overflows let g = Integer :: gcd ( & n1 , & d1 ) ; if ! g . is_zero ( ) { n1 = n1 / g . clone ( ) ; d1 = d1 / g . clone ( ) ; } // Close enough? let ( n_f , d_f ) = match ( < F as NumCast > :: from ( n ) , < F as NumCast > :: from ( d ) ) { ( Some ( n_f ) , Some ( d_f ) ) => ( n_f , d_f ) , _ => break , } ; if ( n_f / d_f - val ) . abs ( ) < max_error { break ; } // Prevent division by ~0 if f < epsilon { break ; } q = f . recip ( ) ; } // Overflow if d1 . is_zero ( ) { return None ; } Some ( Ratio :: new ( n1 , d1 ) ) }
No Unsigned constraint because this also works on positive integers and is called
like that, see above
No Unsigned constraint because this also works on positive integers and is called like that see above
val
F
max_error
F
max_iterations
usize