-
Notifications
You must be signed in to change notification settings - Fork 403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid implicit conversions for bitwise operators #2708
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,6 +81,43 @@ namespace xt | |
} \ | ||
} | ||
|
||
// This functor avoids implicit conversions of small integral types to 'int' | ||
// by returning the same type instead of 'auto'. | ||
#define UNARY_BITWISE_OPERATOR_FUNCTOR(NAME, OP) \ | ||
struct NAME \ | ||
{ \ | ||
template <class A1> \ | ||
constexpr std::decay_t<A1> operator()(const A1& arg) const \ | ||
{ \ | ||
return OP arg; \ | ||
} \ | ||
template <class B> \ | ||
constexpr auto simd_apply(const B& arg) const \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question out of ignorance: Why don't you use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be great, yes! |
||
{ \ | ||
return OP arg; \ | ||
} \ | ||
} | ||
|
||
// This functor avoids implicit conversions of small integral types to 'int' | ||
// by returning the largest type instead of 'auto'. | ||
#define BINARY_BITWISE_OPERATOR_FUNCTOR(NAME, OP) \ | ||
struct NAME \ | ||
{ \ | ||
template <class T1, class T2> \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existing |
||
constexpr std:: \ | ||
conditional_t<(sizeof(std::decay_t<T1>) > sizeof(std::decay_t<T2>)), std::decay_t<T1>, std::decay_t<T2>> \ | ||
operator()(T1&& arg1, T2&& arg2) const \ | ||
Comment on lines
+107
to
+109
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have no idea what happens here: the opening and closing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tricky part of this expression is that one of the The first argument to The other arguments to Combining two equally-sized unsigned and signed types currently yields the second type, e.g, combining For other operations, like addition or subtraction, I can imagine we have to follow the C++ rules closer. I found the following results when using
Perhaps the following stategy will work for all binary operations:
Code similar to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you so much for the clarification!! I'm just not sure about the latter case: stripping the signedness is dangerous here no? |
||
{ \ | ||
using xt::detail::operator OP; \ | ||
return (std::forward<T1>(arg1) OP std::forward<T2>(arg2)); \ | ||
} \ | ||
template <class B> \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't you allow the two types here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existing |
||
constexpr auto simd_apply(const B& arg1, const B& arg2) const \ | ||
{ \ | ||
return (arg1 OP arg2); \ | ||
} \ | ||
} | ||
|
||
namespace detail | ||
{ | ||
DEFINE_COMPLEX_OVERLOAD(+); | ||
|
@@ -112,10 +149,10 @@ namespace xt | |
BINARY_OPERATOR_FUNCTOR(logical_or, ||); | ||
BINARY_OPERATOR_FUNCTOR(logical_and, &&); | ||
UNARY_OPERATOR_FUNCTOR(logical_not, !); | ||
BINARY_OPERATOR_FUNCTOR(bitwise_or, |); | ||
BINARY_OPERATOR_FUNCTOR(bitwise_and, &); | ||
BINARY_OPERATOR_FUNCTOR(bitwise_xor, ^); | ||
UNARY_OPERATOR_FUNCTOR(bitwise_not, ~); | ||
BINARY_BITWISE_OPERATOR_FUNCTOR(bitwise_or, |); | ||
BINARY_BITWISE_OPERATOR_FUNCTOR(bitwise_and, &); | ||
BINARY_BITWISE_OPERATOR_FUNCTOR(bitwise_xor, ^); | ||
UNARY_BITWISE_OPERATOR_FUNCTOR(bitwise_not, ~); | ||
BINARY_OPERATOR_FUNCTOR(left_shift, <<); | ||
BINARY_OPERATOR_FUNCTOR(right_shift, >>); | ||
BINARY_OPERATOR_FUNCTOR(less, <); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: is the name
A1
something that was used in similar bits of codes. If not, I would find e.g.T
more logical (or evenA
orE
which is used in many places)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing
UNARY_OPERATOR_FUNCTOR
indeed also usesA1
. I'll happily change both toT
,A
, orE
.