Skupiny Google už nepodporujú nové príspevky ani odbery Usenet. Historický obsah zostáva viditeľný.

Conversion from 370 floating point to RS6000 floating point.

1 zobrazenie
Preskočiť na prvú neprečítanú správu

Glenn Farrow

neprečítané,
23. 8. 1993, 21:07:1223. 8. 1993
komu:
I need to move some binary files from a 370 to an RS6000 and have to convert
between floating point formats in the process. I would appreciate any info
anyone has on either the 370 format or the RS6000 format. (Conversion to
text files is not feasible given the amount of data involved).


Steven Lebowitz

neprečítané,
24. 8. 1993, 8:09:3724. 8. 1993
komu:

Here is a file which was posted some time ago to this newsgroup. It includes
functions for converting both single and double precision numbers to/from
370 and IEEE formats. Having tested them, I can say that they work very well.

Many thanks to the original author Derek Lieber...

--- CUT HERE --- cieee.c

/* Convert floating point numbers between IBM/370 and IEEE representations
*
* Synopsis:
*
* void f370toIEEE(src, dst) -- convert 370 float to IEEE float
* float *src, *dst;
*
* void d370toIEEE(src, dst) -- convert 370 double to IEEE double
* double *src, *dst;
*
* void fIEEEto370(src, dst) -- convert IEEE float to 370 float
* float *src, *dst;
*
* void dIEEEto370(src, dst) -- convert IEEE double to 370 double
* double *src, *dst;
*
* Notes:
*
* Magnitudes which underflow during conversion are converted to 0. Magnitudes
* which overflow during conversion are converted to the largest representable
* number.
*
* History:
* 10/10/86 -- written (Derek Lieber)
*/
#define PC 0 /* are we running on a pc? */
#define CHECKOUT 1 /* compile as standalone program for debugging? */

#if PC
#define HI 1 /* index of hi order byte/word/long */
#define LO 0 /* index of lo order byte/word/long */
#else
#define HI 0 /* index of hi order byte/word/long */
#define LO 1 /* index of lo order byte/word/long */
#endif

/* largest representable numbers, IEEE format */
#define fMAXIEEE 0x7F7FFFFF
#define dMAXIEEEhi 0x7FEFFFFF
#define dMAXIEEElo 0xFFFFFFFF

/* largest representable numbers, 370 format */
#define fMAX370 0x7FFFFFFF
#define dMAX370hi 0x7FFFFFFF
#define dMAX370lo 0xFFFFFFFF

/* Summary of floating point representations
*
* ************************
* IBM/370 single precision
* ************************
*
* xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx
* |-exp--| |--------fraction-----------|
* (7) (24)
*
* value = (-1)**s * 16**(e - 64) * .f range = 5E-79 ... 7E+75
*
* *********************
* IEEE single precision
* *********************
*
* xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx
* |--exp---||-------fraction-----------|
* (8) (23)
*
* value = (-1)**s * 2**(e - 127) * 1.f range = 1E-38 ... 3E+38
*
* ************************
* IBM/370 double precision
* ************************
*
* xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx yyyy.yyyy yyyy.yyyy yyyy.yyyy yyyy.yyyy
* |-exp--| |-------------------------------fraction----------------------------|
* (7) (56)
*
* value = (-1)**s * 16**(e - 64) * .f range = 5E-79 ... 7E+75
*
* *********************
* IEEE double precision
* *********************
*
* xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx yyyy.yyyy yyyy.yyyy yyyy.yyyy yyyy.yyyy
* |--exponent-| |-------------------------fraction-----------------------------|
* (11) (52)
*
* value = (-1)**s * 2**(e - 1023) * 1.f range = 2E-308 ... 3E+308
*/

/* Convert IBM/370 "float" to IEEE "float"
*/
f370toIEEE(src, dst)
unsigned long src[1], dst[1];
{
unsigned long x, s, f;
long e;

x = *src;

/* check for special case */
if ((x & 0x7fffffff) == 0)
{
*dst = x;
return; /* zero */
}

/* fetch the sign, exponent (removing excess 64), and fraction */
s = x & 0x80000000;
e = ((x & 0x7f000000) >> 24) - 64;
f = x & 0x00ffffff;

/* convert 24 bit fraction to 23 bit fraction */
f >>= 1;

/* convert scale factor from "16**exponent" to "2**exponent" format
* -- we simply multiply the exponent by 4
*/
if (e >= 0)
e <<= 2;
else
e = -((-e) << 2);

/* normalize the fraction */
if (f)
while ((f & 0x00800000) == 0)
{
f <<= 1;
e -= 1;
}

/* drop the implied '1' preceeding the binary point */
f &= 0x007fffff;

/* convert exponent to excess 127 and store the number */
if ((e += 127) >= 255)
*dst = s | fMAXIEEE;
else if (e <= 0)
*dst = s;
else
*dst = s | (e << 23) | f;
}

/* Convert IBM/370 "double" to IEEE "double"
*/
d370toIEEE(src, dst)
unsigned long src[2], dst[2];
{
unsigned long x, s, f[2];
long e;

x = src[HI];

/* check for special case */
if ((x & 0x7fffffff) == 0)
{
dst[HI] = src[HI];
dst[LO] = src[LO];
return; /* zero */
}

/* fetch the sign, exponent (removing excess 64), and fraction */
s = x & 0x80000000;
e = ((x & 0x7f000000) >> 24) - 64;
f[0] = x & 0x00ffffff;
f[1] = src[LO];

/* convert 56 bit fraction to 52 bit fraction */
rshift(f, 4);

/* convert scale factor from "16**exponent" to "2**exponent" format
* -- we simply multiply the exponent by 4
*/
if (e >= 0)
e <<= 2;
else
e = -((-e) << 2);

/* normalize the fraction */
if (f[0])
while ((f[0] & 0x00100000) == 0)
{
lshift(f, 1);
e -= 1;
}

/* drop the implied '1' preceeding the binary point */
f[0] &= 0x000fffff;

/* convert exponent to excess 1023 and store the number */
if ((e += 1023) >= 2047)
{
dst[HI] = s | dMAXIEEEhi;
dst[LO] = dMAXIEEElo;
}
else if (e <= 0)
{
dst[HI] = s;
dst[LO] = 0;
}
else
{
dst[HI] = s | (e << 20) | f[0];
dst[LO] = f[1];
}
}

/* Convert IEEE "float" to IBM/370 "float"
*/
fIEEEto370(src, dst)
unsigned long src[1], dst[1];
{
unsigned long x, s, f;
long e;

x = *src;

/* check for special case */
if ((x & 0x7fffffff) == 0)
{
*dst = x;
return; /* zero */
}

/* fetch the sign, exponent (removing excess 127), and fraction */
s = x & 0x80000000;
e = ((x & 0x7f800000) >> 23) - 127;
f = x & 0x007fffff;

/* convert 23 bit fraction to 24 bit fraction */
f <<= 1; /* >>fraction is now 24 bits<< */

/* restore the implied '1' which preceeded the IEEE binary point */
f |= 0x01000000; /* >>fraction is now 25 bits<< */

/* convert scale factor from "2**exponent" to "16**exponent" format
* -- we adjust fraction and exponent in opposite directions until
* exponent is a multiple of 4, then divide the exponent by 4
*/
if (e >= 0)
{
f <<= (e & 3); /* >>fraction is now 28 bits, max<< */
e >>= 2;
}
else
{
f >>= ((-e) & 3); /* >>fraction is now 25 bits, max<< */
e = -((-e) >> 2);
}

/* reduce fraction to 24 bits */
if (f & 0x0f000000)
{
f >>= 4;
e += 1;
}

/* convert exponent to excess 64 and store the number */
if ((e += 64) > 127)
*dst = s | fMAX370;
else if (e < 0)
*dst = s;
else
*dst = s | (e << 24) | f;
}

/* Convert IEEE "double" to IBM/370 "double"
*/
dIEEEto370(src, dst)
unsigned long src[2], dst[2];
{
unsigned long x, s, f[2];
long e;

x = src[HI];

/* check for special case */
if ((x & 0x7fffffff) == 0)
{
dst[HI] = src[HI];
dst[LO] = src[LO];
return; /* zero */
}

/* fetch the sign, exponent (removing excess 1023), and fraction */
s = x & 0x80000000;
e = ((x & 0x7ff00000) >> 20) - 1023;
f[0] = x & 0x000fffff;
f[1] = src[LO];

/* convert 52 bit fraction to 56 bit fraction */
lshift(f, 4); /* >>fraction is now 56 bits<< */

/* restore the implied '1' which preceeded the IEEE binary point */
f[0] |= 0x01000000; /* >>fraction is now 57 bits<< */

/* convert scale factor from "2**exponent" to "16**exponent" format
* -- we adjust fraction and exponent in opposite directions until
* exponent is a multiple of 4, then divide the exponent by 4
*/
if (e >= 0)
{
lshift(f, e & 3); /* >>fraction is now 60 bits, max<< */
e >>= 2;
}
else
{
rshift(f, (-e) & 3); /* >>fraction is now 57 bits, max<< */
e = -((-e) >> 2);
}

/* reduce fraction to 56 bits */
if (f[0] & 0x0f000000)
{
rshift(f, 4);
e += 1;
}

/* convert exponent to excess 64 and store the number */
if ((e += 64) > 127)
{
dst[HI] = s | dMAX370hi;
dst[LO] = dMAX370lo;
}
else if (e < 0)
{
dst[HI] = s;
dst[LO] = 0;
}
else
{
dst[HI] = s | (e << 24) | f[0];
dst[LO] = f[1];
}
}

/* 64 bit shift left
*/
static
lshift(p, n)
unsigned long p[]; int n;
{
register unsigned long hi, lo;

hi = p[0];
lo = p[1];

while (n-- > 0)
{
hi = (hi << 1) | ((lo >> 31) & 0x00000001);
lo <<= 1;
}

p[0] = hi;
p[1] = lo;
}

/* 64 bit shift right
*/
static
rshift(p, n)
unsigned long p[]; int n;
{
register unsigned long hi, lo;

hi = p[0];
lo = p[1];

while (n-- > 0)
{
lo = (hi << 31) | ((lo >> 1) & 0x7fffffff);
hi >>= 1;
}

p[0] = hi;
p[1] = lo;
}

#if CHECKOUT
/* Checkout the above functions
*/
#include <stdio.h>
main()
{
char buf[80];
int IEEEto370, singlePrecision;
unsigned long fin[1], fout[1];
unsigned long din[2], dout[2];

for (;;)
{
printf("convert from IEEE to 370 (y/n/q)?");
if (IEEEto370 = (*gets(buf) == 'y'))
printf("(converting from IEEE to 370)\n");
else if (*buf == 'n')
printf("(converting from 370 to IEEE)\n");
else
exit(0);

printf("single precision (y/n)?");
if (singlePrecision = (*gets(buf) == 'y'))
printf("(single precision)\n");
else
printf("(double precision)\n");

if (singlePrecision)
{
if (IEEEto370) for (;;)
{
if (get("IEEE", fin, sizeof fin))
break;
fIEEEto370(fin, fout);
put("IEEE", fin, sizeof fin);
put("370 ", fout, sizeof fout);
}
else for (;;)
{
if (get("370 ", fin, sizeof fin))
break;
f370toIEEE(fin, fout);
put("370 ", fin, sizeof fin);
put("IEEE", fout, sizeof fout);
}
}
else
{
if (IEEEto370) for (;;)
{
if (get("IEEE", din, sizeof din))
break;
dIEEEto370(din, dout);
put("IEEE", din, sizeof din);
put("370 ", dout, sizeof dout);
}
else for (;;)
{
if (get("370 ", din, sizeof din))
break;
d370toIEEE(din, dout);
put("370 ", din, sizeof din);
put("IEEE", dout, sizeof dout);
}
}
}
}

get(s, p, n)
char *s; unsigned long *p; int n;
{
if (n == 4)
{
printf("enter %s number (as 4-byte-hex) >", s);
return scanf("%lx", p) != 1;
}
else
{
printf("enter %s number (2 groups of 4-byte-hex) >", s);
return scanf("%lx%lx", p + HI, p + LO) != 2;
}
}

put(s, p, n)
char *s; unsigned long *p; int n;
{
if (n == 4)
printf("%s: %lx\n", s, *p);
else
printf("%s: %lx%lx\n", s, p[HI], p[LO]);
}
#endif /* CHECKOUT */

/*--end--*/

--- CUT HERE ---
--
Steven Lebowitz IBM Federal Systems Company
(301) 564-2613 6705 Rockledge Drive
lebo...@nova.bet.ibm.com Bethesda, Maryland 20817
#include<standard/disclaimer>

IanMaclure

neprečítané,
24. 8. 1993, 14:01:1124. 8. 1993
komu:
Aren't they the same?
IEEE. I sort of thought they were?

IBM
--
################ No Times Like The Maritimes, Eh! ######################
# IBM # ian_macl...@QMGATE.arc.nasa.gov (desk) #
# aka # mac...@toulouse.arc.nasa.gov (currently) #
# Ian B MacLure # mac...@eos.arc.nasa.gov (internet port) #

Steven Lebowitz

neprečítané,
24. 8. 1993, 14:59:4524. 8. 1993
komu:
In article <1993Aug24.1...@eos.arc.nasa.gov> mac...@eos.arc.nasa.gov (IanMaclure) writes:
>Aren't they the same?
>IEEE. I sort of thought they were?
>

No. The 370/390 machines use a different floating point representation
than is specified by IEEE. The comments in the code I posted show
the different formats and how they are interpreted. Since the RS/6000
uses IEEE format floating point numbers, the routines come in handy.

James R. Christian

neprečítané,
25. 8. 1993, 3:44:2025. 8. 1993
komu:
unixg.ubc.ca!gfarrow (Glenn Farrow) wrote on August 24:

>I need to move some binary files from a 370 to an RS6000 and have to convert
>between floating point formats in the process. I would appreciate any info
>anyone has on either the 370 format or the RS6000 format. (Conversion to
>text files is not feasible given the amount of data involved).

I wrote the following document a few years ago for a similar conversion
from 370 to Intel architecture. Both the Intel 80x86 and RS/6000 processors
use IEEE floating point format, although the byte order is different.
Another guy programmed a conversion routine in 370 assembler using this
algorihm, so I think it is pretty accurate. No guarantees, of course.


Summary
=======
IBM System/370 mainframes and PCs based on Intel 80x86 microprocessors use
fundamentally different internal storage formats for real, or floating point numbers.
This documents describes the internal formats and shows how to convert from
one format to another.

IBM System/370 Floating Point Format
====================================
On IBM System/370 mainframes, a floating point number is expressed as a signed
hexadecimal fraction multiplied by a power of 16. Three forms exist:
Short or single precision (4 byte)
Long or double precision (8 byte)
Extended (16 byte)
The only difference among these is the number of bits assigned to the fraction.
The short form will be described below.

The fraction is 24 bits representing a number in the range 0 to 1. Generally the
fraction is normalized so that the leading hexadecimal digit is not zero, which limits
the range to 0 and from 1/16 to 1. There is a separate sign bit (0=positive
1=negative).

The fraction is multiplied by a power of 16. The multiplier is stored as an
unsigned 7 bit binary integer called the characteristic. The characteristic
represents a signed exponent in excess-64 notation (in other words, subtract 64
[or hex 40] from the characteristic to obtain the exponent). The range of the
characteristic is 0 to 127, which corresponds to an exponent range of -64 to
+63. Hence the extreme values that can be represented are 16^-64 to 16^+63,
or about 10^-79 to 10^+76.

The storage format for short (4 byte) real numbers is:
Byte 0 1 2 3
Bit 11 1111 1111 2222 2222 2233
0123 4567 8901 2345 6789 0123 4567 8901
+---------+---------+---------+---------+
|sccc cccc|ffff ffff|ffff ffff|ffff ffff|
+---------+---------+---------+---------+
Here "s" represents the sign bit, "c" represents the characteristic, and "f" the
fraction.

Consider the following example:
Value 3.14159
Standard 370 format +0.196 * 16^1
Fraction 0.196 (or hex 0.324)
Sign 0 (positive)
Characteristic 65 (or hex 41)
Hexadecimal 41 32 43 F7
Binary 0100 0001 0011 0010 0100 0011 1111 0111
^---+---- ----------+------------------
| | +--->fraction
| +------------------->characteristic
+----------------------->sign


Intel 80x86 Floating Point Format
=================================
Intel 80x86 microprocessors use the IEEE format. A floating point number is
expressed as a signed binary fraction multiplied by a power of 2. Two forms
exist:
Short or single precision (4 byte)
Long or double precision (8 byte)
The two forms differ in the number of bits assigned to the fraction and in the way
the exponent is represented. The short form is described below.

The fraction, or mantissa, is 23 bits representing a number in the range 1 to 2.
Since the high order bit of the fraction is always 1, it is not stored. Because of
the range, normalization considerations do not apply. There is a separate sign bit
(0=positive 1=negative).

The fraction is multiplied by a power of 2. The multiplier is stored as an unsigned
8 bit binary integer called the characteristic. The characteristic represents a
signed exponent in excess-127 notation. The range of the characteristic is 0 to
255, which corresponds to an exponent range of -127 to +128. Hence the
extreme values that can be represented are 2^-127 to 2^+128, or about 10^-38
to 10^+38.

Intel microprocessors store bytes in reverse order. Ignoring (for now) that fact,
the storage format for short (4 byte) real numbers is:
Byte 0 1 2 3
Bit 11 1111 1111 2222 2222 2233
0123 4567 8901 2345 6789 0123 4567 8901
+---------+---------+---------+---------+
|sccc cccc|cfff ffff|ffff ffff|ffff ffff|
+---------+---------+---------+---------+

In reality, the storage format appears as:
Byte 3 2 1 0
Bit 2222 2233 1111 2222 11 1111
4567 8902 6789 0123 8901 2345 0123 4567
+---------+---------+---------+---------+
|ffff ffff|ffff ffff|cfff ffff|sccc cccc|
+---------+---------+---------+---------+
Here "s" represents the sign bit, "c" represents the characteristic, and "f" is the
fraction.

Consider the following example:
Value 3.14159
Standard IEEE format +1.57 * 2^1
Fraction 0.57 (or hex 0.922)
Sign 0 (positive)
Characteristic 128 (or hex 80)
Hexadecimal (in order) 40 49 0F DB
Binary (in order) 0100 0000 0100 1001 0000 1111 1101 1011
Hexadecimal (as stored) DB 0F 49 40
Binary (as stored) 1101 1011 0000 1111 0100 1001 0100 0000
- --------
| | |
sign<-------------------+ |
characteristic<----------+-------------+

Long or double format is similar, except it uses a 52 bit fraction and an 11 bit
excess 1023 exponent. Hence the range is about 10^-308 to 10^+308.


RS/6000 Floating Point Format
=============================
RS/6000's use IEEE floating point format like Intel 80x86's. The only difference is
that the byte order is reversed.


Converting from IBM to Intel Format
===================================
The following algorithm can be applied to convert a number from 370 to IEEE
format on Intel architecture. There are two special cases: zero and not available.
These two values must not be converted because the internal representations are
the same in 370 and IEEE format.

1. Multiply the fraction by a power of two to convert it from the IBM range (0
to 1) to the IEEE range (1 to 2). To do so:
i) Count the number of binary leading zeros in the fraction. (In other
words, count the number of zeros that appear together beginning
with bit 8.) This will be a number in the range 0-3. Call this k.
ii) Shift the fraction k bits to the left, filling with zeros on the right.
Note that bit 8 will contain a 1. This bit is no longer needed and will
be discarded in step (v).
2. Multiply the exponent by four to convert it from a hexadecimal to a binary
exponent, and subtract the decimal value 130+k to account for the
different excess notation and the multiplication in step 1. To do so:
iii) Save the sign bit (bit 0).
iv) Shift the exponent one bit to the left (i.e. shift bits 1-7 to positions 0-
6), filling position 7 with a zero.
v) Put a zero in bit 8.
vi) Subtract the decimal value 130+k from the 9 bit number represented
in bits 0-8. (Equivalently, subtract decimal 16,640 + k*2^7 from the
unsigned integer represented by the first two bytes.)
vii) Restore the sign bit.
3. Reverse the byte order.


Representing "Not Available"
============================
The 370 floating point format has multiple representations of zero. (Any value
with a zero fraction is zero, regardless of the sign bit or exponent.) A convenient
way in 370 format to represent that a value is not available is by "negative zero".
Negative zero, or hex 80 00 00 00 has no meaning to the 370 architecture, and
so it is convenient to mean something else.

IEEE floating point format has only one representation of zero (I think). Negative
zero can be used to represent missing values, even though it has an alternative
interpretation (to the hardware) of -1.0*2-127. The hex representation would be
00 00 00 80 on Intel hardware, 80 00 00 00 on an RS/6000.
--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Jim Christian jrch...@bhof01.ctg.nl
Profimatics, Inc. voice: +31 (0)2503 50554
Amsterdam, Netherlands #include <witty.comment>

0 nových správ