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