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 <stdint.h> | |
9 | |
10 #include <limits> | |
11 | |
12 #include "base/compiler_specific.h" | |
13 | |
14 #if defined(ARCH_CPU_ARM_FAMILY) && defined(COMPILER_GCC) && __OPTIMIZE__ | |
15 | |
16 // If we're building ARM on GCC we replace the C++ versions with some | |
17 // native ARM assembly for speed. | |
18 #include "base/numerics/saturated_arithmetic_arm.h" | |
19 | |
20 #else | |
21 | |
22 namespace base { | |
23 | |
24 inline int32_t SaturatedAddition(int32_t a, int32_t b) { | |
25 uint32_t ua = a; | |
26 uint32_t ub = b; | |
27 uint32_t result = ua + ub; | |
28 | |
29 // Can only overflow if the signed bit of the two values match. If the | |
30 // signed bit of the result and one of the values differ it overflowed. | |
31 // The branch compiles to a CMOVNS instruction on x86. | |
32 if (~(ua ^ ub) & (result ^ ua) & (1 << 31)) | |
33 return std::numeric_limits<int>::max() + (ua >> 31); | |
34 | |
35 return result; | |
36 } | |
37 | |
38 inline int32_t SaturatedSubtraction(int32_t a, int32_t b) { | |
39 uint32_t ua = a; | |
40 uint32_t ub = b; | |
41 uint32_t result = ua - ub; | |
42 | |
43 // Can only overflow if the signed bit of the two input values differ. If | |
44 // the signed bit of the result and the first value differ it overflowed. | |
45 // The branch compiles to a CMOVNS instruction on x86. | |
46 if ((ua ^ ub) & (result ^ ua) & (1 << 31)) | |
47 return std::numeric_limits<int>::max() + (ua >> 31); | |
48 | |
49 return result; | |
50 } | |
51 | |
52 inline int32_t SaturatedNegative(int32_t a) { | |
53 if (UNLIKELY(a == std::numeric_limits<int>::min())) | |
54 return std::numeric_limits<int>::max(); | |
55 return -a; | |
56 } | |
57 | |
58 inline int GetMaxSaturatedSetResultForTesting(int fractional_shift) { | |
59 // For C version the set function maxes out to max int, this differs from | |
60 // the ARM asm version, see saturated_arithmetic_arm.h for the equivalent asm | |
61 // version. | |
62 return std::numeric_limits<int>::max(); | |
63 } | |
64 | |
65 inline int GetMinSaturatedSetResultForTesting(int fractional_shift) { | |
66 return std::numeric_limits<int>::min(); | |
67 } | |
68 | |
69 template <int fractional_shift> | |
70 inline int SaturatedSet(int value) { | |
71 const int kIntMaxForLayoutUnit = | |
esprehn
2016/11/14 22:26:06
Should probably give these better names not specif
| |
72 std::numeric_limits<int>::max() >> fractional_shift; | |
73 | |
74 const int kIntMinForLayoutUnit = | |
75 std::numeric_limits<int>::min() >> fractional_shift; | |
76 | |
77 if (value > kIntMaxForLayoutUnit) | |
78 return std::numeric_limits<int>::max(); | |
79 | |
80 if (value < kIntMinForLayoutUnit) | |
81 return std::numeric_limits<int>::min(); | |
82 | |
83 return value << fractional_shift; | |
84 } | |
85 | |
86 template <int fractional_shift> | |
87 inline int SaturatedSet(unsigned value) { | |
88 const unsigned kIntMaxForLayoutUnit = | |
89 std::numeric_limits<int>::max() >> fractional_shift; | |
90 | |
91 if (value >= kIntMaxForLayoutUnit) | |
92 return std::numeric_limits<int>::max(); | |
93 | |
94 return value << fractional_shift; | |
95 } | |
96 | |
97 } // namespace base | |
98 | |
99 #endif // CPU(ARM) && COMPILER(GCC) | |
100 #endif // BASE_NUMERICS_SATURATED_ARITHMETIC_H_ | |
OLD | NEW |