|
|
@@ -202,26 +202,26 @@ extern int _cond_resched(void);
|
|
|
|
|
|
/**
|
|
|
* abs - return absolute value of an argument
|
|
|
- * @x: the value. If it is unsigned type, it is converted to signed type first
|
|
|
- * (s64, long or int depending on its size).
|
|
|
+ * @x: the value. If it is unsigned type, it is converted to signed type first.
|
|
|
+ * char is treated as if it was signed (regardless of whether it really is)
|
|
|
+ * but the macro's return type is preserved as char.
|
|
|
*
|
|
|
- * Return: an absolute value of x. If x is 64-bit, macro's return type is s64,
|
|
|
- * otherwise it is signed long.
|
|
|
+ * Return: an absolute value of x.
|
|
|
*/
|
|
|
-#define abs(x) __builtin_choose_expr(sizeof(x) == sizeof(s64), ({ \
|
|
|
- s64 __x = (x); \
|
|
|
- (__x < 0) ? -__x : __x; \
|
|
|
- }), ({ \
|
|
|
- long ret; \
|
|
|
- if (sizeof(x) == sizeof(long)) { \
|
|
|
- long __x = (x); \
|
|
|
- ret = (__x < 0) ? -__x : __x; \
|
|
|
- } else { \
|
|
|
- int __x = (x); \
|
|
|
- ret = (__x < 0) ? -__x : __x; \
|
|
|
- } \
|
|
|
- ret; \
|
|
|
- }))
|
|
|
+#define abs(x) __abs_choose_expr(x, long long, \
|
|
|
+ __abs_choose_expr(x, long, \
|
|
|
+ __abs_choose_expr(x, int, \
|
|
|
+ __abs_choose_expr(x, short, \
|
|
|
+ __abs_choose_expr(x, char, \
|
|
|
+ __builtin_choose_expr( \
|
|
|
+ __builtin_types_compatible_p(typeof(x), char), \
|
|
|
+ (char)({ signed char __x = (x); __x<0?-__x:__x; }), \
|
|
|
+ ((void)0)))))))
|
|
|
+
|
|
|
+#define __abs_choose_expr(x, type, other) __builtin_choose_expr( \
|
|
|
+ __builtin_types_compatible_p(typeof(x), signed type) || \
|
|
|
+ __builtin_types_compatible_p(typeof(x), unsigned type), \
|
|
|
+ ({ signed type __x = (x); __x < 0 ? -__x : __x; }), other)
|
|
|
|
|
|
/**
|
|
|
* reciprocal_scale - "scale" a value into range [0, ep_ro)
|