| Index: base/numerics/saturated_arithmetic.h
|
| diff --git a/base/numerics/saturated_arithmetic.h b/base/numerics/saturated_arithmetic.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..37f9a2d32a33ed7142c53f362736dcd1e928a5a4
|
| --- /dev/null
|
| +++ b/base/numerics/saturated_arithmetic.h
|
| @@ -0,0 +1,101 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef BASE_NUMERICS_SATURATED_ARITHMETIC_H_
|
| +#define BASE_NUMERICS_SATURATED_ARITHMETIC_H_
|
| +
|
| +#include <stdint.h>
|
| +
|
| +#include <limits>
|
| +
|
| +#include "base/compiler_specific.h"
|
| +
|
| +#if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS) && \
|
| + defined(COMPILER_GCC) && !defined(OS_NACL) && __OPTIMIZE__
|
| +
|
| +// If we're building ARM 32-bit on GCC we replace the C++ versions with some
|
| +// native ARM assembly for speed.
|
| +#include "base/numerics/saturated_arithmetic_arm.h"
|
| +
|
| +#else
|
| +
|
| +namespace base {
|
| +
|
| +inline int32_t SaturatedAddition(int32_t a, int32_t b) {
|
| + uint32_t ua = a;
|
| + uint32_t ub = b;
|
| + uint32_t result = ua + ub;
|
| +
|
| + // Can only overflow if the signed bit of the two values match. If the
|
| + // signed bit of the result and one of the values differ it overflowed.
|
| + // The branch compiles to a CMOVNS instruction on x86.
|
| + if (~(ua ^ ub) & (result ^ ua) & (1 << 31))
|
| + return std::numeric_limits<int>::max() + (ua >> 31);
|
| +
|
| + return result;
|
| +}
|
| +
|
| +inline int32_t SaturatedSubtraction(int32_t a, int32_t b) {
|
| + uint32_t ua = a;
|
| + uint32_t ub = b;
|
| + uint32_t result = ua - ub;
|
| +
|
| + // Can only overflow if the signed bit of the two input values differ. If
|
| + // the signed bit of the result and the first value differ it overflowed.
|
| + // The branch compiles to a CMOVNS instruction on x86.
|
| + if ((ua ^ ub) & (result ^ ua) & (1 << 31))
|
| + return std::numeric_limits<int>::max() + (ua >> 31);
|
| +
|
| + return result;
|
| +}
|
| +
|
| +inline int32_t SaturatedNegative(int32_t a) {
|
| + if (UNLIKELY(a == std::numeric_limits<int>::min()))
|
| + return std::numeric_limits<int>::max();
|
| + return -a;
|
| +}
|
| +
|
| +inline int GetMaxSaturatedSetResultForTesting(int fractional_shift) {
|
| + // For C version the set function maxes out to max int, this differs from
|
| + // the ARM asm version, see saturated_arithmetic_arm.h for the equivalent asm
|
| + // version.
|
| + return std::numeric_limits<int>::max();
|
| +}
|
| +
|
| +inline int GetMinSaturatedSetResultForTesting(int fractional_shift) {
|
| + return std::numeric_limits<int>::min();
|
| +}
|
| +
|
| +template <int fractional_shift>
|
| +inline int SaturatedSet(int value) {
|
| + const int kIntMaxForLayoutUnit =
|
| + std::numeric_limits<int>::max() >> fractional_shift;
|
| +
|
| + const int kIntMinForLayoutUnit =
|
| + std::numeric_limits<int>::min() >> fractional_shift;
|
| +
|
| + if (value > kIntMaxForLayoutUnit)
|
| + return std::numeric_limits<int>::max();
|
| +
|
| + if (value < kIntMinForLayoutUnit)
|
| + return std::numeric_limits<int>::min();
|
| +
|
| + return value << fractional_shift;
|
| +}
|
| +
|
| +template <int fractional_shift>
|
| +inline int SaturatedSet(unsigned value) {
|
| + const unsigned kIntMaxForLayoutUnit =
|
| + std::numeric_limits<int>::max() >> fractional_shift;
|
| +
|
| + if (value >= kIntMaxForLayoutUnit)
|
| + return std::numeric_limits<int>::max();
|
| +
|
| + return value << fractional_shift;
|
| +}
|
| +
|
| +} // namespace base
|
| +
|
| +#endif // CPU(ARM) && COMPILER(GCC)
|
| +#endif // BASE_NUMERICS_SATURATED_ARITHMETIC_H_
|
|
|