We need to manipulate piecewise constant floating point-valued (double-precision) functions of integers (f: I->R). These are to be implemented according to the interfaces defined in the attached headers (see classes Function and PiecewiseConstant, ignore Linear, Polynomial, RationalFunction).
Exploiting operator overloading in C++, we want to manipulate PiecewiseConstant objects, add and substract them transparently as in:
double a: ConstantPiece b; PiecewiseConstant c; PiecewiseConstant d; d = a + b - c;
Our estimate is that there are 28 member functions to implement, this estimate can be off by +- 10%.
The good news is that there is a lot of boilerplate code !
There are two bad new though.
First one is: the same piecewise constant can be represented in different ways. For example a piecewise constant function with value -1.0 for strictly negative integers and +1.0 for positive integers can be represente as:
ConstantPiece(INT_MIN, INT_MAX, 1.0)+ConstantPiece(INT_MIN, -1, -2.0)
ConstantPiece(INT_MIN, -1, 1.0)-ConstantPiece(0, INT_MAX, -1.0)
We call the second representation canonical, i.e.:
- the pieces are sorted in order of strictly increasing min_ field
- and the domain of the pieces have null intersection
NOTE: it is the responsibility of the member functions that change the pieces to restore the canonical representation by calling the normalize member function if necessary !
Second bad new is: when two piecewise constant functions are added or subtracted, if their pieces have different boundaries, you need to break up and create new pieces in the destination function. And make sure the final result is in canonical form !
We want to use a TTD (Test Driven Development) approach. We have written a basic suite of tests, with 4 test functions TODO (see file TestPiecewiseConstant.cc). The basic idea of the tests is that the piecewise functions can be evaluated for any value of the integer independent variable, using their operator(). Therefore all operations can be checked by brute-force iterating over a suitable range of integer values, and comparing the results with a manual implementation.
Before acceptance, the tests will have to cover all implemented functions (100% coverage). Writing the tests is not the responsibility of the coder, but in accordance to the TDD methodology, the coder is advised to test at least the basic functionality. If necessary, we will write the rest of the tests to reach the complete coverage.