OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef BASE_NUMERICS_SATURATED_ARITHMETIC_H_ | |
6 #define BASE_NUMERICS_SATURATED_ARITHMETIC_H_ | |
7 | |
8 #include <limits> | |
9 | |
10 #include "base/compiler_specific.h" | |
11 | |
12 #if defined(ARCH_CPU_ARM_FAMILY) && defined(COMPILER_GCC) && __OPTIMIZE__ | |
13 | |
14 // If we're building ARM on GCC we replace the C++ versions with some | |
15 // native ARM assembly for speed. | |
16 #include "base/numerics/saturated_arithmetic_arm.h" | |
17 | |
18 #else | |
19 | |
20 namespace base { | |
21 | |
22 inline int32_t SaturatedAddition(int32_t a, int32_t b) { | |
23 uint32_t ua = a; | |
24 uint32_t ub = b; | |
25 uint32_t result = ua + ub; | |
26 | |
27 // Can only overflow if the signed bit of the two values match. If the | |
28 // signed bit of the result and one of the values differ it overflowed. | |
29 // The branch compiles to a CMOVNS instruction on x86. | |
30 if (~(ua ^ ub) & (result ^ ua) & (1 << 31)) | |
31 return std::numeric_limits<int>::max() + (ua >> 31); | |
32 | |
33 return result; | |
34 } | |
35 | |
36 inline int32_t SaturatedSubtraction(int32_t a, int32_t b) { | |
37 uint32_t ua = a; | |
38 uint32_t ub = b; | |
39 uint32_t result = ua - ub; | |
40 | |
41 // Can only overflow if the signed bit of the two input values differ. If | |
42 // the signed bit of the result and the first value differ it overflowed. | |
43 // The branch compiles to a CMOVNS instruction on x86. | |
44 if ((ua ^ ub) & (result ^ ua) & (1 << 31)) | |
45 return std::numeric_limits<int>::max() + (ua >> 31); | |
46 | |
47 return result; | |
48 } | |
49 | |
50 inline int32_t SaturatedNegative(int32_t a) { | |
51 if (UNLIKELY(a == std::numeric_limits<int>::min())) | |
52 return std::numeric_limits<int>::max(); | |
53 return -a; | |
54 } | |
55 | |
56 inline int GetMaxSaturatedSetResultForTesting(int fractional_shift) { | |
57 // For C version the set function maxes out to max int, this differs from | |
58 // the ARM asm version, see saturated_arithmetic_arm.h for the equivalent asm | |
59 // version. | |
60 return std::numeric_limits<int>::max(); | |
61 } | |
62 | |
63 inline int GetMinSaturatedSetResultForTesting(int fractional_shift) { | |
64 return std::numeric_limits<int>::min(); | |
65 } | |
66 | |
67 template <int FractionalShift> | |
danakj
2016/11/12 02:03:19
nit: should be kFractionalShift? or fractional_shi
| |
68 inline int SaturatedSet(int value) { | |
69 const int kIntMaxForLayoutUnit = | |
70 std::numeric_limits<int>::max() >> FractionalShift; | |
71 | |
72 const int kIntMinForLayoutUnit = | |
73 std::numeric_limits<int>::min() >> FractionalShift; | |
74 | |
75 if (value > kIntMaxForLayoutUnit) | |
76 return std::numeric_limits<int>::max(); | |
77 | |
78 if (value < kIntMinForLayoutUnit) | |
79 return std::numeric_limits<int>::min(); | |
80 | |
81 return value << FractionalShift; | |
82 } | |
83 | |
84 template <int FractionalShift> | |
85 inline int SaturatedSet(unsigned value) { | |
86 const unsigned kIntMaxForLayoutUnit = | |
87 std::numeric_limits<int>::max() >> FractionalShift; | |
88 | |
89 if (value >= kIntMaxForLayoutUnit) | |
90 return std::numeric_limits<int>::max(); | |
91 | |
92 return value << FractionalShift; | |
93 } | |
94 | |
95 } // namespace base | |
96 | |
97 #endif // CPU(ARM) && COMPILER(GCC) | |
98 #endif // BASE_NUMERICS_SATURATED_ARITHMETIC_H_ | |
OLD | NEW |