Design question SafeFloat
Hi, I'm working in simplifying safe_float to prepare it for future review. For now I'm focusing in a C++17 compatible version. Currently safefloat receives 2 template parameters: template<typename FP, typename P> class safe_float ... Where FP is the floating point value being made "safe", float, double, long double ... and P is a Policy of what to check and how to react. The how to react is a class that I pass by template parameter to the Policy. So, policy looks like: template<typename R> class policy_x .... I had a very complicated way of producing those policies, I used many TMP tricks so the logic stays in the policy and combines, but now that if-constexpr is available it may not make sense to take that path anymore. And, I see it may be better to simplify as much as possible. So, I'm thiking in make policy like a "config" description and put if constexprs in the safe_float class to decide what to do based in that. I want a bad policy to fail execution. I'm wondering what is the best approach for defining that "config-like" policy. A policy check is a bidimensional matrix of the operation affected and the flags considered (FE_ENV flags). For example, I want a policy to tell something like "check overflow in additions and underflow in division". These are the options I'm considering 1) define typenames for each flag and assign them tuple of affected operations class addition; class division; class multiplication; class subtraction; template<typename R> struct policy_x { using reporter=R; using overflow=tuple<addition>; using underflow=tuple<division>; using invalid=tuple<>; using inexact=tuple<>; }; 2) define typename by operation, passing class with constexprs of flags being evaluated struct empty_check{ static constexpr bool check_overflow=false; static constexpr bool check_underflow=false; static constexpr bool check_invalid=false; static constexpr bool check_inexact=false; }; struct check_overflow : public empty_check { static constexpr bool check_overflow=true; }; struct check_underflow : public empty_check { static constexpr bool check_underflow=true; }; template<typename R> struct policy_x { using reporter=R; using addition=check_overflow; using subtraction=empty_check; using multiplication=empty_check; using division=check_underflow; }; 3) similar to 2, but using true_type, and false_type in place of constexpr variables. struct empty_check{ using check_overflow=false_type; using check_underflow=false_type; using check_invalid=false_type; using check_inexact=false_type; }; struct check_overflow : public empty_check { using check_overflow=true_type; }; struct check_underflow : public empty_check { using check_underflow=true_type; }; template<typename R> struct policy_x { using reporter=R; using addition=check_overflow; using subtraction=empty_check; using multiplication=empty_check; using division=check_underflow; 4) other options? Thanks for any comments in advance. Damian
On 7/26/18 8:25 PM, Damian Vicino via Boost wrote:
Hi, I'm working in simplifying safe_float to prepare it for future review.
For now I'm focusing in a C++17 compatible version.
Currently safefloat receives 2 template parameters:
template<typename FP, typename P> class safe_float ...
Where FP is the floating point value being made "safe", float, double, long double ... and P is a Policy of what to check and how to react.
It might be helpful to look at how safe numerics does it. Robert Ramey
Hi Robert, Thanks for the comment, I started following whats on safe_numerics, but I feel it gets too complicated to use in the case of floating point where there is so many policy combinations I want to allow. I got the feeling something easier can be built to handle this particular case. However, I'm exploring alternatives, if I cannot find a simple elegant solution I will go back to similar approach to the one used in safe_numerics. 2018-07-27 10:05 GMT-04:00 Robert Ramey via Boost <boost@lists.boost.org>:
On 7/26/18 8:25 PM, Damian Vicino via Boost wrote:
Hi, I'm working in simplifying safe_float to prepare it for future review.
For now I'm focusing in a C++17 compatible version.
Currently safefloat receives 2 template parameters:
template<typename FP, typename P> class safe_float ...
Where FP is the floating point value being made "safe", float, double, long double ... and P is a Policy of what to check and how to react.
It might be helpful to look at how safe numerics does it.
Robert Ramey
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost
AMDG On 07/26/2018 09:25 PM, Damian Vicino via Boost wrote:
I'm working in simplifying safe_float to prepare it for future review.
For now I'm focusing in a C++17 compatible version.
Currently safefloat receives 2 template parameters:
template<typename FP, typename P> class safe_float ...
Where FP is the floating point value being made "safe", float, double, long double ... and P is a Policy of what to check and how to react.
<snip> These are the options I'm considering
1) define typenames for each flag and assign them tuple of affected operations
class addition; <snip>
template<typename R> struct policy_x { using reporter=R; using overflow=tuple<addition>; <snip> };
2) define typename by operation, passing class with constexprs of flags being evaluated
struct empty_check{ static constexpr bool check_overflow=false; <snip> };
<snip>
3) similar to 2, but using true_type, and false_type in place of constexpr variables. <snip> 4) other options?
What about doing this the old-fashioned way: constexpr check_policy_t empty_check = 0; constexpr check_policy_t check_underflow = 0x1; constexpr check_policy_t check_overflow = 0x2; ... // with a bit of syntactic sugar: struct operation_id { check_policy_t offset; constexpr check_policy_t operator=(check_policy_t value) const { return offset * value; } }; constexpr operation_id addition=0x1, subtraction=0x100, multiplication=0x10000 ...; // Usage: addition=check_overflow|subtraction=empty_check In Christ, Steven Watanabe
Hi Steven, Thats kind of what I would like to have, I was wondering of something like that using "enum class" for type_safety would work. I will give it a try and see how it goes. Thanks for the comment. Damian 2018-07-27 14:38 GMT-04:00 Steven Watanabe via Boost <boost@lists.boost.org> :
AMDG
On 07/26/2018 09:25 PM, Damian Vicino via Boost wrote:
I'm working in simplifying safe_float to prepare it for future review.
For now I'm focusing in a C++17 compatible version.
Currently safefloat receives 2 template parameters:
template<typename FP, typename P> class safe_float ...
Where FP is the floating point value being made "safe", float, double, long double ... and P is a Policy of what to check and how to react.
<snip> These are the options I'm considering
1) define typenames for each flag and assign them tuple of affected operations
class addition; <snip>
template<typename R> struct policy_x { using reporter=R; using overflow=tuple<addition>; <snip> };
2) define typename by operation, passing class with constexprs of flags being evaluated
struct empty_check{ static constexpr bool check_overflow=false; <snip> };
<snip>
3) similar to 2, but using true_type, and false_type in place of constexpr variables. <snip> 4) other options?
What about doing this the old-fashioned way:
constexpr check_policy_t empty_check = 0; constexpr check_policy_t check_underflow = 0x1; constexpr check_policy_t check_overflow = 0x2; ...
// with a bit of syntactic sugar: struct operation_id { check_policy_t offset; constexpr check_policy_t operator=(check_policy_t value) const { return offset * value; } };
constexpr operation_id addition=0x1, subtraction=0x100, multiplication=0x10000 ...;
// Usage: addition=check_overflow|subtraction=empty_check
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
participants (3)
-
Damian Vicino
-
Robert Ramey
-
Steven Watanabe