Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining a piecewise function (e.g. polynomial)

Tags:

c++

What's the best way to define a piecewise function in C++, needed for example when working with splines?

Example:

        f1(x) if x from [0, 5)
f(x) =  f2(x) if x from [5, 10)
        f3(x) if x from [10, 20)

My current approach looks like this:

class Function
{
    virtual double operator()( double x ) = 0;
}

class SomeFun : public Function
{
   // implements operator() in a meaningful way
}

class PiecewiseFunction : public Function
{
    // holds functions along with the upper bound of the interval
    // for which they are defined
    // e.g. (5, f1), (10, f2), (20, f3)
    std::map< double, Function* > fns;

    virtual double operator()( double x )
    {
       // search for the first upper interval boundary which is greater than x
       auto it = fns.lower_bound( x );
       // ... and evaluate the underlying function.
       return *(it->second)(x);
    }
}

This approach lacks of checking if x is in the overall bounds of the function, like [0, 20) in the example above, I know, and perhaps the naming is not the best (Function vs. std::function and so on).

Any ideas how to do that in a smarter way? The approach uses the property of the keys to be sorted in a std::map. It's not about efficiency, it's more about a clean design.

SLICING

Not exactly part of the question, but in one of the comments, slicing is mentioned, here you can read about it.

std::map unable to handle polymorphism?

I corrected this in my code above.

like image 529
wal-o-mat Avatar asked Mar 25 '26 06:03

wal-o-mat


1 Answers

An issue with the current design it doesn't allow for functions that are most naturally thought of as being undefined over certain intervals or points (like 0), but there are plenty of these, so it's another motivation for range-checking. Also Function needs to be replaced with Function* which necessitates some other changes in syntax.

class PiecewiseFunction : public Function
{
    //Holds function and interval
    std::map< std::pair<double,double>, Function* > fns;

   double operator()( double x )
   {
           auto iter = std::find_if(fns.cbegin(), fns.cend(), 
                             [=](const std::pair< std::pair<double,double>, Function*>& fn) 
                             {  
                                return x>=fn.first.first &&  x<fn.first.second; 
                             });

       if (iter == fns.end()) throw... //Or something
       return (*iter->second)(x);
    }
};
like image 123
Matt Phillips Avatar answered Mar 27 '26 18:03

Matt Phillips



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!