mirror of
https://github.com/cryb-to/cryb-to.git
synced 2024-12-24 05:21:07 +00:00
Make rolN / rorN safe for all counts.
The current version invokes undefined behavior when the count is negative, zero, or equal to or greater than the width of the operand. The new version masks the count to avoid these situations. Although branchless, it is relatively inefficient if the compiler does not recognize it and translate it to a rol or ror instruction. Empirical tests show that both clang and gcc get it right for constant counts, and recent versions of clang (but not gcc) get it right for variable counts as well. Note that our current code base has no instances of rolN / rorN with a variable count.
This commit is contained in:
parent
c556bc0aa8
commit
d2d16d26da
1 changed files with 3 additions and 3 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2012 The University of Oslo
|
* Copyright (c) 2012 The University of Oslo
|
||||||
* Copyright (c) 2012-2016 Dag-Erling Smørgrav
|
* Copyright (c) 2012-2017 Dag-Erling Smørgrav
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -40,11 +40,11 @@ CRYB_BEGIN
|
||||||
#define CRYB_ROL_ROR(N) \
|
#define CRYB_ROL_ROR(N) \
|
||||||
static inline uint##N##_t rol##N(uint##N##_t i, int n) \
|
static inline uint##N##_t rol##N(uint##N##_t i, int n) \
|
||||||
{ \
|
{ \
|
||||||
return (i << n | i >> (N - n)); \
|
return (i << (n & (N - 1)) | i >> (-n & (N - 1))); \
|
||||||
} \
|
} \
|
||||||
static inline uint##N##_t ror##N(uint##N##_t i, int n) \
|
static inline uint##N##_t ror##N(uint##N##_t i, int n) \
|
||||||
{ \
|
{ \
|
||||||
return (i << (N - n) | i >> n); \
|
return (i << (-n & (N - 1)) | i >> (n & (N - 1))); \
|
||||||
}
|
}
|
||||||
|
|
||||||
CRYB_ROL_ROR(8);
|
CRYB_ROL_ROR(8);
|
||||||
|
|
Loading…
Reference in a new issue