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