Search code examples
cpolynomials

Safe variable length return in C


I want to make a function that returns the roots of a polynomial, as part of a basic exercise. Is there a safe way to return a variable number of elements (0, 1 or 2, in this case), i.e. making sure the receiver knows how many items were returned so they can avoid a segfault ?

This is arguably more a question of API design than pure programming, the roots themselves are trivial but getting them there safely puzzles me.


Solution

  • The case of a polynomial is special, as the caller knows how many roots there are at maximum. So the caller knows how much memory is needed to safely store the return value.

    In this case it is easiest to let the caller pass a buffer to your function and store the roots in there. Your roots function would then only return the number of roots it found.

    The other case (where the function returns freshly allocated memory) is way more complicated, and should be avoided if possible. You would introduce strong dependencies to your function (memory allocator) and this way fix the memory allocation schema. This is quite restraining (and unnecessary for your and perhaps many other use-cases). [1]

    This could work:

    int roots( double roots_out[], double coefs_in[], int ord)
    

    This would be better (less error prone, even if one demands roots_out must have ord-1 elements)

    int roots( double roots_out[], int nroots_max, double coefs_in[], int ord)
    

    ord is the order of the polynomial (not the degree) and indicates how many elements there are in coefs_in

    Note that there are still some questions left:

    • What to return if there are infinitely many roots? (zero polynomial?)
    • What to do if the buffer is too small? (Your solver may generate duplicate roots due to numerical inaccuracies. In other words nroots_max = ord-1 may be sae from mathematical point of view, but not numerically)

    [1]: Also even if you may think this way one would save some memory as the number of roots may be less than the degree, this comes with a caveat. During root calculation one needs a big buffer anyway as the number of roots is not known beforehand. So memory saving is a two step process anyway, and, in my opinion, this task should be delegated to the caller. This is most efficient I guess.