1 /* Check for underflow and force underflow exceptions.
2    Copyright (C) 2015-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #ifndef _MATH_UNDERFLOW_H
20 #define _MATH_UNDERFLOW_H	1
21 
22 #include <float.h>
23 #include <math.h>
24 
25 #include <math-barriers.h>
26 
27 #define fabs_tg(x) __MATH_TG ((x), (__typeof (x)) __builtin_fabs, (x))
28 
29 /* These must be function-like macros because some __MATH_TG
30    implementations macro-expand the function-name argument before
31    concatenating a suffix to it.  */
32 #define min_of_type_f() FLT_MIN
33 #define min_of_type_() DBL_MIN
34 #define min_of_type_l() LDBL_MIN
35 #define min_of_type_f128() FLT128_MIN
36 
37 #define min_of_type(x) __MATH_TG ((x), (__typeof (x)) min_of_type_, ())
38 
39 /* If X (which is not a NaN) is subnormal, force an underflow
40    exception.  */
41 #define math_check_force_underflow(x)				\
42   do								\
43     {								\
44       __typeof (x) force_underflow_tmp = (x);			\
45       if (fabs_tg (force_underflow_tmp)				\
46 	  < min_of_type (force_underflow_tmp))			\
47 	{							\
48 	  __typeof (force_underflow_tmp) force_underflow_tmp2	\
49 	    = force_underflow_tmp * force_underflow_tmp;	\
50 	  math_force_eval (force_underflow_tmp2);		\
51 	}							\
52     }								\
53   while (0)
54 /* Likewise, but X is also known to be nonnegative.  */
55 #define math_check_force_underflow_nonneg(x)			\
56   do								\
57     {								\
58       __typeof (x) force_underflow_tmp = (x);			\
59       if (force_underflow_tmp					\
60 	  < min_of_type (force_underflow_tmp))			\
61 	{							\
62 	  __typeof (force_underflow_tmp) force_underflow_tmp2	\
63 	    = force_underflow_tmp * force_underflow_tmp;	\
64 	  math_force_eval (force_underflow_tmp2);		\
65 	}							\
66     }								\
67   while (0)
68 /* Likewise, for both real and imaginary parts of a complex
69    result.  */
70 #define math_check_force_underflow_complex(x)				\
71   do									\
72     {									\
73       __typeof (x) force_underflow_complex_tmp = (x);			\
74       math_check_force_underflow (__real__ force_underflow_complex_tmp); \
75       math_check_force_underflow (__imag__ force_underflow_complex_tmp); \
76     }									\
77   while (0)
78 
79 #endif /* math-underflow.h */
80