summaryrefslogtreecommitdiff
path: root/doc/intprops.texi
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2015-11-04 08:27:57 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2015-11-04 08:29:17 -0800
commit8780c1786db440a0ef1c0776dfff68134602fcea (patch)
tree05e23c1e030b92154c7a60acddc90abf2a0b6b38 /doc/intprops.texi
parent24fb386f25ce0800577ac64f2d2303822e9e615c (diff)
downloadgnulib-8780c1786db440a0ef1c0776dfff68134602fcea.tar.gz
intprops: revise _WRAPV macros, revert _OVERFLOW
The incompatible changes to the _OVERFLOW macros were too much of a hassle in practice, so revert them. Instead, change the new _WRAPV macros to make them closer in behavior to GCC 5's new builtin_add_overflow etc. functions. No other software was using these newly-added macros yet, so this should be OK. * NEWS: Revert previous change, since the incompatible change has been reverted, and nobody used the incompatible version. * doc/intprops.texi (Wraparound Arithmetic, Integer Type Overflow): Document revised behavior. (Integer Range Overflow): Adjust example to match above revisions. * lib/intprops.h (INT_ADD_OVERFLOW, INT_SUBTRACT_OVERFLOW) (INT_MULTIPLY_OVERFLOW): Revert previous change, so that these can be used in integer constant expressions again. (INT_CONST_ADD_OVERFLOW, INT_CONST_SUBTRACT_OVERFLOW) (INT_CONST_MULTIPLY_OVERFLOW): Remove, as these are no longer needed. (INT_CONST_ADD_WRAPV, INT_CONST_SUBTRACT_WRAPV) (INT_NEGATE_WRAPV, INT_CONST_MULTIPLY_WRAPV, INT_DIVIDE_WRAPV) (INT_REMAINDER_WRAPV, INT_LEFT_SHIFT_WRAPV): Remove, as they did not seem that useful. (INT_ADD_WRAPV, INT_SUBTRACT_WRAPV, INT_MULTIPLY_WRAPV) (_GL_INT_OP_WRAPV, _GL_INT_OP_WRAPV_LONGISH) (_GL_INT_OP_WRAPV_VIA_UNSIGNED): Support new semantics. (__has_builtin): New macro, if not alreay defined. (_GL__GENERIC_BOGUS, _GL_INT_OP_CALC, _GL_INT_OP_CALC1): New macros. * tests/test-intprops.c (INT_CONST_DIVIDE_OVERFLOW) (INT_CONST_REMAINDER_OVERFLOW, INT_CONST_LEFT_SHIFT_OVERFLOW) (INT_CONST_DIVIDE_WRAPV, INT_CONST_REMAINDER_WRAPV) (INT_CONST_LEFT_SHIFT_WRAPV): Remove. (CHECK_SBINOP, CHECK_SSUM, CHECK_SUM1, CHECK_SSUM1) (CHECK_SDIFFERENCE, CHECK_SPRODUCT, CHECK_PRODUCT1, CHECK_SPRODUCT1): New macros. (CHECK_BINOP, CHECK_UNOP, main, CHECK_SUM): Test new behavior.
Diffstat (limited to 'doc/intprops.texi')
-rw-r--r--doc/intprops.texi196
1 files changed, 83 insertions, 113 deletions
diff --git a/doc/intprops.texi b/doc/intprops.texi
index 489bcb934e..55e60e99a6 100644
--- a/doc/intprops.texi
+++ b/doc/intprops.texi
@@ -147,97 +147,77 @@ necessarily yield @code{INT_MIN}, because the compiler may do
calculations with a 64-bit register, or may generate code that
traps on signed integer overflow.
-The following macros work around this problem by yielding the
-wraparound value, i.e., the low-order bits of the correct answer. For
-example, @code{INT_ADD_WRAPV (INT_MAX, 1)} reliably yields
-@code{INT_MIN} on a two's complement machine. You can also use
-overflow-checking macros to check whether wraparound occurred.
-@xref{Integer Type Overflow}.
+The following macros work around this problem by storing the
+wraparound value, i.e., the low-order bits of the correct answer, and
+by returning an overflow indication. For example, if @code{i} is of
+type @code{int}, @code{INT_ADD_WRAPV (INT_MAX, 1, &i)} sets @code{i}
+to @code{INT_MIN} and returns 1 on a two's complement machine. On
+newer platforms, these macros are typically more efficient than the
+overflow-checking macros. @xref{Integer Type Overflow}.
+
+Example usage:
+
+@example
+#include <intprops.h>
+#include <stdio.h>
+
+/* Print the low order bits of A * B,
+ reporting whether overflow occurred. */
+void
+print_product (long int a, long int b)
+@{
+ long int r;
+ int overflow = INT_MULTIPLY_WRAPV (a, b, &r);
+ printf ("result is %ld (%s)\n", r,
+ (overflow
+ ? "after overflow"
+ : "no overflow"));
+@}
+@end example
@noindent
These macros have the following restrictions:
@itemize @bullet
@item
-Their arguments must be integer expressions.
+Their first two arguments must be integer expressions.
+
+@item
+Their last argument must be a non-null pointer to a signed integer.
+To calculate a wraparound unsigned integer you can use ordinary C
+arithmetic; to tell whether it overflowed, you can use the
+overflow-checking macros.
@item
They may evaluate their arguments zero or multiple times, so the
arguments should not have side effects.
@item
-On non-GCC-compatible compilers that do not support C11, the type of
-@code{INT_ADD_WRAPV (@var{a}, @var{b})} might differ from the native
-type of @code{@var{a} + @var{b}}, so it is wise to convert the result
-to the native type. Such a conversion is safe and cannot trap. This
-issue applies to all the @code{_WRAP} macros.
+They are not necessarily constant expressions, even if all their
+arguments are constant expressions.
@end itemize
-These macros are tuned for their last argument being a constant.
-
@table @code
-@item INT_ADD_WRAP (@var{a}, @var{b})
-@findex INT_ADD_WRAP
-Return the low-order bits of @code{@var{a} + @var{b}}. See above for
+@item INT_ADD_WRAPV (@var{a}, @var{b}, @var{r})
+@findex INT_ADD_WRAPV
+Store the low-order bits of the sum of @var{a} and @var{b} into
+@code{*@var{r}}. Return true if overflow occurred, false if the
+low-order bits are the mathematically-correct sum. See above for
restrictions.
-@item INT_CONST_ADD_WRAP (@var{a}, @var{b})
-@findex INT_CONST_ADD_WRAP
-Return the low-order bits of @code{@var{a} + @var{b}}. See above for
-restrictions. This macro differs from @code{INT_ADD_WRAP} in that
-although its implementation is typically slower, it is an integer
-constant expression if its arguments are.
-
-@item INT_SUBTRACT_WRAP (@var{a}, @var{b})
-@findex INT_SUBTRACT_WRAP
-Return the low-order bits of @code{@var{a} - @var{b}}. See above for
+@item INT_SUBTRACT_WRAPV (@var{a}, @var{b}, @var{r})
+@findex INT_SUBTRACT_WRAPV
+Store the low-order bits of the difference between @var{a} and @var{b}
+into @code{*@var{r}}. Return true if overflow occurred, false if the
+low-order bits are the mathematically-correct difference. See above
+for restrictions.
+
+@item INT_MULTIPLY_WRAPV (@var{a}, @var{b}, @var{r})
+@findex INT_MULTIPLY_WRAPV
+Store the low-order bits of the product of @var{a} and @var{b} into
+@code{*@var{r}}. Return true if overflow occurred, false if the
+low-order bits are the mathematically-correct product. See above for
restrictions.
-
-@item INT_CONST_SUBTRACT_WRAP (@var{a}, @var{b})
-@findex INT_CONST_SUBTRACT_WRAP
-Return the low-order bits of @code{@var{a} - @var{b}}. See above for
-restrictions. This macro differs from @code{INT_SUBTRACT_WRAP} in
-that although its implementation is typically slower, it is an integer
-constant expression if its arguments are.
-
-@item INT_NEGATE_WRAP (@var{a})
-@findex INT_NEGATE_WRAP
-Return the low-order bits of @code{-@var{a}}. See above for restrictions.
-This macro is an integer constant expression if its arguments are.
-
-@item INT_MULTIPLY_WRAP (@var{a}, @var{b})
-@findex INT_MULTIPLY_WRAP
-Return the low-order bits of @code{@var{a} * @var{b}}. See above for
-restrictions.
-
-@item INT_CONST_MULTIPLY_WRAP (@var{a}, @var{b})
-@findex INT_CONST_MULTIPLY_WRAP
-Return the low-order bits of @code{@var{a} * @var{b}}. See above for
-restrictions. This macro differs from @code{INT_MULTIPLY_WRAP} in
-that although its implementation is typically slower, it is an integer
-constant expression if its arguments are.
-
-@item INT_DIVIDE_WRAP (@var{a}, @var{b})
-@findex INT_DIVIDE_WRAP
-Return the low-order bits of @code{@var{a} / @var{b}}. See above for
-restrictions. This macro does not check for division by zero. This
-macro is an integer constant expression if its arguments are.
-
-@item INT_REMAINDER_WRAP (@var{a}, @var{b})
-@findex INT_REMAINDER_WRAP
-Return the low-order bits of @code{@var{a} % @var{b}}. See above for
-restrictions. This macro does not check for division by zero. This
-macro is an integer constant expression if its arguments are.
-
-@item INT_LEFT_SHIFT_WRAP (@var{a}, @var{b})
-@findex INT_LEFT_SHIFT_WRAP
-Return the low-order bits of @code{@var{a} << @var{b}}. See above for
-restrictions. The C standard says that behavior is undefined for
-shifts unless 0@leq{}@var{b}<@var{w} where @var{w} is @var{a}'s word
-width, and that when @var{a} is negative then @code{@var{a} <<
-@var{b}} has undefined behavior, but this macro does not check these
-other restrictions. This macro is an integer constant expression if
-its arguments are.
@end table
@node Integer Type Overflow
@@ -262,34 +242,35 @@ These macros yield 1 if the corresponding C operators might not yield
numerically correct answers due to arithmetic overflow of an integer
type. They work correctly on all known practical hosts, and do not
rely on undefined behavior due to signed arithmetic overflow. They
+are integer constant expressions if their arguments are. They
are typically easier to use than the integer range overflow macros
-(@pxref{Integer Range Overflow}).
+(@pxref{Integer Range Overflow}), and they support more operations and
+evaluation contexts than the wraparound macros (@pxref{Wraparound
+Arithmetic}).
-Example usages:
+Example usage:
@example
#include <intprops.h>
#include <limits.h>
+#include <stdio.h>
-/* Print the low order bits of A * B,
- reporting whether overflow occurred.
- When optimized this code typically
- multiplies A and B only once. */
+/* Print A * B if in range, an overflow
+ indicator otherwise. */
void
print_product (long int a, long int b)
@{
- long int result = INT_MULTIPLY_WRAPV (a, b);
- printf ("result is %ld (%s)\n", result,
- (INT_MULTIPLY_OVERFLOW (a, b)
- ? "after overflow"
- : "no overflow"));
+ if (INT_MULTIPLY_OVERFLOW (a, b))
+ printf ("multiply would overflow");
+ else
+ printf ("product is %ld", a * b);
@}
/* Does the product of two ints always fit
in a long int? */
enum @{
INT_PRODUCTS_FIT_IN_LONG
- = ! (INT_CONST_MULTIPLY_OVERFLOW
+ = ! (INT_MULTIPLY_OVERFLOW
((long int) INT_MIN, INT_MIN))
@};
@end example
@@ -306,6 +287,7 @@ They may evaluate their arguments zero or multiple times, so the
arguments should not have side effects.
@end itemize
+@noindent
These macros are tuned for their last argument being a constant.
@table @code
@@ -314,49 +296,26 @@ These macros are tuned for their last argument being a constant.
Yield 1 if @code{@var{a} + @var{b}} would overflow. See above for
restrictions.
-@item INT_CONST_ADD_OVERFLOW (@var{a}, @var{b})
-@findex INT_CONST_ADD_OVERFLOW
-Yield 1 if @code{@var{a} + @var{b}} would overflow. See above for
-restrictions. This macro differs from @code{INT_ADD_OVERFLOW} in that
-although its implementation is typically slower, it is an integer
-constant expression if its arguments are.
-
@item INT_SUBTRACT_OVERFLOW (@var{a}, @var{b})
@findex INT_SUBTRACT_OVERFLOW
Yield 1 if @code{@var{a} - @var{b}} would overflow. See above for
restrictions.
-@item INT_CONST_SUBTRACT_OVERFLOW (@var{a}, @var{b})
-@findex INT_CONST_SUBTRACT_OVERFLOW
-Yield 1 if @code{@var{a} - @var{b}} would overflow. See above for
-restrictions. This macro differs from @code{INT_SUBTRACT_OVERFLOW} in
-that although its implementation is typically slower, it is an integer
-constant expression if its arguments are.
-
@item INT_NEGATE_OVERFLOW (@var{a})
@findex INT_NEGATE_OVERFLOW
Yields 1 if @code{-@var{a}} would overflow. See above for restrictions.
-This macro is an integer constant expression if its arguments are.
@item INT_MULTIPLY_OVERFLOW (@var{a}, @var{b})
@findex INT_MULTIPLY_OVERFLOW
Yield 1 if @code{@var{a} * @var{b}} would overflow. See above for
restrictions.
-@item INT_CONST_MULTIPLY_OVERFLOW (@var{a}, @var{b})
-@findex INT_CONST_MULTIPLY_OVERFLOW
-Yield 1 if @code{@var{a} * @var{b}} would overflow. See above for
-restrictions. This macro differs from @code{INT_SUBTRACT_OVERFLOW} in
-that although its implementation is typically slower, it is an integer
-constant expression if its arguments are.
-
@item INT_DIVIDE_OVERFLOW (@var{a}, @var{b})
@findex INT_DIVIDE_OVERFLOW
Yields 1 if @code{@var{a} / @var{b}} would overflow. See above for
restrictions. Division overflow can happen on two's complement hosts
when dividing the most negative integer by @minus{}1. This macro does
-not check for division by zero. This macro is an integer constant
-expression if its arguments are.
+not check for division by zero.
@item INT_REMAINDER_OVERFLOW (@var{a}, @var{b})
@findex INT_REMAINDER_OVERFLOW
@@ -365,8 +324,7 @@ restrictions. Remainder overflow can happen on two's complement hosts
when dividing the most negative integer by @minus{}1; although the
mathematical result is always 0, in practice some implementations
trap, so this counts as an overflow. This macro does not check for
-division by zero. This macro is an integer constant expression if its
-arguments are.
+division by zero.
@item INT_LEFT_SHIFT_OVERFLOW (@var{a}, @var{b})
@findex INT_LEFT_SHIFT_OVERFLOW
@@ -375,8 +333,7 @@ restrictions. The C standard says that behavior is undefined for
shifts unless 0@leq{}@var{b}<@var{w} where @var{w} is @var{a}'s word
width, and that when @var{a} is negative then @code{@var{a} <<
@var{b}} has undefined behavior, but this macro does not check these
-other restrictions. This macro is an integer constant expression if
-its arguments are.
+other restrictions.
@end table
@node Integer Range Overflow
@@ -407,6 +364,9 @@ Example usage:
@example
#include <intprops.h>
+#include <limits.h>
+#include <stdio.h>
+
void
print_product (long int a, long int b)
@{
@@ -415,6 +375,15 @@ print_product (long int a, long int b)
else
printf ("product is %ld", a * b);
@}
+
+/* Does the product of two ints always fit
+ in a long int? */
+enum @{
+ INT_PRODUCTS_FIT_IN_LONG
+ = ! (INT_MULTIPLY_RANGE_OVERFLOW
+ ((long int) INT_MIN, (long int) INT_MIN,
+ LONG_MIN, LONG_MAX))
+@};
@end example
@noindent
@@ -436,6 +405,7 @@ maximum @var{max}. Unsigned values should use a zero @var{min} of the
proper type, for example, @code{(unsigned int) 0}.
@end itemize
+@noindent
These macros are tuned for constant @var{min} and @var{max}. For
commutative operations such as @code{@var{a} + @var{b}}, they are also
tuned for constant @var{b}.