xref: /netbsd-src/external/bsd/ntp/dist/libparse/ieee754io.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: ieee754io.c,v 1.6 2024/08/18 20:47:17 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4abb0f93cSkardel  * /src/NTP/ntp4-dev/libntp/ieee754io.c,v 4.12 2005/04/16 17:32:10 kardel RELEASE_20050508_A
5abb0f93cSkardel  *
6abb0f93cSkardel  * ieee754io.c,v 4.12 2005/04/16 17:32:10 kardel RELEASE_20050508_A
7abb0f93cSkardel  *
88585484eSchristos  * $Created: Sun Jul 13 09:12:02 1997 $
9abb0f93cSkardel  *
10abb0f93cSkardel  * Copyright (c) 1997-2005 by Frank Kardel <kardel <AT> ntp.org>
11abb0f93cSkardel  *
12abb0f93cSkardel  * Redistribution and use in source and binary forms, with or without
13abb0f93cSkardel  * modification, are permitted provided that the following conditions
14abb0f93cSkardel  * are met:
15abb0f93cSkardel  * 1. Redistributions of source code must retain the above copyright
16abb0f93cSkardel  *    notice, this list of conditions and the following disclaimer.
17abb0f93cSkardel  * 2. Redistributions in binary form must reproduce the above copyright
18abb0f93cSkardel  *    notice, this list of conditions and the following disclaimer in the
19abb0f93cSkardel  *    documentation and/or other materials provided with the distribution.
20abb0f93cSkardel  * 3. Neither the name of the author nor the names of its contributors
21abb0f93cSkardel  *    may be used to endorse or promote products derived from this software
22abb0f93cSkardel  *    without specific prior written permission.
23abb0f93cSkardel  *
24abb0f93cSkardel  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25abb0f93cSkardel  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26abb0f93cSkardel  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27abb0f93cSkardel  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28abb0f93cSkardel  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29abb0f93cSkardel  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30abb0f93cSkardel  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31abb0f93cSkardel  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32abb0f93cSkardel  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33abb0f93cSkardel  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34abb0f93cSkardel  * SUCH DAMAGE.
35abb0f93cSkardel  *
36abb0f93cSkardel  */
37abb0f93cSkardel 
38abb0f93cSkardel #ifdef HAVE_CONFIG_H
39abb0f93cSkardel #include "config.h"
40abb0f93cSkardel #endif
41abb0f93cSkardel 
42abb0f93cSkardel #include <stdio.h>
43abb0f93cSkardel #include "l_stdlib.h"
44abb0f93cSkardel #include "ntp_stdlib.h"
45abb0f93cSkardel #include "ntp_fp.h"
46abb0f93cSkardel #include "ieee754io.h"
47abb0f93cSkardel 
48abb0f93cSkardel static unsigned char get_byte (unsigned char *, offsets_t, int *);
49abb0f93cSkardel #ifdef __not_yet__
50abb0f93cSkardel static void put_byte (unsigned char *, offsets_t, int *, unsigned char);
51abb0f93cSkardel #endif
52abb0f93cSkardel 
53abb0f93cSkardel #ifdef LIBDEBUG
54abb0f93cSkardel 
55abb0f93cSkardel static char *
56abb0f93cSkardel fmt_blong(
57abb0f93cSkardel 	  unsigned long val,
58abb0f93cSkardel 	  int cnt
59abb0f93cSkardel 	  )
60abb0f93cSkardel {
61abb0f93cSkardel   char *buf, *s;
62abb0f93cSkardel   int i = cnt;
63abb0f93cSkardel 
64abb0f93cSkardel   val <<= 32 - cnt;
65abb0f93cSkardel   LIB_GETBUF(buf);
66abb0f93cSkardel   s = buf;
67abb0f93cSkardel 
68abb0f93cSkardel   while (i--)
69abb0f93cSkardel     {
70abb0f93cSkardel       if (val & 0x80000000)
71abb0f93cSkardel 	{
72abb0f93cSkardel 	  *s++ = '1';
73abb0f93cSkardel 	}
74abb0f93cSkardel       else
75abb0f93cSkardel 	{
76abb0f93cSkardel 	  *s++ = '0';
77abb0f93cSkardel 	}
78abb0f93cSkardel       val <<= 1;
79abb0f93cSkardel     }
80abb0f93cSkardel   *s = '\0';
81abb0f93cSkardel   return buf;
82abb0f93cSkardel }
83abb0f93cSkardel 
84abb0f93cSkardel static char *
85abb0f93cSkardel fmt_flt(
86abb0f93cSkardel 	unsigned int sign,
87abb0f93cSkardel 	unsigned long mh,
88abb0f93cSkardel 	unsigned long ml,
89abb0f93cSkardel 	unsigned long ch
90abb0f93cSkardel 	)
91abb0f93cSkardel {
92abb0f93cSkardel 	char *buf;
93abb0f93cSkardel 
94abb0f93cSkardel 	LIB_GETBUF(buf);
958585484eSchristos 	snprintf(buf, LIB_BUFLENGTH, "%c %s %s %s", sign ? '-' : '+',
96abb0f93cSkardel 		 fmt_blong(ch, 11),
97abb0f93cSkardel 		 fmt_blong(mh, 20),
98abb0f93cSkardel 		 fmt_blong(ml, 32));
998585484eSchristos 
100abb0f93cSkardel 	return buf;
101abb0f93cSkardel }
102abb0f93cSkardel 
103abb0f93cSkardel static char *
104abb0f93cSkardel fmt_hex(
105abb0f93cSkardel 	unsigned char *bufp,
106abb0f93cSkardel 	int length
107abb0f93cSkardel 	)
108abb0f93cSkardel {
109abb0f93cSkardel 	char *	buf;
1108585484eSchristos 	char	hex[4];
111abb0f93cSkardel 	int	i;
112abb0f93cSkardel 
113abb0f93cSkardel 	LIB_GETBUF(buf);
1148585484eSchristos 	buf[0] = '\0';
1158585484eSchristos 	for (i = 0; i < length; i++) {
1168585484eSchristos 		snprintf(hex, sizeof(hex), "%02x", bufp[i]);
1178585484eSchristos 		strlcat(buf, hex, LIB_BUFLENGTH);
118abb0f93cSkardel 	}
1198585484eSchristos 
120abb0f93cSkardel 	return buf;
121abb0f93cSkardel }
122abb0f93cSkardel 
123abb0f93cSkardel #endif
124abb0f93cSkardel 
125abb0f93cSkardel static unsigned char
126abb0f93cSkardel get_byte(
127abb0f93cSkardel 	 unsigned char *bufp,
128abb0f93cSkardel 	 offsets_t offset,
129abb0f93cSkardel 	 int *fieldindex
130abb0f93cSkardel 	 )
131abb0f93cSkardel {
132abb0f93cSkardel   unsigned char val;
133abb0f93cSkardel 
134abb0f93cSkardel   val     = *(bufp + offset[*fieldindex]);
135abb0f93cSkardel #ifdef LIBDEBUG
136abb0f93cSkardel   if (debug > 4)
137abb0f93cSkardel     printf("fetchieee754: getbyte(0x%08x, %d) = 0x%02x\n", (unsigned int)(bufp)+offset[*fieldindex], *fieldindex, val);
138abb0f93cSkardel #endif
139abb0f93cSkardel   (*fieldindex)++;
140abb0f93cSkardel   return val;
141abb0f93cSkardel }
142abb0f93cSkardel 
143abb0f93cSkardel #ifdef __not_yet__
144abb0f93cSkardel static void
145abb0f93cSkardel put_byte(
146abb0f93cSkardel 	 unsigned char *bufp,
147abb0f93cSkardel 	 offsets_t offsets,
148abb0f93cSkardel 	 int *fieldindex,
149abb0f93cSkardel 	 unsigned char val
150abb0f93cSkardel 	 )
151abb0f93cSkardel {
152abb0f93cSkardel   *(bufp + offsets[*fieldindex]) = val;
153abb0f93cSkardel   (*fieldindex)++;
154abb0f93cSkardel }
155abb0f93cSkardel #endif
156abb0f93cSkardel 
157abb0f93cSkardel /*
158abb0f93cSkardel  * make conversions to and from external IEEE754 formats and internal
159abb0f93cSkardel  * NTP FP format.
160abb0f93cSkardel  */
161abb0f93cSkardel int
162abb0f93cSkardel fetch_ieee754(
163abb0f93cSkardel 	      unsigned char **buffpp,
164abb0f93cSkardel 	      int size,
165abb0f93cSkardel 	      l_fp *lfpp,
166abb0f93cSkardel 	      offsets_t offsets
167abb0f93cSkardel 	      )
168abb0f93cSkardel {
169abb0f93cSkardel   unsigned char *bufp = *buffpp;
170abb0f93cSkardel   unsigned int sign;
171abb0f93cSkardel   unsigned int bias;
172abb0f93cSkardel   unsigned int maxexp;
173abb0f93cSkardel   int mbits;
174abb0f93cSkardel   u_long mantissa_low;
175abb0f93cSkardel   u_long mantissa_high;
176abb0f93cSkardel   u_long characteristic;
177abb0f93cSkardel   long exponent;
178abb0f93cSkardel #ifdef LIBDEBUG
179abb0f93cSkardel   int length;
180abb0f93cSkardel #endif
181abb0f93cSkardel   unsigned char val;
182abb0f93cSkardel   int fieldindex = 0;
183abb0f93cSkardel 
184abb0f93cSkardel   switch (size)
185abb0f93cSkardel     {
186abb0f93cSkardel     case IEEE_DOUBLE:
187abb0f93cSkardel #ifdef LIBDEBUG
188abb0f93cSkardel       length = 8;
189abb0f93cSkardel #endif
190abb0f93cSkardel       mbits  = 52;
191abb0f93cSkardel       bias   = 1023;
192abb0f93cSkardel       maxexp = 2047;
193abb0f93cSkardel       break;
194abb0f93cSkardel 
195abb0f93cSkardel     case IEEE_SINGLE:
196abb0f93cSkardel #ifdef LIBDEBUG
197abb0f93cSkardel       length = 4;
198abb0f93cSkardel #endif
199abb0f93cSkardel       mbits  = 23;
200abb0f93cSkardel       bias   = 127;
201abb0f93cSkardel       maxexp = 255;
202abb0f93cSkardel       break;
203abb0f93cSkardel 
204abb0f93cSkardel     default:
205abb0f93cSkardel       return IEEE_BADCALL;
206abb0f93cSkardel     }
207abb0f93cSkardel 
208abb0f93cSkardel   val = get_byte(bufp, offsets, &fieldindex); /* fetch sign byte & first part of characteristic */
209abb0f93cSkardel 
210abb0f93cSkardel   sign     = (val & 0x80) != 0;
211abb0f93cSkardel   characteristic = (val & 0x7F);
212abb0f93cSkardel 
213abb0f93cSkardel   val = get_byte(bufp, offsets, &fieldindex); /* fetch rest of characteristic and start of mantissa */
214abb0f93cSkardel 
215abb0f93cSkardel   switch (size)
216abb0f93cSkardel     {
217abb0f93cSkardel     case IEEE_SINGLE:
218abb0f93cSkardel       characteristic <<= 1;
219abb0f93cSkardel       characteristic  |= (val & 0x80) != 0; /* grab last characteristic bit */
220abb0f93cSkardel 
221abb0f93cSkardel       mantissa_high  = 0;
222abb0f93cSkardel 
223abb0f93cSkardel       mantissa_low   = (val &0x7F) << 16;
2248585484eSchristos       mantissa_low  |= (u_long)get_byte(bufp, offsets, &fieldindex) << 8;
225abb0f93cSkardel       mantissa_low  |= get_byte(bufp, offsets, &fieldindex);
226abb0f93cSkardel       break;
227abb0f93cSkardel 
228abb0f93cSkardel     case IEEE_DOUBLE:
229abb0f93cSkardel       characteristic <<= 4;
230abb0f93cSkardel       characteristic  |= (val & 0xF0) >> 4; /* grab lower characteristic bits */
231abb0f93cSkardel 
232abb0f93cSkardel       mantissa_high  = (val & 0x0F) << 16;
2338585484eSchristos       mantissa_high |= (u_long)get_byte(bufp, offsets, &fieldindex) << 8;
234abb0f93cSkardel       mantissa_high |= get_byte(bufp, offsets, &fieldindex);
235abb0f93cSkardel 
2368585484eSchristos       mantissa_low   = (u_long)get_byte(bufp, offsets, &fieldindex) << 24;
2378585484eSchristos       mantissa_low  |= (u_long)get_byte(bufp, offsets, &fieldindex) << 16;
2388585484eSchristos       mantissa_low  |= (u_long)get_byte(bufp, offsets, &fieldindex) << 8;
239abb0f93cSkardel       mantissa_low  |= get_byte(bufp, offsets, &fieldindex);
240abb0f93cSkardel       break;
241abb0f93cSkardel 
242abb0f93cSkardel     default:
243abb0f93cSkardel       return IEEE_BADCALL;
244abb0f93cSkardel     }
245abb0f93cSkardel #ifdef LIBDEBUG
246abb0f93cSkardel   if (debug > 4)
247abb0f93cSkardel   {
248abb0f93cSkardel     double d;
249abb0f93cSkardel     float f;
250abb0f93cSkardel 
251abb0f93cSkardel     if (size == IEEE_SINGLE)
252abb0f93cSkardel       {
253abb0f93cSkardel 	int i;
254abb0f93cSkardel 
255abb0f93cSkardel 	for (i = 0; i < length; i++)
256abb0f93cSkardel 	  {
257abb0f93cSkardel 	    *((unsigned char *)(&f)+i) = *(*buffpp + offsets[i]);
258abb0f93cSkardel 	  }
259abb0f93cSkardel 	d = f;
260abb0f93cSkardel       }
261abb0f93cSkardel     else
262abb0f93cSkardel       {
263abb0f93cSkardel 	int i;
264abb0f93cSkardel 
265abb0f93cSkardel 	for (i = 0; i < length; i++)
266abb0f93cSkardel 	  {
267abb0f93cSkardel 	    *((unsigned char *)(&d)+i) = *(*buffpp + offsets[i]);
268abb0f93cSkardel 	  }
269abb0f93cSkardel       }
270abb0f93cSkardel 
271abb0f93cSkardel     printf("fetchieee754: FP: %s -> %s -> %e(=%s)\n", fmt_hex(*buffpp, length),
272abb0f93cSkardel 	   fmt_flt(sign, mantissa_high, mantissa_low, characteristic),
273abb0f93cSkardel 	   d, fmt_hex((unsigned char *)&d, length));
274abb0f93cSkardel   }
275abb0f93cSkardel #endif
276abb0f93cSkardel 
277abb0f93cSkardel   *buffpp += fieldindex;
278abb0f93cSkardel 
279abb0f93cSkardel   /*
280abb0f93cSkardel    * detect funny numbers
281abb0f93cSkardel    */
282abb0f93cSkardel   if (characteristic == maxexp)
283abb0f93cSkardel     {
284abb0f93cSkardel       /*
285abb0f93cSkardel        * NaN or Infinity
286abb0f93cSkardel        */
287abb0f93cSkardel       if (mantissa_low || mantissa_high)
288abb0f93cSkardel 	{
289abb0f93cSkardel 	  /*
290abb0f93cSkardel 	   * NaN
291abb0f93cSkardel 	   */
292abb0f93cSkardel 	  return IEEE_NAN;
293abb0f93cSkardel 	}
294abb0f93cSkardel       else
295abb0f93cSkardel 	{
296abb0f93cSkardel 	  /*
297abb0f93cSkardel 	   * +Inf or -Inf
298abb0f93cSkardel 	   */
299abb0f93cSkardel 	  return sign ? IEEE_NEGINFINITY : IEEE_POSINFINITY;
300abb0f93cSkardel 	}
301abb0f93cSkardel     }
302abb0f93cSkardel   else
303abb0f93cSkardel     {
304abb0f93cSkardel       /*
305abb0f93cSkardel        * collect real numbers
306abb0f93cSkardel        */
307abb0f93cSkardel 
308abb0f93cSkardel       L_CLR(lfpp);
309abb0f93cSkardel 
310abb0f93cSkardel       /*
311abb0f93cSkardel        * check for overflows
312abb0f93cSkardel        */
313abb0f93cSkardel       exponent = characteristic - bias;
314abb0f93cSkardel 
315abb0f93cSkardel       if (exponent > 31)	/* sorry - hardcoded */
316abb0f93cSkardel 	{
317abb0f93cSkardel 	  /*
318abb0f93cSkardel 	   * overflow only in respect to NTP-FP representation
319abb0f93cSkardel 	   */
320abb0f93cSkardel 	  return sign ? IEEE_NEGOVERFLOW : IEEE_POSOVERFLOW;
321abb0f93cSkardel 	}
322abb0f93cSkardel       else
323abb0f93cSkardel 	{
324abb0f93cSkardel 	  int frac_offset;	/* where the fraction starts */
325abb0f93cSkardel 
326abb0f93cSkardel 	  frac_offset = mbits - exponent;
327abb0f93cSkardel 
328abb0f93cSkardel 	  if (characteristic == 0)
329abb0f93cSkardel 	    {
330abb0f93cSkardel 	      /*
331abb0f93cSkardel 	       * de-normalized or tiny number - fits only as 0
332abb0f93cSkardel 	       */
333abb0f93cSkardel 	      return IEEE_OK;
334abb0f93cSkardel 	    }
335abb0f93cSkardel 	  else
336abb0f93cSkardel 	    {
337abb0f93cSkardel 	      /*
338abb0f93cSkardel 	       * adjust for implied 1
339abb0f93cSkardel 	       */
340abb0f93cSkardel 	      if (mbits > 31)
341abb0f93cSkardel 		mantissa_high |= 1 << (mbits - 32);
342abb0f93cSkardel 	      else
343abb0f93cSkardel 		mantissa_low  |= 1 << mbits;
344abb0f93cSkardel 
345abb0f93cSkardel 	      /*
346abb0f93cSkardel 	       * take mantissa apart - if only all machine would support
347abb0f93cSkardel 	       * 64 bit operations 8-(
348abb0f93cSkardel 	       */
349abb0f93cSkardel 	      if (frac_offset > mbits)
350abb0f93cSkardel 		{
351abb0f93cSkardel 		  lfpp->l_ui = 0; /* only fractional number */
352abb0f93cSkardel 		  frac_offset -= mbits + 1; /* will now contain right shift count - 1*/
353abb0f93cSkardel 		  if (mbits > 31)
354abb0f93cSkardel 		    {
355abb0f93cSkardel 		      lfpp->l_uf   = mantissa_high << (63 - mbits);
356abb0f93cSkardel 		      lfpp->l_uf  |= mantissa_low  >> (mbits - 33);
357abb0f93cSkardel 		      lfpp->l_uf >>= frac_offset;
358abb0f93cSkardel 		    }
359abb0f93cSkardel 		  else
360abb0f93cSkardel 		    {
361abb0f93cSkardel 		      lfpp->l_uf = mantissa_low >> frac_offset;
362abb0f93cSkardel 		    }
363abb0f93cSkardel 		}
364abb0f93cSkardel 	      else
365abb0f93cSkardel 		{
366abb0f93cSkardel 		  if (frac_offset > 32)
367abb0f93cSkardel 		    {
368abb0f93cSkardel 		      /*
369abb0f93cSkardel 		       * must split in high word
370abb0f93cSkardel 		       */
371abb0f93cSkardel 		      lfpp->l_ui  =  mantissa_high >> (frac_offset - 32);
372abb0f93cSkardel 		      lfpp->l_uf  = (mantissa_high & ((1 << (frac_offset - 32)) - 1)) << (64 - frac_offset);
373abb0f93cSkardel 		      lfpp->l_uf |=  mantissa_low  >> (frac_offset - 32);
374abb0f93cSkardel 		    }
375abb0f93cSkardel 		  else
376abb0f93cSkardel 		    {
377abb0f93cSkardel 		      /*
378abb0f93cSkardel 		       * must split in low word
379abb0f93cSkardel 		       */
380abb0f93cSkardel 		      lfpp->l_ui  =  mantissa_high << (32 - frac_offset);
381abb0f93cSkardel 		      lfpp->l_ui |= (mantissa_low >> frac_offset) & ((1 << (32 - frac_offset)) - 1);
382abb0f93cSkardel 		      lfpp->l_uf  = (mantissa_low & ((1 << frac_offset) - 1)) << (32 - frac_offset);
383abb0f93cSkardel 		    }
384abb0f93cSkardel 		}
385abb0f93cSkardel 
386abb0f93cSkardel 	      /*
387abb0f93cSkardel 	       * adjust for sign
388abb0f93cSkardel 	       */
389abb0f93cSkardel 	      if (sign)
390abb0f93cSkardel 		{
391abb0f93cSkardel 		  L_NEG(lfpp);
392abb0f93cSkardel 		}
393abb0f93cSkardel 
394abb0f93cSkardel 	      return IEEE_OK;
395abb0f93cSkardel 	    }
396abb0f93cSkardel 	}
397abb0f93cSkardel     }
398abb0f93cSkardel }
399abb0f93cSkardel 
400*eabc0478Schristos /*
401*eabc0478Schristos  * DLH: This function is currently unused in ntpd.  If you think about
402*eabc0478Schristos  * using it, be sure it does what you intend.  I notice the bufpp arg
403*eabc0478Schristos  * is never referenced, and the calculated mantissa_high & mantissa_low
404*eabc0478Schristos  * are only referenced in debug output.  It seems they're supposed to
405*eabc0478Schristos  * be composed into an ieee754-format float and stored at *bufpp or
406*eabc0478Schristos  * possibly **bufpp.  Brought to my attention by this:
407*eabc0478Schristos  *
408*eabc0478Schristos  * ieee754io.c:414:10: warning: variable 'mantissa_low' set but not used
409*eabc0478Schristos  * [-Wunused-but-set-variable]
410*eabc0478Schristos  *
411*eabc0478Schristos  * To quiet it I'm #ifdef'ing the function away for now, here and below
412*eabc0478Schristos  * the call to it in main().
413*eabc0478Schristos  */
414*eabc0478Schristos #ifdef PUT_IEEE754_UNUSED_FUNC
415abb0f93cSkardel int
416abb0f93cSkardel put_ieee754(
417abb0f93cSkardel 	    unsigned char **bufpp,
418abb0f93cSkardel 	    int size,
419abb0f93cSkardel 	    l_fp *lfpp,
420abb0f93cSkardel 	    offsets_t offsets
421abb0f93cSkardel 	    )
422abb0f93cSkardel {
423abb0f93cSkardel   l_fp outlfp;
424abb0f93cSkardel #ifdef LIBDEBUG
425abb0f93cSkardel   unsigned int sign;
426abb0f93cSkardel   unsigned int bias;
427abb0f93cSkardel #endif
428abb0f93cSkardel /*unsigned int maxexp;*/
429abb0f93cSkardel   int mbits;
430abb0f93cSkardel   int msb;
431abb0f93cSkardel   u_long mantissa_low = 0;
432abb0f93cSkardel   u_long mantissa_high = 0;
433abb0f93cSkardel #ifdef LIBDEBUG
434abb0f93cSkardel   u_long characteristic = 0;
435abb0f93cSkardel   long exponent;
436abb0f93cSkardel #endif
437abb0f93cSkardel /*int length;*/
438abb0f93cSkardel   unsigned long mask;
439abb0f93cSkardel 
440abb0f93cSkardel   outlfp = *lfpp;
441abb0f93cSkardel 
442abb0f93cSkardel   switch (size)
443abb0f93cSkardel     {
444abb0f93cSkardel     case IEEE_DOUBLE:
445abb0f93cSkardel     /*length = 8;*/
446abb0f93cSkardel       mbits  = 52;
447abb0f93cSkardel #ifdef LIBDEBUG
448abb0f93cSkardel       bias   = 1023;
449abb0f93cSkardel #endif
450abb0f93cSkardel     /*maxexp = 2047;*/
451abb0f93cSkardel       break;
452abb0f93cSkardel 
453abb0f93cSkardel     case IEEE_SINGLE:
454abb0f93cSkardel     /*length = 4;*/
455abb0f93cSkardel       mbits  = 23;
456abb0f93cSkardel #ifdef LIBDEBUG
457abb0f93cSkardel       bias   = 127;
458abb0f93cSkardel #endif
459abb0f93cSkardel     /*maxexp = 255;*/
460abb0f93cSkardel       break;
461abb0f93cSkardel 
462abb0f93cSkardel     default:
463abb0f93cSkardel       return IEEE_BADCALL;
464abb0f93cSkardel     }
465abb0f93cSkardel 
466abb0f93cSkardel   /*
467abb0f93cSkardel    * find sign
468abb0f93cSkardel    */
469abb0f93cSkardel   if (L_ISNEG(&outlfp))
470abb0f93cSkardel     {
471abb0f93cSkardel       L_NEG(&outlfp);
472abb0f93cSkardel #ifdef LIBDEBUG
473abb0f93cSkardel       sign = 1;
474abb0f93cSkardel #endif
475abb0f93cSkardel     }
476abb0f93cSkardel   else
477abb0f93cSkardel     {
478abb0f93cSkardel #ifdef LIBDEBUG
479abb0f93cSkardel       sign = 0;
480abb0f93cSkardel #endif
481abb0f93cSkardel     }
482abb0f93cSkardel 
483abb0f93cSkardel   if (L_ISZERO(&outlfp))
484abb0f93cSkardel     {
485abb0f93cSkardel #ifdef LIBDEBUG
486abb0f93cSkardel       exponent = mantissa_high = mantissa_low = 0; /* true zero */
487abb0f93cSkardel #endif
488abb0f93cSkardel     }
489abb0f93cSkardel   else
490abb0f93cSkardel     {
491abb0f93cSkardel       /*
492abb0f93cSkardel        * find number of significant integer bits
493abb0f93cSkardel        */
494abb0f93cSkardel       mask = 0x80000000;
495abb0f93cSkardel       if (outlfp.l_ui)
496abb0f93cSkardel 	{
497abb0f93cSkardel 	  msb = 63;
498abb0f93cSkardel 	  while (mask && ((outlfp.l_ui & mask) == 0))
499abb0f93cSkardel 	    {
500abb0f93cSkardel 	      mask >>= 1;
501abb0f93cSkardel 	      msb--;
502abb0f93cSkardel 	    }
503abb0f93cSkardel 	}
504abb0f93cSkardel       else
505abb0f93cSkardel 	{
506abb0f93cSkardel 	  msb = 31;
507abb0f93cSkardel 	  while (mask && ((outlfp.l_uf & mask) == 0))
508abb0f93cSkardel 	    {
509abb0f93cSkardel 	      mask >>= 1;
510abb0f93cSkardel 	      msb--;
511abb0f93cSkardel 	    }
512abb0f93cSkardel 	}
513abb0f93cSkardel 
514abb0f93cSkardel       switch (size)
515abb0f93cSkardel 	{
516abb0f93cSkardel 	case IEEE_SINGLE:
517abb0f93cSkardel 	  mantissa_high = 0;
518abb0f93cSkardel 	  if (msb >= 32)
519abb0f93cSkardel 	    {
520abb0f93cSkardel 	      mantissa_low  = (outlfp.l_ui & ((1 << (msb - 32)) - 1)) << (mbits - (msb - 32));
521abb0f93cSkardel 	      mantissa_low |=  outlfp.l_uf >> (mbits - (msb - 32));
522abb0f93cSkardel 	    }
523abb0f93cSkardel 	  else
524abb0f93cSkardel 	    {
525abb0f93cSkardel 	      mantissa_low  = (outlfp.l_uf << (mbits - msb)) & ((1 << mbits) - 1);
526abb0f93cSkardel 	    }
527abb0f93cSkardel 	  break;
528abb0f93cSkardel 
529abb0f93cSkardel 	case IEEE_DOUBLE:
530abb0f93cSkardel 	  if (msb >= 32)
531abb0f93cSkardel 	    {
532abb0f93cSkardel 	      mantissa_high  = (outlfp.l_ui << (mbits - msb)) & ((1 << (mbits - 32)) - 1);
533abb0f93cSkardel 	      mantissa_high |=  outlfp.l_uf >> (32 - (mbits - msb));
534abb0f93cSkardel 	      mantissa_low   = (outlfp.l_ui & ((1 << (msb - mbits)) - 1)) << (32 - (msb - mbits));
535abb0f93cSkardel 	      mantissa_low  |=  outlfp.l_uf >> (msb - mbits);
536abb0f93cSkardel 	    }
537abb0f93cSkardel 	  else
538abb0f93cSkardel 	    {
539abb0f93cSkardel 	      mantissa_high  = outlfp.l_uf << (mbits - 32 - msb);
540abb0f93cSkardel 	      mantissa_low   = outlfp.l_uf << (mbits - 32);
541abb0f93cSkardel 	    }
542abb0f93cSkardel 	}
543abb0f93cSkardel 
544abb0f93cSkardel #ifdef LIBDEBUG
545abb0f93cSkardel       exponent = msb - 32;
546abb0f93cSkardel       characteristic = exponent + bias;
547abb0f93cSkardel 
548abb0f93cSkardel       if (debug > 4)
549abb0f93cSkardel 	printf("FP: %s\n", fmt_flt(sign, mantissa_high, mantissa_low, characteristic));
550abb0f93cSkardel #endif
551abb0f93cSkardel     }
552abb0f93cSkardel   return IEEE_OK;
553abb0f93cSkardel }
554*eabc0478Schristos #endif	/* PUT_IEEE754_UNUSED_FUNC */
555abb0f93cSkardel 
556abb0f93cSkardel 
557abb0f93cSkardel #if defined(DEBUG) && defined(LIBDEBUG)
558abb0f93cSkardel int main(
559abb0f93cSkardel 	 int argc,
560abb0f93cSkardel 	 char **argv
561abb0f93cSkardel 	 )
562abb0f93cSkardel {
563abb0f93cSkardel   static offsets_t native_off = { 0, 1, 2, 3, 4, 5, 6, 7 };
564abb0f93cSkardel   double f = 1.0;
565abb0f93cSkardel   double *f_p = &f;
566abb0f93cSkardel   l_fp fp;
567abb0f93cSkardel 
568abb0f93cSkardel   if (argc == 2)
569abb0f93cSkardel     {
570abb0f93cSkardel       if (sscanf(argv[1], "%lf", &f) != 1)
571abb0f93cSkardel 	{
572abb0f93cSkardel 	  printf("cannot convert %s to a float\n", argv[1]);
573abb0f93cSkardel 	  return 1;
574abb0f93cSkardel 	}
575abb0f93cSkardel     }
576abb0f93cSkardel 
577abb0f93cSkardel   printf("double: %s %s\n", fmt_blong(*(unsigned long *)&f, 32), fmt_blong(*(unsigned long *)((char *)(&f)+4), 32));
578abb0f93cSkardel   printf("fetch from %f = %d\n", f, fetch_ieee754((void *)&f_p, IEEE_DOUBLE, &fp, native_off));
579abb0f93cSkardel   printf("fp [%s %s] = %s\n", fmt_blong(fp.l_ui, 32), fmt_blong(fp.l_uf, 32), mfptoa(fp.l_ui, fp.l_uf, 15));
580abb0f93cSkardel   f_p = &f;
581*eabc0478Schristos #ifdef PUT_IEEE754_UNUSED_FUNC
582abb0f93cSkardel   put_ieee754((void *)&f_p, IEEE_DOUBLE, &fp, native_off);
583*eabc0478Schristos /* there should be a check on *f_p (f) having the expected result here */
584*eabc0478Schristos #endif	/* PUT_IEEE754_UNUSED_FUNC */
585abb0f93cSkardel 
586abb0f93cSkardel   return 0;
587abb0f93cSkardel }
588abb0f93cSkardel 
589abb0f93cSkardel #endif
590abb0f93cSkardel /*
591abb0f93cSkardel  * History:
592abb0f93cSkardel  *
593abb0f93cSkardel  * ieee754io.c,v
594abb0f93cSkardel  * Revision 4.12  2005/04/16 17:32:10  kardel
595abb0f93cSkardel  * update copyright
596abb0f93cSkardel  *
597abb0f93cSkardel  * Revision 4.11  2004/11/14 15:29:41  kardel
598abb0f93cSkardel  * support PPSAPI, upgrade Copyright to Berkeley style
599abb0f93cSkardel  *
600abb0f93cSkardel  * Revision 4.8  1999/02/21 12:17:36  kardel
601abb0f93cSkardel  * 4.91f reconcilation
602abb0f93cSkardel  *
603abb0f93cSkardel  * Revision 4.7  1999/02/21 11:26:03  kardel
604abb0f93cSkardel  * renamed index to fieldindex to avoid index() name clash
605abb0f93cSkardel  *
606abb0f93cSkardel  * Revision 4.6  1998/11/15 20:27:52  kardel
607abb0f93cSkardel  * Release 4.0.73e13 reconcilation
608abb0f93cSkardel  *
609abb0f93cSkardel  * Revision 4.5  1998/08/16 19:01:51  kardel
610abb0f93cSkardel  * debug information only compile for LIBDEBUG case
611abb0f93cSkardel  *
612abb0f93cSkardel  * Revision 4.4  1998/08/09 09:39:28  kardel
613abb0f93cSkardel  * Release 4.0.73e2 reconcilation
614abb0f93cSkardel  *
615abb0f93cSkardel  * Revision 4.3  1998/06/13 11:56:19  kardel
616abb0f93cSkardel  * disabled putbute() for the time being
617abb0f93cSkardel  *
618abb0f93cSkardel  * Revision 4.2  1998/06/12 15:16:58  kardel
619abb0f93cSkardel  * ansi2knr compatibility
620abb0f93cSkardel  *
621abb0f93cSkardel  * Revision 4.1  1998/05/24 07:59:56  kardel
622abb0f93cSkardel  * conditional debug support
623abb0f93cSkardel  *
624abb0f93cSkardel  * Revision 4.0  1998/04/10 19:46:29  kardel
625abb0f93cSkardel  * Start 4.0 release version numbering
626abb0f93cSkardel  *
627abb0f93cSkardel  * Revision 1.1  1998/04/10 19:27:46  kardel
628abb0f93cSkardel  * initial NTP VERSION 4 integration of PARSE with GPS166 binary support
629abb0f93cSkardel  *
630abb0f93cSkardel  * Revision 1.1  1997/10/06 21:05:45  kardel
631abb0f93cSkardel  * new parse structure
632abb0f93cSkardel  *
633abb0f93cSkardel  */
634