@@ -87,7 +87,8 @@
X##_c = FP_CLS_NAN; \
/* Check for signaling NaN. */ \
if (_FP_FRAC_SNANP (fs, X)) \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID \
+ | FP_EX_INVALID_SNAN); \
} \
break; \
} \
@@ -123,14 +124,14 @@
/* Check for a semi-raw value being a signaling NaN and raise the
invalid exception if so. */
-#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \
- do \
- { \
- if (X##_e == _FP_EXPMAX_##fs \
- && !_FP_FRAC_ZEROP_##wc (X) \
- && _FP_FRAC_SNANP_SEMIRAW (fs, X)) \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
- } \
+#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \
+ do \
+ { \
+ if (X##_e == _FP_EXPMAX_##fs \
+ && !_FP_FRAC_ZEROP_##wc (X) \
+ && _FP_FRAC_SNANP_SEMIRAW (fs, X)) \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SNAN); \
+ } \
while (0)
/* Choose a NaN result from an operation on two semi-raw NaN
@@ -741,7 +742,8 @@
R##_s = _FP_NANSIGN_##fs; \
_FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
_FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID \
+ | FP_EX_INVALID_ISI); \
} \
else \
{ \
@@ -893,7 +895,7 @@
R##_s = _FP_NANSIGN_##fs; \
R##_c = FP_CLS_NAN; \
_FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_IMZ); \
break; \
\
default: \
@@ -1057,7 +1059,7 @@
_FP_FMA_T##_s = _FP_NANSIGN_##fs; \
_FP_FMA_T##_c = FP_CLS_NAN; \
_FP_FRAC_SET_##wc (_FP_FMA_T, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_IMZ_FMA); \
break; \
\
default: \
@@ -1102,7 +1104,7 @@
R##_s = _FP_NANSIGN_##fs; \
R##_c = FP_CLS_NAN; \
_FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_ISI); \
} \
break; \
\
@@ -1176,7 +1178,10 @@
R##_s = _FP_NANSIGN_##fs; \
R##_c = FP_CLS_NAN; \
_FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID \
+ | (X##_c == FP_CLS_INF \
+ ? FP_EX_INVALID_IDI \
+ : FP_EX_INVALID_ZDZ)); \
break; \
\
default: \
@@ -1190,17 +1195,25 @@
raise exceptions for signaling NaN operands, 2 to raise exceptions
for all NaN operands. */
-#define _FP_CMP_CHECK_NAN(fs, wc, X, Y, ex) \
- do \
- { \
- if (ex) \
- { \
- if ((ex) == 2 \
- || _FP_ISSIGNAN (fs, wc, X) \
- || _FP_ISSIGNAN (fs, wc, Y)) \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
- } \
- } \
+#define _FP_CMP_CHECK_NAN(fs, wc, X, Y, ex) \
+ do \
+ { \
+ if (ex) \
+ { \
+ if (FP_EX_INVALID_SNAN || FP_EX_INVALID_VC) \
+ { \
+ if ((ex) == 2) \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_VC); \
+ if (_FP_ISSIGNAN (fs, wc, X) \
+ || _FP_ISSIGNAN (fs, wc, Y)) \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SNAN); \
+ } \
+ else if ((ex) == 2 \
+ || _FP_ISSIGNAN (fs, wc, X) \
+ || _FP_ISSIGNAN (fs, wc, Y)) \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ } \
+ } \
while (0)
/* Main differential comparison routine. The inputs should be raw not
@@ -1285,58 +1298,58 @@
/* Main square root routine. The input value should be cooked. */
-#define _FP_SQRT(fs, wc, R, X) \
- do \
- { \
- _FP_FRAC_DECL_##wc (_FP_SQRT_T); \
- _FP_FRAC_DECL_##wc (_FP_SQRT_S); \
- _FP_W_TYPE _FP_SQRT_q; \
- switch (X##_c) \
- { \
- case FP_CLS_NAN: \
- _FP_FRAC_COPY_##wc (R, X); \
- R##_s = X##_s; \
- R##_c = FP_CLS_NAN; \
- break; \
- case FP_CLS_INF: \
- if (X##_s) \
- { \
- R##_s = _FP_NANSIGN_##fs; \
- R##_c = FP_CLS_NAN; /* NAN */ \
- _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
- } \
- else \
- { \
- R##_s = 0; \
- R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
- } \
- break; \
- case FP_CLS_ZERO: \
- R##_s = X##_s; \
- R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
- break; \
- case FP_CLS_NORMAL: \
- R##_s = 0; \
- if (X##_s) \
- { \
- R##_c = FP_CLS_NAN; /* NAN */ \
- R##_s = _FP_NANSIGN_##fs; \
- _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
- break; \
- } \
- R##_c = FP_CLS_NORMAL; \
- if (X##_e & 1) \
- _FP_FRAC_SLL_##wc (X, 1); \
- R##_e = X##_e >> 1; \
- _FP_FRAC_SET_##wc (_FP_SQRT_S, _FP_ZEROFRAC_##wc); \
- _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
- _FP_SQRT_q = _FP_OVERFLOW_##fs >> 1; \
- _FP_SQRT_MEAT_##wc (R, _FP_SQRT_S, _FP_SQRT_T, X, \
- _FP_SQRT_q); \
- } \
- } \
+#define _FP_SQRT(fs, wc, R, X) \
+ do \
+ { \
+ _FP_FRAC_DECL_##wc (_FP_SQRT_T); \
+ _FP_FRAC_DECL_##wc (_FP_SQRT_S); \
+ _FP_W_TYPE _FP_SQRT_q; \
+ switch (X##_c) \
+ { \
+ case FP_CLS_NAN: \
+ _FP_FRAC_COPY_##wc (R, X); \
+ R##_s = X##_s; \
+ R##_c = FP_CLS_NAN; \
+ break; \
+ case FP_CLS_INF: \
+ if (X##_s) \
+ { \
+ R##_s = _FP_NANSIGN_##fs; \
+ R##_c = FP_CLS_NAN; /* NAN */ \
+ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SQRT); \
+ } \
+ else \
+ { \
+ R##_s = 0; \
+ R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
+ } \
+ break; \
+ case FP_CLS_ZERO: \
+ R##_s = X##_s; \
+ R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
+ break; \
+ case FP_CLS_NORMAL: \
+ R##_s = 0; \
+ if (X##_s) \
+ { \
+ R##_c = FP_CLS_NAN; /* NAN */ \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SQRT); \
+ break; \
+ } \
+ R##_c = FP_CLS_NORMAL; \
+ if (X##_e & 1) \
+ _FP_FRAC_SLL_##wc (X, 1); \
+ R##_e = X##_e >> 1; \
+ _FP_FRAC_SET_##wc (_FP_SQRT_S, _FP_ZEROFRAC_##wc); \
+ _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
+ _FP_SQRT_q = _FP_OVERFLOW_##fs >> 1; \
+ _FP_SQRT_MEAT_##wc (R, _FP_SQRT_S, _FP_SQRT_T, X, \
+ _FP_SQRT_q); \
+ } \
+ } \
while (0)
/* Convert from FP to integer. Input is raw. */
@@ -1399,12 +1412,16 @@
}) \
: 0); \
if (!_FP_FRAC_ZEROP_##wc (X)) \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \
else if (_FP_TO_INT_inexact) \
FP_SET_EXCEPTION (FP_EX_INEXACT); \
} \
else \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID \
+ | FP_EX_INVALID_CVI \
+ | (_FP_FRAC_SNANP (fs, X) \
+ ? FP_EX_INVALID_SNAN \
+ : 0)); \
} \
else \
{ \
@@ -1563,7 +1580,8 @@
if (!_FP_FRAC_ZEROP_##swc (S)) \
{ \
if (_FP_FRAC_SNANP (sfs, S)) \
- FP_SET_EXCEPTION (FP_EX_INVALID); \
+ FP_SET_EXCEPTION (FP_EX_INVALID \
+ | FP_EX_INVALID_SNAN); \
_FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \
- _FP_FRACBITS_##sfs)); \
_FP_SETQNAN (dfs, dwc, D); \
@@ -83,6 +83,44 @@
# define FP_EX_DENORM 0
#endif
+/* Sub-exceptions of "invalid". */
+/* Signaling NaN operand. */
+#ifndef FP_EX_INVALID_SNAN
+# define FP_EX_INVALID_SNAN 0
+#endif
+/* Inf * 0. */
+#ifndef FP_EX_INVALID_IMZ
+# define FP_EX_INVALID_IMZ 0
+#endif
+/* fma (Inf, 0, c). */
+#ifndef FP_EX_INVALID_IMZ_FMA
+# define FP_EX_INVALID_IMZ_FMA 0
+#endif
+/* Inf - Inf. */
+#ifndef FP_EX_INVALID_ISI
+# define FP_EX_INVALID_ISI 0
+#endif
+/* 0 / 0. */
+#ifndef FP_EX_INVALID_ZDZ
+# define FP_EX_INVALID_ZDZ 0
+#endif
+/* Inf / Inf. */
+#ifndef FP_EX_INVALID_IDI
+# define FP_EX_INVALID_IDI 0
+#endif
+/* sqrt (negative). */
+#ifndef FP_EX_INVALID_SQRT
+# define FP_EX_INVALID_SQRT 0
+#endif
+/* Invalid conversion to integer. */
+#ifndef FP_EX_INVALID_CVI
+# define FP_EX_INVALID_CVI 0
+#endif
+/* Invalid comparison. */
+#ifndef FP_EX_INVALID_VC
+# define FP_EX_INVALID_VC 0
+#endif
+
/* _FP_STRUCT_LAYOUT may be defined as an attribute to determine the
struct layout variant used for structures where bit-fields are used
to access specific parts of binary floating-point numbers. This is