Bug 93727 - Fortran 2018: EX edit descriptor
Summary: Fortran 2018: EX edit descriptor
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: libfortran (show other bugs)
Version: 10.0
: P4 normal
Target Milestone: ---
Assignee: Jerry DeLisle
URL:
Keywords:
: 96569 (view as bug list)
Depends on:
Blocks: F2018
  Show dependency treegraph
 
Reported: 2020-02-13 08:57 UTC by Thomas Henlich
Modified: 2024-03-10 17:17 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-07-12 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Henlich 2020-02-13 08:57:37 UTC
13.7.2.3.6 EX editing

1 The EX edit descriptor produces an output field in the form of a hexadecimal-significand number.

2 The EXw.d and EXw.dEe edit descriptors indicate that the external field occupies w positions, except when w is zero in which case the processor selects the field width. The fractional part of the field contains d hexadecimal digits, except when d is zero in which case the processor selects the number of hexadecimal digits to be the minimum required so that the output field is equal to the internal value; d shall not be zero if the radix of the internal value is not a power of two. The hexadecimal point, represented by a decimal symbol, appears after the first hexadecimal digit. For the form EXw.d, and for EXw.dE0, the exponent part contains the minimum number of digits needed to represent the exponent; otherwise the exponent contains e digits. The e has no effect on input. The scale factor has no effect on output. 

3 The form and interpretation of the input field is the same as for Fw.d editing (13.7.2.3.2).

4 For an internal value that is an IEEE infinity or NaN, the form of the output field is the same as for Fw.d.

5 For an internal value that is neither an IEEE infinity nor a NaN, the form of the output field is
  [ ± ] 0X x0 . x1x2 . . . exp
where:

• ± signifies a plus sign or a minus sign;
• . signifies a decimal symbol (13.6);
• x0x1x2 . . . are the most significant hexadecimal digits of the internal value, after rounding if d is not zero (13.7.2.3.8);
• exp is a binary exponent expressed as a decimal integer; for EXw.d and EXw.dE0, the form is P ±z1 . . . zn20 , where n is the minimum number of digits needed to represent exp, and for EXw.dEe with e greater than zero the form is P ±z1 . . . ze22 . The choice of binary exponent is processor dependent. If the most significant binary digits of the internal value are b0b1b2 . . ., the binary exponent might make the value of x0 be that of b0, b0b1, b0b1b2, or b0b1b2b3. A plus sign is produced if the exponent value is zero.
 
Examples:
Internal value  Edit descriptor  Possible output with SS in effect
1.375           EX0.1            0X1.6P+0
−15.625         EX14.4E3         -0X1.F400P+003
1048580.0       EX0.0            0X1.00004P+20
2.375           EX0.1            0X2.6P+0
Comment 1 Jerry DeLisle 2020-07-14 12:51:11 UTC
I will take this one.
Comment 2 Dominique d'Humieres 2020-08-11 14:41:09 UTC
*** Bug 96569 has been marked as a duplicate of this bug. ***
Comment 3 Jerry DeLisle 2020-08-14 21:34:33 UTC
Interesting language if not sort of weird:

"exp is a binary exponent expressed as a decimal integer"

I am in early stages of choosing how to do this.
Comment 4 Jerry DeLisle 2020-08-29 18:04:53 UTC
An Update. I have the front end and runtime parsing for OUTPUT done and am now looking at the actual implementation.  We have the printf series of functions available and can use the %A format specifier to create the hexidecimal float string.

I want to note here that on input, apparently the F editing requires one to be able to READ a hexadecimal float with the F descriptor as well as the EX descriptor. See 
13.7.2.3.2 part 7.

Another aspect I am studying has to do with rounding.  On output I assume we must support RU, RD, RN vs truncating. Considering that the purpose of this type of representation of a float is mostly for "looking under the hood" I initially was thinking simple truncation should suffice and if a user does not know they have not specified enough precision for all hexadecimals, tough beans.  After all, in hexadecimal, it is always an exact fit. I am curious what others think about this.

Regardless, we will need a new rounding function to round the hexadecimals before output.

On input, obviously we need to do a new read function and for the F descriptor we will have to look ahead to identify that it is a hexadecimal before processing it, otherwise it just looks like a bad float.
Comment 5 Jerry DeLisle 2024-03-10 03:37:13 UTC
I have been studying this a bit by looking at the 2023 std and functionality of printf().
Specifically printf() provides the 'A' descriptor which can be used for float (kind=4) and double (kind=8).  It will accept a long double (80 bit aka kind=10). I am noticing that the results of double and long double are identical, no extra precision visible. It is very possible I am not doing that correctly.

I do not see anything related to quad precision floats.  I am posting this as i think we will have to do some of our own translating byte portions of floats ourselves. Portability may be an issue. For example IBM 360 128bit precision or some other processor may not follow the same internal representations.

Regardless I have preliminary code for the frontend that results in calling anew fucntion write_ex in transfer.c

I think that kind=4 and kind=8 will be fine. Any thoughts on kind=10 or kind=16 I would appreciate as I further explore this.
Comment 6 Thomas Henlich 2024-03-10 09:41:42 UTC
(In reply to Jerry DeLisle from comment #5)
> I have been studying this a bit by looking at the 2023 std and functionality
> of printf().
> Specifically printf() provides the 'A' descriptor which can be used for
> float (kind=4) and double (kind=8).  It will accept a long double (80 bit
> aka kind=10). I am noticing that the results of double and long double are
> identical, no extra precision visible. It is very possible I am not doing
> that correctly.
> 
> I do not see anything related to quad precision floats.  I am posting this
> as i think we will have to do some of our own translating byte portions of
> floats ourselves. Portability may be an issue. For example IBM 360 128bit
> precision or some other processor may not follow the same internal
> representations.
> 
> Regardless I have preliminary code for the frontend that results in calling
> anew fucntion write_ex in transfer.c
> 
> I think that kind=4 and kind=8 will be fine. Any thoughts on kind=10 or
> kind=16 I would appreciate as I further explore this.

Just some thoughts:

Have you tried "%LA" for long double?

Have you tried quadmath_snprintf (https://gcc.gnu.org/onlinedocs/libquadmath/quadmath_005fsnprintf.html) with "%QA" for quad precision?
Comment 7 Jerry DeLisle 2024-03-10 17:17:28 UTC
(In reply to Thomas Henlich from comment #6)
--- snip ---
> Just some thoughts:
> 
> Have you tried "%LA" for long double?
> 
> Have you tried quadmath_snprintf
> (https://gcc.gnu.org/onlinedocs/libquadmath/quadmath_005fsnprintf.html) with
> "%QA" for quad precision?

That was the hint I needed.

#include <stdio.h>
int main()
  {
     float x =       1.0f / 3.0f;
     double y =      1.0l / 3.0l;
     long double z = 1.0L / 3.0L;
     printf("   FLOAT: %.18A\n", x);
     printf("  DOUBLE: %.18lA\n", y);
     printf("LONG DBL: %.18LA\n", z);
     printf("          123456789012345678901234567890\n");
     printf("   FLOAT: %.20f\n", x);
     printf("  DOUBLE: %.20lf\n", y);
     printf("LONG DBL: %.20Lf\n", z);
  }

$ gcc hexfloat.c 
$ ./a.out 
   FLOAT: 0X1.555556000000000000P-2
  DOUBLE: 0X1.555555555555500000P-2
LONG DBL: 0XA.AAAAAAAAAAAAAAB000P-5
          123456789012345678901234567890
   FLOAT: 0.33333334326744079590
  DOUBLE: 0.33333333333333331483
LONG DBL: 0.33333333333333333334

I will check the libqudmath version as well.

Thanks.