File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / libparse / ieee754io.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 5 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>