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 55f9e186fSgt29601 * Common Development and Distribution License (the "License"). 65f9e186fSgt29601 * 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 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)); 664b05e997SJason King 674b05e997SJason King case XDR_DECODE: 68*7f93f875SJason King return (XDR_GETINT32(xdrs, (int *)fp)); 694b05e997SJason King 704b05e997SJason King case XDR_FREE: 714b05e997SJason King return (TRUE); 724b05e997SJason King } 734b05e997SJason King return (FALSE); 744b05e997SJason King } 754b05e997SJason King 764b05e997SJason King bool_t 774b05e997SJason King xdr_double(XDR *xdrs, double *dp) 784b05e997SJason King { 79*7f93f875SJason King int64_t *i64p = (int64_t *)dp; 80*7f93f875SJason King int64_t val; 81*7f93f875SJason King bool_t ret; 82*7f93f875SJason King 834b05e997SJason King switch (xdrs->x_op) { 844b05e997SJason King 854b05e997SJason King case XDR_ENCODE: 86*7f93f875SJason King val = BE_64(*i64p); 87*7f93f875SJason King return (XDR_PUTBYTES(xdrs, (char *)&val, sizeof (val))); 884b05e997SJason King 894b05e997SJason King 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); 944b05e997SJason King 954b05e997SJason King case XDR_FREE: 964b05e997SJason King return (TRUE); 974b05e997SJason King } 984b05e997SJason King 994b05e997SJason King return (FALSE); 1004b05e997SJason King } 1014b05e997SJason King 1024b05e997SJason King /* ARGSUSED */ 1034b05e997SJason King bool_t 1044b05e997SJason King xdr_quadruple(XDR *xdrs, long double *fp) 1054b05e997SJason King { 1064b05e997SJason King /* 1074b05e997SJason King * The Sparc uses IEEE FP encoding, so just do a byte copy 1084b05e997SJason King */ 1094b05e997SJason King 1104b05e997SJason King #if !defined(sparc) 1114b05e997SJason King return (FALSE); 1127c478bd9Sstevel@tonic-gate #else 1134b05e997SJason King switch (xdrs->x_op) { 1144b05e997SJason King case XDR_ENCODE: 1154b05e997SJason King return (XDR_PUTBYTES(xdrs, (char *)fp, sizeof (long double))); 1164b05e997SJason King case XDR_DECODE: 1174b05e997SJason King return (XDR_GETBYTES(xdrs, (char *)fp, sizeof (long double))); 1184b05e997SJason King case XDR_FREE: 1194b05e997SJason King return (TRUE); 1207c478bd9Sstevel@tonic-gate } 1214b05e997SJason King return (FALSE); 1224b05e997SJason King #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 130*7f93f875SJason King xdr_float(XDR *xdrs, float *fp) 1317c478bd9Sstevel@tonic-gate { 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * Every machine can do this, its just not very efficient. 1347c478bd9Sstevel@tonic-gate * In addtion, some rounding errors may occur do to the 1357c478bd9Sstevel@tonic-gate * calculations involved. 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate float f; 1387c478bd9Sstevel@tonic-gate int neg = 0; 1397c478bd9Sstevel@tonic-gate int exp = 0; 1407c478bd9Sstevel@tonic-gate int32_t val; 1417c478bd9Sstevel@tonic-gate 142*7f93f875SJason King switch (xdrs->x_op) { 143*7f93f875SJason King case XDR_ENCODE: 1447c478bd9Sstevel@tonic-gate f = *fp; 1457c478bd9Sstevel@tonic-gate if (f == 0) { 1467c478bd9Sstevel@tonic-gate val = 0; 14761961e0fSrobinson return (XDR_PUTINT32(xdrs, &val)); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate if (f < 0) { 1507c478bd9Sstevel@tonic-gate f = 0 - f; 1517c478bd9Sstevel@tonic-gate neg = 1; 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate while (f < 1) { 1547c478bd9Sstevel@tonic-gate f = f * 2; 1557c478bd9Sstevel@tonic-gate --exp; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate while (f >= 2) { 1587c478bd9Sstevel@tonic-gate f = f/2; 1597c478bd9Sstevel@tonic-gate ++exp; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate if ((exp > 128) || (exp < -127)) { 1627c478bd9Sstevel@tonic-gate /* over or under flowing ieee exponent */ 1637c478bd9Sstevel@tonic-gate return (FALSE); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate val = neg; 1667c478bd9Sstevel@tonic-gate val = val << 8; /* for the exponent */ 1677c478bd9Sstevel@tonic-gate val += 127 + exp; /* 127 is the bias */ 1687c478bd9Sstevel@tonic-gate val = val << 23; /* for the mantissa */ 1697c478bd9Sstevel@tonic-gate val += (int32_t)((f - 1) * 8388608); /* 2 ^ 23 */ 17061961e0fSrobinson return (XDR_PUTINT32(xdrs, &val)); 1717c478bd9Sstevel@tonic-gate 172*7f93f875SJason King case XDR_DECODE: 1737c478bd9Sstevel@tonic-gate /* 174*7f93f875SJason King * It assumes that the decoding machine's float can represent 175*7f93f875SJason King * any value in the range of 1767c478bd9Sstevel@tonic-gate * ieee largest float = (2 ^ 128) * 0x1.fffff 1777c478bd9Sstevel@tonic-gate * to 1787c478bd9Sstevel@tonic-gate * ieee smallest float = (2 ^ -127) * 0x1.00000 1797c478bd9Sstevel@tonic-gate * In addtion, some rounding errors may occur do to the 1807c478bd9Sstevel@tonic-gate * calculations involved. 1817c478bd9Sstevel@tonic-gate */ 1827c478bd9Sstevel@tonic-gate 18361961e0fSrobinson if (!XDR_GETINT32(xdrs, (int32_t *)&val)) 1847c478bd9Sstevel@tonic-gate return (FALSE); 1857c478bd9Sstevel@tonic-gate neg = val & 0x80000000; 1867c478bd9Sstevel@tonic-gate exp = (val & 0x7f800000) >> 23; 1877c478bd9Sstevel@tonic-gate exp -= 127; /* subtract exponent base */ 1887c478bd9Sstevel@tonic-gate f = (val & 0x007fffff) * 0.00000011920928955078125; 1897c478bd9Sstevel@tonic-gate /* 2 ^ -23 */ 1907c478bd9Sstevel@tonic-gate f++; 1914b05e997SJason King 1927c478bd9Sstevel@tonic-gate while (exp != 0) { 1937c478bd9Sstevel@tonic-gate if (exp < 0) { 1947c478bd9Sstevel@tonic-gate f = f/2.0; 1957c478bd9Sstevel@tonic-gate ++exp; 1967c478bd9Sstevel@tonic-gate } else { 1977c478bd9Sstevel@tonic-gate f = f * 2.0; 1987c478bd9Sstevel@tonic-gate --exp; 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate } 2014b05e997SJason King 2027c478bd9Sstevel@tonic-gate if (neg) 2037c478bd9Sstevel@tonic-gate f = 0 - f; 2044b05e997SJason King 2057c478bd9Sstevel@tonic-gate *fp = f; 2067c478bd9Sstevel@tonic-gate return (TRUE); 207*7f93f875SJason King 208*7f93f875SJason King case XDR_FREE: 209*7f93f875SJason King return (TRUE); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 212*7f93f875SJason King return (FALSE); 213*7f93f875SJason King } 214*7f93f875SJason King 215*7f93f875SJason King bool_t 216*7f93f875SJason King xdr_double(XDR *xdrs, double *dp) 2177c478bd9Sstevel@tonic-gate { 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * Every machine can do this, its just not very efficient. 2207c478bd9Sstevel@tonic-gate * In addtion, some rounding errors may occur do to the 2217c478bd9Sstevel@tonic-gate * calculations involved. 2227c478bd9Sstevel@tonic-gate */ 2234b05e997SJason King 2244b05e997SJason King int *lp; 2257c478bd9Sstevel@tonic-gate double d; 2267c478bd9Sstevel@tonic-gate int neg = 0; 2277c478bd9Sstevel@tonic-gate int exp = 0; 2287c478bd9Sstevel@tonic-gate int32_t val[2]; 2297c478bd9Sstevel@tonic-gate 230*7f93f875SJason King switch (xdrs->x_op) { 231*7f93f875SJason King case XDR_ENCODE: 2327c478bd9Sstevel@tonic-gate d = *dp; 2337c478bd9Sstevel@tonic-gate if (d == 0) { 2347c478bd9Sstevel@tonic-gate val[0] = 0; 2357c478bd9Sstevel@tonic-gate val[1] = 0; 2367c478bd9Sstevel@tonic-gate lp = val; 237*7f93f875SJason King return (XDR_PUTINT32(xdrs, lp++) && 238*7f93f875SJason King XDR_PUTINT32(xdrs, lp)); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate if (d < 0) { 2417c478bd9Sstevel@tonic-gate d = 0 - d; 2427c478bd9Sstevel@tonic-gate neg = 1; 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate while (d < 1) { 2457c478bd9Sstevel@tonic-gate d = d * 2; 2467c478bd9Sstevel@tonic-gate --exp; 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate while (d >= 2) { 2497c478bd9Sstevel@tonic-gate d = d/2; 2507c478bd9Sstevel@tonic-gate ++exp; 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate if ((exp > 1024) || (exp < -1023)) { 2537c478bd9Sstevel@tonic-gate /* over or under flowing ieee exponent */ 2547c478bd9Sstevel@tonic-gate return (FALSE); 2557c478bd9Sstevel@tonic-gate } 256*7f93f875SJason King val[0] = (neg << 11); /* for the exponent */ 2577c478bd9Sstevel@tonic-gate val[0] += 1023 + exp; /* 1023 is the bias */ 2587c478bd9Sstevel@tonic-gate val[0] = val[0] << 20; /* for the mantissa */ 2597c478bd9Sstevel@tonic-gate 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 */ 2627c478bd9Sstevel@tonic-gate lp = val; 2637c478bd9Sstevel@tonic-gate 2644b05e997SJason King return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 2654b05e997SJason King 266*7f93f875SJason King case XDR_DECODE: 2677c478bd9Sstevel@tonic-gate /* 268*7f93f875SJason King * It assumes that the decoding machine's 2697c478bd9Sstevel@tonic-gate * double can represent any value in the range of 2707c478bd9Sstevel@tonic-gate * ieee largest double = (2 ^ 1024) * 0x1.fffffffffffff 2717c478bd9Sstevel@tonic-gate * to 2727c478bd9Sstevel@tonic-gate * ieee smallest double = (2 ^ -1023) * 0x1.0000000000000 2737c478bd9Sstevel@tonic-gate * In addtion, some rounding errors may occur do to the 2747c478bd9Sstevel@tonic-gate * calculations involved. 2757c478bd9Sstevel@tonic-gate */ 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate lp = val; 27861961e0fSrobinson if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 2797c478bd9Sstevel@tonic-gate return (FALSE); 2807c478bd9Sstevel@tonic-gate neg = val[0] & 0x80000000; 2817c478bd9Sstevel@tonic-gate exp = (val[0] & 0x7ff00000) >> 20; 2827c478bd9Sstevel@tonic-gate exp -= 1023; /* subtract exponent base */ 2837c478bd9Sstevel@tonic-gate d = (val[0] & 0x000fffff) * 0.00000095367431640625; 2847c478bd9Sstevel@tonic-gate /* 2 ^ -20 */ 2857c478bd9Sstevel@tonic-gate d += (val[1] * 0.0000000000000002220446049250313); 2867c478bd9Sstevel@tonic-gate /* 2 ^ -52 */ 2877c478bd9Sstevel@tonic-gate d++; 2887c478bd9Sstevel@tonic-gate while (exp != 0) { 2897c478bd9Sstevel@tonic-gate if (exp < 0) { 2907c478bd9Sstevel@tonic-gate d = d/2.0; 2917c478bd9Sstevel@tonic-gate ++exp; 2927c478bd9Sstevel@tonic-gate } else { 2937c478bd9Sstevel@tonic-gate d = d * 2.0; 2947c478bd9Sstevel@tonic-gate --exp; 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate if (neg) 2987c478bd9Sstevel@tonic-gate d = 0 - d; 2994b05e997SJason King 3007c478bd9Sstevel@tonic-gate *dp = d; 3017c478bd9Sstevel@tonic-gate return (TRUE); 302*7f93f875SJason King 303*7f93f875SJason King case XDR_FREE: 304*7f93f875SJason King return (TRUE); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 307*7f93f875SJason King return (FALSE); 308*7f93f875SJason King } 309*7f93f875SJason King 310*7f93f875SJason King bool_t 311*7f93f875SJason King xdr_quadruple(XDR *xdrs, long double *fp) 312*7f93f875SJason King { 313*7f93f875SJason King return (FALSE); 314*7f93f875SJason King } 315*7f93f875SJason King 316*7f93f875SJason King #endif /* _IEEE_754 */ 317