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

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN

Reply via email to