Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Hex Long Floating Point & REXX

308 views
Skip to first unread message

Uwe Oswald

unread,
May 19, 2013, 5:40:52 AM5/19/13
to
Hi @ll,



has someone ever tried to extract fields SMF30DDS and SMF30DDR (long floating point hex) or any field in REXX? There are a couple of F2"something" routines out there but it seems that none of them produce the right value. Has somebody a REXX example for me? Anything would be very appreciated since it might bring me further.



Thx in advance.



Cheers



Uwe

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to list...@listserv.ua.edu with the message: INFO IBM-MAIN

Robert AH Prins

unread,
May 19, 2013, 7:25:21 AM5/19/13
to
On 2013-05-19 09:40, Uwe Oswald wrote:
> Hi @ll,
>
> has someone ever tried to extract fields SMF30DDS and SMF30DDR (long floating
> point hex) or any field in REXX? There are a couple of F2"something" routines
> out there but it seems that none of them produce the right value. Has
> somebody a REXX example for me? Anything would be very appreciated since it
> might bring me further.

This code coming from Michel Castelein & Jim Connelly might be of some use


/* REXX - convert float to dec + dec to float routines */
"ispclear"
do until opt = 0 | opt = ''
say 'Select option'
say
say ' 0: exit'
say ' 1: Castelein, float(hex) to dec'
say ' 2: Connelly, dec (char) to float(hex) to dec'

pull opt
opt = left(opt, 1)

select
when opt = 1 then call castelein
when opt = 2 then call connelly
otherwise
end
end
exit 0

/* This REXX exec computes a S/370 floating-point's value ...
e.g. X'C1280000' represents -2.5
(Michel Castelein, 5 November 1997)*/
castelein:

say 'Enter the S/370 floating-point (4, 8, or 16 bytes):'
numeric digits 34
pull float

float = X2C(float) /* convert float to a hexadecimal string*/
float_size = LENGTH(float) /* size in Bytes*/

Byte_0 = SUBSTR(float, 1, 1)
select
when BITAND(Byte_0, '80'x) == '00'x then sign = '+'
when BITAND(Byte_0, '80'x) == '80'x then sign = '-'
end

exponent = C2D(BITAND(Byte_0, '7F'x)) - 64
fraction = 0
power = -1

do i = 2 to float_size
if i = 9 then iterate /* skip bits 64-71*/
Next_Byte = C2D(SUBSTR(float, i, 1))
left_Digit = Next_Byte % 16
fraction = fraction + left_Digit * 16**power
right_Digit = Next_Byte // 16
power = power - 1
fraction = fraction + right_Digit * 16**power
power = power - 1
end
interpret 'value =' sign ( fraction * 16 ** exponent )
say "The floating-point's value is" value
say
say 'Press Enter to continue'
pull
return
/*
TEST_WORK.FS=1.00000E+01;
TEST_WORK.FL=1.000000000000000E+01;
TEST_WORK.FE=1.00000000000000000000000000000000E+01;
'41A00000'B
'41A0000000000000'B
'41A00000000000003300000000000000'B
TEST_WORK.FS=3.16227E+00;
3.16227722167968750000
TEST_WORK.FL=3.162277660168379E+00;
3.162277660168379300742458326567430049181
TEST_WORK.FE=3.16227766016837933199889354443270E+00;
3.162277660168379331998893544432716995013
'413298B0'B
'413298B075B4B6A5'B
'413298B075B4B6A533240945790619B3'B
*/

/*------------ REXX -----------------------------+
* |
* Converts a number to internal float format. |
* Displays the result |
* Then converts the result back out to decimal. |
* |
* Written by Jim Connelley |
* |
* Tracing thru this code is a good way to get |
* familiar with IBM system 390 internal |
* floating point format. |
* |
*-----------------------------------------------+
*/
connelly:
Numeric Digits 100 /* handle BIG numbers */
/*
Parse Upper Arg input_val .
*/

say 'Enter S/390 floating point value'
pull input_val .

Say "Input Value: " input_val
If datatype(input_val) /= "NUM" Then Do
Say "invalid value"
return
End
If input_val = 0 Then Do /* special case zero */
Say "Resulting Value: 0000000000000000"
Say "Floating value converted back: 0"
return
End
input_val = Format(input_val)

/*-------------------------------------------------------+
* Handle leading minus sign |
*-------------------------------------------------------+
*/
If left(input_val,1) = "-" Then Do
Sign = "80"x
input_val = Substr(input_val,2) /* remove sign */
End
Else Do
Sign = "00"x
End

/*-------------------------------------------------------+
* Separate input into integer and fraction |
*-------------------------------------------------------+
*/
Parse Var input_val input_integer "." input_fract

/*-------------------------------------------------------+
* If no fraction given, then default to zero |
*-------------------------------------------------------+
*/
If input_fract = "" Then input_fract = 0
input_fract = "."input_fract

/*-------------------------------------------------------+
* Convert integer portion directly |
*-------------------------------------------------------+
*/
float_value = D2x(input_integer)
If float_value = "0" Then float_value = ""

/*-------------------------------------------------------+
* If there is no integer portion, then we can normalize |
* just the fraction portion of the input value. |
*-------------------------------------------------------+
*/
exponent = Length(float_value)
If exponent = 0 Then Do Forever
normalizing_fraction = input_fract * 16
If normalizing_fraction >= 1 Then Leave
input_fract = normalizing_fraction
exponent = exponent - 1
End

/*-------------------------------------------------------+
* compute amount to normalize |
*-------------------------------------------------------+
*/
If exponent < 0 Then Do
amount_to_normalize = 0
End
Else Do
amount_to_normalize = exponent
End

/*-------------------------------------------------------+
* Normalize the build float value. |
*-------------------------------------------------------+
*/
remainder = input_fract
Do i = 1 To (14 - amount_to_normalize)
normalizing_value = remainder * 16
quotient = normalizing_value % 1
remainder = normalizing_value // 1
float_value = float_value || D2x(quotient)
End

/*-------------------------------------------------------+
* Convert integer portion directly |
*-------------------------------------------------------+
*/
sign_and_exponent = C2x(Bitor(X2c(D2x(exponent+64)),Sign))
result_value = Substr(C2x(X2c(sign_and_exponent||float_value)),1,16)
Say "Resulting floating value: " result_value

/*-------------------------------------------------------+
* Now begin conversion back out to decimal display. |
*-------------------------------------------------------+
*/
internal_float = X2c(result_value)

/*-------------------------------------------------------+
* Extract the sign and exponent byte |
*-------------------------------------------------------+
*/
sign_and_exponent = Substr(internal_float,1,1)

/*-------------------------------------------------------+
* Compute the true exponent |
*-------------------------------------------------------+
*/
x_exponent = Bitand(sign_and_exponent,"7f"x)
excess_64_exp = C2d(x_exponent)
true_exponent = excess_64_exp - 65

/*-------------------------------------------------------+
* Create a factor of +1 or -1 from the sign bit |
*-------------------------------------------------------+
*/
sign_factor = ((Bitand(sign_and_exponent,"80"x)="00"x)-.5)*2

/*-------------------------------------------------------+
* Extract the "fraction" part of the number |
*-------------------------------------------------------+
*/
fraction = Substr(internal_float,2)
hex_fraction = C2x(fraction)
result_value = 0

/*-------------------------------------------------------+
* Sum the result value by processing each hex digit |
*-------------------------------------------------------+
*/
Do i = 1 To Length(hex_fraction)
hex_digit = X2d(Substr(hex_fraction,i,1))
result_value = result_value + (hex_digit * (16**true_exponent))
true_exponent = true_exponent - 1
End

/*-------------------------------------------------------+
* Factor in the sign |
*-------------------------------------------------------+
*/
result_value = result_value * sign_factor

/*-------------------------------------------------------+
* Format the result |
*-------------------------------------------------------+
*/
print_value = Strip(Strip(Format(result_value,,14),T,0),T,.)
If print_value = 0 Then /* Maybe we stripped too much */
print_value = Format(result_value,2,14,2,0)

Say "Floating value converted back:" print_value
say
say 'Press Enter to continue'
pull
return


--
Robert AH Prins
robert(a)prino(d)org

Lizette Koehler

unread,
May 19, 2013, 8:25:40 AM5/19/13
to
You may wish to check out this url. It is an article from IBM Systems News
on handling SMF with REXX. It may have some pointers

http://www.ibmsystemsmag.com/mainframe/tipstechniques/applicationdevelopment
/rexx_smf_part2/?page=2


Lizette

Paul Gilmartin

unread,
May 19, 2013, 11:12:15 AM5/19/13
to
On Sun, 19 May 2013 13:24:49 +0000, Robert AH Prins wrote:

>On 2013-05-19 09:40, Uwe Oswald wrote:
>> Hi @ll,
>>
>> has someone ever tried to extract fields SMF30DDS and SMF30DDR (long floating
>> point hex) or any field in REXX? There are a couple of F2"something" routines
>> out there but it seems that none of them produce the right value. Has
>> somebody a REXX example for me? Anything would be very appreciated since it
>> might bring me further.
>
>This code coming from Michel Castelein & Jim Connelly might be of some use
>
...
Eek! Clearly the author's brain was rotted by excessive exposure to
Assembler programming. Why not simply:

/* This REXX exec computes a S/370 floating-point's value ...
e.g. X'C1280000' represents -2.5
*/
castelein:
parse arg Float
numeric digits ( length( Float ) % 0.4 ) /* 1 / log( 256 ) */

parse var Float Hexponent 2 Mantissa

sign = 1 - c2d( Hexponent ) % 128 * 2
Hexponent = c2d( bitand( Hexponent, '7F'x ) ) - 64
Hexponent = Hexponent - 2 * length( Mantissa )

Dec = sign * 16 ** Hexponent * c2d( Mantissa )
say c2x( Float ) Dec
return( Dec )


The problem of decimal to HFP is a nightmare, relatively. I'd be
tempted to use iteration to find a root of the HFP to decimal function.

-- gil

John Gilmore

unread,
May 19, 2013, 1:12:57 PM5/19/13
to
There is plenty of C and PL/I support available for BFP. Having a
brain "rotted by excessive exposure to assembly language, I would thus
use the conversion machine instructions THDER, THDR, TBDER, and TBDR
to move back and forth between HFP and BFP.

As yet there are no conversion instructions for HFP<==>DFP or even
BFP<==>DFP; but they are, I suspect, in the womb of time, perhaps
indeed nearly at term.

John Gilmore, Ashland, MA 01721 - USA

Michel Castelein

unread,
May 19, 2013, 1:22:15 PM5/19/13
to PaulGB...@aim.com
The guy with the rotted brain - thanks indeed - thinks your code doesn't
take in consideration that in a 16-byte (i.e. extended precision)
hexadecimal floating-point (HFP) the fraction's absolute value is
denoted by bits 8-63 and 72-127, i.e. bits 64-71 (the first byte of the
second word) must be ignored.
;-)

Next, the components e and f of a floating-point number are called the
exponent and fraction parts, respectively. Other names are occasionally
used for this purpose, notably “characteristic” and “mantissa”, but both
Donald Knuth and Mike Cowlishaw insist that it is an ABUSE of
terminology to call the fraction part a mantissa since this concept
refers to the fractional part of a logarithm.
;-)

Michel Castelein
z/OS Instructor
http://www.arcis-services.net
0 new messages