1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * Copyright 2017 John R. Marino <draco@marino.st>
32 *
33 * This was not part of the original libm release. The fpclass function
34 * has been reconstructed from Illumos sources as it is required for
35 * proper libm functionality (x86 only)
36 */
37
38 /* double precision */
39 typedef union {
40 struct {
41 unsigned lo :32;
42 unsigned hi :20;
43 unsigned exp :11;
44 unsigned sign :1;
45 } fparts;
46 struct {
47 unsigned lo :32;
48 unsigned hi :19;
49 unsigned qnan_bit :1;
50 unsigned exp :11;
51 unsigned sign :1;
52 } nparts;
53 struct {
54 unsigned lo :32;
55 unsigned hi :32;
56 } fwords;
57 double d;
58 } _dval;
59
60 /* single precision */
61 typedef union {
62 struct {
63 unsigned fract :23;
64 unsigned exp :8;
65 unsigned sign :1;
66 } fparts;
67 struct {
68 unsigned fract :22;
69 unsigned qnan_bit :1;
70 unsigned exp :8;
71 unsigned sign :1;
72 } nparts;
73 unsigned long fword;
74 float f;
75 } _fval;
76
77 #define SIGNBIT(X) (((_dval *)&(X))->fparts.sign)
78 #define EXPONENT(X) (((_dval *)&(X))->fparts.exp)
79
80 #define HIFRACTION(X) (((_dval *)&(X))->fparts.hi)
81 #define LOFRACTION(X) (((_dval *)&(X))->fparts.lo)
82 #define QNANBIT(X) (((_dval *)&(X))->nparts.qnan_bit)
83
84 #define MAXEXP 0x7ff /* maximum exponent of double */
85
86 #include <sys/ieeefp.h>
87
88 /*
89 * FPCLASS(X)
90 * fpclass(x) returns the floating point class to which x belongs
91 *
92 * The original function distinguished between positive and negative
93 * versions of infinity, normal, denormal, and zero, but the
94 * fp_class_type enumeration doesn't make this distinguishment.
95 *
96
97 fpclass_t
98 fpclass(double x)
99 {
100 int sign, exp;
101
102 exp = EXPONENT(x);
103 sign = SIGNBIT(x);
104 if (exp == 0) { * de-normal or zero *
105 if (HIFRACTION(x) || LOFRACTION(x)) * de-normal *
106 return (sign ? FP_NDENORM : FP_PDENORM);
107 else
108 return (sign ? FP_NZERO : FP_PZERO);
109 }
110 if (exp == MAXEXP) { * infinity or NaN *
111 if ((HIFRACTION(x) == 0) && (LOFRACTION(x) == 0)) * infinity *
112 return (sign ? FP_NINF : FP_PINF);
113 else
114 if (QNANBIT(x))
115 * hi-bit of mantissa set - quiet nan *
116 return (FP_QNAN);
117 else return (FP_SNAN);
118 }
119 * if we reach here we have non-zero normalized number *
120 return (sign ? FP_NNORM : FP_PNORM);
121 }
122 */
123
124 enum fp_class_type
fp_class(double x)125 fp_class(double x)
126 {
127 int exp;
128 exp = EXPONENT(x);
129 if (exp == 0) {
130 if (HIFRACTION(x) || LOFRACTION(x))
131 return fp_subnormal;
132 else
133 return fp_zero;
134 }
135 if (exp == MAXEXP) {
136 /* infinity or NaN */
137 if ((HIFRACTION(x) == 0) && (LOFRACTION(x) == 0))
138 return fp_infinity;
139 else {
140 if (QNANBIT(x))
141 return fp_quiet;
142 else
143 return fp_signaling;
144 }
145 }
146 /* if we reach here we have non-zero normalized number */
147 return fp_normal;
148 }
149