[rational] Over/underflow checked update ready for comments

Le 06/09/12 04:28, Dan Searles a ?crit :>Le 06/09/12 04:28, Dan Searles a ?crit :
For those interested in the rational number class, see: https://svn.boost.org/svn/boost/sandbox/rational
Requesting comments on the code, and review for inclusion in the next release.
Hi,
the enum type could follow the one defined in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3352.html "When an overflow does occur, the desirable behavior depends on the application, so programmers may specify the overflow mode with a value of type |enum class overflow|. The possible values are:
|impossible| Programmer analysis of the program has determined that overflow cannot occur. Uses of this mode should be accompanied by an argument supporting the conclusion. |undefined| Programmers are willing to accept undefined behavior in the event of an overflow. |modulus| The assigned value is the dynamic value mod the range of the variable. This mode makes sense only with unsigned numbers. It is useful for angular measures. |saturate| If the dynamic value exceeds the range of the variable, assign the nearest representable value. |exception| If the dynamic value exceeds the range of the variable, throw an exception of type |std::overflow_error|. 'impossible' and 'undefined' are effectively the same thing, and equivalent to the 'no check' currently implemented. Yes and not. Maybe from the point of view of the library, but this is a useful information from the user point of view.
So for the 'impossible' case, what should the library do when there is an over/underflow?
'modulus' makes more sense for the fixed point class that it's being described for than rational numbers. I'm not sure a useful definition can even be made for rationals. You are right. modulus for rational has not a clear sense. 'Saturate' sounds like it might be useful, but gets problematic quickly when there is under/overflow within the largest/smallest range limits. Could you clarify?
'Saturate' implies returning the max value when the computed result is larger than can be represented, and returning the min value when the computed is smaller (more negative) than can be represented, but rationals can underflow between those extremes. For example, what is 1/2 * 1/maxint?
The point is that if a result of a calculation is not exactly representable, you will get an exception to notify you. And of course 'exception' is in the new implementation for just that purpose. A user can be interested in overflow check without exceptions. The saturate policy should be a good replacement in context where exceptions are not allowed.
I can't quite see a point for there being 3 possible results when there is an overflow: exception, undefined, and ???. Maybe if '???' is a wrong value, but as close as possible? If you don't need the exact answers, float or double would probably be better. Returning zero for ??? might work.
Anyway, you should replace the CamelCase use in the definition of this new enumeration. I think that basing your definition on the preceding one could be acceptable.
Which ones? Please suggest the names you think would be appropriate. (I tried to pick names that had a low probability of ever being used anywhere else. Common single dictionary words are probably not good.)
BTW, I have no access to the link for the examples and the test. I have not changed those files. The existing examples and test are still valid for the original non-checked case. For the checked case, I have tests which run for hours. The tests for rational instantiated with signed char is exhaustive (there are only so many normalized values. Pairing up each value with every other value on the binary operators doesn't result in much more that 2**32 combinations). For short/int/long long, sets of interesting values are created, and each value is paired up with every other value in the set. I can provide the test drivers if anyone is interested.
I was interested by the examples and test using the new facility. Could you commit them in the sandbox, please?
Uploaded the test driver to: https://svn.boost.org/svn/boost/sandbox/rational/Test_Rationals
Best, Vicente
Thanks Dan Searles

Le 07/09/12 02:53, Dan Searles a écrit :
Le 06/09/12 04:28, Dan Searles a ?crit :>Le 06/09/12 04:28, Dan Searles a ?crit :
For those interested in the rational number class, see: https://svn.boost.org/svn/boost/sandbox/rational
Requesting comments on the code, and review for inclusion in the next release.
Hi,
the enum type could follow the one defined in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3352.html "When an overflow does occur, the desirable behavior depends on the application, so programmers may specify the overflow mode with a value of type |enum class overflow|. The possible values are:
|impossible| Programmer analysis of the program has determined that overflow cannot occur. Uses of this mode should be accompanied by an argument supporting the conclusion. |undefined| Programmers are willing to accept undefined behavior in the event of an overflow. |modulus| The assigned value is the dynamic value mod the range of the variable. This mode makes sense only with unsigned numbers. It is useful for angular measures. |saturate| If the dynamic value exceeds the range of the variable, assign the nearest representable value. |exception| If the dynamic value exceeds the range of the variable, throw an exception of type |std::overflow_error|. 'impossible' and 'undefined' are effectively the same thing, and equivalent to the 'no check' currently implemented. Yes and not. Maybe from the point of view of the library, but this is a useful information from the user point of view. So for the 'impossible' case, what should the library do when there is an over/underflow? The idea is that for impossible you don't need to avoid overflow check as the user told you it is impossible. undefined let the library choose the behavior as it is undefined.
'modulus' makes more sense for the fixed point class that it's being described for than rational numbers. I'm not sure a useful definition can even be made for rationals. You are right. modulus for rational has not a clear sense. 'Saturate' sounds like it might be useful, but gets problematic quickly when there is under/overflow within the largest/smallest range limits. Could you clarify? 'Saturate' implies returning the max value when the computed result is larger than can be represented, and returning the min value when the computed is smaller (more negative) than can be represented, but rationals can underflow between those extremes. For example, what is 1/2 * 1/maxint?
Good point. I had not though about this case. That depends on where you apply the overflow logic. If it is applied to the Integral type, as I will expect, saturate will give you 2/maxint. Which I agree is not completly satisfactory. I don't know if you could take in account also a rounding policy. The result of this expression could depend also on the rounding policy. I don't know how complex could be to implement it.
The point is that if a result of a calculation is not exactly representable, you will get an exception to notify you. And of course 'exception' is in the new implementation for just that purpose. A user can be interested in overflow check without exceptions. The saturate policy should be a good replacement in context where exceptions are not allowed. I can't quite see a point for there being 3 possible results when there is an overflow: exception, undefined, and ???. impossible: don't check for overflow, saturate: as you described above Maybe if '???' is a wrong value, but as close as possible? Yes rounding should applies here. If you don't need the exact answers, float or double would probably be better. The user can always cast to float or double so that this behavior seems not necessary. Returning zero for ??? might work. This will depend on the rounding policy. Anyway, you should replace the CamelCase use in the definition of this new enumeration. I think that basing your definition on the preceding one could be acceptable. Which ones? Please suggest the names you think would be appropriate. (I tried to pick names that had a low probability of ever being used anywhere else. Common single dictionary words are probably not good.)
Naming is often subject to conflicts. Boost use lowercase namming convention. So your enumeration enum RationalChecktype {RationalNoChecking, RationalCheckforOverflow}; should be enum rational_checktype {rational_no_checking, rational_check_for_overflow}; As we have scoped enums now the preceding could be renamed to enum class rational_checktype {no_checking, check_for_overflow}; Note that Boost provides two scoped enums emulations in the file boost/detail/scoped_enum_emulation.hpp. The names I would propose are, overflow and rounding enum class rational_overflow {impossible, undefined, saturate, exception}; enum class rational_rounding {undefined, exception, towards_zero, ...}; As I said above I have not think too much about all this, and I'm surely trying to apply the fixed_point design to rationals, which could surely be the wrong thing.
BTW, I have no access to the link for the examples and the test. I have not changed those files. The existing examples and test are still valid for the original non-checked case. For the checked case, I have tests which run for hours. The tests for rational instantiated with signed char is exhaustive (there are only so many normalized values. Pairing up each value with every other value on the binary operators doesn't result in much more that 2**32 combinations). For short/int/long long, sets of interesting values are created, and each value is paired up with every other value in the set. I can provide the test drivers if anyone is interested. I was interested by the examples and test using the new facility. Could you commit them in the sandbox, please?
Uploaded the test driver to: https://svn.boost.org/svn/boost/sandbox/rational/Test_Rationals
Thanks, I will take a look soon. Vicente
participants (2)
-
Dan Searles
-
Vicente J. Botet Escriba