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