Annotation of embedaddon/ntp/libparse/ieee754io.c, revision 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>