I find that the fact that the functions min and max have the same name as the variables min and max increases cognitive load which makes it harder to think about it. I find the following easier to read : Math.min(Math.max(num, lower_bound), upper_bound)
That doesn't really help. "Max" to enforce a "lower bound" is briefly halting.
But "min(-, constant_x)" should be thought of as "at most constant_x" and similarly for max. Maybe there's a way to make it more expressive.