diff --git a/source/basic.tex b/source/basic.tex index c1f58de60a..5300eee890 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -5680,13 +5680,14 @@ in that type through the most positive finite floating-point number representable in that type. In addition, if negative infinity is representable in a type, -the range of that type is extended to all negative real numbers; +the range of representable values of that type is extended to all negative real numbers; likewise, if positive infinity is representable in a type, -the range of that type is extended to all positive real numbers. +the range of representable values of that type is extended to all positive real numbers. \begin{note} Since negative and positive infinity are representable in \IsoFloatUndated{} formats, -all real numbers lie within the range of representable values of +all real numbers (but not infinity or NaN) +lie within the range of representable values of a floating-point type adhering to \IsoFloatUndated{}. \end{note} diff --git a/source/expressions.tex b/source/expressions.tex index 72f77d87bb..2b592792b5 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -62,9 +62,52 @@ \indextext{overflow!undefined}% \indextext{zero!division by undefined}% \indextext{zero!remainder undefined}% -If during the evaluation of an expression, the result is not -mathematically defined or not in the range of representable values for -its type, the behavior is undefined. +An \defnadj{arithmetic}{expression} is +\begin{itemize} +\item a unary plus or minus\iref{expr.unary.op}, +\item an addition\iref{expr.add}, +\item a subtraction\iref{expr.sub}, or +\item a multiplication, division, or remainder\iref{expr.mul} +\end{itemize} +expression where every (possibly converted) operand is of arithmetic type. +\begin{note} +There exist non-arithmetic expressions such as compound assignment\iref{expr.assign} +which are defined in terms of arithmetic expressions. +\end{note} +The behavior of evaluating an arithmetic expression is undefined +if the mathematical result is neither +\begin{itemize} +\item +in the range of representable values for its type nor +\item +a negative infinity, positive infinity, or NaN +that is among the values of the type. +\end{itemize} +\begin{note} +If the operands are of a type that adheres to \IsoFloatUndated, +division by zero is the only case +where an arithmetic expression has undefined behavior\iref{expr.mul}. +However, some well-defined arithmetic expressions +are not core constant expressions\iref{expr.const.core}. +\begin{example} +The following example assumes that \tcode{std::float32_t} is supported\iref{basic.extended.fp}. +\begin{codeblock} +constexpr std::float32_t min = std::numeric_limits::min(); // OK +constexpr std::float32_t max = std::numeric_limits::max(); // OK +constexpr std::float32_t inf = std::numeric_limits::infinity(); // OK +constexpr std::float32_t nan = std::numeric_limits::quiet_NaN(); // OK + +// Furthermore, if arithmetic expressions with operands of type \tcode{std::float32_t} +// behave as specified in ISO/IEC 60559 for binary32: +constexpr std::float32_t inf2 = inf * 2; // OK, also positive infinity +constexpr std::float32_t zero = min / max; // OK, result cannot be represented, and is rounded to zero +constexpr std::float32_t oflo = max * 2; // error: non-finite result but operands are finite\iref{expr.const.core} +constexpr std::float32_t nan2 = nan * 2; // OK, propagating a NaN +constexpr std::float32_t udef = inf * 0; // error: result is NaN but neither operand is NaN\iref{expr.const.core} +constexpr std::float32_t div0 = max / 0; // error: division by zero is undefined\iref{expr.mul,expr.const.core} +\end{codeblock} +\end{example} +\end{note} \begin{note} \indextext{overflow}% Treatment of division by zero, forming a remainder using a zero divisor, @@ -8491,6 +8534,14 @@ zero\iref{expr.mul}, or certain shift operations\iref{expr.shift}. \end{footnote} +\item +an arithmetic expression\iref{expr.pre} where +\begin{itemize} +\item all operands are finite and the result is not finite, +\item any operand is a signaling NaN, or +\item no operand is NaN and the result is NaN; +\end{itemize} + \item an lvalue-to-rvalue conversion\iref{conv.lval} unless it is applied to diff --git a/source/lex.tex b/source/lex.tex index bfd55be51d..42d9adecd1 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -1795,7 +1795,7 @@ values for its type, the program is ill-formed. Otherwise, the value of a \grammarterm{floating-point-literal} is the scaled value if representable, -else the larger or smaller representable value nearest the scaled value, +else the next greater or lesser value of the type, chosen in an \impldef{choice of larger or smaller value of \grammarterm{floating-point-literal}} manner. \begin{example}