1
2 /* Vis5D version 5.0 */
3
4 /*
5 Vis5D system for visualizing five dimensional gridded data sets
6 Copyright (C) 1990 - 1997 Bill Hibbard, Johan Kellum, Brian Paul,
7 Dave Santek, and Andre Battaiola.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 1, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 /*
25 * Functions to do binary I/O of floats, ints.
26 *
27 * >>>> These functions are built on top of Unix I/O functions, not stdio! <<<<
28 *
29 * The file format is assumed to be BIG-ENDIAN.
30 * If this code is compiled with -DLITTLE and executes on a little endian
31 * CPU then byte-swapping will be done.
32 *
33 * If an ANSI compiler is used prototypes and ANSI function declarations
34 * are used. Otherwise use K&R conventions.
35 *
36 * If we're running on a CRAY (8-byte ints and floats), conversions will
37 * be done as needed.
38 */
39
40
41 /*
42 * Updates:
43 *
44 * April 13, 1995, brianp
45 * added cray_to_ieee and iee_to_cray array conversion functions.
46 * fixed potential cray bug in write_float4_array function.
47 *
48 */
49
50
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #ifdef _CRAY
56 # include <string.h>
57 #include <grass/gis.h>
58 #endif
59 #include "binio.h"
60
61
62
63
64 /**********************************************************************/
65
66 /****** Byte Flipping *****/
67
68 /**********************************************************************/
69
70
71 #define FLIP4( n ) ( (n & 0xff000000) >> 24 \
72 | (n & 0x00ff0000) >> 8 \
73 | (n & 0x0000ff00) << 8 \
74 | (n & 0x000000ff) << 24 )
75
76
77 #define FLIP2( n ) (((unsigned short) (n & 0xff00)) >> 8 | (n & 0x00ff) << 8)
78
79
80
81 /*
82 * Flip the order of the 4 bytes in an array of 4-byte words.
83 */
flip4(const unsigned int * src,unsigned int * dest,int n)84 void flip4(const unsigned int *src, unsigned int *dest, int n)
85 {
86 int i;
87
88 for (i = 0; i < n; i++) {
89 unsigned int tmp = src[i];
90
91 dest[i] = FLIP4(tmp);
92 }
93 }
94
95
96
97 /*
98 * Flip the order of the 2 bytes in an array of 2-byte words.
99 */
flip2(const unsigned short * src,unsigned short * dest,int n)100 void flip2(const unsigned short *src, unsigned short *dest, int n)
101 {
102 int i;
103
104 for (i = 0; i < n; i++) {
105 unsigned short tmp = src[i];
106
107 dest[i] = FLIP2(tmp);
108 }
109 }
110
111
112 #ifdef _CRAY
113
114 /*****************************************************************************
115 *
116 * The following source code is in the public domain.
117 * Specifically, we give to the public domain all rights for future licensing
118 * of the source code, all resale rights, and all publishing rights.
119 *
120 * We ask, but do not require, that the following message be included in all
121 * derived works:
122 *
123 * Portions developed at the National Center for Supercomputing Applications at
124 * the University of Illinois at Urbana-Champaign.
125 *
126 * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
127 * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
128 * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
129 *
130 ****************************************************************************/
131
132 /** THESE ROUTINES MUST BE COMPILED ON THE CRAY ONLY SINCE THEY **/
133
134 /** REQUIRE 8-BYTES PER C-TYPE LONG **/
135
136 /* Cray to IEEE single precision */
c_to_if(long * t,const long * f)137 static void c_to_if(long *t, const long *f)
138 {
139 if (*f != 0) {
140 *t = (((*f & 0x8000000000000000) | /* sign bit */
141 ((((*f & 0x7fff000000000000) >> 48) - 16258) << 55)) + /* exp */
142 (((*f & 0x00007fffff000000) + ((*f & 0x0000000000800000) << 1)) << 8)); /* mantissa */
143 }
144 else
145 *t = *f;
146 }
147
148
149 #define C_TO_IF( T, F ) \
150 if (F != 0) { \
151 T = (((F & 0x8000000000000000) | \
152 ((((F & 0x7fff000000000000) >> 48)-16258) << 55)) + \
153 (((F & 0x00007fffff000000) + \
154 ((F & 0x0000000000800000) << 1)) << 8)); \
155 } \
156 else { \
157 T = F; \
158 }
159
160
161
162 /* IEEE single precison to Cray */
if_to_c(long * t,const long * f)163 static void if_to_c(long *t, const long *f)
164 {
165 if (*f != 0) {
166 *t = (((*f & 0x8000000000000000) |
167 ((*f & 0x7f80000000000000) >> 7) +
168 (16258 << 48)) |
169 (((*f & 0x007fffff00000000) >> 8) | (0x0000800000000000)));
170 if ((*f << 1) == 0)
171 *t = 0;
172 }
173 else
174 *t = *f;
175 }
176
177 /* T and F must be longs! */
178 #define IF_TO_C( T, F ) \
179 if (F != 0) { \
180 T = (((F & 0x8000000000000000) | \
181 ((F & 0x7f80000000000000) >> 7) + \
182 (16258 << 48)) | \
183 (((F & 0x007fffff00000000) >> 8) | (0x0000800000000000))); \
184 if ((F << 1) == 0) T = 0; \
185 } \
186 else { \
187 T = F; \
188 }
189
190
191
192
193 /*
194 * Convert an array of Cray 8-byte floats to an array of IEEE 4-byte floats.
195 */
cray_to_ieee_array(long * dest,const float * source,int n)196 void cray_to_ieee_array(long *dest, const float *source, int n)
197 {
198 long *dst;
199 const long *src;
200 long tmp1, tmp2;
201 int i;
202
203 dst = dest;
204 src = (const long *)source;
205
206 for (i = 0; i < n; i += 2) { /* add 1 in case n is odd */
207 c_to_if(&tmp1, &src[i]);
208 c_to_if(&tmp2, &src[i + 1]);
209 *dst = (tmp1 & 0xffffffff00000000) | (tmp2 >> 32);
210 dst++;
211 }
212 }
213
214
215
216 /*
217 * Convert an array of IEEE 4-byte floats to an array of 8-byte Cray floats.
218 */
ieee_to_cray_array(float * dest,const long * source,int n)219 void ieee_to_cray_array(float *dest, const long *source, int n)
220 {
221 long *dst;
222 const long *src;
223 int i;
224 long ieee;
225
226 src = source;
227 dst = (long *)dest;
228
229 for (i = 0; i < n; i++) {
230 /* most significant 4-bytes of ieee contain bit pattern to convert */
231 if ((i & 1) == 0) {
232 /* get upper half */
233 ieee = src[i / 2] & 0xffffffff00000000;
234 }
235 else {
236 /* get lower half */
237 ieee = src[i / 2] << 32;
238 }
239 if_to_c(dst, &ieee);
240 dst++;
241 }
242 }
243
244
245 #endif /*_CRAY*/
246
247
248
249 /**********************************************************************/
250
251 /***** Read Functions *****/
252
253 /**********************************************************************/
254
255
256 /*
257 * Read a block of bytes.
258 * Input: f - the file descriptor to read from.
259 * b - address of buffer to read into.
260 * n - number of bytes to read.
261 * Return: number of bytes read, 0 if error.
262 */
read_bytes(int f,void * b,int n)263 int read_bytes(int f, void *b, int n)
264 {
265 return read(f, b, n);
266 }
267
268
269
270 /*
271 * Read an array of 2-byte integers.
272 * Input: f - file descriptor
273 * iarray - address to put integers
274 * n - number of integers to read.
275 * Return: number of integers read.
276 */
read_int2_array(int f,short * iarray,int n)277 int read_int2_array(int f, short *iarray, int n)
278 {
279 #ifdef _CRAY
280 int i;
281 signed char *buffer;
282 int nread;
283
284 buffer = (signed char *)G_malloc(n * 2);
285 if (!buffer)
286 return 0;
287 nread = read(f, buffer, n * 2);
288 if (nread <= 0)
289 return 0;
290 nread /= 2;
291 for (i = 0; i < nread; i++) {
292 /* don't forget about sign extension! */
293 iarray[i] = (buffer[i * 2] * 256) | buffer[i * 2 + 1];
294 }
295 G_free(buffer);
296 return nread;
297 #else
298 int nread = read(f, iarray, n * 2);
299
300 if (nread <= 0)
301 return 0;
302 #ifdef LITTLE
303 flip2((const unsigned short *)iarray, (unsigned short *)iarray,
304 nread / 2);
305 #endif
306 return nread / 2;
307 #endif
308 }
309
310
311
312 /*
313 * Read an array of unsigned 2-byte integers.
314 * Input: f - file descriptor
315 * iarray - address to put integers
316 * n - number of integers to read.
317 * Return: number of integers read.
318 */
read_uint2_array(int f,unsigned short * iarray,int n)319 int read_uint2_array(int f, unsigned short *iarray, int n)
320 {
321 #ifdef _CRAY
322 int i;
323 unsigned char *buffer;
324 int nread;
325
326 buffer = (unsigned char *)G_malloc(n * 2);
327 if (!buffer)
328 return 0;
329 nread = read(f, buffer, n * 2);
330 if (nread <= 0)
331 return 0;
332 nread /= 2;
333 for (i = 0; i < nread; i++) {
334 iarray[i] = (buffer[i * 2] << 8) | buffer[i * 2 + 1];
335 }
336 G_free(buffer);
337 return nread;
338 #else
339 int nread = read(f, iarray, n * 2);
340
341 if (nread <= 0)
342 return 0;
343 #ifdef LITTLE
344 flip2(iarray, iarray, nread / 2);
345 #endif
346 return nread / 2;
347 #endif
348 }
349
350
351
352 /*
353 * Read a 4-byte integer.
354 * Input: f - the file descriptor to read from
355 * i - pointer to integer to put result into.
356 * Return: 1 = ok, 0 = error
357 */
read_int4(int f,int * i)358 int read_int4(int f, int *i)
359 {
360 #ifdef LITTLE
361 /* read big endian and convert to little endian */
362 unsigned int n;
363
364 if (read(f, &n, 4) == 4) {
365 *i = FLIP4(n);
366 return 1;
367 }
368 else {
369 return 0;
370 }
371 #else
372 if (read(f, i, 4) == 4) {
373 # ifdef _CRAY
374 *i = *i >> 32;
375 # endif
376 return 1;
377 }
378 else {
379 return 0;
380 }
381 #endif
382 }
383
384
385
386 /*
387 * Read an array of 4-byte integers.
388 * Input: f - file descriptor
389 * iarray - address to put integers
390 * n - number of integers to read.
391 * Return: number of integers read.
392 */
read_int4_array(int f,int * iarray,int n)393 int read_int4_array(int f, int *iarray, int n)
394 {
395 #ifdef _CRAY
396 int j, nread;
397 int *buffer;
398
399 buffer = (int *)G_malloc((n + 1) * 4);
400 if (!buffer)
401 return 0;
402 nread = read(f, buffer, 4 * n);
403 if (nread <= 0) {
404 return 0;
405 }
406 nread /= 4;
407
408 for (j = 0; j < nread; j++) {
409 if ((j & 1) == 0) {
410 iarray[j] = buffer[j / 2] >> 32;
411 }
412 else {
413 iarray[j] = buffer[j / 2] & 0xffffffff;
414 }
415 }
416 G_free(buffer);
417 return nread;
418 #else
419 int nread = read(f, iarray, 4 * n);
420
421 if (nread <= 0)
422 return 0;
423 # ifdef LITTLE
424 flip4((const unsigned int *)iarray, (unsigned int *)iarray, nread / 4);
425 # endif
426 return nread / 4;
427 #endif
428 }
429
430
431
432 /*
433 * Read a 4-byte IEEE float.
434 * Input: f - the file descriptor to read from.
435 * x - pointer to float to put result into.
436 * Return: 1 = ok, 0 = error
437 */
read_float4(int f,float * x)438 int read_float4(int f, float *x)
439 {
440 #ifdef _CRAY
441 long buffer = 0;
442
443 if (read(f, &buffer, 4) == 4) {
444 /* convert IEEE float (buffer) to Cray float (x) */
445 if_to_c((long *)x, &buffer);
446 return 1;
447 }
448 return 0;
449 #else
450 # ifdef LITTLE
451 unsigned int n, *iptr;
452
453 if (read(f, &n, 4) == 4) {
454 iptr = (unsigned int *)x;
455 *iptr = FLIP4(n);
456 return 1;
457 }
458 else {
459 return 0;
460 }
461 # else
462 if (read(f, x, 4) == 4) {
463 return 1;
464 }
465 else {
466 return 0;
467 }
468 # endif
469 #endif
470 }
471
472
473
474 /*
475 * Read an array of 4-byte IEEE floats.
476 * Input: f - file descriptor
477 * x - address to put floats
478 * n - number of floats to read.
479 * Return: number of floats read.
480 */
read_float4_array(int f,float * x,int n)481 int read_float4_array(int f, float *x, int n)
482 {
483 #ifdef _CRAY
484 /* read IEEE floats into buffer, then convert to Cray format */
485 long *buffer;
486 int i, nread;
487
488 buffer = (long *)G_malloc((n + 1) * 4);
489 if (!buffer)
490 return 0;
491 nread = read(f, buffer, n * 4);
492 if (nread <= 0)
493 return 0;
494 nread /= 4;
495 ieee_to_cray_array(x, buffer, nread);
496 G_free(buffer);
497 return nread;
498 #else
499 int nread = read(f, x, 4 * n);
500
501 if (nread <= 0)
502 return 0;
503 #ifdef LITTLE
504 flip4((const unsigned int *)x, (unsigned int *)x, nread / 4);
505 #endif
506 return nread / 4;
507 #endif
508 }
509
510
511
512 /*
513 * Read a block of memory.
514 * Input: f - file descriptor
515 * data - address of first byte
516 * elements - number of elements to read
517 * elsize - size of each element to read (1, 2 or 4)
518 * Return: number of elements written
519 */
read_block(int f,void * data,int elements,int elsize)520 int read_block(int f, void *data, int elements, int elsize)
521 {
522 if (elsize == 1) {
523 return read(f, data, elements);
524 }
525 else if (elsize == 2) {
526 #ifdef LITTLE
527 int n;
528
529 n = read(f, data, elements * 2) / 2;
530 if (n == elements) {
531 flip2((const unsigned short *)data, (unsigned short *)data,
532 elements);
533 }
534 return n;
535 #else
536 return read(f, data, elements * 2) / 2;
537 #endif
538 }
539 else if (elsize == 4) {
540 #ifdef LITTLE
541 int n;
542
543 n = read(f, data, elements * 4) / 4;
544 if (n == elements) {
545 flip4((const unsigned int *)data, (unsigned int *)data, elements);
546 }
547 return n;
548 #else
549 return read(f, data, elements * 4) / 4;
550 #endif
551 }
552 else {
553 printf("Fatal error in read_block(): bad elsize (%d)\n", elsize);
554 abort();
555 }
556 return 0;
557 }
558
559
560
561
562 /**********************************************************************/
563
564 /***** Write Functions *****/
565
566 /**********************************************************************/
567
568
569
570 /*
571 * Write a block of bytes.
572 * Input: f - the file descriptor to write to.
573 * b - address of buffer to write.
574 * n - number of bytes to write.
575 * Return: number of bytes written, 0 if error.
576 */
write_bytes(int f,const void * b,int n)577 int write_bytes(int f, const void *b, int n)
578 {
579 return write(f, b, n);
580 }
581
582
583
584
585 /*
586 * Write an array of 2-byte integers.
587 * Input: f - file descriptor
588 * iarray - address to put integers
589 * n - number of integers to write.
590 * Return: number of integers written
591 */
write_int2_array(int f,const short * iarray,int n)592 int write_int2_array(int f, const short *iarray, int n)
593 {
594 #ifdef _CRAY
595 printf("write_int2_array not implemented!\n");
596 exit(1);
597 #else
598 int nwritten;
599
600 #ifdef LITTLE
601 flip2((const unsigned short *)iarray, (unsigned short *)iarray, n);
602 #endif
603 nwritten = write(f, iarray, 2 * n);
604 #ifdef LITTLE
605 flip2((const unsigned short *)iarray, (unsigned short *)iarray, n);
606 #endif
607 if (nwritten <= 0)
608 return 0;
609 return nwritten / 2;
610 #endif
611 }
612
613
614
615 /*
616 * Write an array of 2-byte unsigned integers.
617 * Input: f - file descriptor
618 * iarray - address to put integers
619 * n - number of integers to write.
620 * Return: number of integers written
621 */
write_uint2_array(int f,const unsigned short * iarray,int n)622 int write_uint2_array(int f, const unsigned short *iarray, int n)
623 {
624 #ifdef _CRAY
625 int i, nwritten;
626 unsigned char *buffer;
627
628 buffer = (unsigned char *)G_malloc(2 * n);
629 if (!buffer)
630 return 0;
631 for (i = 0; i < n; i++) {
632 buffer[i * 2] = (iarray[i] >> 8) & 0xff;
633 buffer[i * 2 + 1] = iarray[i] & 0xff;
634 }
635 nwritten = write(f, buffer, 2 * n);
636 G_free(buffer);
637 if (nwritten <= 0)
638 return 0;
639 else
640 return nwritten / 2;
641 #else
642 int nwritten;
643
644 #ifdef LITTLE
645 flip2(iarray, (unsigned short *)iarray, n);
646 #endif
647 nwritten = write(f, iarray, 2 * n);
648 #ifdef LITTLE
649 flip2(iarray, (unsigned short *)iarray, n);
650 #endif
651 if (nwritten <= 0)
652 return 0;
653 else
654 return nwritten / 2;
655 #endif
656 }
657
658
659
660 /*
661 * Write a 4-byte integer.
662 *Input: f - the file descriptor
663 * i - the integer
664 * Return: 1 = ok, 0 = error
665 */
write_int4(int f,int i)666 int write_int4(int f, int i)
667 {
668 #ifdef _CRAY
669 i = i << 32;
670 return write(f, &i, 4) > 0;
671 #else
672 # ifdef LITTLE
673 i = FLIP4(i);
674 # endif
675 return write(f, &i, 4) > 0;
676 #endif
677 }
678
679
680
681 /*
682 * Write an array of 4-byte integers.
683 * Input: f - the file descriptor
684 * i - the array of ints
685 * n - the number of ints in array
686 * Return: number of integers written.
687 */
write_int4_array(int f,const int * i,int n)688 int write_int4_array(int f, const int *i, int n)
689 {
690 #ifdef _CRAY
691 int j, nwritten;
692 char *buf, *b, *ptr;
693
694 b = buf = (char *)G_malloc(n * 4 + 8);
695 if (!b)
696 return 0;
697 ptr = (char *)i;
698 for (j = 0; j < n; j++) {
699 ptr += 4; /* skip upper 4 bytes */
700 *b++ = *ptr++;
701 *b++ = *ptr++;
702 *b++ = *ptr++;
703 *b++ = *ptr++;
704 }
705 nwritten = write(f, buf, 4 * n);
706 G_free(buf);
707 if (nwritten <= 0)
708 return 0;
709 else
710 return nwritten / 4;
711 #else
712 # ifdef LITTLE
713 int nwritten;
714
715 flip4((const unsigned int *)i, (unsigned int *)i, n);
716 nwritten = write(f, i, 4 * n);
717 flip4((const unsigned int *)i, (unsigned int *)i, n);
718 if (nwritten <= 0)
719 return 0;
720 else
721 return nwritten / 4;
722 # else
723 return write(f, i, 4 * n) / 4;
724 # endif
725 #endif
726 }
727
728
729
730 /*
731 * Write a 4-byte IEEE float.
732 * Input: f - the file descriptor
733 * x - the float
734 * Return: 1 = ok, 0 = error
735 */
write_float4(int f,float x)736 int write_float4(int f, float x)
737 {
738 #ifdef _CRAY
739 char buffer[8];
740
741 c_to_if((long *)buffer, (const long *)&x);
742 return write(f, buffer, 4) > 0;
743 #else
744 # ifdef LITTLE
745 float y;
746 unsigned int *iptr = (unsigned int *)&y, temp;
747
748 y = (float)x;
749 temp = FLIP4(*iptr);
750 return write(f, &temp, 4) > 0;
751 # else
752 float y;
753
754 y = (float)x;
755 return write(f, &y, 4) > 0;
756 # endif
757 #endif
758 }
759
760
761
762 /*
763 * Write an array of 4-byte IEEE floating point numbers.
764 * Input: f - the file descriptor
765 * x - the array of floats
766 * n - number of floats in array
767 * Return: number of float written.
768 */
write_float4_array(int f,const float * x,int n)769 int write_float4_array(int f, const float *x, int n)
770 {
771 #ifdef _CRAY
772 /* convert cray floats to IEEE and put into buffer */
773 int nwritten;
774 long *buffer;
775
776 buffer = (long *)G_malloc(n * 4 + 8);
777 if (!buffer)
778 return 0;
779 cray_to_ieee_array(buffer, x, n);
780 nwritten = write(f, buffer, 4 * n);
781 G_free(buffer);
782 if (nwritten <= 0)
783 return 0;
784 else
785 return nwritten / 4;
786 #else
787 # ifdef LITTLE
788 int nwritten;
789
790 flip4((const unsigned int *)x, (unsigned int *)x, n);
791 nwritten = write(f, x, 4 * n);
792 flip4((const unsigned int *)x, (unsigned int *)x, n);
793 if (nwritten <= 0)
794 return 0;
795 else
796 return nwritten / 4;
797 # else
798 return write(f, x, 4 * n) / 4;
799 # endif
800 #endif
801 }
802
803
804
805 /*
806 * Write a block of memory.
807 * Input: f - file descriptor
808 * data - address of first byte
809 * elements - number of elements to write
810 * elsize - size of each element to write (1, 2 or 4)
811 * Return: number of elements written
812 */
write_block(int f,const void * data,int elements,int elsize)813 int write_block(int f, const void *data, int elements, int elsize)
814 {
815 if (elsize == 1) {
816 return write(f, data, elements);
817 }
818 else if (elsize == 2) {
819 #ifdef LITTLE
820 int n;
821
822 flip2((const unsigned short *)data, (unsigned short *)data, elements);
823 n = write(f, data, elements * 2) / 2;
824 flip2((const unsigned short *)data, (unsigned short *)data, elements);
825 return n;
826 #else
827 return write(f, data, elements * 2) / 2;
828 #endif
829 }
830 else if (elsize == 4) {
831 #ifdef LITTLE
832 int n;
833
834 flip4((const unsigned int *)data, (unsigned int *)data, elements);
835 n = write(f, data, elements * 4) / 4;
836 flip4((const unsigned int *)data, (unsigned int *)data, elements);
837 return n;
838 #else
839 return write(f, data, elements * 4) / 4;
840 #endif
841 }
842 else {
843 printf("Fatal error in write_block(): bad elsize (%d)\n", elsize);
844 abort();
845 }
846 return 0;
847 }
848