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