Function roots::find_roots_linear

source ·
pub fn find_roots_linear<F: FloatType>(a1: F, a0: F) -> Roots<F>
Expand description

Solves a linear equation a1*x + a0 = 0.

Examples

use roots::Roots;
use roots::find_roots_linear;

// Returns Roots::No([]) as '0*x + 1 = 0' has no roots;
let no_root = find_roots_linear(0f32, 1f32);
assert_eq!(no_root, Roots::No([]));

// Returns Roots::Two([0f64]) as '1*x + 0 = 0' has the root 0
let root = find_roots_linear(1f64, 0f64);
assert_eq!(root, Roots::One([0f64]));

// Returns Roots::One([0f32]) as 0 is one of roots of '0*x + 0 = 0'
let zero_root = find_roots_linear(0f32, 0f32);
assert_eq!(zero_root, Roots::One([0f32]));
Examples found in repository?
src/numerical/polynom.rs (line 447)
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
pub fn find_roots_sturm<F>(a: &[F], convergency: &mut dyn Convergency<F>) -> Vec<Result<F, SearchError>>
where
    F: FloatType,
{
    match a.len() {
        0 => Vec::new(),
        1 => find_roots_linear(F::one(), a[0]).as_ref().iter().map(|s| Ok(*s)).collect(),
        2 => find_roots_quadratic(F::one(), a[0], a[1])
            .as_ref()
            .iter()
            .map(|s| Ok(*s))
            .collect(),
        3 => find_roots_cubic(F::one(), a[0], a[1], a[2])
            .as_ref()
            .iter()
            .map(|s| Ok(*s))
            .collect(),
        _ => {
            let mut result = Vec::new();
            let derivative_polynom = a.derivative_polynom();
            match find_root_intervals(a, &derivative_polynom, convergency) {
                Ok(root_intervals) => {
                    for root_interval in &root_intervals {
                        if let Ok(mut narrowed) = narrow_down(&root_interval, a, &derivative_polynom, convergency) {
                            result.push(a.find_root(&mut narrowed, convergency));
                        }
                    }
                }
                Err(error) => {
                    result.push(Err(error));
                }
            }
            result
        }
    }
}
More examples
Hide additional examples
src/analytical/quadratic.rs (line 51)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
pub fn find_roots_quadratic<F: FloatType>(a2: F, a1: F, a0: F) -> Roots<F> {
    // Handle non-standard cases
    if a2 == F::zero() {
        // a2 = 0; a1*x+a0=0; solve linear equation
        super::linear::find_roots_linear(a1, a0)
    } else {
        let _2 = F::from(2i16);
        let _4 = F::from(4i16);

        // Rust lacks a simple way to convert an integer constant to generic type F
        let discriminant = a1 * a1 - _4 * a2 * a0;
        if discriminant < F::zero() {
            Roots::No([])
        } else {
            let a2x2 = _2 * a2;
            if discriminant == F::zero() {
                Roots::One([-a1 / a2x2])
            } else {
                // To improve precision, do not use the smallest divisor.
                // See https://people.csail.mit.edu/bkph/articles/Quadratics.pdf
                let sq = discriminant.sqrt();

                let (same_sign, diff_sign) = if a1 < F::zero() {
                    (-a1 + sq, -a1 - sq)
                } else {
                    (-a1 - sq, -a1 + sq)
                };

                let (x1, x2) = if same_sign.abs() > a2x2.abs() {
                    let a0x2 = _2 * a0;
                    if diff_sign.abs() > a2x2.abs() {
                        // 2*a2 is the smallest divisor, do not use it
                        (a0x2 / same_sign, a0x2 / diff_sign)
                    } else {
                        // diff_sign is the smallest divisor, do not use it
                        (a0x2 / same_sign, same_sign / a2x2)
                    }
                } else {
                    // 2*a2 is the greatest divisor, use it
                    (diff_sign / a2x2, same_sign / a2x2)
                };

                // Order roots
                if x1 < x2 {
                    Roots::Two([x1, x2])
                } else {
                    Roots::Two([x2, x1])
                }
            }
        }
    }
}