htond.c

Go to the documentation of this file.
00001 /*                         H T O N D . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2004-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** \addtogroup hton */
00023 /*@{*/
00024 /** @file htond.c
00025  *@brief convert doubles to host/network format
00026  *
00027  *  Library routines for conversion between the local host
00028  *  64-bit ("double precision") representation, and
00029  *  64-bit IEEE double precision representation, in "network order",
00030  *  ie, big-endian, the MSB in byte [0], on the left.
00031  *
00032  *  As a quick review, the IEEE double precision format is as follows:
00033  *  sign bit, 11 bits of exponent (bias 1023), and 52 bits of mantissa,
00034  *  with a hidden leading one (0.1 binary).
00035  *  When the exponent is 0, IEEE defines a "denormalized number",
00036  *  which is not supported here.
00037  *  When the exponent is 2047 (all bits set), and:
00038  *      all mantissa bits are zero, value is infinity*sign,
00039  *      mantissa is non-zero, and:
00040  *              msb of mantissa=0:  signaling NAN
00041  *              msb of mantissa=1:  quiet NAN
00042  *
00043  *  Note that neither the input or output buffers need be word aligned,
00044  *  for greatest flexability in converting data, even though this
00045  *  imposes a speed penalty here.
00046  *
00047  *  These subroutines operate on a sequential block of numbers,
00048  *  to save on subroutine linkage execution costs, and to allow
00049  *  some hope for vectorization.
00050  *
00051  *  On brain-damaged machines like the SGI 3-D, where type "double"
00052  *  allocates only 4 bytes of space, these routines *still* return
00053  *  8 bytes in the IEEE buffer.
00054  *
00055  *  Author -
00056  *      Michael John Muuss
00057  *
00058  *  Source -
00059  *      SECAD/VLD Computing Consortium, Bldg 394
00060  *      The U. S. Army Ballistic Research Laboratory
00061  *      Aberdeen Proving Ground, Maryland  21005-5066
00062  */
00063 
00064 #ifndef lint
00065 static const char libbu_htond_RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbu/htond.c,v 14.13 2006/09/03 15:14:07 lbutler Exp $ (BRL)";
00066 #endif
00067 
00068 #include "common.h"
00069 
00070 
00071 #include <stdio.h>
00072 #include "machine.h"
00073 #include "bu.h"
00074 
00075 #ifdef HAVE_MEMORY_H
00076 #  include <memory.h>
00077 #endif
00078 #include <stdio.h>
00079 
00080 #define OUT_IEEE_ZERO   { \
00081         *out++ = 0; \
00082         *out++ = 0; \
00083         *out++ = 0; \
00084         *out++ = 0; \
00085         *out++ = 0; \
00086         *out++ = 0; \
00087         *out++ = 0; \
00088         *out++ = 0; \
00089         continue; } \
00090 
00091 #define OUT_IEEE_NAN    { /* Signaling NAN */ \
00092         *out++ = 0xFF; \
00093         *out++ = 0xF0; \
00094         *out++ = 0x0B; \
00095         *out++ = 0xAD; \
00096         *out++ = 0x0B; \
00097         *out++ = 0xAD; \
00098         *out++ = 0x0B; \
00099         *out++ = 0xAD; \
00100         continue; } \
00101 
00102 /**
00103  *                      H T O N D
00104  *
00105  *  @brief Host to Network Doubles
00106  */
00107 void
00108 htond(register unsigned char *out, register const unsigned char *in, int count)
00109 {
00110 #if     defined(NATURAL_IEEE)
00111         /*
00112          *  First, the case where the system already operates in
00113          *  IEEE format internally, using big-endian order.
00114          *  These are the lucky ones.
00115          */
00116 #       ifdef HAVE_MEMORY_H
00117                 memcpy( out, in, count*8 );
00118 #       else
00119                 bcopy( in, out, count*8 );
00120 #       endif
00121         return;
00122 #       define  HTOND   yes1
00123 #endif
00124 #if     defined(REVERSE_IEEE)
00125         /* This machine uses IEEE, but in little-endian byte order */
00126         register int    i;
00127         for( i=count-1; i >= 0; i-- )  {
00128                 *out++ = in[7];
00129                 *out++ = in[6];
00130                 *out++ = in[5];
00131                 *out++ = in[4];
00132                 *out++ = in[3];
00133                 *out++ = in[2];
00134                 *out++ = in[1];
00135                 *out++ = in[0];
00136                 in += SIZEOF_NETWORK_DOUBLE;
00137         }
00138         return;
00139 #       define  HTOND   yes2
00140 
00141         /* Now, for the machine-specific stuff. */
00142 
00143 #endif
00144 #if     defined(sgi) && !defined(mips)
00145         /*
00146          *  Silicon Graphics Iris workstation.
00147          *  On the 2-D and 3-D, a double is type converted to a float
00148          *  (4 bytes), but IEEE single precision has a different
00149          *  number of exponent bits than double precision, so we
00150          *  have to engage in gyrations here.
00151          */
00152         register int    i;
00153         for( i=count-1; i >= 0; i-- )  {
00154                 /* Brain-damaged 3-D case */
00155                 float small;
00156                 long float big;
00157                 register unsigned char *fp = (unsigned char *)&small;
00158 
00159                 *fp++ = *in++;
00160                 *fp++ = *in++;
00161                 *fp++ = *in++;
00162                 *fp++ = *in++;
00163                 big = small;            /* H/W cvt to IEEE double */
00164 
00165                 fp = (unsigned char *)&big;
00166                 *out++ = *fp++;
00167                 *out++ = *fp++;
00168                 *out++ = *fp++;
00169                 *out++ = *fp++;
00170                 *out++ = *fp++;
00171                 *out++ = *fp++;
00172                 *out++ = *fp++;
00173                 *out++ = *fp++;
00174         }
00175         return;
00176 #       define  HTOND   yes3
00177 #endif
00178 #if     defined(vax)
00179         /*
00180          *  Digital Equipment's VAX.
00181          *  VAX order is +6, +4, +2, sign|exp|fraction+0
00182          *  with 8 bits of exponent, excess 128 base 2, exp=0 => zero.
00183          */
00184         register int    i;
00185         for( i=count-1; i >= 0; i-- )  {
00186                 register unsigned long left, right, signbit;
00187                 register int exp;
00188 
00189                 left  = (in[1]<<24) | (in[0]<<16) | (in[3]<<8) | in[2];
00190                 right = (in[5]<<24) | (in[4]<<16) | (in[7]<<8) | in[6];
00191                 in += 8;
00192 
00193                 exp = (left >> 23) & 0xFF;
00194                 signbit = left & 0x80000000;
00195                 if( exp == 0 )  {
00196                         if( signbit )  {
00197                                 OUT_IEEE_NAN;
00198                         } else {
00199                                 OUT_IEEE_ZERO;
00200                         }
00201                 }
00202                 exp += 1023 - 129;
00203                 /* Round LSB by adding 4, rather than truncating */
00204 #               ifdef ROUNDING
00205                         right = (left<<(32-3)) | ((right+4)>>3);
00206 #               else
00207                         right = (left<<(32-3)) | (right>>3);
00208 #               endif
00209                 left =  ((left & 0x007FFFFF)>>3) | signbit | (exp<<20);
00210                 *out++ = left>>24;
00211                 *out++ = left>>16;
00212                 *out++ = left>>8;
00213                 *out++ = left;
00214                 *out++ = right>>24;
00215                 *out++ = right>>16;
00216                 *out++ = right>>8;
00217                 *out++ = right;
00218         }
00219         return;
00220 #       define  HTOND   yes4
00221 #endif
00222 #if     defined(ibm) || defined(gould)
00223         /*
00224          *  IBM Format.
00225          *  7-bit exponent, base 16.
00226          *  No hidden bits in mantissa (56 bits).
00227          */
00228         register int    i;
00229         for( i=count-1; i >= 0; i-- )  {
00230                 register unsigned long left, right, signbit;
00231                 register int exp;
00232 
00233                 left  = (in[0]<<24) | (in[1]<<16) | (in[2]<<8) | in[3];
00234                 right = (in[4]<<24) | (in[5]<<16) | (in[6]<<8) | in[7];
00235                 in += 8;
00236 
00237                 exp = (left>>24) & 0x7F;        /* excess 64, base 16 */
00238                 if( left == 0 && right == 0 )
00239                         OUT_IEEE_ZERO;
00240 
00241                 signbit = left & 0x80000000;
00242                 left &= 0x00FFFFFF;
00243                 if( signbit )  {
00244                         /* The IBM uses 2's compliment on the mantissa,
00245                          * and IEEE does not.
00246                          */
00247                         left  ^= 0xFFFFFFFF;
00248                         right ^= 0xFFFFFFFF;
00249                         if( right & 0x80000000 )  {
00250                                 /* There may be a carry */
00251                                 right += 1;
00252                                 if( (right & 0x80000000) == 0 )  {
00253                                         /* There WAS a carry */
00254                                         left += 1;
00255                                 }
00256                         } else {
00257                                 /* There will be no carry to worry about */
00258                                 right += 1;
00259                         }
00260                         left &= 0x00FFFFFF;
00261                         exp = (~exp) & 0x7F;
00262                 }
00263                 exp -= (64-32+1);               /* excess 32, base 16, + fudge */
00264                 exp *= 4;                       /* excess 128, base 2 */
00265 ibm_normalized:
00266                 if( left & 0x00800000 )  {
00267                         /* fix = 0; */
00268                         exp += 1023-129+1+ 3-0;/* fudge, slide hidden bit */
00269                 } else if( left & 0x00400000 ) {
00270                         /* fix = 1; */
00271                         exp += 1023-129+1+ 3-1;
00272                         left = (left<<1) |
00273                                 ( (right>>(32-1)) & (0x7FFFFFFF>>(31-1)) );
00274                         right <<= 1;
00275                 } else if( left & 0x00200000 ) {
00276                         /* fix = 2; */
00277                         exp += 1023-129+1+ 3-2;
00278                         left = (left<<2) |
00279                                 ( (right>>(32-2)) & (0x7FFFFFFF>>(31-2)) );
00280                         right <<= 2;
00281                 } else if( left & 0x00100000 ){
00282                         /* fix = 3; */
00283                         exp += 1023-129+1+ 3-3;
00284                         left = (left<<3) |
00285                                 ( (right>>(32-3)) & (0x7FFFFFFF>>(31-3)) );
00286                         right <<= 3;
00287                 } else {
00288                         /*  Encountered 4 consecutive 0 bits of mantissa,
00289                          *  attempt to normalize, and loop.
00290                          *  This case was not expected, but does happen,
00291                          *  at least on the Gould.
00292                          */
00293                         exp -= 4;
00294                         left = (left<<4) | (right>>(32-4));
00295                         right <<= 4;
00296                         goto ibm_normalized;
00297                 }
00298 
00299                 /* After suitable testing, this check can be deleted */
00300                 if( (left & 0x00800000) == 0 )  {
00301                         fprintf(stderr,"ibm->ieee missing 1, left=x%x\n", left);
00302                         left = (left<<1) | (right>>31);
00303                         right <<= 1;
00304                         goto ibm_normalized;
00305                 }
00306 
00307                 /* Having nearly VAX format, shift to IEEE, rounding. */
00308 #               ifdef ROUNDING
00309                         right = (left<<(32-3)) | ((right+4)>>3);
00310 #               else
00311                         right = (left<<(32-3)) | (right>>3);
00312 #               endif
00313                 left =  ((left & 0x007FFFFF)>>3) | signbit | (exp<<20);
00314 
00315                 *out++ = left>>24;
00316                 *out++ = left>>16;
00317                 *out++ = left>>8;
00318                 *out++ = left;
00319                 *out++ = right>>24;
00320                 *out++ = right>>16;
00321                 *out++ = right>>8;
00322                 *out++ = right;
00323         }
00324         return;
00325 #       define  HTOND   yes5
00326 #endif
00327 #if     defined(CRAY1) || defined(CRAY2) || defined(eta10)
00328         /*
00329          *  Cray version.  Somewhat easier using 64-bit registers.
00330          *  15 bit exponent, biased 040000 (octal).  48 mantissa bits.
00331          *  No hidden bits.
00332          */
00333         register int    i;
00334         for( i=count-1; i >= 0; i-- )  {
00335                 register unsigned long word, signbit;
00336                 register int exp;
00337 
00338 #ifdef never
00339                 if( (((int)in) & 07) == 0 )
00340                         word = *((unsigned long *)in);
00341                 else
00342 #endif
00343                         word  = (((long)in[0])<<56) | (((long)in[1])<<48) |
00344                                 (((long)in[2])<<40) | (((long)in[3])<<32) |
00345                                 (((long)in[4])<<24) | (((long)in[5])<<16) |
00346                                 (((long)in[6])<<8) | ((long)in[7]);
00347                 in += 8;
00348 
00349                 if( word == 0 )
00350                         OUT_IEEE_ZERO;
00351                 exp = (word >> 48) & 0x7FFF;
00352                 signbit = word & 0x8000000000000000L;
00353 #ifdef redundant
00354                 if( exp <= 020001 || exp >= 060000 )
00355                         OUT_IEEE_NAN;
00356 #endif
00357                 exp += 1023 - 040000 - 1;
00358                 if( (exp & ~0x7FF) != 0 )  {
00359                         fprintf(stderr,"htond:  Cray exponent too large on x%x\n", word);
00360                         OUT_IEEE_NAN;
00361                 }
00362 
00363 #if defined(CRAY2) && defined(ROUNDING)
00364                 /* Cray-2 seems to round down, XMP rounds up */
00365                 word += 1;
00366 #endif
00367                 word = ((word & 0x00007FFFFFFFFFFFL) << (15-11+1)) |
00368                         signbit | (((long)exp)<<(64-12));
00369 
00370                 *out++ = word>>56;
00371                 *out++ = word>>48;
00372                 *out++ = word>>40;
00373                 *out++ = word>>32;
00374                 *out++ = word>>24;
00375                 *out++ = word>>16;
00376                 *out++ = word>>8;
00377                 *out++ = word;
00378         }
00379         return;
00380 #       define  HTOND   yes6
00381 #endif
00382 #if defined(convex_NATIVE) || defined(__convex__NATIVE)
00383         /*
00384          *  Convex C1 version, for Native Convex floating point.
00385          *  (Which seems to be VAX "G" format -- almost IEEE).
00386          *  CC_OPTS = -fn to get this.
00387          *  In modern times, Convex seems to use IEEE by default,
00388          *  so we do too.
00389          */
00390         register int    i;
00391         for( i=count-1; i >= 0; i-- )  {
00392                 register unsigned long long     word;
00393                 register int exp;
00394 
00395 
00396                 word = *((unsigned long long *)in);
00397                 in += 8;
00398 
00399                 if( word == 0 )
00400                         OUT_IEEE_ZERO;
00401                 exp = (word >> 52) & 0x7FF;
00402                 /* What value here is a Convex NaN ? */
00403                 exp += 1023 - 1024 - 1;
00404                 if( (exp & ~0x7FF) != 0 )  {
00405                         fprintf(stderr,"htond:  Convex exponent too large on x%lx\n", word);
00406                         OUT_IEEE_NAN;
00407                 }
00408 
00409                 word = ((word & 0x800FFFFFFFFFFFFFLL) |
00410                         ((long long)exp)<<52);
00411 
00412                 *((unsigned long long *)out) = word;
00413                 out += 8;
00414         }
00415         return;
00416 #       define  HTOND   yes7
00417 #endif
00418 
00419 #ifndef HTOND
00420 # include "htond.c:  ERROR, no HtoND conversion for this machine type"
00421 #endif
00422 }
00423 
00424 /**
00425  *                      N T O H D
00426  *
00427  *  @brief Network to Host Doubles
00428  */
00429 void
00430 ntohd(register unsigned char *out, register const unsigned char *in, int count)
00431 {
00432 #ifdef NATURAL_IEEE
00433         /*
00434          *  First, the case where the system already operates in
00435          *  IEEE format internally, using big-endian order.
00436          *  These are the lucky ones.
00437          */
00438         if( sizeof(double) != SIZEOF_NETWORK_DOUBLE )
00439                 bu_bomb("ntohd:  sizeof(double) != SIZEOF_NETWORK_DOUBLE\n");
00440 #       ifdef HAVE_MEMORY_H
00441                 memcpy( out, in, count*SIZEOF_NETWORK_DOUBLE );
00442 #       else
00443                 bcopy( in, out, count*SIZEOF_NETWORK_DOUBLE );
00444 #       endif
00445         return;
00446 #       define  NTOHD   yes1
00447 #endif
00448 #if     defined(REVERSE_IEEE)
00449         /* This machine uses IEEE, but in little-endian byte order */
00450         register int    i;
00451         for( i=count-1; i >= 0; i-- )  {
00452                 *out++ = in[7];
00453                 *out++ = in[6];
00454                 *out++ = in[5];
00455                 *out++ = in[4];
00456                 *out++ = in[3];
00457                 *out++ = in[2];
00458                 *out++ = in[1];
00459                 *out++ = in[0];
00460                 in += SIZEOF_NETWORK_DOUBLE;
00461         }
00462         return;
00463 #       define  NTOHD   yes2
00464 #endif
00465 #if     defined(sgi) && !defined(mips)
00466         /*
00467          *  Silicon Graphics Iris workstation.
00468          *  See comments in htond() for discussion of the braindamage.
00469          */
00470         register int    i;
00471         for( i=count-1; i >= 0; i-- )  {
00472                 /* Brain-damaged 3-D case */
00473                 float small;
00474                 long float big;
00475                 register unsigned char *fp = (unsigned char *)&big;
00476                 *fp++ = *in++;
00477                 *fp++ = *in++;
00478                 *fp++ = *in++;
00479                 *fp++ = *in++;
00480                 *fp++ = *in++;
00481                 *fp++ = *in++;
00482                 *fp++ = *in++;
00483                 *fp++ = *in++;
00484                 small = big;            /* H/W cvt to IEEE double */
00485                 fp = (unsigned char *)&small;
00486                 *out++ = *fp++;
00487                 *out++ = *fp++;
00488                 *out++ = *fp++;
00489                 *out++ = *fp++;
00490         }
00491         return;
00492 #       define  NTOHD   yes3
00493 #endif
00494 #if     defined(vax)
00495         /*
00496          *  Digital Equipment's VAX.
00497          *  VAX order is +6, +4, +2, sign|exp|fraction+0
00498          *  with 8 bits of exponent, excess 128 base 2, exp=0 => zero.
00499          */
00500         register int    i;
00501         for( i=count-1; i >= 0; i-- )  {
00502                 register unsigned long left, right, signbit;
00503                 register int fix, exp;
00504 
00505                 left  = (in[0]<<24) | (in[1]<<16) | (in[2]<<8) | in[3];
00506                 right = (in[4]<<24) | (in[5]<<16) | (in[6]<<8) | in[7];
00507                 in += 8;
00508 
00509                 exp = (left >> 20) & 0x7FF;
00510                 signbit = left & 0x80000000;
00511                 if( exp == 0 )  {
00512                         *out++ = 0;             /* VAX zero */
00513                         *out++ = 0;
00514                         *out++ = 0;
00515                         *out++ = 0;
00516                         *out++ = 0;
00517                         *out++ = 0;
00518                         *out++ = 0;
00519                         *out++ = 0;
00520                         continue;
00521                 } else if( exp == 0x7FF )  {
00522 vax_undef:              *out++ = 0x80;          /* VAX "undefined" */
00523                         *out++ = 0;
00524                         *out++ = 0;
00525                         *out++ = 0;
00526                         *out++ = 0;
00527                         *out++ = 0;
00528                         *out++ = 0;
00529                         *out++ = 0;
00530                         continue;
00531                 }
00532                 exp += 129 - 1023;
00533                 /* Check for exponent out of range */
00534                 if( (exp & ~0xFF) != 0 )  {
00535                         fprintf(stderr,"ntohd: VAX exponent overflow\n");
00536                         goto vax_undef;
00537                 }
00538                 left = ((left & 0x000FFFFF)<<3) | signbit | (exp<<23) |
00539                         (right >> (32-3));
00540                 right <<= 3;
00541                 out[1] = left>>24;
00542                 out[0] = left>>16;
00543                 out[3] = left>>8;
00544                 out[2] = left;
00545                 out[5] = right>>24;
00546                 out[4] = right>>16;
00547                 out[7] = right>>8;
00548                 out[6] = right;
00549                 out += 8;
00550         }
00551         return;
00552 #       define  NTOHD   yes4
00553 #endif
00554 #if     defined(ibm) || defined(gould)
00555         /*
00556          *  IBM Format.
00557          *  7-bit exponent, base 16.
00558          *  No hidden bits in mantissa (56 bits).
00559          */
00560         register int    i;
00561         for( i=count-1; i >= 0; i-- )  {
00562                 register unsigned long left, right;
00563                 register int fix, exp, signbit;
00564 
00565                 left  = (in[0]<<24) | (in[1]<<16) | (in[2]<<8) | in[3];
00566                 right = (in[4]<<24) | (in[5]<<16) | (in[6]<<8) | in[7];
00567                 in += 8;
00568 
00569                 exp = ((left >> 20) & 0x7FF);
00570                 signbit = (left & 0x80000000) >> 24;
00571                 if( exp == 0 || exp == 0x7FF )  {
00572 ibm_undef:              *out++ = 0;             /* IBM zero.  No NAN */
00573                         *out++ = 0;
00574                         *out++ = 0;
00575                         *out++ = 0;
00576                         *out++ = 0;
00577                         *out++ = 0;
00578                         *out++ = 0;
00579                         *out++ = 0;
00580                         continue;
00581                 }
00582 
00583                 left = (left & 0x000FFFFF) | 0x00100000;/* replace "hidden" bit */
00584 
00585                 exp += 129 - 1023 -1;   /* fudge, to make /4 and %4 work */
00586                 fix = exp % 4;          /* 2^4 == 16^1;  get fractional exp */
00587                 exp /= 4;               /* excess 32, base 16 */
00588                 exp += (64-32+1);       /* excess 64, base 16, plus fudge */
00589                 if( (exp & ~0xFF) != 0 )  {
00590                         fprintf(stderr,"ntohd:  IBM exponent overflow\n");
00591                         goto ibm_undef;
00592                 }
00593 
00594                 if( fix )  {
00595                         left = (left<<fix) | (right >> (32-fix));
00596                         right <<= fix;
00597                 }
00598 
00599                 if( signbit )  {
00600                         /* The IBM actually uses complimented mantissa
00601                          * and exponent.
00602                          */
00603                         left  ^= 0xFFFFFFFF;
00604                         right ^= 0xFFFFFFFF;
00605                         if( right & 0x80000000 )  {
00606                                 /* There may be a carry */
00607                                 right += 1;
00608                                 if( (right & 0x80000000) == 0 )  {
00609                                         /* There WAS a carry */
00610                                         left += 1;
00611                                 }
00612                         } else {
00613                                 /* There will be no carry to worry about */
00614                                 right += 1;
00615                         }
00616                         left &= 0x00FFFFFF;
00617                         exp = (~exp) & 0x7F;
00618                 }
00619 
00620 
00621                 /*  Not actually required, but for comparison purposes,
00622                  *  normalize the number.  Remove for production speed.
00623                  */
00624                 while( (left & 0x00F00000) == 0 && left != 0 )  {
00625                         if( signbit && exp <= 0x41 )  break;
00626 
00627                         left = (left << 4) | (right >> (32-4));
00628                         right <<= 4;
00629                         if(signbit)  exp--;
00630                         else exp++;
00631                 }
00632 
00633                 *out++ = signbit | exp;
00634                 *out++ = left>>16;
00635                 *out++ = left>>8;
00636                 *out++ = left;
00637                 *out++ = right>>24;
00638                 *out++ = right>>16;
00639                 *out++ = right>>8;
00640                 *out++ = right;
00641         }
00642         return;
00643 #       define  NTOHD   yes5
00644 #endif
00645 #if     defined(CRAY1) || defined(CRAY2) || defined(eta10)
00646         /*
00647          *  Cray version.  Somewhat easier using 64-bit registers.
00648          *  15 bit exponent, biased 040000 (octal).  48 mantissa bits.
00649          *  No hidden bits.
00650          */
00651         register int    i;
00652         for( i=count-1; i >= 0; i-- )  {
00653                 register unsigned long word, signbit;
00654                 register int exp;
00655 
00656 #ifdef never
00657                 if( (((int)in) & 07) == 0 )
00658                         word = *((unsigned long *)in);
00659                 else
00660 #endif
00661                         word  = (((long)in[0])<<56) | (((long)in[1])<<48) |
00662                                 (((long)in[2])<<40) | (((long)in[3])<<32) |
00663                                 (((long)in[4])<<24) | (((long)in[5])<<16) |
00664                                 (((long)in[6])<<8) | ((long)in[7]);
00665                 in += 8;
00666 
00667                 exp = (word>>(64-12)) & 0x7FF;
00668                 signbit = word & 0x8000000000000000L;
00669                 if( exp == 0 )  {
00670                         word = 0;
00671                         goto cray_out;
00672                 }
00673                 if( exp == 0x7FF )  {
00674                         word = 067777L<<48;     /* Cray out of range */
00675                         goto cray_out;
00676                 }
00677                 exp += 040000 - 1023 + 1;
00678                 word = ((word & 0x000FFFFFFFFFFFFFL) >> (15-11+1)) |
00679                         0x0000800000000000L | signbit |
00680                         (((long)exp)<<(64-16));
00681 
00682 cray_out:
00683                 *out++ = word>>56;
00684                 *out++ = word>>48;
00685                 *out++ = word>>40;
00686                 *out++ = word>>32;
00687                 *out++ = word>>24;
00688                 *out++ = word>>16;
00689                 *out++ = word>>8;
00690                 *out++ = word;
00691         }
00692         return;
00693 #       define  NTOHD   yes6
00694 #endif
00695 #if defined(convex_NATIVE) || defined(__convex__NATIVE)
00696         /*
00697          *  Convex C1 version, for Native Convex floating point.
00698          */
00699         register int    i;
00700         for( i=count-1; i >= 0; i-- )  {
00701                 register unsigned long long     word;
00702                 register int exp;
00703 
00704                 word = *((unsigned long long *)in);
00705                 in += 8;
00706 
00707                 exp = (word >> 52) & 0x7FF;
00708                 if( exp == 0 )  {
00709                         word = 0;
00710                         goto convex_out;
00711                 }
00712                 if( exp == 0x7FF )  {
00713                         /* IEEE NaN = Convex what? */
00714                         fprintf(stderr,"ntohd: Convex NaN unimplemented\n");
00715                         word = 0;
00716                         goto convex_out;
00717                 }
00718                 exp += 1024 - 1023 + 1;
00719                 word = (word & 0x800FFFFFFFFFFFFFLL) |
00720                         (((long long)exp)<<52);
00721 
00722 convex_out:
00723                 *((unsigned long long *)out) = word;
00724                 out += 8;
00725         }
00726         return;
00727 #       define  NTOHD   yes7
00728 #endif
00729 
00730 #ifndef NTOHD
00731 # include "ntohd.c:  ERROR, no NtoHD conversion for this machine type"
00732 #endif
00733 }
00734 /*@}*/
00735 /*
00736  * Local Variables:
00737  * mode: C
00738  * tab-width: 8
00739  * c-basic-offset: 4
00740  * indent-tabs-mode: t
00741  * End:
00742  * ex: shiftwidth=4 tabstop=8
00743  */

Generated on Mon Sep 18 01:24:48 2006 for BRL-CAD by  doxygen 1.4.6