Implementing piecewise linear functions I need to implement piecewise linear functions (this is not homework, it is for my own personal project). However, I have been having difficulties to get it right. Below, I describe the characteristics of the function, operations, and what I have tried so far.
Function: It is defined by linear segments. It may be discontinuous, and some segments may actually be points rather than lines. The function can be any mix of increasing or decreasing parts. The domain is completely bounded by a box with $x \in [0,M]$ and $y \in [0,M]$. The maximum value $M$ is always defined (e.g., never $\infty$).
Operations: The operations I need to perform are fairily simple in mathematical terms. I need:

Shift in $x$ and $y$ (easy)
Shrink/expand pieces (always at the end or start of the function, never in the middle)
Take the maximum between two piecewise linear functions $f(x)$ and $g(x)$ considering that all pieces are within the domains of the box ($[0,M]$) but the actual domain of the functions may not be the same (this has been tricky!)

What I have tried: So far I tried to implement the function as a series of linear pieces defined by their starting starting $(x_0,y_0)$ and ending ($x_1,y_1)$ coordinates. A function then is simply an array of such pieces. However, defining the maximum operation has been quite difficult for me, specially when there are discontinuities and the domain of the two functions $f$ and $g$ are different.
I know this may look more like a &quot;help me with my code&quot; question, but all I wanted was some guides in how to better implement such functions and operations. For example, is my current strategy good? Is there a description of an algorithm to take the maximum of two functions somewhere in the internet? I have tried Stack, Git, and Googling, but have not found any good result to help me with that. I guess either it is too easy and I just don't see it, or it is too obscure and few people do it.
NOTE: I really don't care about operation complexity right now. As long as it is polynomial it is good for me.
A similar question has been asked before, that may answer your question, here. Quoting the answer:

This is basically an instance of the line segment intersection problem.  One standard approach is to use a sweep line algorithm.  For instance, the Bentley-Ottman algorithm would be a reasonable choice, and is not too difficult to implement.
At each iteration of the algorithm, we have some value of $x$, and we calculate what is the next largest value of $x$ where something interesting happens.  Here, &quot;something interesting&quot; is either (1) two pieces intersect each other at a point, or (2) we reach the end of one of the current pieces.  Then we advance $x$ to this next value.
At each iteration, we keep track of which pieces are currently active (i.e., $x$ is within the domain of that piece) and the order of the pieces, ordered by their $y$-value for that particular value of $x$.  Store them in sorted order, sorted by $y$-value.

So, in some sense it is a matter of proper abstraction: you need to implement a function
 something_interesting_happens(real x, function f1, function f2)

the function should return, given an x-value x, the next x-value where either an intersection occurs or the start or end of a line segment occurs. With this functionality out of the way, to return your maximum function, you just iterate over all the interesting x-values, starting from 0 and repeatedly using something_interesting_happens to get the next interesting x-value. It is a bit simpler for you as you are looking to only maximize two functions, and in the above quote they consider maximizing $n$ functions.
The final issue is that you need to settle on a representation for your piecewise linear functions. As plop points out in the comments, your current representation has an issue: it can't represent discontinuous functions.
Here's one possibility, for simplicity:

Define a piece to be either an open line segment, represented by a pair of points $(x_1, y_1), (x_2, y_2)$, or a single point, represented by $(x_1, y_1)$. This gives you sufficient expressiveness to have both closed and open line segments, without worrying about representing open and closed line segments separately. In particular, a closed line segment will be an open line segment, plus points at both of the endpoints.

It will be probably useful to have some functions on pieces, such as:
intersect(piece p1, piece p2)

to indicate if two pieces intersect in the $x$-values they consider, and
less-than(piece p1, piece p2)

which means that p1 and p2 don't intersect, and p1 is before p2.

Represent a piecewise linear function by a (possibly empty) sequence of pieces. The pieces should be sorted, so that less-than(p1, p2) holds for all pieces in the list p1 and p2 where p1 occurs before than p1.