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