import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / nsl / xdr_float.c
blob5c92fac36dc1d657639ea21e6949e46d4e902d0a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley
31 * 4.3 BSD under license from the Regents of the University of
32 * California.
35 * Copyright 2011 Jason King. All rights reserved
39 * Generic XDR routines impelmentation.
41 * These are the "floating point" xdr routines used to (de)serialize
42 * most common data items. See xdr.h for more info on the interface to
43 * xdr.
46 #include "mt.h"
47 #include <sys/types.h>
48 #include <stdio.h>
49 #include <values.h>
50 #include <rpc/types.h>
51 #include <rpc/xdr.h>
52 #include <sys/byteorder.h>
54 #ifdef _IEEE_754
57 * The OTW format is IEEE 754 with big endian ordering.
59 bool_t
60 xdr_float(XDR *xdrs, float *fp)
62 switch (xdrs->x_op) {
64 case XDR_ENCODE:
65 return (XDR_PUTINT32(xdrs, (int *)fp));
67 case XDR_DECODE:
68 return (XDR_GETINT32(xdrs, (int *)fp));
70 case XDR_FREE:
71 return (TRUE);
73 return (FALSE);
76 bool_t
77 xdr_double(XDR *xdrs, double *dp)
79 int64_t *i64p = (int64_t *)dp;
80 int64_t val;
81 bool_t ret;
83 switch (xdrs->x_op) {
85 case XDR_ENCODE:
86 val = BE_64(*i64p);
87 return (XDR_PUTBYTES(xdrs, (char *)&val, sizeof (val)));
89 case XDR_DECODE:
90 ret = XDR_GETBYTES(xdrs, (char *)dp, sizeof (double));
91 if (ret)
92 *i64p = BE_64(*i64p);
93 return (ret);
95 case XDR_FREE:
96 return (TRUE);
99 return (FALSE);
102 /* ARGSUSED */
103 bool_t
104 xdr_quadruple(XDR *xdrs, long double *fp)
107 * The Sparc uses IEEE FP encoding, so just do a byte copy
110 #if !defined(sparc)
111 return (FALSE);
112 #else
113 switch (xdrs->x_op) {
114 case XDR_ENCODE:
115 return (XDR_PUTBYTES(xdrs, (char *)fp, sizeof (long double)));
116 case XDR_DECODE:
117 return (XDR_GETBYTES(xdrs, (char *)fp, sizeof (long double)));
118 case XDR_FREE:
119 return (TRUE);
121 return (FALSE);
122 #endif
125 #else
127 #warn No platform specific implementation defined for floats
129 bool_t
130 xdr_float(XDR *xdrs, float *fp)
133 * Every machine can do this, its just not very efficient.
134 * In addtion, some rounding errors may occur do to the
135 * calculations involved.
137 float f;
138 int neg = 0;
139 int exp = 0;
140 int32_t val;
142 switch (xdrs->x_op) {
143 case XDR_ENCODE:
144 f = *fp;
145 if (f == 0) {
146 val = 0;
147 return (XDR_PUTINT32(xdrs, &val));
149 if (f < 0) {
150 f = 0 - f;
151 neg = 1;
153 while (f < 1) {
154 f = f * 2;
155 --exp;
157 while (f >= 2) {
158 f = f/2;
159 ++exp;
161 if ((exp > 128) || (exp < -127)) {
162 /* over or under flowing ieee exponent */
163 return (FALSE);
165 val = neg;
166 val = val << 8; /* for the exponent */
167 val += 127 + exp; /* 127 is the bias */
168 val = val << 23; /* for the mantissa */
169 val += (int32_t)((f - 1) * 8388608); /* 2 ^ 23 */
170 return (XDR_PUTINT32(xdrs, &val));
172 case XDR_DECODE:
174 * It assumes that the decoding machine's float can represent
175 * any value in the range of
176 * ieee largest float = (2 ^ 128) * 0x1.fffff
177 * to
178 * ieee smallest float = (2 ^ -127) * 0x1.00000
179 * In addtion, some rounding errors may occur do to the
180 * calculations involved.
183 if (!XDR_GETINT32(xdrs, (int32_t *)&val))
184 return (FALSE);
185 neg = val & 0x80000000;
186 exp = (val & 0x7f800000) >> 23;
187 exp -= 127; /* subtract exponent base */
188 f = (val & 0x007fffff) * 0.00000011920928955078125;
189 /* 2 ^ -23 */
190 f++;
192 while (exp != 0) {
193 if (exp < 0) {
194 f = f/2.0;
195 ++exp;
196 } else {
197 f = f * 2.0;
198 --exp;
202 if (neg)
203 f = 0 - f;
205 *fp = f;
206 return (TRUE);
208 case XDR_FREE:
209 return (TRUE);
212 return (FALSE);
215 bool_t
216 xdr_double(XDR *xdrs, double *dp)
219 * Every machine can do this, its just not very efficient.
220 * In addtion, some rounding errors may occur do to the
221 * calculations involved.
224 int *lp;
225 double d;
226 int neg = 0;
227 int exp = 0;
228 int32_t val[2];
230 switch (xdrs->x_op) {
231 case XDR_ENCODE:
232 d = *dp;
233 if (d == 0) {
234 val[0] = 0;
235 val[1] = 0;
236 lp = val;
237 return (XDR_PUTINT32(xdrs, lp++) &&
238 XDR_PUTINT32(xdrs, lp));
240 if (d < 0) {
241 d = 0 - d;
242 neg = 1;
244 while (d < 1) {
245 d = d * 2;
246 --exp;
248 while (d >= 2) {
249 d = d/2;
250 ++exp;
252 if ((exp > 1024) || (exp < -1023)) {
253 /* over or under flowing ieee exponent */
254 return (FALSE);
256 val[0] = (neg << 11); /* for the exponent */
257 val[0] += 1023 + exp; /* 1023 is the bias */
258 val[0] = val[0] << 20; /* for the mantissa */
259 val[0] += (int32_t)((d - 1) * 1048576); /* 2 ^ 20 */
260 val[1] += (uint32_t)((((d - 1) * 1048576) - val[0]) *
261 4294967296); /* 2 ^ 32 */
262 lp = val;
264 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
266 case XDR_DECODE:
268 * It assumes that the decoding machine's
269 * double can represent any value in the range of
270 * ieee largest double = (2 ^ 1024) * 0x1.fffffffffffff
271 * to
272 * ieee smallest double = (2 ^ -1023) * 0x1.0000000000000
273 * In addtion, some rounding errors may occur do to the
274 * calculations involved.
277 lp = val;
278 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
279 return (FALSE);
280 neg = val[0] & 0x80000000;
281 exp = (val[0] & 0x7ff00000) >> 20;
282 exp -= 1023; /* subtract exponent base */
283 d = (val[0] & 0x000fffff) * 0.00000095367431640625;
284 /* 2 ^ -20 */
285 d += (val[1] * 0.0000000000000002220446049250313);
286 /* 2 ^ -52 */
287 d++;
288 while (exp != 0) {
289 if (exp < 0) {
290 d = d/2.0;
291 ++exp;
292 } else {
293 d = d * 2.0;
294 --exp;
297 if (neg)
298 d = 0 - d;
300 *dp = d;
301 return (TRUE);
303 case XDR_FREE:
304 return (TRUE);
307 return (FALSE);
310 bool_t
311 xdr_quadruple(XDR *xdrs, long double *fp)
313 return (FALSE);
316 #endif /* _IEEE_754 */