2
Copyright (c) 1994 - 2010, Lawrence Livermore National Security, LLC.
6
This file is part of Silo. For details, see silo.llnl.gov.
8
Redistribution and use in source and binary forms, with or without
9
modification, are permitted provided that the following conditions
12
* Redistributions of source code must retain the above copyright
13
notice, this list of conditions and the disclaimer below.
14
* Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the disclaimer (as noted
16
below) in the documentation and/or other materials provided with
18
* Neither the name of the LLNS/LLNL nor the names of its
19
contributors may be used to endorse or promote products derived
20
from this software without specific prior written permission.
22
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE
26
LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR
27
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
This work was produced at Lawrence Livermore National Laboratory under
36
Contract No. DE-AC52-07NA27344 with the DOE.
38
Neither the United States Government nor Lawrence Livermore National
39
Security, LLC nor any of their employees, makes any warranty, express
40
or implied, or assumes any liability or responsibility for the
41
accuracy, completeness, or usefulness of any information, apparatus,
42
product, or process disclosed, or represents that its use would not
43
infringe privately-owned rights.
45
Any reference herein to any specific commercial products, process, or
46
services by trade name, trademark, manufacturer or otherwise does not
47
necessarily constitute or imply its endorsement, recommendation, or
48
favoring by the United States Government or Lawrence Livermore
49
National Security, LLC. The views and opinions of authors expressed
50
herein do not necessarily state or reflect those of the United States
51
Government or Lawrence Livermore National Security, LLC, and shall not
52
be used for advertising or product endorsement purposes.
55
* PDCONV.C - routines to do conversions between data formats
58
* Software Release #92-0043
65
#define ONES_COMP_NEG(n, nb, incr) \
66
{if (nb == 8*sizeof(long)) \
70
msk = (1L << nb) - 1L; \
71
n = (~n + incr) & msk;};}
74
* Forward declarations...
76
static void _PD_btrvout (char*,long,long);
77
static int _PD_get_bit (char*,int,int,int*);
78
static void _PD_insert_field (long,int,char*,int,int,int);
79
static void _PD_ncopy (char**,char**,long,long);
80
static void _PD_ones_complement (char*,long,int);
81
static void _PD_reorder (char*,long,int,int*);
82
static void _PD_set_bit (char*,int);
83
static void _PD_sign_extend (char*,long,int,int,int*);
85
/*--------------------------------------------------------------------------*/
87
/*--------------------------------------------------------------------------*/
90
* Floating Point Format Descriptor
92
* - format[0] = # of bits per number
93
* - format[1] = # of bits in exponent
94
* - format[2] = # of bits in mantissa
95
* - format[3] = start bit of sign
96
* - format[4] = start bit of exponent
97
* - format[5] = start bit of mantissa
98
* - format[6] = high order mantissa bit
99
* - format[7] = bias of exponent
103
int lite_FORMAT_FIELDS = 8 ;
105
int lite_def_float_order[] = {1, 2, 3, 4};
106
int lite_def_double_order[] = {1, 2, 3, 4, 5, 6, 7, 8};
107
int lite_ieee_float_order[] = {1, 2, 3, 4};
108
int lite_ieeea_double_order[] = {1, 2, 3, 4, 5, 6, 7, 8};
109
int lite_ieeeb_double_order[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
110
int lite_intel_float_order[] = {4, 3, 2, 1};
111
int lite_intel_double_order[] = {8, 7, 6, 5, 4, 3, 2, 1};
112
int lite_vax_float_order[] = {2, 1, 4, 3};
113
int lite_vax_double_order[] = {2, 1, 4, 3, 6, 5, 8, 7};
114
int lite_cray_float_order[] = {1, 2, 3, 4, 5, 6, 7, 8};
116
long lite_def_float[] = {32L, 8L, 23L, 0L, 1L, 9L, 0L, 0x7FL};
117
long lite_def_double[] = {64L, 11L, 52L, 0L, 1L, 12L, 0L, 0x3FFL};
118
long lite_ieee_float[] = {32L, 8L, 23L, 0L, 1L, 9L, 0L, 0x7FL};
119
long lite_ieeea_double[] = {64L, 11L, 52L, 0L, 1L, 12L, 0L, 0x3FFL};
120
long lite_ieeeb_double[] = {96L, 15L, 64L, 0L, 1L, 32L, 1L, 0x3FFEL};
121
long lite_intel_float[] = {32L, 8L, 23L, 0L, 1L, 9L, 0L, 0x7FL};
122
long lite_intel_double[] = {64L, 11L, 52L, 0L, 1L, 12L, 0L, 0x3FFL};
123
long lite_cray_float[] = {64L, 15L, 48L, 0L, 1L, 16L, 1L, 0x4000L};
126
long lite_vax_float[] = {32L, 8L, 23L, 0L, 1L, 9L, 0L, 0x81L};
127
long lite_vax_double[] = {64L, 11L, 52L, 0L, 1L, 12L, 0L, 0x401L};
129
long lite_vax_float[] = {32L, 8L, 23L, 0L, 1L, 9L, 0L, 0x81L};
130
long lite_vax_double[] = {64L, 8L, 55L, 0L, 1L, 9L, 0L, 0x81L};
135
* Data standard for the different architectures
137
* struct s_data_standard
146
* long *float_format;
149
* long *double_format;
150
* int *double_order;};
152
* typedef struct s_data_standard data_standard;
154
* Mark C. Miller, Fri Nov 13 15:33:42 PST 2009
155
* Added support for long long datatype.
159
lite_DEF_STD = {4, /* size of pointer */
160
2, NORMAL_ORDER, /* size and order of short */
161
4, NORMAL_ORDER, /* size and order of int */
162
4, NORMAL_ORDER, /* size and order of long */
163
4, NORMAL_ORDER, /* size and order of long long */
164
4, lite_def_float, /* float definition */
165
lite_def_float_order,
166
8, lite_def_double, /* double definition */
167
lite_def_double_order},
168
lite_IEEEA_STD = {4, /* size of pointer */
169
2, NORMAL_ORDER, /* size and order of short */
170
4, NORMAL_ORDER, /* size and order of int */
171
4, NORMAL_ORDER, /* size and order of long */
172
8, NORMAL_ORDER, /* size and order of long long */
173
4, lite_ieee_float, /* float definition */
174
lite_ieee_float_order,
175
8, lite_ieeea_double, /* double definition */
176
lite_ieeea_double_order},
177
lite_IEEEB_STD = {4, /* size of pointer */
178
2, NORMAL_ORDER, /* size and order of short */
179
2, NORMAL_ORDER, /* size and order of int */
180
4, NORMAL_ORDER, /* size and order of long */
181
4, NORMAL_ORDER, /* size and order of long long */
182
4, lite_ieee_float, /* float definition */
183
lite_ieee_float_order,
184
12, lite_ieeeb_double, /* double definition */
185
lite_ieeeb_double_order},
186
lite_INTELA_STD = {4, /* size of pointer */
187
2, REVERSE_ORDER, /* size and order of short */
188
2, REVERSE_ORDER, /* size and order of int */
189
4, REVERSE_ORDER, /* size and order of long */
190
4, REVERSE_ORDER, /* size and order of long long */
191
4, lite_intel_float, /* float definition */
192
lite_intel_float_order,
193
8, lite_intel_double, /* double definition */
194
lite_intel_double_order},
195
lite_VAX_STD = {4, /* size of pointer */
196
2, REVERSE_ORDER, /* size and order of short */
197
4, REVERSE_ORDER, /* size and order of int */
198
4, REVERSE_ORDER, /* size and order of long */
199
4, REVERSE_ORDER, /* size and order of long long */
200
4, lite_vax_float, /* float definition */
201
lite_vax_float_order,
202
8, lite_vax_double, /* double definition */
203
lite_vax_double_order},
204
lite_CRAY_STD = {8, /* size of pointer */
205
8, NORMAL_ORDER, /* size and order of short */
206
8, NORMAL_ORDER, /* size and order of int */
207
8, NORMAL_ORDER, /* size and order of long */
208
8, NORMAL_ORDER, /* size and order of long long */
209
8, lite_cray_float, /* float definition */
210
lite_cray_float_order,
211
8, lite_cray_float, /* double definition */
212
lite_cray_float_order};
215
/*--------------------------------------------------------------------------*/
216
/* DATA_ALIGNMENTS */
217
/*--------------------------------------------------------------------------*/
220
* Word Alignment for the different architectures
223
* struct s_data_alignment
224
* {int char_alignment;
226
* int short_alignment;
228
* int long_alignment;
229
* int float_alignment;
230
* int double_alignment;
231
* int struct_alignment;};
233
* typedef struct s_data_alignment data_alignment;
235
* Mark C. Miller, Fri Nov 13 15:33:42 PST 2009
236
* Added support for long long datatype.
247
lite_RS6000_ALIGNMENT = {1, 4, 2, 4, 4, 8, 4, 4, 0},
248
lite_SPARC_ALIGNMENT = {1, 4, 2, 4, 4, 4, 4, 8, 0},
249
lite_MIPS_ALIGNMENT = {1, 4, 2, 4, 4, 8, 4, 8, 0},
250
lite_M68000_ALIGNMENT = {1, 2, 2, 2, 2, 2, 2, 2, 0},
251
lite_INTELA_ALIGNMENT = {1, 2, 2, 2, 2, 2, 2, 2, 0},
252
lite_UNICOS_ALIGNMENT = {4, 8, 8, 8, 8, 8, 8, 8, 8},
253
lite_DEF_ALIGNMENT = {1, 4, 4, 4, 4, 4, 4, 4, 0};
256
/*--------------------------------------------------------------------------*/
257
/*--------------------------------------------------------------------------*/
260
/*-------------------------------------------------------------------------
261
* Function: lite_PD_convert
263
* Purpose: Convert from one machine format to another NITEMS of type
264
* TYPE from IN and put them in OUT. ISTD and OSTD are the
265
* data format standards of IN and OUT respectively.
271
* Programmer: Adapted from PACT PDB
272
* Mar 6, 1996 11:34 AM EST
276
*-------------------------------------------------------------------------
279
lite_PD_convert (char **out, char **in, char *intype, char *outtype,
280
long nitems, data_standard *istd, data_standard *ostd,
281
data_standard *hstd, long *pin_offs, long *pout_offs,
282
HASHTAB *in_chart, HASHTAB *out_chart, int boffs, int error) {
285
long i, mitems, in_incr, out_incr;
287
defstr *idp, *odp, *midp, *modp;
290
if (_lite_PD_indirection(outtype)) {
291
in_incr = _lite_PD_align(*pin_offs, intype, in_chart, &tmp);
292
out_incr = _lite_PD_align(*pout_offs, outtype, out_chart, &tmp);
293
*pin_offs += in_incr;
294
*pout_offs += out_incr;
295
*in += istd->ptr_bytes + in_incr;
296
*out += ostd->ptr_bytes + out_incr;
300
idp = PD_inquire_table_type(in_chart, intype);
302
lite_PD_error("BAD TYPE IN_CHART - PD_CONVERT", error);
304
odp = PD_inquire_table_type(out_chart, outtype);
306
lite_PD_error("BAD TYPE OUT_CHART - PD_CONVERT", error);
309
* If members is non-NULL then it is a derived type.
311
if (odp->members != NULL) {
312
for (i = 0L; i < nitems; i++) {
313
in_incr = _lite_PD_align(*pin_offs, intype, in_chart, &tmp);
314
out_incr = _lite_PD_align(*pout_offs, outtype, out_chart, &tmp);
315
*pin_offs += in_incr;
316
*pout_offs += out_incr;
320
for (desc = odp->members; desc != NULL; desc = desc->next) {
321
mitems = desc->number;
323
in_incr = _lite_PD_align(*pin_offs, mtype, in_chart, &tmp);
324
out_incr = _lite_PD_align(*pout_offs, mtype, out_chart, &tmp);
327
* Increment the offsets to the alignments.
329
*pin_offs += in_incr;
330
*pout_offs += out_incr;
334
if (_lite_PD_indirection(mtype)) {
336
* Don't even think about converting pointers - they will be
337
* recomputed. However, don't throw away information about
338
* whether or not pointer is null.
340
if (!_lite_PD_null_pointer(*in, istd->ptr_bytes)) **out = 1;
341
*in += istd->ptr_bytes;
342
*out += ostd->ptr_bytes;
343
*pin_offs += istd->ptr_bytes;
344
*pout_offs += ostd->ptr_bytes;
347
} else if (_lite_PD_prim_typep(desc->base_type, in_chart, error)) {
349
* Check for direct primitives.
351
modp = PD_inquire_table_type(out_chart, mtype);
353
lite_PD_error("BAD OUT TYPE IN STRUCT - PD_CONVERT", error);
355
midp = PD_inquire_table_type(in_chart, mtype);
357
lite_PD_error("BAD IN TYPE IN STRUCT - PD_CONVERT", error);
359
ret = _lite_PD_convert((char **) out, in, mitems, boffs,
360
midp, modp, hstd, pin_offs, pout_offs);
364
* Recurse for direct derived types.
366
ret = lite_PD_convert(out, in, mtype, mtype, mitems,
367
istd, ostd, hstd, pin_offs, pout_offs,
368
in_chart, out_chart, boffs, error);
372
lite_PD_error("STRUCT CONVERSION FAILED - PD_CONVERT",
379
* if members is NULL then it is a primitive type.
381
ret = _lite_PD_convert((char **) out, in, nitems, boffs, idp, odp,
382
hstd, pin_offs, pout_offs);
384
lite_PD_error("PRIMITIVE CONVERSION FAILED - PD_CONVERT", error);
391
/*-------------------------------------------------------------------------
392
* Function: _lite_PD_null_pointer
394
* Purpose: Does input contain only null bytes?
396
* Return: Success: TRUE
400
* Programmer: Adapted from PACT PDB
401
* Mar 6, 1996 12:02 PM EST
405
*-------------------------------------------------------------------------
408
_lite_PD_null_pointer (char *in, int bytes) {
412
for (i = 0; i < bytes; i++) {
413
if (*in++) return(FALSE);
420
/*-------------------------------------------------------------------------
421
* Function: _lite_PD_prim_typep
423
* Purpose: Is the given struct member a primitive data type?
425
* Return: Success: TRUE
429
* Programmer: Adapted from PACT PDB
430
* Mar 6, 1996 12:03 PM EST
434
*-------------------------------------------------------------------------
437
_lite_PD_prim_typep (char *memb, HASHTAB *chrt, int error) {
441
pd = PD_inquire_table_type(chrt, memb);
443
lite_PD_error("BAD TYPE FROM STRUCTURE CHART - _PD_PRIM_TYPEP", error);
445
return((pd->members == NULL));
449
/*-------------------------------------------------------------------------
450
* Function: _lite_PD_convert
452
* Purpose: Convert primitive types from one machine format to another.
453
* Guaranteed that there will be no indirects here. Convert
454
* NITEMS of type TYPE from IN and put them in OUT. ISTD
455
* defines the data format of the data from IN. PIN_OFFS and
456
* POUT_OFFS are pointers to external offset counters and
457
* they are incremented to account for data alignment.
459
* Return: Success: TRUE
463
* Programmer: Adapted from PACT PDB
464
* Mar 6, 1996 11:58 AM EST
468
*-------------------------------------------------------------------------
471
_lite_PD_convert (char **out, char **in, long nitems, int boffs,
472
defstr *idp, defstr *odp, data_standard *hstd,
473
long *pin_offs, long *pout_offs) {
475
int l_order, l_bytes, in_bits, onescmp, unsgned, ret;
476
long in_bytes, out_bytes;
477
int in_flag, out_flag, *in_order, *out_order;
478
long *in_format, *out_format;
479
char *in_type, *out_type;
482
out_type = odp->type;
483
in_bits = idp->size_bits;
484
in_bytes = idp->size;
485
out_bytes = odp->size;
486
in_order = idp->order;
487
out_order = odp->order;
488
in_flag = idp->order_flag;
489
out_flag = odp->order_flag;
490
in_format = idp->format;
491
out_format = odp->format;
492
onescmp = idp->onescmp;
493
unsgned = idp->unsgned;
495
if ((strchr(in_type, '*') != NULL) || (strchr(out_type, '*') != NULL))
498
l_order = hstd->long_order;
499
l_bytes = hstd->long_bytes;
502
if ((in_format != NULL) && (out_format != NULL)) {
504
* Handle floating point conversions.
506
_lite_PD_fconvert(out, in, nitems, boffs, in_format, in_order,
507
out_format, out_order, l_order, l_bytes, onescmp);
509
*pin_offs += in_bytes*nitems;
510
*pout_offs += out_bytes*nitems;
511
} else if (in_bits > 0) {
513
* Handle integral bitstreams.
517
if (out_bytes == sizeof(char)) ityp = SC_CHAR_I;
518
else if (out_bytes == sizeof(short)) ityp = SC_SHORT_I;
519
else if (out_bytes == sizeof(int)) ityp = SC_INTEGER_I;
520
else if (out_bytes == sizeof(long)) ityp = SC_LONG_I;
524
* Unpack the bitstream into a bytestream.
526
ret = _lite_PD_unp_bits(*out, *in, ityp, in_bits,
527
0, nitems, nitems, boffs);
529
if (strcmp(in_type, lite_SC_CHAR_S) == 0) {
531
* Convert characters.
533
_lite_PD_convert_ascii(*out, *in, nitems, in_bits, 0);
540
_PD_sign_extend(*out, nitems, out_bytes,
543
*in += in_bytes*nitems;
544
*out += out_bytes*nitems;
545
*pin_offs += in_bytes*nitems;
546
*pout_offs += out_bytes*nitems;
549
} else if ((in_flag != -1) && (out_flag != -1)) {
551
* Handle integer conversions.
553
_lite_PD_iconvert(out, in, nitems,
554
(int) in_bytes, in_flag,
555
(int) out_bytes, out_flag, onescmp);
557
*pin_offs += in_bytes*nitems;
558
*pout_offs += out_bytes*nitems;
562
* Handle character or unconverted types.
564
_PD_ncopy(out, in, nitems, in_bytes);
566
*pin_offs += in_bytes*nitems;
567
*pout_offs += out_bytes*nitems;
573
/*--------------------------------------------------------------------------*/
574
/* ASCII CONVERSION ROUTINES */
575
/*--------------------------------------------------------------------------*/
578
/*-------------------------------------------------------------------------
579
* Function: _lite_PD_convert_ascii
581
* Purpose: Translate characters fromBCPI bit ASCII to 8-bit ASCII.
582
* This is only here to allow PDB to read old machine data
583
* which may not be 8-bit ASCII.
585
* Inputs: IN: Input buffer.
586
* NITEMS: Number of fields to translate.
587
* BCPI: Bits per character on input.
588
* OFFS: Zero-origin bit offset from IN to start of data.
590
* Output: OUT: Output buffer.
594
* Programmer: Adapted from PACT PDB
595
* Mar 6, 1996 12:05 PM EST
598
* Sean Ahern, Wed Apr 12 10:44:26 PDT 2000
599
* Put in an ARGSUSED comment to prevent compiler warnings. I don't want
600
* to remove the parameters, since I don't know how this is called.
601
*-------------------------------------------------------------------------*/
604
_lite_PD_convert_ascii (char *out, char *in, long nitems, int bpci, int offs) {
609
* Stretch input characters into 8 bits right-justified
613
/* translate chars by adding a blank (0x20) character
614
* to give upper-case letters then or-ing the sum with a blank
615
* to give lower-case letters
617
for (i = 0; i < nitems; i++) out[i] = (out[i] + ' ') | ' ';
620
/*--------------------------------------------------------------------------*/
621
/* INTEGER CONVERSION ROUTINES */
622
/*--------------------------------------------------------------------------*/
625
/*-------------------------------------------------------------------------
626
* Function: _lite_PD_iconvert
628
* Purpose: Convert integers of nbi bytes to integers of nbo bytes.
629
* The number of bytes for each integer are give.
633
* Programmer: Adapted from PACT PDB
634
* Mar 6, 1996 12:14 PM EST
638
*-------------------------------------------------------------------------
641
_lite_PD_iconvert (char **out, char **in, long nitems, long nbi, int ordi,
642
long nbo, int ordo, int onescmp) {
646
char *lout, *lin, *po, *pi;
652
* Convert nitems integers.
653
* test sign bit to properly convert negative integers
656
if (ordi == REVERSE_ORDER) {
657
for (j = nbi; j < nbo; j++) {
660
for (i = 0L; i < nitems; i++) {
661
*po = (*pi & 0x80) ? 0xff : 0;
666
for (j = nbi; j > 0; j--) {
669
for (i = 0L; i < nitems; i++) {
676
for (j = nbi; j < nbo; j++) {
679
for (i = 0L; i < nitems; i++) {
680
*po = (*pi & 0x80) ? 0xff : 0;
685
for (j = 0; j < nbi; j++) {
686
po = lout + j + nbo - nbi;
688
for (i = 0L; i < nitems; i++) {
696
} else if (nbi >= nbo) {
697
if (ordi == REVERSE_ORDER) {
698
for (j = nbo; j > 0; j--) {
701
for (i = 0L; i < nitems; i++) {
708
for (j = nbi - nbo; j < nbi; j++) {
709
po = lout + j - nbi + nbo;
711
for (i = 0L; i < nitems; i++) {
721
* If the input used ones complement arithmetic
722
* convert to twos complement.
724
if (onescmp) _PD_ones_complement(*out, nitems, nbo);
726
if (ordo == REVERSE_ORDER) _PD_btrvout(*out, nbo, nitems);
732
/*--------------------------------------------------------------------------*/
733
/* FLOAT CONVERSION ROUTINES */
734
/*--------------------------------------------------------------------------*/
736
/* Parametrized Data Conversion Method
738
* Floating point formats are characterized by a set of parameters which
739
* describe the fundamental elements of a floating point number. These are
741
* Sign - always assumed to be a single bit
742
* - requires bit offset
743
* Exponent - assumed to be a biased integer smaller than 32 bits
744
* - (this allows the conversion to use a long on all known
745
* - platforms - an exponent greater than 32 bits long would
746
* - allow much larger numbers than should be needed for
747
* - scientific computations)
748
* - requires a bit offset, a bit length, and a bias
749
* Mantissa - assumed to be a bitstream of arbitrary length
750
* - requires a bit offset and a bit length
751
* HMB - in all floating point representations the mantissa is
752
* - normalized so that the most significant bit is one.
753
* - in some formats the one is explicitly included in the
754
* - representation and in others it is only implicit
755
* - this gives some formats an extra bit of precision.
756
* - requires a flag which is TRUE if the HMB is explicit
758
* Two other factors involved are: the byte order which could be
759
* mixed with the bit layout of the numbers but isn't in actual practice
760
* on current machines; and whether one's complement or two's complement
761
* arithmetic is used. Modern machines all use two's complement arithmetic
762
* and the model used here and now is that data from one's complement
763
* machines is to be read only. This restriction is relatively easy
764
* to relax, but there is no evidence that it should be.
766
* An issue which is not a problem in the current implementation is that
767
* old machines with byte sizes other than 8 bits can be accomodated
768
* because the conversions treat the input and output as bitstreams
769
* instead of bytestreams.
771
* The conversion process is summarized as follows:
772
* 1) Extract the sign bit and exponent field from the input number
773
* 2) Subtract the bias of the source format and add the bias
774
* of the target format
775
* 3) Check for overflow in the exponent
776
* 4) Insert the new exponent and the sign bit in the target stream
777
* 5) Copy the mantissa bits from the source to the target
778
* compensating for differences in the HMB between the two
780
* 6) Take care of any known anomalies - e.g. CRAY format is
781
* inconsistent in that the HMB is explicitly on for all numbers
782
* with the exception of 0.0
783
* 7) Reorder the bytes of the target stream appropriately
785
* The floating point formats for a variety of platforms are supplied by
786
* PDBLib and are defined at the top of this file
791
/*-------------------------------------------------------------------------
792
* Function: _lite_PD_fconvert
794
* Purpose: General floating point conversion routine. Convert from
795
* floating point format specified by infor to format
796
* specified by outfor.
798
* floating point format specification:
800
* format[0] = # of bits per number
801
* format[1] = # of bits in exponent
802
* format[2] = # of bits in mantissa
803
* format[3] = start bit of sign
804
* format[4] = start bit of exponent
805
* format[5] = start bit of mantissa
806
* format[6] = high order mantissa bit (CRAY needs this)
807
* format[7] = bias of exponent
811
* Programmer: Adapted from PACT PDB
812
* Mar 6, 1996 12:08 PM EST
815
* Sean Ahern, Fri Mar 2 09:39:53 PST 2001
816
* Added a logic path suggested by Dan Schikore for when the formats
819
* Sean Ahern, Fri Mar 2 09:40:15 PST 2001
820
* Reformatted some of the code.
822
*-------------------------------------------------------------------------*/
824
_lite_PD_fconvert (char **out, char **in, long nitems, int boffs, long *infor,
825
int *inord, long *outfor, int *outord, int l_order,
826
int l_bytes, int onescmp) {
828
long i, expn, expn_max, hexpn, mant, DeltaBias, hmbo, hmbi;
829
int nbits, inbytes, outbytes, sign;
830
int indxin, indxout, inrem, outrem, dindx;
831
int bi_sign, bo_sign, bi_exp, bo_exp, bi_mant, bo_mant;
832
int nbi_exp, nbo_exp, nbi, nbo;
835
static int BitsMax = 8*sizeof(long);
842
bi_sign = infor[3] + boffs;
844
bi_exp = infor[4] + boffs;
846
bi_mant = infor[5] + boffs;
849
hmbo = (outfor[6] & 1L);
850
hmbi = (infor[6] & 1L);
852
inbytes = (nbi + 7) >> 3;
853
outbytes = (nbo + 7) >> 3;
854
DeltaBias = outfor[7] + hmbo - infor[7] - hmbi;
855
hexpn = 1L << (outfor[1] - 1L);
856
expn_max = (1L << outfor[1]) - 1L;
858
if ( (inord[0] != outord[0]) ||
859
(infor[0] != outfor[0]) || (infor[1] != outfor[1]) ||
860
(infor[2] != outfor[2]) || (infor[3] != outfor[3]) ||
861
(infor[4] != outfor[4]) || (infor[5] != outfor[5]) ||
862
(infor[6] != outfor[6]) || (infor[7] != outfor[7]) )
865
* Zero out the output buffer.
867
memset(*out, 0, nitems*outbytes);
871
for (i = 0L; i < nitems; i++) {
873
* Move the exponent over.
875
expn = _lite_PD_extract_field(lin, bi_exp, nbi_exp, inbytes, inord);
876
sign = _PD_get_bit(lin, bi_sign, inbytes, inord);
879
* If we have a negative number and ones complement arithmetic on the
880
* input side (won't have it on the output side with modern data)
881
* take the complement of the exponent and mantissa.
885
ONES_COMP_NEG(expn, nbi_exp, 1L);
887
expn += (expn < hexpn);
891
if (expn != 0) expn += DeltaBias;
893
if ((0 <= expn) && (expn < expn_max)) {
894
_PD_insert_field(expn, nbo_exp, lout, bo_exp,
897
if (sign) _PD_set_bit(lout, bo_sign);
907
* If input high mantissa bit (HMB) is assumed 1 and not written
908
* (e.g. IEEE) but output HMB is assumed 0 (e.g. CRAY) write the
909
* input starting at the output HMB+1 and set the HMB.
911
_PD_set_bit(lout, indxout);
914
} else if (dindx < 0) {
916
* If input HMB is assumed 0 (e.g. CRAY) but output HMB is assumed
917
* 1 and not written (e.g. IEEE) take the input from HMB+1 and
918
* write it to output HMB.
925
* Move the mantissa over in sizeof(long) packets.
927
while ((inrem > 0) && (outrem > 0)) {
928
nbits = MIN(BitsMax, inrem);
929
nbits = MIN(nbits, outrem);
930
mant = _lite_PD_extract_field(lin, indxin, nbits,
934
* Do complement for negative ones complement data.
936
if (onescmp && sign) ONES_COMP_NEG(mant, nbits, 0L);
938
_PD_insert_field(mant, nbits, lout, indxout,
946
} else if (expn_max <= expn) {
948
* In case of overflow use 1.0e+(expn_max)
950
_PD_insert_field(expn_max, nbo_exp, lout, bo_exp,
953
if (_PD_get_bit(lin, bi_sign, inbytes, inord))
954
_PD_set_bit(lout, bo_sign);
966
* Handle CRAY inconsistency which has zero as the only floating point
967
* number with a 0 in the HMB. Also problem for IEEE 96 bit float.
968
* Fixed by Dave Munro
971
int j, mask = (1 << (7 - bo_mant % 8));
973
indxout = outfor[5]/8;
974
rout = (unsigned char *) *out;
975
for (i = 0L; i < nitems; i++, rout += outbytes) {
976
for (j = 0; j < outbytes; j++) {
977
if ((j == indxout) ? (rout[j] != mask) : rout[j]) break;
979
if (j == outbytes) rout[indxout] = 0;
984
memcpy(*out, *in, nitems*outbytes);
987
* Put the output bytes into the specified order.
989
for (i=0; i<outbytes; i++)
990
if (inord[i] != outord[i])
993
_PD_reorder(*out, nitems, outbytes, outord);
995
*in += nitems*inbytes;
996
*out += nitems*outbytes;
999
/*--------------------------------------------------------------------------*/
1000
/* HELPER ROUTINES */
1001
/*--------------------------------------------------------------------------*/
1004
/*-------------------------------------------------------------------------
1005
* Function: _PD_ncopy
1007
* Purpose: Copy the NITEMS of size BYTEPITEM from IN to OUT
1011
* Programmer: Adapted from PACT PDB
1012
* Mar 6, 1996 12:22 PM EST
1016
*-------------------------------------------------------------------------
1019
_PD_ncopy (char **out, char **in, long nitems, long bytepitem) {
1023
nbytes = nitems*bytepitem;
1024
memcpy(*out, *in, nbytes);
1031
/*-------------------------------------------------------------------------
1032
* Function: _lite_PD_unp_bits
1034
* Purpose: Unpack an array that contains a bitstream. Arguments are
1036
* ITYP the target type of the data when unpacked
1037
* NBITS the number of bits per item
1038
* PADSZ the number of bits of pad preceding the fields
1039
* FPP the number of fields per pad
1040
* NITEMS the number of items expected
1041
* OFFS the bit offset of the first pad
1047
* Programmer: Adapted from PACT PDB
1048
* Mar 6, 1996 12:26 PM EST
1052
*-------------------------------------------------------------------------
1055
_lite_PD_unp_bits (char *out, char *in, int ityp, int nbits, int padsz,
1056
int fpp, long nitems, long offs) {
1058
long i, bita, fld, np, *pl;
1077
for (i = 0L; i < nitems; i++) {
1079
bita = np*padsz + i*nbits + offs;
1080
fld = _lite_PD_extract_field(in, bita, nbits, INT_MAX, NULL);
1087
ps[i] = (short) fld;
1102
/*-------------------------------------------------------------------------
1103
* Function: _PD_sign_extend
1105
* Purpose: Sign extend integers which may come from odd bit
1110
* Programmer: Adapted from PACT PDB
1111
* Mar 6, 1996 12:23 PM EST
1115
*-------------------------------------------------------------------------
1118
_PD_sign_extend (char *out, long nitems, int nbo, int nbti, int *ord) {
1120
int i, j, sba, mask, sign, indx;
1121
unsigned char *lout;
1126
* If sba is less than zero we have truncated the integers and really
1127
* don't know about the sign.
1129
if (sba < 0) return;
1131
lout = (unsigned char *) out;
1132
for (i = 0L; i < nitems; i++) {
1133
sign = _PD_get_bit((char *) lout, sba, nbo, ord);
1135
for (j = 0; (sba > 8); j++) {
1136
indx = (ord != NULL) ? ord[j] : j;
1140
mask = ((1 << sba) - 1) << nbti;
1141
indx = (ord != NULL) ? ord[j] : j;
1149
/*-------------------------------------------------------------------------
1150
* Function: _PD_ones_complement
1152
* Purpose: Convert ones complement integers to twos complement.
1153
* Note: modern machines use two's complement arithmetic
1154
* and therefore this is a one way conversion.
1158
* Programmer: Adapted from PACT PDB
1159
* Mar 6, 1996 12:40 PM EST
1163
*-------------------------------------------------------------------------
1166
_PD_ones_complement (char *out, long nitems, int nbo) {
1172
lout = (signed char *) out;
1173
for (i = 0L; i < nitems; i++) {
1176
for (j = nbo-1; (j >= 0) && (carry > 0); j--) {
1178
lout[j] = carry & 0xFF;
1179
carry = (carry > 0xFF);
1188
/*-------------------------------------------------------------------------
1189
* Function: _PD_btrvout
1191
* Purpose: Byte reverse nitems words each word is nb bytes long
1196
* Programmer: Adapted from PACT PDB
1197
* Mar 6, 1996 12:31 PM EST
1201
*-------------------------------------------------------------------------
1204
_PD_btrvout (char *out, long nb, long nitems) {
1206
long i, jl, jh, nbo2;
1211
for (jl = 0; jl < nbo2; jl++) {
1215
for (i = 0L; i < nitems; i++) {
1226
/*-------------------------------------------------------------------------
1227
* Function: _lite_PD_extract_field
1229
* Purpose: Make a copy of the bit field specified by the starting
1230
* bit OFFS and the number of bits NBI from the byte array
1231
* pointed to by IN. All indexing is zero based. The copy
1232
* is to be put in a long and returned. This imposes a 32
1233
* bit limit (minimum) so repeated calls must be made for
1238
* Programmer: Adapted from PACT PDB
1239
* Mar 6, 1996 12:32 PM EST
1243
*-------------------------------------------------------------------------
1246
_lite_PD_extract_field (char *in, int offs, int nbi, int nby, int *ord) {
1250
unsigned char mask, bpb;
1255
* Move past the apropriate number of bytes so that the start bit is
1256
* in the first byte. OFFY is the offset of the byte containing the
1265
* Advance the pointer past the unneeded items.
1277
ind = (ord[offy++] - 1);
1281
mask = (1 << bpb) - 1;
1282
bit_field = ((bit_field << bpb) | (tgt & mask));
1285
bit_field = bit_field >> (-nbi);
1287
for (; nbi > 0; nbi -= bpb) {
1295
ind = (ord[offy++] - 1);
1300
mask = (1 << bpb) - 1;
1301
bit_field = ((bit_field << bpb) |
1302
((tgt >> (8 - bpb)) & mask));
1309
/*-------------------------------------------------------------------------
1310
* Function: _PD_insert_field
1312
* Purpose: Copy the least significatn NB bits from the given long
1313
* into the byte array pointed to by OUT. All indexint
1314
* is zero based. OFFS is the offst from the beginning of
1315
* OUT in bits. This assumes that the output bit array is
1316
* initialized to all zeros after offs.
1320
* Programmer: Adapted from PACT PDB
1321
* Mar 6, 1996 12:35 PM EST
1325
*-------------------------------------------------------------------------
1328
_PD_insert_field (long in_long, int nb, char *out, int offs,
1329
int l_order, int l_bytes) {
1333
static int MaxBits = 8*sizeof(long);
1337
in = (char *) &in_long;
1340
* If the output start bit is not in the first byte move past the apropriate
1341
* number of bytes so that the start bit is in the first byte.
1349
* If mi is less than offs, copy the first dm bits over, reset offs to 0,
1350
* advance mi by dm, and handle the rest as if mi >= offs.
1354
dm = MaxBits - (8 - offs);
1355
if (nb == MaxBits) {
1356
longmask = ~((1L << dm) - 1L);
1358
longmask = ((1L << nb) - 1L) ^ ((1L << dm) - 1L);
1361
fb = ((in_long & longmask) >> dm) & ((1L << (nb - dm)) - 1L);
1369
* Assuming mi >= offs, left shift the input so that it is bit aligned
1373
longmask = ~((1L << dm) - 1L);
1374
in_long = (in_long << dm) & longmask;
1377
* Reorder the bytes apropriately.
1379
if (l_order == REVERSE_ORDER) _PD_btrvout(in, l_bytes, 1L);
1382
* Copy the remaining aligned bytes over.
1384
for (n = (offs+nb+7)/8; n > 0; n--, *(out++) |= *(in++)) /*void*/ ;
1388
/*-------------------------------------------------------------------------
1389
* Function: _PD_set_bit
1391
* Purpose: Set the bit specified as o offset from the given pointer.
1395
* Programmer: Adapted from PACT PDB
1396
* Mar 6, 1996 12:37 PM EST
1400
*-------------------------------------------------------------------------
1403
_PD_set_bit (char *base, int offs) {
1411
mask = (1 << (7 - offs));
1416
/*-------------------------------------------------------------------------
1417
* Function: _PD_get_bit
1419
* Purpose: Return the bit specified as on offst from the given ptr.
1421
* Return: Success: 0 or 1
1425
* Programmer: Adapted from PACT PDB
1426
* Mar 6, 1996 12:38 PM EST
1430
*-------------------------------------------------------------------------
1433
_PD_get_bit (char *base, int offs, int nby, int *ord) {
1435
int nbytes, mask, n;
1442
if (ord == NULL) base += (n + nbytes);
1443
else base += (n + (ord[nbytes] - 1));
1445
mask = (1 << (7 - offs));
1447
return((*base & mask) != 0);
1451
/*-------------------------------------------------------------------------
1452
* Function: _PD_reorder
1454
* Purpose: Given a pointer to an array ARR with NITEMS of NBYTES each
1455
* put them in the order defined by ORD.
1459
* Programmer: Adapted from PACT PDB
1460
* Mar 6, 1996 12:39 PM EST
1464
*-------------------------------------------------------------------------
1467
_PD_reorder (char *arr, long nitems, int nbytes, int *ord) {
1469
char local[MAXLINE];
1472
for (; nitems > 0; nitems--) {
1474
for (j = 0; j < nbytes; local[j] = arr[ord[j]], j++) /*void*/ ;
1476
for (j = 0; j < nbytes; *(arr++) = local[j++]) /*void*/ ;