Polynomial implementation

Just sharing my implementation of polynomial:

/// Evaluate a polynomial with coefficients `coeffs` at `x`.
/// 
/// coeffs are in decreasing order.
/// 
/// For example:
/// coeffs &.{1.0, 2.0, -3.0} is polynomial y = 1.0*x^2 + 2.0*x - 3.0.
/// 
/// Special cases:
/// - when coeffs.len == 0, always returns zero.
pub fn poly(coeffs: []const f64, x: f64) f64 {
    // Horner's method.
    // https://en.wikipedia.org/wiki/Horner%27s_method
    var result: f64 = 0;
    for (coeffs) |coeff| {
        result = result * x + coeff;
    }
    return result;
}

test poly {
    try std.testing.expectEqual(2.0, poly(&.{ 2.0, 0.0 }, 1.0));
    try std.testing.expectEqual(4.0, poly(&.{ 2.0, 0.0 }, 2.0));
    try std.testing.expectEqual(21.0, poly(&.{ 1.0, 1.0, 1.0 }, 4.0));
}

Surprisingly easy! Would you do it differently?

3 Likes

This is the right way for evaluating a polynomial. Of course, if you need to support more operations (derivation, integration, symbolic manipulation), you need more.

You can try and use @mulAdd buildin. It should give a bit more precision. Not sure how much but maybe fun to calculate it.

p.s. i checked but for some reason it produced less precise results. Compiler Explorer i probably doing something wrong.

p.s 2: It seems I was just unlucky its two times more precise on average Compiler Explorer

1 Like

Maybe I would reverse storage and computation in such a way that the i-th coefficient means x^i.
Your example polynom would be represented by &.{-3, 2, 1} then.
Of course that’s just a question of taste.