linux/kernel.h: Fix DIV_ROUND_CLOSEST to support negative dividends
authorGuenter Roeck <linux@roeck-us.net>
Sat, 25 Aug 2012 00:25:01 +0000 (17:25 -0700)
committerGuenter Roeck <linux@roeck-us.net>
Sun, 2 Sep 2012 01:58:09 +0000 (18:58 -0700)
DIV_ROUND_CLOSEST returns a bad result for negative dividends:
DIV_ROUND_CLOSEST(-2, 2) = 0

Most of the time this does not matter. However, in the hardware monitoring
subsystem, DIV_ROUND_CLOSEST is sometimes used on integers which can be
negative (such as temperatures).

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Jean Delvare <khali@linux-fr.org>
include/linux/kernel.h

index 604382143bcfccd6772260ed56e16589800af83c..594b419b7d20229cf79715b1250124491abe4ca6 100644 (file)
        __x - (__x % (y));                              \
 }                                                      \
 )
+
+/*
+ * Divide positive or negative dividend by positive divisor and round
+ * to closest integer. Result is undefined for negative divisors.
+ */
 #define DIV_ROUND_CLOSEST(x, divisor)(                 \
 {                                                      \
-       typeof(divisor) __divisor = divisor;            \
-       (((x) + ((__divisor) / 2)) / (__divisor));      \
+       typeof(x) __x = x;                              \
+       typeof(divisor) __d = divisor;                  \
+       (((typeof(x))-1) >= 0 || (__x) >= 0) ?          \
+               (((__x) + ((__d) / 2)) / (__d)) :       \
+               (((__x) - ((__d) / 2)) / (__d));        \
 }                                                      \
 )