Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: base/numerics/safe_math.h

Issue 2480953002: Make Checked* functions better align with GCC/Clang intrinsics (Closed)
Patch Set: nits + compile fix Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/numerics/safe_math_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_NUMERICS_SAFE_MATH_H_ 5 #ifndef BASE_NUMERICS_SAFE_MATH_H_
6 #define BASE_NUMERICS_SAFE_MATH_H_ 6 #define BASE_NUMERICS_SAFE_MATH_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <limits> 10 #include <limits>
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 T ValueUnsafe() const { return state_.value(); } 112 T ValueUnsafe() const { return state_.value(); }
113 113
114 // Prototypes for the supported arithmetic operator overloads. 114 // Prototypes for the supported arithmetic operator overloads.
115 template <typename Src> CheckedNumeric& operator+=(Src rhs); 115 template <typename Src> CheckedNumeric& operator+=(Src rhs);
116 template <typename Src> CheckedNumeric& operator-=(Src rhs); 116 template <typename Src> CheckedNumeric& operator-=(Src rhs);
117 template <typename Src> CheckedNumeric& operator*=(Src rhs); 117 template <typename Src> CheckedNumeric& operator*=(Src rhs);
118 template <typename Src> CheckedNumeric& operator/=(Src rhs); 118 template <typename Src> CheckedNumeric& operator/=(Src rhs);
119 template <typename Src> CheckedNumeric& operator%=(Src rhs); 119 template <typename Src> CheckedNumeric& operator%=(Src rhs);
120 120
121 CheckedNumeric operator-() const { 121 CheckedNumeric operator-() const {
122 bool is_valid;
123 T value = CheckedNeg(state_.value(), &is_valid);
124 // Negation is always valid for floating point. 122 // Negation is always valid for floating point.
125 if (std::numeric_limits<T>::is_iec559) 123 T value = 0;
126 return CheckedNumeric<T>(value); 124 bool is_valid = (std::numeric_limits<T>::is_iec559 || IsValid()) &&
127 125 CheckedNeg(state_.value(), &value);
128 is_valid &= state_.is_valid();
129 return CheckedNumeric<T>(value, is_valid); 126 return CheckedNumeric<T>(value, is_valid);
130 } 127 }
131 128
132 CheckedNumeric Abs() const { 129 CheckedNumeric Abs() const {
133 bool is_valid;
134 T value = CheckedAbs(state_.value(), &is_valid);
135 // Absolute value is always valid for floating point. 130 // Absolute value is always valid for floating point.
136 if (std::numeric_limits<T>::is_iec559) 131 T value = 0;
137 return CheckedNumeric<T>(value); 132 bool is_valid = (std::numeric_limits<T>::is_iec559 || IsValid()) &&
138 133 CheckedAbs(state_.value(), &value);
139 is_valid &= state_.is_valid();
140 return CheckedNumeric<T>(value, is_valid); 134 return CheckedNumeric<T>(value, is_valid);
141 } 135 }
142 136
143 // This function is available only for integral types. It returns an unsigned 137 // This function is available only for integral types. It returns an unsigned
144 // integer of the same width as the source type, containing the absolute value 138 // integer of the same width as the source type, containing the absolute value
145 // of the source, and properly handling signed min. 139 // of the source, and properly handling signed min.
146 CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const { 140 CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const {
147 return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( 141 return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
148 CheckedUnsignedAbs(state_.value()), state_.is_valid()); 142 SafeUnsignedAbs(state_.value()), state_.is_valid());
149 } 143 }
150 144
151 CheckedNumeric& operator++() { 145 CheckedNumeric& operator++() {
152 *this += 1; 146 *this += 1;
153 return *this; 147 return *this;
154 } 148 }
155 149
156 CheckedNumeric operator++(int) { 150 CheckedNumeric operator++(int) {
157 CheckedNumeric value = *this; 151 CheckedNumeric value = *this;
158 *this += 1; 152 *this += 1;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 // TODO(jschuh): extract these out into templates. 207 // TODO(jschuh): extract these out into templates.
214 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ 208 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \
215 /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ 209 /* Binary arithmetic operator for CheckedNumerics of the same type. */ \
216 template <typename T> \ 210 template <typename T> \
217 CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \ 211 CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \
218 const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \ 212 const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \
219 typedef typename ArithmeticPromotion<T>::type Promotion; \ 213 typedef typename ArithmeticPromotion<T>::type Promotion; \
220 /* Floating point always takes the fast path */ \ 214 /* Floating point always takes the fast path */ \
221 if (std::numeric_limits<T>::is_iec559) \ 215 if (std::numeric_limits<T>::is_iec559) \
222 return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ 216 return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \
217 if (!rhs.IsValid() || !lhs.IsValid()) \
218 return CheckedNumeric<Promotion>(0, false); \
223 if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \ 219 if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \
224 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ 220 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() \
225 rhs.IsValid() && lhs.IsValid()); \ 221 OP rhs.ValueUnsafe()); \
226 bool is_valid = true; \ 222 Promotion result = 0; \
227 T result = static_cast<T>( \ 223 bool is_valid = \
228 Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \ 224 Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \
229 static_cast<Promotion>(rhs.ValueUnsafe()), &is_valid)); \ 225 static_cast<Promotion>(rhs.ValueUnsafe()), &result); \
230 return CheckedNumeric<Promotion>( \ 226 return CheckedNumeric<Promotion>(result, is_valid); \
231 result, is_valid && lhs.IsValid() && rhs.IsValid()); \
232 } \ 227 } \
233 /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ 228 /* Assignment arithmetic operator implementation from CheckedNumeric. */ \
234 template <typename T> \ 229 template <typename T> \
235 template <typename Src> \ 230 template <typename Src> \
236 CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \ 231 CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \
237 *this = CheckedNumeric<T>::cast(*this) \ 232 *this = CheckedNumeric<T>::cast(*this) \
238 OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \ 233 OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \
239 return *this; \ 234 return *this; \
240 } \ 235 } \
241 /* Binary arithmetic operator for CheckedNumeric of different type. */ \ 236 /* Binary arithmetic operator for CheckedNumeric of different type. */ \
242 template <typename T, typename Src> \ 237 template <typename T, typename Src> \
243 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ 238 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
244 const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \ 239 const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \
245 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ 240 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
241 if (!rhs.IsValid() || !lhs.IsValid()) \
242 return CheckedNumeric<Promotion>(0, false); \
246 if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ 243 if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
247 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ 244 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe());\
248 rhs.IsValid() && lhs.IsValid()); \
249 return CheckedNumeric<Promotion>::cast(lhs) \ 245 return CheckedNumeric<Promotion>::cast(lhs) \
250 OP CheckedNumeric<Promotion>::cast(rhs); \ 246 OP CheckedNumeric<Promotion>::cast(rhs); \
251 } \ 247 } \
252 /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ 248 /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \
253 template <typename T, typename Src, \ 249 template <typename T, typename Src, \
254 typename std::enable_if<std::is_arithmetic<Src>::value>::type* = \ 250 typename std::enable_if<std::is_arithmetic<Src>::value>::type* = \
255 nullptr> \ 251 nullptr> \
256 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ 252 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
257 const CheckedNumeric<T>& lhs, Src rhs) { \ 253 const CheckedNumeric<T>& lhs, Src rhs) { \
258 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ 254 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
(...skipping 25 matching lines...) Expand all
284 280
285 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS 281 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS
286 282
287 } // namespace internal 283 } // namespace internal
288 284
289 using internal::CheckedNumeric; 285 using internal::CheckedNumeric;
290 286
291 } // namespace base 287 } // namespace base
292 288
293 #endif // BASE_NUMERICS_SAFE_MATH_H_ 289 #endif // BASE_NUMERICS_SAFE_MATH_H_
OLDNEW
« no previous file with comments | « no previous file | base/numerics/safe_math_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698