Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/xdr/xdr_float.c
39530 views
1
/* $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ */
2
3
/*-
4
* SPDX-License-Identifier: BSD-3-Clause
5
*
6
* Copyright (c) 2010, Oracle America, Inc.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions are
10
* met:
11
*
12
* * Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* * Redistributions in binary form must reproduce the above
15
* copyright notice, this list of conditions and the following
16
* disclaimer in the documentation and/or other materials
17
* provided with the distribution.
18
* * Neither the name of the "Oracle America, Inc." nor the names of its
19
* contributors may be used to endorse or promote products derived
20
* from this software without specific prior written permission.
21
*
22
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
*/
35
36
/*
37
* xdr_float.c, Generic XDR routines implementation.
38
*
39
* These are the "floating point" xdr routines used to (de)serialize
40
* most common data items. See xdr.h for more info on the interface to
41
* xdr.
42
*/
43
44
#include "namespace.h"
45
#include <sys/param.h>
46
47
#include <stdio.h>
48
49
#include <rpc/types.h>
50
#include <rpc/xdr.h>
51
#include "un-namespace.h"
52
53
/*
54
* NB: Not portable.
55
* This routine works on machines with IEEE754 FP and Vaxen.
56
*/
57
58
#include <machine/endian.h>
59
#define IEEEFP
60
61
#if defined(__vax__)
62
63
/* What IEEE single precision floating point looks like on a Vax */
64
struct ieee_single {
65
unsigned int mantissa: 23;
66
unsigned int exp : 8;
67
unsigned int sign : 1;
68
};
69
70
/* Vax single precision floating point */
71
struct vax_single {
72
unsigned int mantissa1 : 7;
73
unsigned int exp : 8;
74
unsigned int sign : 1;
75
unsigned int mantissa2 : 16;
76
};
77
78
#define VAX_SNG_BIAS 0x81
79
#define IEEE_SNG_BIAS 0x7f
80
81
static struct sgl_limits {
82
struct vax_single s;
83
struct ieee_single ieee;
84
} sgl_limits[2] = {
85
{{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
86
{ 0x0, 0xff, 0x0 }}, /* Max IEEE */
87
{{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
88
{ 0x0, 0x0, 0x0 }} /* Min IEEE */
89
};
90
#endif /* vax */
91
92
bool_t
93
xdr_float(XDR *xdrs, float *fp)
94
{
95
#ifndef IEEEFP
96
struct ieee_single is;
97
struct vax_single vs, *vsp;
98
struct sgl_limits *lim;
99
u_int i;
100
#endif
101
switch (xdrs->x_op) {
102
103
case XDR_ENCODE:
104
#ifdef IEEEFP
105
return (XDR_PUTINT32(xdrs, (int32_t *)fp));
106
#else
107
vs = *((struct vax_single *)fp);
108
for (i = 0, lim = sgl_limits; i < nitems(sgl_limits);
109
i++, lim++) {
110
if ((vs.mantissa2 == lim->s.mantissa2) &&
111
(vs.exp == lim->s.exp) &&
112
(vs.mantissa1 == lim->s.mantissa1)) {
113
is = lim->ieee;
114
goto shipit;
115
}
116
}
117
is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
118
is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
119
shipit:
120
is.sign = vs.sign;
121
return (XDR_PUTINT32(xdrs, (int32_t *)&is));
122
#endif
123
124
case XDR_DECODE:
125
#ifdef IEEEFP
126
return (XDR_GETINT32(xdrs, (int32_t *)fp));
127
#else
128
vsp = (struct vax_single *)fp;
129
if (!XDR_GETINT32(xdrs, (int32_t *)&is))
130
return (FALSE);
131
for (i = 0, lim = sgl_limits; i < nitems(sgl_limits);
132
i++, lim++) {
133
if ((is.exp == lim->ieee.exp) &&
134
(is.mantissa == lim->ieee.mantissa)) {
135
*vsp = lim->s;
136
goto doneit;
137
}
138
}
139
vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
140
vsp->mantissa2 = is.mantissa;
141
vsp->mantissa1 = (is.mantissa >> 16);
142
doneit:
143
vsp->sign = is.sign;
144
return (TRUE);
145
#endif
146
147
case XDR_FREE:
148
return (TRUE);
149
}
150
/* NOTREACHED */
151
return (FALSE);
152
}
153
154
#if defined(__vax__)
155
/* What IEEE double precision floating point looks like on a Vax */
156
struct ieee_double {
157
unsigned int mantissa1 : 20;
158
unsigned int exp : 11;
159
unsigned int sign : 1;
160
unsigned int mantissa2 : 32;
161
};
162
163
/* Vax double precision floating point */
164
struct vax_double {
165
unsigned int mantissa1 : 7;
166
unsigned int exp : 8;
167
unsigned int sign : 1;
168
unsigned int mantissa2 : 16;
169
unsigned int mantissa3 : 16;
170
unsigned int mantissa4 : 16;
171
};
172
173
#define VAX_DBL_BIAS 0x81
174
#define IEEE_DBL_BIAS 0x3ff
175
#define MASK(nbits) ((1 << nbits) - 1)
176
177
static struct dbl_limits {
178
struct vax_double d;
179
struct ieee_double ieee;
180
} dbl_limits[2] = {
181
{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
182
{ 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
183
{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
184
{ 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
185
};
186
187
#endif /* vax */
188
189
190
bool_t
191
xdr_double(XDR *xdrs, double *dp)
192
{
193
#ifdef IEEEFP
194
int32_t *i32p;
195
bool_t rv;
196
#else
197
int32_t *lp;
198
struct ieee_double id;
199
struct vax_double vd;
200
struct dbl_limits *lim;
201
u_int i;
202
#endif
203
204
switch (xdrs->x_op) {
205
206
case XDR_ENCODE:
207
#ifdef IEEEFP
208
i32p = (int32_t *)(void *)dp;
209
#if BYTE_ORDER == BIG_ENDIAN
210
rv = XDR_PUTINT32(xdrs, i32p);
211
if (!rv)
212
return (rv);
213
rv = XDR_PUTINT32(xdrs, i32p+1);
214
#else
215
rv = XDR_PUTINT32(xdrs, i32p+1);
216
if (!rv)
217
return (rv);
218
rv = XDR_PUTINT32(xdrs, i32p);
219
#endif
220
return (rv);
221
#else
222
vd = *((struct vax_double *)dp);
223
for (i = 0, lim = dbl_limits; i < nitems(dbl_limits);
224
i++, lim++) {
225
if ((vd.mantissa4 == lim->d.mantissa4) &&
226
(vd.mantissa3 == lim->d.mantissa3) &&
227
(vd.mantissa2 == lim->d.mantissa2) &&
228
(vd.mantissa1 == lim->d.mantissa1) &&
229
(vd.exp == lim->d.exp)) {
230
id = lim->ieee;
231
goto shipit;
232
}
233
}
234
id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
235
id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
236
id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
237
(vd.mantissa3 << 13) |
238
((vd.mantissa4 >> 3) & MASK(13));
239
shipit:
240
id.sign = vd.sign;
241
lp = (int32_t *)&id;
242
return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
243
#endif
244
245
case XDR_DECODE:
246
#ifdef IEEEFP
247
i32p = (int32_t *)(void *)dp;
248
#if BYTE_ORDER == BIG_ENDIAN
249
rv = XDR_GETINT32(xdrs, i32p);
250
if (!rv)
251
return (rv);
252
rv = XDR_GETINT32(xdrs, i32p+1);
253
#else
254
rv = XDR_GETINT32(xdrs, i32p+1);
255
if (!rv)
256
return (rv);
257
rv = XDR_GETINT32(xdrs, i32p);
258
#endif
259
return (rv);
260
#else
261
lp = (int32_t *)&id;
262
if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
263
return (FALSE);
264
for (i = 0, lim = dbl_limits; i < nitems(dbl_limits);
265
i++, lim++) {
266
if ((id.mantissa2 == lim->ieee.mantissa2) &&
267
(id.mantissa1 == lim->ieee.mantissa1) &&
268
(id.exp == lim->ieee.exp)) {
269
vd = lim->d;
270
goto doneit;
271
}
272
}
273
vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
274
vd.mantissa1 = (id.mantissa1 >> 13);
275
vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
276
(id.mantissa2 >> 29);
277
vd.mantissa3 = (id.mantissa2 >> 13);
278
vd.mantissa4 = (id.mantissa2 << 3);
279
doneit:
280
vd.sign = id.sign;
281
*dp = *((double *)&vd);
282
return (TRUE);
283
#endif
284
285
case XDR_FREE:
286
return (TRUE);
287
}
288
/* NOTREACHED */
289
return (FALSE);
290
}
291
292