-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
BUG: Don't produce undefined behavior for a << b if b >= bitsof(a) #13739
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
Changes from 1 commit
24b2a2d
b12a869
e487889
ff11d01
fca077c
79d7bc2
6cf6ece
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
This avoids duplication, as suggested in review. The suffices `l`, `ull` etc are for consistency with `strtoull` and friends. `h` and `uhh` are inspired from the C99 printf specifiers.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -716,3 +716,44 @@ npy_@func@@c@(@type@ a, @type@ b) | |
return npy_@func@u@c@(a < 0 ? -a : a, b < 0 ? -b : b); | ||
} | ||
/**end repeat**/ | ||
|
||
/* Unlike LCM and GCD, we need byte and short variants for the shift operators, | ||
* since the result is dependent on the width of the type | ||
*/ | ||
/**begin repeat | ||
* | ||
* #type = byte, short, int, long, longlong# | ||
* #c = hh,h,,l,ll# | ||
*/ | ||
/**begin repeat1 | ||
* | ||
* #u = u,# | ||
* #is_signed = 0,1# | ||
*/ | ||
NPY_INPLACE npy_@u@@type@ | ||
npy_lshift@u@@c@(npy_@u@@type@ a, npy_@u@@type@ b) | ||
{ | ||
if (NPY_LIKELY((size_t)b < sizeof(a) * CHAR_BIT)) { | ||
return a << b; | ||
} | ||
else { | ||
return 0; | ||
} | ||
} | ||
NPY_INPLACE npy_@u@@type@ | ||
npy_rshift@u@@c@(npy_@u@@type@ a, npy_@u@@type@ b) | ||
{ | ||
if (NPY_LIKELY((size_t)b < sizeof(a) * CHAR_BIT)) { | ||
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. Do we want to deal with the possibility that 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. Not that currently the shift value is cast to unsigned and masked, at least on my hardware.
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 think there was a comment in the old/new code about that as well. Maybe we can push it off to another PR? That seems the easiest way forward? We can ignore the codecov failures. 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. xref gh-13898 |
||
return a >> b; | ||
} | ||
#if @is_signed@ | ||
else if (a < 0) { | ||
return (npy_@u@@type@)-1; /* preserve the sign bit */ | ||
} | ||
#endif | ||
else { | ||
return 0; | ||
} | ||
} | ||
/**end repeat1**/ | ||
/**end repeat**/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -699,6 +699,7 @@ BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED | |
* #ftype = npy_float, npy_float, npy_float, npy_float, npy_double, npy_double, | ||
* npy_double, npy_double, npy_double, npy_double# | ||
* #SIGNED = 1, 0, 1, 0, 1, 0, 1, 0, 1, 0# | ||
* #c = hh,uhh,h,uh,,u,l,ul,ll,ull# | ||
*/ | ||
|
||
#define @TYPE@_floor_divide @TYPE@_divide | ||
|
@@ -808,46 +809,30 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void | |
* which is undefined in C. | ||
*/ | ||
|
||
#define INT_left_shift_needs_clear_floatstatus | ||
#define UINT_left_shift_needs_clear_floatstatus | ||
|
||
NPY_NO_EXPORT NPY_GCC_OPT_3 void | ||
@TYPE@_left_shift@isa@(char **args, npy_intp *dimensions, npy_intp *steps, | ||
void *NPY_UNUSED(func)) | ||
{ | ||
BINARY_LOOP_FAST(@type@, @type@, | ||
if (NPY_LIKELY(in2 < sizeof(@type@) * CHAR_BIT)) { | ||
*out = in1 << in2; | ||
} | ||
else { | ||
*out = 0; | ||
} | ||
); | ||
BINARY_LOOP_FAST(@type@, @type@, *out = npy_lshift@c@(in1, in2)); | ||
|
||
#ifdef @TYPE@_left_shift_needs_clear_floatstatus | ||
// For some reason, our macOS CI sets an "invalid" flag here, but only | ||
// for some types. | ||
npy_clear_floatstatus_barrier((char*)dimensions); | ||
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 why this happens. Is our macOS run x86, or something else? Do we have a resident macOS expert? 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, was thinking about putting it in godbold, but it is quite a lot of code around it (and I am not sure it is likely to show anything in any case). @charris, I think I am good with this as is. But you had a look at it before and know 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. Could be a clang thing. |
||
#endif | ||
} | ||
|
||
#undef INT_left_shift_needs_clear_floatstatus | ||
#undef UINT_left_shift_needs_clear_floatstatus | ||
|
||
NPY_NO_EXPORT NPY_GCC_OPT_3 void | ||
@TYPE@_right_shift@isa@(char **args, npy_intp *dimensions, npy_intp *steps, | ||
void *NPY_UNUSED(func)) | ||
{ | ||
#if @SIGNED@ | ||
BINARY_LOOP_FAST(@type@, @type@, { | ||
if (NPY_LIKELY(in2 < sizeof(@type@) * CHAR_BIT)) { | ||
*out = in1 >> in2; | ||
} | ||
else if (in1 < 0) { | ||
*out = (@type@)-1; /* shift right preserves the sign bit */ | ||
} | ||
else { | ||
*out = 0; | ||
} | ||
}); | ||
#else | ||
BINARY_LOOP_FAST(@type@, @type@, { | ||
if (NPY_LIKELY(in2 < sizeof(@type@) * CHAR_BIT)) { | ||
*out = in1 >> in2; | ||
} | ||
else { | ||
*out = 0; | ||
} | ||
}); | ||
#endif | ||
BINARY_LOOP_FAST(@type@, @type@, *out = npy_rshift@c@(in1, in2)); | ||
} | ||
|
||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.