1960
|
1 // data-conv.cc -*- C++ -*- |
|
2 /* |
|
3 |
|
4 Copyright (C) 1996 John W. Eaton |
|
5 |
|
6 This file is part of Octave. |
|
7 |
|
8 Octave is free software; you can redistribute it and/or modify it |
|
9 under the terms of the GNU General Public License as published by the |
|
10 Free Software Foundation; either version 2, or (at your option) any |
|
11 later version. |
|
12 |
|
13 Octave is distributed in the hope that it will be useful, but WITHOUT |
|
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
16 for more details. |
|
17 |
|
18 You should have received a copy of the GNU General Public License |
|
19 along with Octave; see the file COPYING. If not, write to the Free |
|
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
21 |
|
22 */ |
|
23 |
|
24 #ifdef HAVE_CONFIG_H |
|
25 #include <config.h> |
|
26 #endif |
|
27 |
|
28 #include <iostream.h> |
|
29 |
|
30 #include "byte-swap.h" |
|
31 #include "data-conv.h" |
|
32 #include "lo-error.h" |
|
33 |
|
34 #define swap_1_bytes(x, y) |
|
35 |
|
36 #define LS_DO_READ(TYPE,swap,data,size,len,stream) \ |
|
37 do \ |
|
38 { \ |
|
39 volatile TYPE *ptr = (TYPE *) data; \ |
|
40 stream.read ((TYPE *) ptr, size * len); \ |
|
41 if (swap) \ |
|
42 swap_ ## size ## _bytes ((char *) ptr, len); \ |
|
43 TYPE tmp = ptr[0]; \ |
|
44 for (int i = len - 1; i > 0; i--) \ |
|
45 data[i] = ptr[i]; \ |
|
46 data[0] = tmp; \ |
|
47 } \ |
|
48 while (0) |
|
49 |
|
50 // Have to use copy here to avoid writing over data accessed via |
|
51 // Matrix::data(). |
|
52 |
|
53 #define LS_DO_WRITE(TYPE,data,size,len,stream) \ |
|
54 do \ |
|
55 { \ |
|
56 char tmp_type = (char) type; \ |
|
57 stream.write (&tmp_type, 1); \ |
|
58 TYPE *ptr = new TYPE [len]; \ |
|
59 for (int i = 0; i < len; i++) \ |
|
60 ptr[i] = (TYPE) data[i]; \ |
|
61 stream.write ((TYPE *) ptr, size * len); \ |
|
62 delete [] ptr ; \ |
|
63 } \ |
|
64 while (0) |
|
65 |
|
66 // Loading variables from files. |
|
67 |
|
68 static void |
|
69 gripe_unrecognized_float_fmt (void) |
|
70 { |
|
71 (*current_liboctave_error_handler) |
|
72 ("unrecognized floating point format requested"); |
|
73 } |
|
74 |
|
75 static void |
|
76 gripe_data_conversion (const char *from, const char *to) |
|
77 { |
|
78 (*current_liboctave_error_handler) |
|
79 ("unable to convert from %s to %s format", from, to); |
|
80 } |
|
81 |
|
82 // But first, some data conversion routines. |
|
83 |
|
84 // Currently, we only handle conversions for the IEEE types. To fix |
|
85 // that, make more of the following routines work. |
|
86 |
|
87 // XXX FIXME XXX -- assumes sizeof (Complex) == 8 |
|
88 // XXX FIXME XXX -- assumes sizeof (double) == 8 |
|
89 // XXX FIXME XXX -- assumes sizeof (float) == 4 |
|
90 |
|
91 static void |
|
92 IEEE_big_double_to_IEEE_little_double (double *d, int len) |
|
93 { |
|
94 swap_8_bytes ((char *) d, len); |
|
95 } |
|
96 |
|
97 static void |
|
98 VAX_D_double_to_IEEE_little_double (double * /* d */, int /* len */) |
|
99 { |
|
100 gripe_data_conversion ("VAX D float", "IEEE little endian format"); |
|
101 } |
|
102 |
|
103 static void |
|
104 VAX_G_double_to_IEEE_little_double (double * /* d */, int /* len */) |
|
105 { |
|
106 gripe_data_conversion ("VAX G float", "IEEE little endian format"); |
|
107 } |
|
108 |
|
109 static void |
|
110 Cray_to_IEEE_little_double (double * /* d */, int /* len */) |
|
111 { |
|
112 gripe_data_conversion ("Cray", "IEEE little endian format"); |
|
113 } |
|
114 |
|
115 static void |
|
116 IEEE_big_float_to_IEEE_little_float (float *d, int len) |
|
117 { |
|
118 swap_4_bytes ((char *) d, len); |
|
119 } |
|
120 |
|
121 static void |
|
122 VAX_D_float_to_IEEE_little_float (float * /* d */, int /* len */) |
|
123 { |
|
124 gripe_data_conversion ("VAX D float", "IEEE little endian format"); |
|
125 } |
|
126 |
|
127 static void |
|
128 VAX_G_float_to_IEEE_little_float (float * /* d */, int /* len */) |
|
129 { |
|
130 gripe_data_conversion ("VAX G float", "IEEE little endian format"); |
|
131 } |
|
132 |
|
133 static void |
|
134 Cray_to_IEEE_little_float (float * /* d */, int /* len */) |
|
135 { |
|
136 gripe_data_conversion ("Cray", "IEEE little endian format"); |
|
137 } |
|
138 |
|
139 static void |
|
140 IEEE_little_double_to_IEEE_big_double (double *d, int len) |
|
141 { |
|
142 swap_8_bytes ((char *) d, len); |
|
143 } |
|
144 |
|
145 static void |
|
146 VAX_D_double_to_IEEE_big_double (double * /* d */, int /* len */) |
|
147 { |
|
148 gripe_data_conversion ("VAX D float", "IEEE big endian format"); |
|
149 } |
|
150 |
|
151 static void |
|
152 VAX_G_double_to_IEEE_big_double (double * /* d */, int /* len */) |
|
153 { |
|
154 gripe_data_conversion ("VAX G float", "IEEE big endian format"); |
|
155 } |
|
156 |
|
157 static void |
|
158 Cray_to_IEEE_big_double (double * /* d */, int /* len */) |
|
159 { |
|
160 gripe_data_conversion ("Cray", "IEEE big endian format"); |
|
161 } |
|
162 |
|
163 static void |
|
164 IEEE_little_float_to_IEEE_big_float (float *d, int len) |
|
165 { |
|
166 swap_4_bytes ((char *) d, len); |
|
167 } |
|
168 |
|
169 static void |
|
170 VAX_D_float_to_IEEE_big_float (float * /* d */, int /* len */) |
|
171 { |
|
172 gripe_data_conversion ("VAX D float", "IEEE big endian format"); |
|
173 } |
|
174 |
|
175 static void |
|
176 VAX_G_float_to_IEEE_big_float (float * /* d */, int /* len */) |
|
177 { |
|
178 gripe_data_conversion ("VAX G float", "IEEE big endian format"); |
|
179 } |
|
180 |
|
181 static void |
|
182 Cray_to_IEEE_big_float (float * /* d */, int /* len */) |
|
183 { |
|
184 gripe_data_conversion ("Cray", "IEEE big endian format"); |
|
185 } |
|
186 |
|
187 static void |
|
188 IEEE_little_double_to_VAX_D_double (double * /* d */, int /* len */) |
|
189 { |
|
190 gripe_data_conversion ("IEEE little endian", "VAX D"); |
|
191 } |
|
192 |
|
193 static void |
|
194 IEEE_big_double_to_VAX_D_double (double * /* d */, int /* len */) |
|
195 { |
|
196 gripe_data_conversion ("IEEE big endian", "VAX D"); |
|
197 } |
|
198 |
|
199 static void |
|
200 VAX_G_double_to_VAX_D_double (double * /* d */, int /* len */) |
|
201 { |
|
202 gripe_data_conversion ("VAX G float", "VAX D"); |
|
203 } |
|
204 |
|
205 static void |
|
206 Cray_to_VAX_D_double (double * /* d */, int /* len */) |
|
207 { |
|
208 gripe_data_conversion ("Cray", "VAX D"); |
|
209 } |
|
210 |
|
211 static void |
|
212 IEEE_little_float_to_VAX_D_float (float * /* d */, int /* len */) |
|
213 { |
|
214 gripe_data_conversion ("IEEE little endian", "VAX D"); |
|
215 } |
|
216 |
|
217 static void |
|
218 IEEE_big_float_to_VAX_D_float (float * /* d */, int /* len */) |
|
219 { |
|
220 gripe_data_conversion ("IEEE big endian", "VAX D"); |
|
221 } |
|
222 |
|
223 static void |
|
224 VAX_G_float_to_VAX_D_float (float * /* d */, int /* len */) |
|
225 { |
|
226 gripe_data_conversion ("VAX G float", "VAX D"); |
|
227 } |
|
228 |
|
229 static void |
|
230 Cray_to_VAX_D_float (float * /* d */, int /* len */) |
|
231 { |
|
232 gripe_data_conversion ("Cray", "VAX D"); |
|
233 } |
|
234 |
|
235 static void |
|
236 IEEE_little_double_to_VAX_G_double (double * /* d */, int /* len */) |
|
237 { |
|
238 gripe_data_conversion ("IEEE little endian", "VAX G"); |
|
239 } |
|
240 |
|
241 static void |
|
242 IEEE_big_double_to_VAX_G_double (double * /* d */, int /* len */) |
|
243 { |
|
244 gripe_data_conversion ("IEEE big endian", "VAX G"); |
|
245 } |
|
246 |
|
247 static void |
|
248 VAX_D_double_to_VAX_G_double (double * /* d */, int /* len */) |
|
249 { |
|
250 gripe_data_conversion ("VAX D float", "VAX G"); |
|
251 } |
|
252 |
|
253 static void |
|
254 Cray_to_VAX_G_double (double * /* d */, int /* len */) |
|
255 { |
|
256 gripe_data_conversion ("VAX G float", "VAX G"); |
|
257 } |
|
258 |
|
259 static void |
|
260 IEEE_little_float_to_VAX_G_float (float * /* d */, int /* len */) |
|
261 { |
|
262 gripe_data_conversion ("IEEE little endian", "VAX G"); |
|
263 } |
|
264 |
|
265 static void |
|
266 IEEE_big_float_to_VAX_G_float (float * /* d */, int /* len */) |
|
267 { |
|
268 gripe_data_conversion ("IEEE big endian", "VAX G"); |
|
269 } |
|
270 |
|
271 static void |
|
272 VAX_D_float_to_VAX_G_float (float * /* d */, int /* len */) |
|
273 { |
|
274 gripe_data_conversion ("VAX D float", "VAX G"); |
|
275 } |
|
276 |
|
277 static void |
|
278 Cray_to_VAX_G_float (float * /* d */, int /* len */) |
|
279 { |
|
280 gripe_data_conversion ("VAX G float", "VAX G"); |
|
281 } |
|
282 |
|
283 void |
|
284 do_double_format_conversion (double *data, int len, |
|
285 floating_point_format fmt) |
|
286 { |
|
287 switch (native_float_format) |
|
288 { |
|
289 case OCTAVE_IEEE_LITTLE: |
|
290 switch (fmt) |
|
291 { |
|
292 case OCTAVE_IEEE_LITTLE: |
|
293 break; |
|
294 |
|
295 case OCTAVE_IEEE_BIG: |
|
296 IEEE_big_double_to_IEEE_little_double (data, len); |
|
297 break; |
|
298 |
|
299 case OCTAVE_VAX_D: |
|
300 VAX_D_double_to_IEEE_little_double (data, len); |
|
301 break; |
|
302 |
|
303 case OCTAVE_VAX_G: |
|
304 VAX_G_double_to_IEEE_little_double (data, len); |
|
305 break; |
|
306 |
|
307 case OCTAVE_CRAY: |
|
308 Cray_to_IEEE_little_double (data, len); |
|
309 break; |
|
310 |
|
311 default: |
|
312 gripe_unrecognized_float_fmt (); |
|
313 break; |
|
314 } |
|
315 break; |
|
316 |
|
317 case OCTAVE_IEEE_BIG: |
|
318 switch (fmt) |
|
319 { |
|
320 case OCTAVE_IEEE_LITTLE: |
|
321 IEEE_little_double_to_IEEE_big_double (data, len); |
|
322 break; |
|
323 |
|
324 case OCTAVE_IEEE_BIG: |
|
325 break; |
|
326 |
|
327 case OCTAVE_VAX_D: |
|
328 VAX_D_double_to_IEEE_big_double (data, len); |
|
329 break; |
|
330 |
|
331 case OCTAVE_VAX_G: |
|
332 VAX_G_double_to_IEEE_big_double (data, len); |
|
333 break; |
|
334 |
|
335 case OCTAVE_CRAY: |
|
336 Cray_to_IEEE_big_double (data, len); |
|
337 break; |
|
338 |
|
339 default: |
|
340 gripe_unrecognized_float_fmt (); |
|
341 break; |
|
342 } |
|
343 break; |
|
344 |
|
345 case OCTAVE_VAX_D: |
|
346 switch (fmt) |
|
347 { |
|
348 case OCTAVE_IEEE_LITTLE: |
|
349 IEEE_little_double_to_VAX_D_double (data, len); |
|
350 break; |
|
351 |
|
352 case OCTAVE_IEEE_BIG: |
|
353 IEEE_big_double_to_VAX_D_double (data, len); |
|
354 break; |
|
355 |
|
356 case OCTAVE_VAX_D: |
|
357 break; |
|
358 |
|
359 case OCTAVE_VAX_G: |
|
360 VAX_G_double_to_VAX_D_double (data, len); |
|
361 break; |
|
362 |
|
363 case OCTAVE_CRAY: |
|
364 Cray_to_VAX_D_double (data, len); |
|
365 break; |
|
366 |
|
367 default: |
|
368 gripe_unrecognized_float_fmt (); |
|
369 break; |
|
370 } |
|
371 break; |
|
372 |
|
373 case OCTAVE_VAX_G: |
|
374 switch (fmt) |
|
375 { |
|
376 case OCTAVE_IEEE_LITTLE: |
|
377 IEEE_little_double_to_VAX_G_double (data, len); |
|
378 break; |
|
379 |
|
380 case OCTAVE_IEEE_BIG: |
|
381 IEEE_big_double_to_VAX_G_double (data, len); |
|
382 break; |
|
383 |
|
384 case OCTAVE_VAX_D: |
|
385 VAX_D_double_to_VAX_G_double (data, len); |
|
386 break; |
|
387 |
|
388 case OCTAVE_VAX_G: |
|
389 break; |
|
390 |
|
391 case OCTAVE_CRAY: |
|
392 Cray_to_VAX_G_double (data, len); |
|
393 break; |
|
394 |
|
395 default: |
|
396 gripe_unrecognized_float_fmt (); |
|
397 break; |
|
398 } |
|
399 break; |
|
400 |
|
401 default: |
|
402 (*current_liboctave_error_handler) |
|
403 ("impossible state reached in file `%s' at line %d", |
|
404 __FILE__, __LINE__); |
|
405 break; |
|
406 } |
|
407 } |
|
408 |
|
409 void |
|
410 do_float_format_conversion (float *data, int len, |
|
411 floating_point_format fmt) |
|
412 { |
|
413 switch (native_float_format) |
|
414 { |
|
415 case OCTAVE_IEEE_LITTLE: |
|
416 switch (fmt) |
|
417 { |
|
418 case OCTAVE_IEEE_LITTLE: |
|
419 break; |
|
420 |
|
421 case OCTAVE_IEEE_BIG: |
|
422 IEEE_big_float_to_IEEE_little_float (data, len); |
|
423 break; |
|
424 |
|
425 case OCTAVE_VAX_D: |
|
426 VAX_D_float_to_IEEE_little_float (data, len); |
|
427 break; |
|
428 |
|
429 case OCTAVE_VAX_G: |
|
430 VAX_G_float_to_IEEE_little_float (data, len); |
|
431 break; |
|
432 |
|
433 case OCTAVE_CRAY: |
|
434 Cray_to_IEEE_little_float (data, len); |
|
435 break; |
|
436 |
|
437 default: |
|
438 gripe_unrecognized_float_fmt (); |
|
439 break; |
|
440 } |
|
441 break; |
|
442 |
|
443 case OCTAVE_IEEE_BIG: |
|
444 switch (fmt) |
|
445 { |
|
446 case OCTAVE_IEEE_LITTLE: |
|
447 IEEE_little_float_to_IEEE_big_float (data, len); |
|
448 break; |
|
449 |
|
450 case OCTAVE_IEEE_BIG: |
|
451 break; |
|
452 |
|
453 case OCTAVE_VAX_D: |
|
454 VAX_D_float_to_IEEE_big_float (data, len); |
|
455 break; |
|
456 |
|
457 case OCTAVE_VAX_G: |
|
458 VAX_G_float_to_IEEE_big_float (data, len); |
|
459 break; |
|
460 |
|
461 case OCTAVE_CRAY: |
|
462 Cray_to_IEEE_big_float (data, len); |
|
463 break; |
|
464 |
|
465 default: |
|
466 gripe_unrecognized_float_fmt (); |
|
467 break; |
|
468 } |
|
469 break; |
|
470 |
|
471 case OCTAVE_VAX_D: |
|
472 switch (fmt) |
|
473 { |
|
474 case OCTAVE_IEEE_LITTLE: |
|
475 IEEE_little_float_to_VAX_D_float (data, len); |
|
476 break; |
|
477 |
|
478 case OCTAVE_IEEE_BIG: |
|
479 IEEE_big_float_to_VAX_D_float (data, len); |
|
480 break; |
|
481 |
|
482 case OCTAVE_VAX_D: |
|
483 break; |
|
484 |
|
485 case OCTAVE_VAX_G: |
|
486 VAX_G_float_to_VAX_D_float (data, len); |
|
487 break; |
|
488 |
|
489 case OCTAVE_CRAY: |
|
490 Cray_to_VAX_D_float (data, len); |
|
491 break; |
|
492 |
|
493 default: |
|
494 gripe_unrecognized_float_fmt (); |
|
495 break; |
|
496 } |
|
497 break; |
|
498 |
|
499 case OCTAVE_VAX_G: |
|
500 switch (fmt) |
|
501 { |
|
502 case OCTAVE_IEEE_LITTLE: |
|
503 IEEE_little_float_to_VAX_G_float (data, len); |
|
504 break; |
|
505 |
|
506 case OCTAVE_IEEE_BIG: |
|
507 IEEE_big_float_to_VAX_G_float (data, len); |
|
508 break; |
|
509 |
|
510 case OCTAVE_VAX_D: |
|
511 VAX_D_float_to_VAX_G_float (data, len); |
|
512 break; |
|
513 |
|
514 case OCTAVE_VAX_G: |
|
515 break; |
|
516 |
|
517 case OCTAVE_CRAY: |
|
518 Cray_to_VAX_G_float (data, len); |
|
519 break; |
|
520 |
|
521 default: |
|
522 gripe_unrecognized_float_fmt (); |
|
523 break; |
|
524 } |
|
525 break; |
|
526 |
|
527 default: |
|
528 (*current_liboctave_error_handler) |
|
529 ("impossible state reached in file `%s' at line %d", |
|
530 __FILE__, __LINE__); |
|
531 break; |
|
532 } |
|
533 } |
|
534 |
|
535 void |
|
536 read_doubles (istream& is, double *data, save_type type, int len, |
|
537 int swap, floating_point_format fmt) |
|
538 { |
|
539 switch (type) |
|
540 { |
|
541 case LS_U_CHAR: |
|
542 LS_DO_READ (unsigned char, swap, data, 1, len, is); |
|
543 break; |
|
544 |
|
545 case LS_U_SHORT: |
|
546 LS_DO_READ (unsigned TWO_BYTE_INT, swap, data, 2, len, is); |
|
547 break; |
|
548 |
|
549 case LS_U_INT: |
|
550 LS_DO_READ (unsigned FOUR_BYTE_INT, swap, data, 4, len, is); |
|
551 break; |
|
552 |
|
553 case LS_CHAR: |
|
554 LS_DO_READ (signed char, swap, data, 1, len, is); |
|
555 break; |
|
556 |
|
557 case LS_SHORT: |
|
558 LS_DO_READ (TWO_BYTE_INT, swap, data, 2, len, is); |
|
559 break; |
|
560 |
|
561 case LS_INT: |
|
562 LS_DO_READ (FOUR_BYTE_INT, swap, data, 4, len, is); |
|
563 break; |
|
564 |
|
565 case LS_FLOAT: |
|
566 { |
|
567 volatile float *ptr = (float *) data; |
|
568 is.read (data, 4 * len); |
|
569 do_float_format_conversion ((float *) data, len, fmt); |
|
570 float tmp = ptr[0]; |
|
571 for (int i = len - 1; i > 0; i--) |
|
572 data[i] = ptr[i]; |
|
573 data[0] = tmp; |
|
574 } |
|
575 break; |
|
576 |
|
577 case LS_DOUBLE: |
|
578 is.read (data, 8 * len); |
|
579 do_double_format_conversion (data, len, fmt); |
|
580 break; |
|
581 |
|
582 default: |
|
583 is.clear (ios::failbit|is.rdstate ()); |
|
584 break; |
|
585 } |
|
586 } |
|
587 |
|
588 void |
|
589 write_doubles (ostream& os, const double *data, save_type type, int len) |
|
590 { |
|
591 switch (type) |
|
592 { |
|
593 case LS_U_CHAR: |
|
594 LS_DO_WRITE (unsigned char, data, 1, len, os); |
|
595 break; |
|
596 |
|
597 case LS_U_SHORT: |
|
598 LS_DO_WRITE (unsigned TWO_BYTE_INT, data, 2, len, os); |
|
599 break; |
|
600 |
|
601 case LS_U_INT: |
|
602 LS_DO_WRITE (unsigned FOUR_BYTE_INT, data, 4, len, os); |
|
603 break; |
|
604 |
|
605 case LS_CHAR: |
|
606 LS_DO_WRITE (signed char, data, 1, len, os); |
|
607 break; |
|
608 |
|
609 case LS_SHORT: |
|
610 LS_DO_WRITE (TWO_BYTE_INT, data, 2, len, os); |
|
611 break; |
|
612 |
|
613 case LS_INT: |
|
614 LS_DO_WRITE (FOUR_BYTE_INT, data, 4, len, os); |
|
615 break; |
|
616 |
|
617 case LS_FLOAT: |
|
618 LS_DO_WRITE (float, data, 4, len, os); |
|
619 break; |
|
620 |
|
621 case LS_DOUBLE: |
|
622 { |
|
623 char tmp_type = (char) type; |
|
624 os.write (&tmp_type, 1); |
|
625 os.write (data, 8 * len); |
|
626 } |
|
627 break; |
|
628 |
|
629 default: |
|
630 (*current_liboctave_error_handler) |
|
631 ("unrecognized data format requested"); |
|
632 break; |
|
633 } |
|
634 } |
|
635 |
|
636 /* |
|
637 ;;; Local Variables: *** |
|
638 ;;; mode: C++ *** |
|
639 ;;; page-delimiter: "^/\\*" *** |
|
640 ;;; End: *** |
|
641 */ |