
On Mon, Dec 8, 2008 at 9:12 AM, Robert Kawulak <robert.kawulak@gmail.com> wrote:
So what's the conclusion in the context of separation of invariant and the test? That we may end up having bounded float with value a bit greater than the upper bound, but that's fine, because the difference will never exceed some user-defined epsilon? Is the epsilon constant? The "delta" (difference between extended and truncated value) may have a very big value for big numbers and very small for small ones, so epsilon should rather be scaled according to the magnitude of compared numbers.
I know little about floats and what the values of the deltas are and how they depend on the value of the float, but: The invariant is still: x < y The exact outcome depends on the policy. If the policy forces truncation and retests, there is no epsilon in the outcome either (it only exists in the test).
Did I get things right so far?
I think so.
Then why complicate things with epsilon at all? If we allow for values outside of the bounds but only a "delta" away, we may simply stay with the "<" comparison. Even better, I would love to see a solution to force truncation of a value, so the comparisons are always performed on truncated values and we may stay with the "test == invariant" approach.
If you are sticking with test == invariant just for the sake of test == invariant (rather than a lack of time to investigate and document the other case), I think you are settling to sell your library for way shorter than you can. And like I've pointed out before, there is no reason why you shouldn't make this a focus of the library and treat it specially (the test==invariant case provides some really nice benefits, like you can test for the invariant exactly and assert after the policy check). You can reserve the word "constraint" for when constraint=test=invariant. You can even do this: constrained_value<T, constraint, policy> expands to what_is_now_constrained_value_minus_the_assert<T, constraint, always_assert_after<policy> >
And another issue is NaN -- it breaks the strict weak ordering, so it may or may not be allowed as a valid value depening on the direction of comparison ("<" or ">"). I guess NaN should not be an allowed value in any case, but I have no idea yet how to enforce this without float-specific implementation of within_bounds.
I haven't taken a close look at bounded values, I'm just thinking of them as a specific case of constrained values. What is your invariant here? That ((min <= value) && (value <= max)) or that !((value < min) || (max < value))? Why do you need a strict weak ordering for either one? I believe NaN will fail the first test but pass the second one - if that is true, why is NaN a problem if you use the first test? (sorry if I'm missing something, like I said I'm not well versed in the details of floats) Best, Stjepan