Annotation of embedaddon/ntp/libparse/ieee754io.c, revision 1.1.1.1

1.1       misho       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>