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