Closed
Bug 1193600
Opened 10 years ago
Closed 9 years ago
Add IsPowerOfTwo and Clamp to MFBT
Categories
(Core :: MFBT, defect)
Core
MFBT
Tracking
()
RESOLVED
FIXED
mozilla43
Tracking | Status | |
---|---|---|
firefox43 | --- | fixed |
People
(Reporter: jgilbert, Assigned: jgilbert)
References
Details
Attachments
(2 files)
1.06 KB,
patch
|
Waldo
:
review+
Waldo
:
feedback+
|
Details | Diff | Splinter Review |
4.80 KB,
patch
|
Waldo
:
review+
|
Details | Diff | Splinter Review |
We use these a bunch in WebGL, and often end with with a couple different functions for them.
Let's just standardize them into MFBT.
Attachment #8646717 -
Flags: review?(jwalden+bmo)
Comment 1•10 years ago
|
||
Comment on attachment 8646717 [details] [diff] [review]
0015-Add-IsPowerOfTwo-and-Clamp-to-mfbt-MathAlgorithms.h.patch
Review of attachment 8646717 [details] [diff] [review]:
-----------------------------------------------------------------
Needs some tests in the appropriate test file, or in TestMathAlgorithms.cpp if it doesn't exist yet -- for all the usual boundary cases, and for the cases where compiler warnings might rear.
::: mfbt/MathAlgorithms.h
@@ +504,5 @@
> + * Returns true if |x| is a power of two.
> + * Zero is not an integer power of two. (-Inf is not an integer)
> + */
> +inline bool
> +IsPowerOfTwo(size_t x)
Maybe preferable:
template<typename T>
inline bool
IsPowerOfTwo(T t)
{
static_assert(mozilla::IsUnsigned<T>::value, "only unsigned types supported");
return x && (x & (x - 1)) == 0;
}
so that use with signed values will fail to compile, not just convert into modulo possibly-nonsense.
@@ +512,5 @@
> +
> +template<typename T>
> +inline T
> +Clamp(const T aValue, const T aMin, const T aMax)
> +{
static_assert(mozilla::IsIntegral<T>::value, "only integral types supported");
Specifically, I'd really like to exclude floating point types here, because such users might or might not want to order -0/+0 here, and I'd rather not impose the cost on every user when only some need it.
If you want it specifically for that case (and that wouldn't surprise me), let's discuss Thursday when I'm back in the office.
@@ +515,5 @@
> +Clamp(const T aValue, const T aMin, const T aMax)
> +{
> + if (aValue < aMin)
> + return aMin;
> + if (aMax < aValue)
This makes me worry/wonder about compilers that warn somewhat too aggressively about vacuous comparisons, should someone ever do Clamp(0u, 15u, unsigned(-1)), say -- unsigned(v) < 0u and unsigned(-1) < unsigned(v) always being false. Convert these two comparisons to <= so that while < might be vacuously false, == is always possible and so the comparisons are never impossible.
Attachment #8646717 -
Flags: review?(jwalden+bmo) → feedback+
Assignee | ||
Comment 2•9 years ago
|
||
Attachment #8655763 -
Flags: review?(jwalden+bmo)
Assignee | ||
Updated•9 years ago
|
Attachment #8646717 -
Flags: review?(jwalden+bmo)
Comment 3•9 years ago
|
||
Comment on attachment 8655763 [details] [diff] [review]
0002-Review-comments-and-add-tests.patch
Review of attachment 8655763 [details] [diff] [review]:
-----------------------------------------------------------------
::: mfbt/MathAlgorithms.h
@@ +510,2 @@
> {
> + static_assert(IsUnsigned<T>::value, "IsPowerOfTwo requries unsigned values.");
requires, and remove the trailing "." at the end -- these are generally sentence fragments.
@@ +516,4 @@
> inline T
> Clamp(const T aValue, const T aMin, const T aMax)
> {
> + static_assert(IsIntegral<T>::value, "Clamp requries integral values.");
Same again here.
@@ +517,5 @@
> Clamp(const T aValue, const T aMin, const T aMax)
> {
> + static_assert(IsIntegral<T>::value, "Clamp requries integral values.");
> + MOZ_ASSERT(aMin <= aMax);
> + // We require integral values so that we don't have to support weird floatisms.
static_assert(IsIntegral<T>::value,
"Clamp accepts only integral types, so that it doesn't have to "
"distinguish differently-signed zeroes (which users may or may "
"not care to distinguish, likely at a perf cost) or to decide "
"how to clamp NaN or a range with a NaN endpoint");
to be a little more precise. And put a linebreak before the static_assert. (This also lets you get rid of the comment -- generally a comment by a static_assert, or touching upon it, should move into the static_assert reason itself.)
::: mfbt/tests/TestMathAlgorithms.cpp
@@ +6,5 @@
> +
> +#include "mozilla/MathAlgorithms.h"
> +
> +using mozilla::IsPowerOfTwo;
> +using mozilla::Clamp;
Flip ordering to be alphabetical.
@@ +28,5 @@
> + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint8_t(UINT8_MAX/2 + 2))); // 129
> + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint8_t(UINT8_MAX - 1))); // 254
> + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint8_t(UINT8_MAX))); // 255
> +
> + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint16_t(UINT16_MAX/2)));
// 32767
and similar comments after all these, and the 32/64-bit cases.
That said, it might perhaps be better to use
UINT8_C(127)
UINT16_C(65535)
and so on for these, to be clearer. But then the boundary-checking is less obvious, so maybe stick with what you have, with the added comments, I guess.
@@ +65,5 @@
> + MOZ_RELEASE_ASSERT(Clamp(1, 1, 3) == 1);
> + MOZ_RELEASE_ASSERT(Clamp(2, 1, 3) == 2);
> + MOZ_RELEASE_ASSERT(Clamp(3, 1, 3) == 3);
> + MOZ_RELEASE_ASSERT(Clamp(4, 1, 3) == 3);
> + MOZ_RELEASE_ASSERT(Clamp(5, 1, 3) == 3);
Add
MOZ_RELEASE_ASSERT(Clamp(uint8_t(-1), uint8_t(0), uint8_t(-1)) == uint8_t(-1));
MOZ_RELEASE_ASSERT(Clamp(uint8_t(0), uint8_t(0), uint8_t(-1)) == uint8_t(0));
to verify type-boundary conditions for an unsigned type, and add
MOZ_RELEASE_ASSERT(Clamp(int8_t(INT8_MIN), int8_t(INT8_MIN), int8_t(INT8_MAX)) == int8_t(INT8_MIN));
MOZ_RELEASE_ASSERT(Clamp(int8_t(INT8_MIN), int8_t(0), int8_t(INT8_MAX)) == int8_t(0));
MOZ_RELEASE_ASSERT(Clamp(int8_t(INT8_MAX), int8_t(INT8_MIN), int8_t(INT8_MAX)) == int8_t(INT8_MAX));
MOZ_RELEASE_ASSERT(Clamp(int8_t(INT8_MAX), int8_t(INT8_MIN), int8_t(0)) == int8_t(0));
to verify them for a signed type.
Attachment #8655763 -
Flags: review?(jwalden+bmo) → review+
Comment 4•9 years ago
|
||
Comment on attachment 8646717 [details] [diff] [review]
0015-Add-IsPowerOfTwo-and-Clamp-to-mfbt-MathAlgorithms.h.patch
Review of attachment 8646717 [details] [diff] [review]:
-----------------------------------------------------------------
r=me with the other patch's changes folded in, and with comments addressed.
Attachment #8646717 -
Flags: review?(jwalden+bmo) → review+
Comment 6•9 years ago
|
||
Should we remove "clamped" in xpcom/base/nsAlgorithm.h and change consumers
to use "Clamp" instead?
Comment 7•9 years ago
|
||
Yes, I think so. Note that Clamp doesn't accept floating-point types, so you might hit cases that can't just be converted. We'll have to add new methods for that, and we'll have to decide how to handle -0/+0/NaN edge cases (and their perf) not present in simple integral clamping.
Comment 8•9 years ago
|
||
Status: NEW → RESOLVED
Closed: 9 years ago
status-firefox43:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla43
You need to log in
before you can comment on or make changes to this bug.
Description
•