BRL-CAD
htond.c
Go to the documentation of this file.
1 /* H T O N D . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 #ifdef HAVE_MEMORY_H
24 # include <memory.h>
25 #endif
26 #include <stdio.h>
27 #include <assert.h>
28 
29 #include "bu/cv.h"
30 #include "bu/endian.h"
31 #include "bu/log.h"
32 
33 #define OUT_IEEE_ZERO { \
34  *out++ = 0; \
35  *out++ = 0; \
36  *out++ = 0; \
37  *out++ = 0; \
38  *out++ = 0; \
39  *out++ = 0; \
40  *out++ = 0; \
41  *out++ = 0; \
42  continue; \
43 }
44 
45 
46 #define OUT_IEEE_NAN { /* Signaling NAN */ \
47  *out++ = 0xFF; \
48  *out++ = 0xF0; \
49  *out++ = 0x0B; \
50  *out++ = 0xAD; \
51  *out++ = 0x0B; \
52  *out++ = 0xAD; \
53  *out++ = 0x0B; \
54  *out++ = 0xAD; \
55  continue; \
56 }
57 
58 
59 void
60 bu_cv_htond(register unsigned char *out, register const unsigned char *in, size_t count)
61 {
62  register size_t i;
63 
64  assert(sizeof(double) == SIZEOF_NETWORK_DOUBLE);
65 
66  switch (bu_byteorder()) {
67  case BU_BIG_ENDIAN:
68  /*
69  * First, the case where the system already operates in
70  * IEEE format internally, using big-endian order. These
71  * are the lucky ones.
72  */
73  memcpy(out, in, count*SIZEOF_NETWORK_DOUBLE);
74  return;
75  case BU_LITTLE_ENDIAN:
76  /*
77  * This machine uses IEEE, but in little-endian byte order
78  */
79  for (i=count; i > 0; i--) {
80  *out++ = in[7];
81  *out++ = in[6];
82  *out++ = in[5];
83  *out++ = in[4];
84  *out++ = in[3];
85  *out++ = in[2];
86  *out++ = in[1];
87  *out++ = in[0];
89  }
90  return;
91  default:
92  /* nada */
93  break;
94  }
95 
96  /* Now, for the machine-specific stuff.
97  *
98  * XXX - Note that the below will not likely work without defining
99  * a corresponding pre-processor flag.
100  */
101 
102 #if defined(sgi) && !defined(mips)
103  /*
104  * Silicon Graphics Iris workstation. On the 2-D and 3-D, a
105  * double is type converted to a float (4 bytes), but IEEE single
106  * precision has a different number of exponent bits than double
107  * precision, so we have to engage in gyrations here.
108  */
109  for (i=count; i > 0; i--) {
110  /* Brain-damaged 3-D case */
111  float small;
112  long float big;
113  register unsigned char *fp = (unsigned char *)&small;
114 
115  *fp++ = *in++;
116  *fp++ = *in++;
117  *fp++ = *in++;
118  *fp++ = *in++;
119  big = small; /* H/W cvt to IEEE double */
120 
121  fp = (unsigned char *)&big;
122  *out++ = *fp++;
123  *out++ = *fp++;
124  *out++ = *fp++;
125  *out++ = *fp++;
126  *out++ = *fp++;
127  *out++ = *fp++;
128  *out++ = *fp++;
129  *out++ = *fp++;
130  }
131  return;
132 #endif
133 #if defined(vax)
134  /*
135  * Digital Equipment's VAX.
136  * VAX order is +6, +4, +2, sign|exp|fraction+0
137  * with 8 bits of exponent, excess 128 base 2, exp=0 => zero.
138  */
139  for (i=count; i > 0; i--) {
140  register unsigned long left, right, signbit;
141  register int exp;
142 
143  left = (in[1]<<24) | (in[0]<<16) | (in[3]<<8) | in[2];
144  right = (in[5]<<24) | (in[4]<<16) | (in[7]<<8) | in[6];
145  in += 8;
146 
147  exp = (left >> 23) & 0xFF;
148  signbit = left & 0x80000000;
149  if (exp == 0) {
150  if (signbit) {
151  OUT_IEEE_NAN;
152  } else {
154  }
155  }
156  exp += 1023 - 129;
157  /* Round LSB by adding 4, rather than truncating */
158 # ifdef ROUNDING
159  right = (left<<(32-3)) | ((right+4)>>3);
160 # else
161  right = (left<<(32-3)) | (right>>3);
162 # endif
163  left = ((left & 0x007FFFFF)>>3) | signbit | (exp<<20);
164  *out++ = left>>24;
165  *out++ = left>>16;
166  *out++ = left>>8;
167  *out++ = left;
168  *out++ = right>>24;
169  *out++ = right>>16;
170  *out++ = right>>8;
171  *out++ = right;
172  }
173  return;
174 #endif
175 #if defined(ibm) || defined(gould)
176  /*
177  * IBM Format.
178  * 7-bit exponent, base 16.
179  * No hidden bits in mantissa (56 bits).
180  */
181  for (i=count; i > 0; i--) {
182  register unsigned long left, right, signbit;
183  register int exp;
184 
185  left = (in[0]<<24) | (in[1]<<16) | (in[2]<<8) | in[3];
186  right = (in[4]<<24) | (in[5]<<16) | (in[6]<<8) | in[7];
187  in += 8;
188 
189  exp = (left>>24) & 0x7F; /* excess 64, base 16 */
190  if (left == 0 && right == 0)
192 
193  signbit = left & 0x80000000;
194  left &= 0x00FFFFFF;
195  if (signbit) {
196  /* The IBM uses 2's compliment on the mantissa,
197  * and IEEE does not.
198  */
199  left ^= 0xFFFFFFFF;
200  right ^= 0xFFFFFFFF;
201  if (right & 0x80000000) {
202  /* There may be a carry */
203  right += 1;
204  if ((right & 0x80000000) == 0) {
205  /* There WAS a carry */
206  left += 1;
207  }
208  } else {
209  /* There will be no carry to worry about */
210  right += 1;
211  }
212  left &= 0x00FFFFFF;
213  exp = (~exp) & 0x7F;
214  }
215  exp -= (64-32+1); /* excess 32, base 16, + fudge */
216  exp *= 4; /* excess 128, base 2 */
217  ibm_normalized:
218  if (left & 0x00800000) {
219  /* fix = 0; */
220  exp += 1023-129+1+ 3-0;/* fudge, slide hidden bit */
221  } else if (left & 0x00400000) {
222  /* fix = 1; */
223  exp += 1023-129+1+ 3-1;
224  left = (left<<1) |
225  ((right>>(32-1)) & (0x7FFFFFFF>>(31-1)));
226  right <<= 1;
227  } else if (left & 0x00200000) {
228  /* fix = 2; */
229  exp += 1023-129+1+ 3-2;
230  left = (left<<2) |
231  ((right>>(32-2)) & (0x7FFFFFFF>>(31-2)));
232  right <<= 2;
233  } else if (left & 0x00100000) {
234  /* fix = 3; */
235  exp += 1023-129+1+ 3-3;
236  left = (left<<3) |
237  ((right>>(32-3)) & (0x7FFFFFFF>>(31-3)));
238  right <<= 3;
239  } else {
240  /* Encountered 4 consecutive 0 bits of mantissa,
241  * attempt to normalize, and loop.
242  * This case was not expected, but does happen,
243  * at least on the Gould.
244  */
245  exp -= 4;
246  left = (left<<4) | (right>>(32-4));
247  right <<= 4;
248  goto ibm_normalized;
249  }
250 
251  /* After suitable testing, this check can be deleted */
252  if ((left & 0x00800000) == 0) {
253  fprintf(stderr, "ibm->ieee missing 1, left=x%x\n", left);
254  left = (left<<1) | (right>>31);
255  right <<= 1;
256  goto ibm_normalized;
257  }
258 
259  /* Having nearly VAX format, shift to IEEE, rounding. */
260 # ifdef ROUNDING
261  right = (left<<(32-3)) | ((right+4)>>3);
262 # else
263  right = (left<<(32-3)) | (right>>3);
264 # endif
265  left = ((left & 0x007FFFFF)>>3) | signbit | (exp<<20);
266 
267  *out++ = left>>24;
268  *out++ = left>>16;
269  *out++ = left>>8;
270  *out++ = left;
271  *out++ = right>>24;
272  *out++ = right>>16;
273  *out++ = right>>8;
274  *out++ = right;
275  }
276  return;
277 #endif
278 #if defined(CRAY1) || defined(CRAY2) || defined(eta10)
279  /*
280  * Cray version. Somewhat easier using 64-bit registers.
281  * 15 bit exponent, biased 040000 (octal). 48 mantissa bits.
282  * No hidden bits.
283  */
284  for (i=count; i > 0; i--) {
285  register unsigned long word, signbit;
286  register int exp;
287 
288  word = (((long)in[0])<<56) | (((long)in[1])<<48) |
289  (((long)in[2])<<40) | (((long)in[3])<<32) |
290  (((long)in[4])<<24) | (((long)in[5])<<16) |
291  (((long)in[6])<<8) | ((long)in[7]);
292  in += 8;
293 
294  if (word == 0)
296  exp = (word >> 48) & 0x7FFF;
297  signbit = word & 0x8000000000000000L;
298 #ifdef redundant
299  if (exp <= 020001 || exp >= 060000)
300  OUT_IEEE_NAN;
301 #endif
302  exp += 1023 - 040000 - 1;
303  if ((exp & ~0x7FF) != 0) {
304  fprintf(stderr, "bu_cv_htond: Cray exponent too large on x%x\n", word);
305  OUT_IEEE_NAN;
306  }
307 
308 #if defined(CRAY2) && defined(ROUNDING)
309  /* Cray-2 seems to round down, XMP rounds up */
310  word += 1;
311 #endif
312  word = ((word & 0x00007FFFFFFFFFFFL) << (15-11+1)) |
313  signbit | (((long)exp)<<(64-12));
314 
315  *out++ = word>>56;
316  *out++ = word>>48;
317  *out++ = word>>40;
318  *out++ = word>>32;
319  *out++ = word>>24;
320  *out++ = word>>16;
321  *out++ = word>>8;
322  *out++ = word;
323  }
324  return;
325 #endif
326 #if defined(convex_NATIVE) || defined(__convex__NATIVE)
327  /*
328  * Convex C1 version, for Native Convex floating point.
329  * (Which seems to be VAX "G" format -- almost IEEE).
330  * CC_OPTS = -fn to get this.
331  * In modern times, Convex seems to use IEEE by default,
332  * so we do too.
333  */
334  for (i=count; i > 0; i--) {
335  register unsigned long long word;
336  register int exp;
337 
338 
339  word = *((unsigned long long *)in);
340  in += 8;
341 
342  if (word == 0)
344  exp = (word >> 52) & 0x7FF;
345  /* What value here is a Convex NaN ? */
346  exp += 1023 - 1024 - 1;
347  if ((exp & ~0x7FF) != 0) {
348  fprintf(stderr, "bu_cv_htond: Convex exponent too large on x%lx\n", word);
349  OUT_IEEE_NAN;
350  }
351 
352  word = ((word & 0x800FFFFFFFFFFFFFLL) |
353  ((long long)exp)<<52);
354 
355  *((unsigned long long *)out) = word;
356  out += 8;
357  }
358  return;
359 #endif
360 
361  bu_bomb("bu_cv_htond.c: ERROR, no HtoND conversion for this machine type\n");
362 }
363 
364 
365 void
366 bu_cv_ntohd(register unsigned char *out, register const unsigned char *in, size_t count)
367 {
368  register size_t i;
369  bu_endian_t order;
370 
371  assert(sizeof(double) == SIZEOF_NETWORK_DOUBLE);
372 
373  order = bu_byteorder();
374 
375  switch (order) {
376  case BU_BIG_ENDIAN:
377  /*
378  * First, the case where the system already operates in
379  * IEEE format internally, using big-endian order. These
380  * are the lucky ones.
381  */
382  memcpy(out, in, count*SIZEOF_NETWORK_DOUBLE);
383  return;
384  case BU_LITTLE_ENDIAN:
385  /*
386  * This machine uses IEEE, but in little-endian byte order
387  */
388  for (i=count; i > 0; i--) {
389  *out++ = in[7];
390  *out++ = in[6];
391  *out++ = in[5];
392  *out++ = in[4];
393  *out++ = in[3];
394  *out++ = in[2];
395  *out++ = in[1];
396  *out++ = in[0];
397  in += SIZEOF_NETWORK_DOUBLE;
398  }
399  return;
400  default:
401  /* nada */
402  break;
403  }
404 
405  /* Now, for the machine-specific stuff.
406  *
407  * XXX - Note that the below will not likely work without defining
408  * a corresponding pre-processor flag.
409  */
410 
411 #if defined(sgi) && !defined(mips)
412  /*
413  * Silicon Graphics Iris workstation.
414  * See comments in bu_cv_htond() for discussion of the braindamage.
415  */
416  for (i=count; i > 0; i--) {
417  /* Brain-damaged 3-D case */
418  float small;
419  long float big;
420  register unsigned char *fp = (unsigned char *)&big;
421  *fp++ = *in++;
422  *fp++ = *in++;
423  *fp++ = *in++;
424  *fp++ = *in++;
425  *fp++ = *in++;
426  *fp++ = *in++;
427  *fp++ = *in++;
428  *fp++ = *in++;
429  small = big; /* H/W cvt to IEEE double */
430  fp = (unsigned char *)&small;
431  *out++ = *fp++;
432  *out++ = *fp++;
433  *out++ = *fp++;
434  *out++ = *fp++;
435  }
436  return;
437 #endif
438 #if defined(vax)
439  /*
440  * Digital Equipment's VAX.
441  * VAX order is +6, +4, +2, sign|exp|fraction+0
442  * with 8 bits of exponent, excess 128 base 2, exp=0 => zero.
443  */
444  for (i=count; i > 0; i--) {
445  register unsigned long left, right, signbit;
446  register int fix, exp;
447 
448  left = (in[0]<<24) | (in[1]<<16) | (in[2]<<8) | in[3];
449  right = (in[4]<<24) | (in[5]<<16) | (in[6]<<8) | in[7];
450  in += 8;
451 
452  exp = (left >> 20) & 0x7FF;
453  signbit = left & 0x80000000;
454  if (exp == 0) {
455  *out++ = 0; /* VAX zero */
456  *out++ = 0;
457  *out++ = 0;
458  *out++ = 0;
459  *out++ = 0;
460  *out++ = 0;
461  *out++ = 0;
462  *out++ = 0;
463  continue;
464  } else if (exp == 0x7FF) {
465  vax_undef:
466  *out++ = 0x80; /* VAX "undefined" */
467  *out++ = 0;
468  *out++ = 0;
469  *out++ = 0;
470  *out++ = 0;
471  *out++ = 0;
472  *out++ = 0;
473  *out++ = 0;
474  continue;
475  }
476  exp += 129 - 1023;
477  /* Check for exponent out of range */
478  if ((exp & ~0xFF) != 0) {
479  fprintf(stderr, "bu_cv_ntohd: VAX exponent overflow\n");
480  goto vax_undef;
481  }
482  left = ((left & 0x000FFFFF)<<3) | signbit | (exp<<23) |
483  (right >> (32-3));
484  right <<= 3;
485  out[1] = left>>24;
486  out[0] = left>>16;
487  out[3] = left>>8;
488  out[2] = left;
489  out[5] = right>>24;
490  out[4] = right>>16;
491  out[7] = right>>8;
492  out[6] = right;
493  out += 8;
494  }
495  return;
496 #endif
497 #if defined(ibm) || defined(gould)
498  /*
499  * IBM Format.
500  * 7-bit exponent, base 16.
501  * No hidden bits in mantissa (56 bits).
502  */
503  for (i=count; i > 0; i--) {
504  register unsigned long left, right;
505  register int fix, exp, signbit;
506 
507  left = (in[0]<<24) | (in[1]<<16) | (in[2]<<8) | in[3];
508  right = (in[4]<<24) | (in[5]<<16) | (in[6]<<8) | in[7];
509  in += 8;
510 
511  exp = ((left >> 20) & 0x7FF);
512  signbit = (left & 0x80000000) >> 24;
513  if (exp == 0 || exp == 0x7FF) {
514  ibm_undef:
515  *out++ = 0; /* IBM zero. No NAN */
516  *out++ = 0;
517  *out++ = 0;
518  *out++ = 0;
519  *out++ = 0;
520  *out++ = 0;
521  *out++ = 0;
522  *out++ = 0;
523  continue;
524  }
525 
526  left = (left & 0x000FFFFF) | 0x00100000;/* replace "hidden" bit */
527 
528  exp += 129 - 1023 -1; /* fudge, to make /4 and %4 work */
529  fix = exp % 4; /* 2^4 == 16^1; get fractional exp */
530  exp /= 4; /* excess 32, base 16 */
531  exp += (64-32+1); /* excess 64, base 16, plus fudge */
532  if ((exp & ~0xFF) != 0) {
533  fprintf(stderr, "bu_cv_ntohd: IBM exponent overflow\n");
534  goto ibm_undef;
535  }
536 
537  if (fix) {
538  left = (left<<fix) | (right >> (32-fix));
539  right <<= fix;
540  }
541 
542  if (signbit) {
543  /* The IBM actually uses complimented mantissa
544  * and exponent.
545  */
546  left ^= 0xFFFFFFFF;
547  right ^= 0xFFFFFFFF;
548  if (right & 0x80000000) {
549  /* There may be a carry */
550  right += 1;
551  if ((right & 0x80000000) == 0) {
552  /* There WAS a carry */
553  left += 1;
554  }
555  } else {
556  /* There will be no carry to worry about */
557  right += 1;
558  }
559  left &= 0x00FFFFFF;
560  exp = (~exp) & 0x7F;
561  }
562 
563 
564  /* Not actually required, but for comparison purposes,
565  * normalize the number. Remove for production speed.
566  */
567  while ((left & 0x00F00000) == 0 && left != 0) {
568  if (signbit && exp <= 0x41) break;
569 
570  left = (left << 4) | (right >> (32-4));
571  right <<= 4;
572  if (signbit) exp--;
573  else exp++;
574  }
575 
576  *out++ = signbit | exp;
577  *out++ = left>>16;
578  *out++ = left>>8;
579  *out++ = left;
580  *out++ = right>>24;
581  *out++ = right>>16;
582  *out++ = right>>8;
583  *out++ = right;
584  }
585  return;
586 #endif
587 #if defined(CRAY1) || defined(CRAY2) || defined(eta10)
588  /*
589  * Cray version. Somewhat easier using 64-bit registers. 15 bit
590  * exponent, biased 040000 (octal). 48 mantissa bits. No hidden
591  * bits.
592  */
593  for (i=count; i > 0; i--) {
594  register unsigned long word, signbit;
595  register int exp;
596 
597  word = (((long)in[0])<<56) | (((long)in[1])<<48) |
598  (((long)in[2])<<40) | (((long)in[3])<<32) |
599  (((long)in[4])<<24) | (((long)in[5])<<16) |
600  (((long)in[6])<<8) | ((long)in[7]);
601  in += 8;
602 
603  exp = (word>>(64-12)) & 0x7FF;
604  signbit = word & 0x8000000000000000L;
605  if (exp == 0) {
606  word = 0;
607  goto cray_out;
608  }
609  if (exp == 0x7FF) {
610  word = 067777L<<48; /* Cray out of range */
611  goto cray_out;
612  }
613  exp += 040000 - 1023 + 1;
614  word = ((word & 0x000FFFFFFFFFFFFFL) >> (15-11+1)) |
615  0x0000800000000000L | signbit |
616  (((long)exp)<<(64-16));
617 
618  cray_out:
619  *out++ = word>>56;
620  *out++ = word>>48;
621  *out++ = word>>40;
622  *out++ = word>>32;
623  *out++ = word>>24;
624  *out++ = word>>16;
625  *out++ = word>>8;
626  *out++ = word;
627  }
628  return;
629 #endif
630 #if defined(convex_NATIVE) || defined(__convex__NATIVE)
631  /*
632  * Convex C1 version, for Native Convex floating point.
633  */
634  for (i=count; i > 0; i--) {
635  register unsigned long long word;
636  register int exp;
637 
638  word = *((unsigned long long *)in);
639  in += 8;
640 
641  exp = (word >> 52) & 0x7FF;
642  if (exp == 0) {
643  word = 0;
644  goto convex_out;
645  }
646  if (exp == 0x7FF) {
647  /* IEEE NaN = Convex what? */
648  fprintf(stderr, "bu_cv_ntohd: Convex NaN unimplemented\n");
649  word = 0;
650  goto convex_out;
651  }
652  exp += 1024 - 1023 + 1;
653  word = (word & 0x800FFFFFFFFFFFFFLL) |
654  (((long long)exp)<<52);
655 
656  convex_out:
657  *((unsigned long long *)out) = word;
658  out += 8;
659  }
660  return;
661 #endif
662 
663  bu_bomb("bu_cv_ntohd.c: ERROR, no NtoHD conversion for this machine type\n");
664 }
665 
666 
667 /*
668  * Local Variables:
669  * mode: C
670  * tab-width: 8
671  * indent-tabs-mode: t
672  * c-file-style: "stroustrup"
673  * End:
674  * ex: shiftwidth=4 tabstop=8
675  */
#define SIZEOF_NETWORK_DOUBLE
Definition: cv.h:48
void bu_cv_ntohd(register unsigned char *out, register const unsigned char *in, size_t count)
Definition: htond.c:366
bu_endian_t bu_byteorder(void)
Definition: endian.c:27
Header file for the BRL-CAD common definitions.
bu_endian_t
Definition: endian.h:41
#define OUT_IEEE_ZERO
Definition: htond.c:33
goto out
Definition: nmg_mod.c:3846
void bu_cv_htond(register unsigned char *out, register const unsigned char *in, size_t count)
Definition: htond.c:60
#define OUT_IEEE_NAN
Definition: htond.c:46
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91