17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55f9e186fSgt * Common Development and Distribution License (the "License").
65f9e186fSgt * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
2061961e0fSrobinson */
2161961e0fSrobinson
2261961e0fSrobinson /*
23e8031f0aSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
26e8031f0aSraf
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley
317c478bd9Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of
327c478bd9Sstevel@tonic-gate * California.
337c478bd9Sstevel@tonic-gate */
344b05e997SJason King /*
354b05e997SJason King * Copyright 2011 Jason King. All rights reserved
364b05e997SJason King */
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /*
39e8031f0aSraf * Generic XDR routines impelmentation.
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * These are the "floating point" xdr routines used to (de)serialize
427c478bd9Sstevel@tonic-gate * most common data items. See xdr.h for more info on the interface to
437c478bd9Sstevel@tonic-gate * xdr.
447c478bd9Sstevel@tonic-gate */
457c478bd9Sstevel@tonic-gate
46e8031f0aSraf #include "mt.h"
477c478bd9Sstevel@tonic-gate #include <sys/types.h>
487c478bd9Sstevel@tonic-gate #include <stdio.h>
49*7f93f875SJason King #include <values.h>
507c478bd9Sstevel@tonic-gate #include <rpc/types.h>
517c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
52*7f93f875SJason King #include <sys/byteorder.h>
537c478bd9Sstevel@tonic-gate
54*7f93f875SJason King #ifdef _IEEE_754
557c478bd9Sstevel@tonic-gate
56*7f93f875SJason King /*
57*7f93f875SJason King * The OTW format is IEEE 754 with big endian ordering.
58*7f93f875SJason King */
597c478bd9Sstevel@tonic-gate bool_t
xdr_float(XDR * xdrs,float * fp)607c478bd9Sstevel@tonic-gate xdr_float(XDR *xdrs, float *fp)
617c478bd9Sstevel@tonic-gate {
627c478bd9Sstevel@tonic-gate switch (xdrs->x_op) {
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate case XDR_ENCODE:
65*7f93f875SJason King return (XDR_PUTINT32(xdrs, (int *)fp));
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate case XDR_DECODE:
68*7f93f875SJason King return (XDR_GETINT32(xdrs, (int *)fp));
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate case XDR_FREE:
717c478bd9Sstevel@tonic-gate return (TRUE);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate return (FALSE);
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate bool_t
xdr_double(XDR * xdrs,double * dp)777c478bd9Sstevel@tonic-gate xdr_double(XDR *xdrs, double *dp)
787c478bd9Sstevel@tonic-gate {
79*7f93f875SJason King int64_t *i64p = (int64_t *)dp;
80*7f93f875SJason King int64_t val;
81*7f93f875SJason King bool_t ret;
82*7f93f875SJason King
837c478bd9Sstevel@tonic-gate switch (xdrs->x_op) {
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate case XDR_ENCODE:
86*7f93f875SJason King val = BE_64(*i64p);
87*7f93f875SJason King return (XDR_PUTBYTES(xdrs, (char *)&val, sizeof (val)));
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate case XDR_DECODE:
90*7f93f875SJason King ret = XDR_GETBYTES(xdrs, (char *)dp, sizeof (double));
91*7f93f875SJason King if (ret)
92*7f93f875SJason King *i64p = BE_64(*i64p);
93*7f93f875SJason King return (ret);
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate case XDR_FREE:
967c478bd9Sstevel@tonic-gate return (TRUE);
977c478bd9Sstevel@tonic-gate }
984b05e997SJason King
997c478bd9Sstevel@tonic-gate return (FALSE);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate
10261961e0fSrobinson /* ARGSUSED */
1037c478bd9Sstevel@tonic-gate bool_t
xdr_quadruple(XDR * xdrs,long double * fp)1047c478bd9Sstevel@tonic-gate xdr_quadruple(XDR *xdrs, long double *fp)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate * The Sparc uses IEEE FP encoding, so just do a byte copy
1087c478bd9Sstevel@tonic-gate */
1097c478bd9Sstevel@tonic-gate
11061961e0fSrobinson #if !defined(sparc)
11161961e0fSrobinson return (FALSE);
11261961e0fSrobinson #else
1137c478bd9Sstevel@tonic-gate switch (xdrs->x_op) {
1147c478bd9Sstevel@tonic-gate case XDR_ENCODE:
11561961e0fSrobinson return (XDR_PUTBYTES(xdrs, (char *)fp, sizeof (long double)));
1167c478bd9Sstevel@tonic-gate case XDR_DECODE:
11761961e0fSrobinson return (XDR_GETBYTES(xdrs, (char *)fp, sizeof (long double)));
1187c478bd9Sstevel@tonic-gate case XDR_FREE:
1197c478bd9Sstevel@tonic-gate return (TRUE);
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate return (FALSE);
12261961e0fSrobinson #endif
1237c478bd9Sstevel@tonic-gate }
1244b05e997SJason King
125*7f93f875SJason King #else
1264b05e997SJason King
127*7f93f875SJason King #warn No platform specific implementation defined for floats
1284b05e997SJason King
129*7f93f875SJason King bool_t
xdr_float(XDR * xdrs,float * fp)130*7f93f875SJason King xdr_float(XDR *xdrs, float *fp)
1314b05e997SJason King {
1324b05e997SJason King /*
1334b05e997SJason King * Every machine can do this, its just not very efficient.
1344b05e997SJason King * In addtion, some rounding errors may occur do to the
1354b05e997SJason King * calculations involved.
1364b05e997SJason King */
1374b05e997SJason King float f;
1384b05e997SJason King int neg = 0;
1394b05e997SJason King int exp = 0;
1404b05e997SJason King int32_t val;
1414b05e997SJason King
142*7f93f875SJason King switch (xdrs->x_op) {
143*7f93f875SJason King case XDR_ENCODE:
144*7f93f875SJason King f = *fp;
145*7f93f875SJason King if (f == 0) {
146*7f93f875SJason King val = 0;
147*7f93f875SJason King return (XDR_PUTINT32(xdrs, &val));
148*7f93f875SJason King }
149*7f93f875SJason King if (f < 0) {
150*7f93f875SJason King f = 0 - f;
151*7f93f875SJason King neg = 1;
152*7f93f875SJason King }
153*7f93f875SJason King while (f < 1) {
154*7f93f875SJason King f = f * 2;
155*7f93f875SJason King --exp;
156*7f93f875SJason King }
157*7f93f875SJason King while (f >= 2) {
158*7f93f875SJason King f = f/2;
159*7f93f875SJason King ++exp;
160*7f93f875SJason King }
161*7f93f875SJason King if ((exp > 128) || (exp < -127)) {
162*7f93f875SJason King /* over or under flowing ieee exponent */
163*7f93f875SJason King return (FALSE);
164*7f93f875SJason King }
165*7f93f875SJason King val = neg;
166*7f93f875SJason King val = val << 8; /* for the exponent */
167*7f93f875SJason King val += 127 + exp; /* 127 is the bias */
168*7f93f875SJason King val = val << 23; /* for the mantissa */
169*7f93f875SJason King val += (int32_t)((f - 1) * 8388608); /* 2 ^ 23 */
1704b05e997SJason King return (XDR_PUTINT32(xdrs, &val));
1714b05e997SJason King
172*7f93f875SJason King case XDR_DECODE:
173*7f93f875SJason King /*
174*7f93f875SJason King * It assumes that the decoding machine's float can represent
175*7f93f875SJason King * any value in the range of
176*7f93f875SJason King * ieee largest float = (2 ^ 128) * 0x1.fffff
177*7f93f875SJason King * to
178*7f93f875SJason King * ieee smallest float = (2 ^ -127) * 0x1.00000
179*7f93f875SJason King * In addtion, some rounding errors may occur do to the
180*7f93f875SJason King * calculations involved.
181*7f93f875SJason King */
182*7f93f875SJason King
183*7f93f875SJason King if (!XDR_GETINT32(xdrs, (int32_t *)&val))
184*7f93f875SJason King return (FALSE);
185*7f93f875SJason King neg = val & 0x80000000;
186*7f93f875SJason King exp = (val & 0x7f800000) >> 23;
187*7f93f875SJason King exp -= 127; /* subtract exponent base */
188*7f93f875SJason King f = (val & 0x007fffff) * 0.00000011920928955078125;
189*7f93f875SJason King /* 2 ^ -23 */
190*7f93f875SJason King f++;
191*7f93f875SJason King
192*7f93f875SJason King while (exp != 0) {
193*7f93f875SJason King if (exp < 0) {
194*7f93f875SJason King f = f/2.0;
195*7f93f875SJason King ++exp;
196*7f93f875SJason King } else {
197*7f93f875SJason King f = f * 2.0;
198*7f93f875SJason King --exp;
199*7f93f875SJason King }
2004b05e997SJason King }
2014b05e997SJason King
202*7f93f875SJason King if (neg)
203*7f93f875SJason King f = 0 - f;
2044b05e997SJason King
205*7f93f875SJason King *fp = f;
206*7f93f875SJason King return (TRUE);
207*7f93f875SJason King
208*7f93f875SJason King case XDR_FREE:
209*7f93f875SJason King return (TRUE);
210*7f93f875SJason King }
211*7f93f875SJason King
212*7f93f875SJason King return (FALSE);
2134b05e997SJason King }
2144b05e997SJason King
215*7f93f875SJason King bool_t
xdr_double(XDR * xdrs,double * dp)216*7f93f875SJason King xdr_double(XDR *xdrs, double *dp)
2174b05e997SJason King {
2184b05e997SJason King /*
2194b05e997SJason King * Every machine can do this, its just not very efficient.
2204b05e997SJason King * In addtion, some rounding errors may occur do to the
2214b05e997SJason King * calculations involved.
2224b05e997SJason King */
2234b05e997SJason King
2244b05e997SJason King int *lp;
2254b05e997SJason King double d;
2264b05e997SJason King int neg = 0;
2274b05e997SJason King int exp = 0;
2284b05e997SJason King int32_t val[2];
2294b05e997SJason King
230*7f93f875SJason King switch (xdrs->x_op) {
231*7f93f875SJason King case XDR_ENCODE:
232*7f93f875SJason King d = *dp;
233*7f93f875SJason King if (d == 0) {
234*7f93f875SJason King val[0] = 0;
235*7f93f875SJason King val[1] = 0;
236*7f93f875SJason King lp = val;
237*7f93f875SJason King return (XDR_PUTINT32(xdrs, lp++) &&
238*7f93f875SJason King XDR_PUTINT32(xdrs, lp));
239*7f93f875SJason King }
240*7f93f875SJason King if (d < 0) {
241*7f93f875SJason King d = 0 - d;
242*7f93f875SJason King neg = 1;
243*7f93f875SJason King }
244*7f93f875SJason King while (d < 1) {
245*7f93f875SJason King d = d * 2;
246*7f93f875SJason King --exp;
247*7f93f875SJason King }
248*7f93f875SJason King while (d >= 2) {
249*7f93f875SJason King d = d/2;
250*7f93f875SJason King ++exp;
251*7f93f875SJason King }
252*7f93f875SJason King if ((exp > 1024) || (exp < -1023)) {
253*7f93f875SJason King /* over or under flowing ieee exponent */
254*7f93f875SJason King return (FALSE);
255*7f93f875SJason King }
256*7f93f875SJason King val[0] = (neg << 11); /* for the exponent */
257*7f93f875SJason King val[0] += 1023 + exp; /* 1023 is the bias */
258*7f93f875SJason King val[0] = val[0] << 20; /* for the mantissa */
259*7f93f875SJason King val[0] += (int32_t)((d - 1) * 1048576); /* 2 ^ 20 */
260*7f93f875SJason King val[1] += (uint32_t)((((d - 1) * 1048576) - val[0]) *
261*7f93f875SJason King 4294967296); /* 2 ^ 32 */
2624b05e997SJason King lp = val;
263*7f93f875SJason King
2644b05e997SJason King return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
2654b05e997SJason King
266*7f93f875SJason King case XDR_DECODE:
267*7f93f875SJason King /*
268*7f93f875SJason King * It assumes that the decoding machine's
269*7f93f875SJason King * double can represent any value in the range of
270*7f93f875SJason King * ieee largest double = (2 ^ 1024) * 0x1.fffffffffffff
271*7f93f875SJason King * to
272*7f93f875SJason King * ieee smallest double = (2 ^ -1023) * 0x1.0000000000000
273*7f93f875SJason King * In addtion, some rounding errors may occur do to the
274*7f93f875SJason King * calculations involved.
275*7f93f875SJason King */
2764b05e997SJason King
277*7f93f875SJason King lp = val;
278*7f93f875SJason King if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
279*7f93f875SJason King return (FALSE);
280*7f93f875SJason King neg = val[0] & 0x80000000;
281*7f93f875SJason King exp = (val[0] & 0x7ff00000) >> 20;
282*7f93f875SJason King exp -= 1023; /* subtract exponent base */
283*7f93f875SJason King d = (val[0] & 0x000fffff) * 0.00000095367431640625;
284*7f93f875SJason King /* 2 ^ -20 */
285*7f93f875SJason King d += (val[1] * 0.0000000000000002220446049250313);
286*7f93f875SJason King /* 2 ^ -52 */
287*7f93f875SJason King d++;
288*7f93f875SJason King while (exp != 0) {
289*7f93f875SJason King if (exp < 0) {
290*7f93f875SJason King d = d/2.0;
291*7f93f875SJason King ++exp;
292*7f93f875SJason King } else {
293*7f93f875SJason King d = d * 2.0;
294*7f93f875SJason King --exp;
295*7f93f875SJason King }
2964b05e997SJason King }
297*7f93f875SJason King if (neg)
298*7f93f875SJason King d = 0 - d;
299*7f93f875SJason King
300*7f93f875SJason King *dp = d;
301*7f93f875SJason King return (TRUE);
302*7f93f875SJason King
303*7f93f875SJason King case XDR_FREE:
304*7f93f875SJason King return (TRUE);
3054b05e997SJason King }
3064b05e997SJason King
307*7f93f875SJason King return (FALSE);
308*7f93f875SJason King }
309*7f93f875SJason King
310*7f93f875SJason King bool_t
xdr_quadruple(XDR * xdrs,long double * fp)311*7f93f875SJason King xdr_quadruple(XDR *xdrs, long double *fp)
312*7f93f875SJason King {
313*7f93f875SJason King return (FALSE);
3144b05e997SJason King }
3154b05e997SJason King
316*7f93f875SJason King #endif /* _IEEE_754 */
317