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 P((unsigned char *, offsets_t, int *)); 47 #ifdef __not_yet__ 48 static void put_byte P((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 */ 611