1 /* Return classification value corresponding to argument.
2    Copyright (C) 1997-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 #include <math.h>
20 
21 #include <math_private.h>
22 #include <math_ldbl_opt.h>
23 
24   /*
25    *		hx                  lx
26    * +NaN	7ffn nnnn nnnn nnnn xxxx xxxx xxxx xxxx
27    * -NaN	fffn nnnn nnnn nnnn xxxx xxxx xxxx xxxx
28    * +Inf	7ff0 0000 0000 0000 xxxx xxxx xxxx xxxx
29    * -Inf	fff0 0000 0000 0000 xxxx xxxx xxxx xxxx
30    * +0		0000 0000 0000 0000 xxxx xxxx xxxx xxxx
31    * -0		8000 0000 0000 0000 xxxx xxxx xxxx xxxx
32    * +normal	0360 0000 0000 0000 0000 0000 0000 0000 (smallest)
33    * -normal	8360 0000 0000 0000 0000 0000 0000 0000 (smallest)
34    * +normal	7fef ffff ffff ffff 7c8f ffff ffff fffe (largest)
35    * +normal	ffef ffff ffff ffff fc8f ffff ffff fffe (largest)
36    * +denorm	0360 0000 0000 0000 8000 0000 0000 0001 (largest)
37    * -denorm	8360 0000 0000 0000 0000 0000 0000 0001 (largest)
38    * +denorm	000n nnnn nnnn nnnn xxxx xxxx xxxx xxxx
39    * -denorm	800n nnnn nnnn nnnn xxxx xxxx xxxx xxxx
40    */
41 
42 int
___fpclassifyl(long double x)43 ___fpclassifyl (long double x)
44 {
45   uint64_t hx, lx;
46   int retval = FP_NORMAL;
47   double xhi, xlo;
48 
49   ldbl_unpack (x, &xhi, &xlo);
50   EXTRACT_WORDS64 (hx, xhi);
51   if ((hx & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) {
52       /* +/-NaN or +/-Inf */
53       if (hx & 0x000fffffffffffffULL) {
54 	  /* +/-NaN */
55 	  retval = FP_NAN;
56       } else {
57 	  retval = FP_INFINITE;
58       }
59   } else {
60       /* +/-zero or +/- normal or +/- denormal */
61       if (hx & 0x7fffffffffffffffULL) {
62 	  /* +/- normal or +/- denormal */
63 	  if ((hx & 0x7ff0000000000000ULL) > 0x0360000000000000ULL) {
64 	      /* +/- normal */
65 	      retval = FP_NORMAL;
66 	  } else {
67 	      if ((hx & 0x7ff0000000000000ULL) == 0x0360000000000000ULL) {
68 		  EXTRACT_WORDS64 (lx, xlo);
69 		  if ((lx & 0x7fffffffffffffff)	/* lower is non-zero */
70 		  && ((lx^hx) & 0x8000000000000000ULL)) { /* and sign differs */
71 		      /* +/- denormal */
72 		      retval = FP_SUBNORMAL;
73 		  } else {
74 		      /* +/- normal */
75 		      retval = FP_NORMAL;
76 		  }
77 	      } else {
78 		  /* +/- denormal */
79 		  retval = FP_SUBNORMAL;
80 	      }
81 	  }
82       } else {
83 	  /* +/- zero */
84 	  retval = FP_ZERO;
85       }
86   }
87 
88   return retval;
89 }
90 long_double_symbol (libm, ___fpclassifyl, __fpclassifyl);
91 #ifdef __LONG_DOUBLE_MATH_OPTIONAL
92 libm_hidden_ver (___fpclassifyl, __fpclassifyl)
93 #else
94 libm_hidden_def (__fpclassifyl)
95 #endif
96