On Fri, Mar 21, 2025 at 01:47:05PM -0500, Robert Dubner wrote:
> > -----Original Message-----
> > From: Robert Dubner <[email protected]>
> > Sent: Friday, March 21, 2025 14:23
> > To: Richard Biener <[email protected]>
> > Cc: [email protected]; Jakub Jelinek <[email protected]>
> > Subject: RE: [PATCH] change cbl_field_data_t::etc_t::value from
> _Float128
> > to tree
> >
> > Crossed in the mail.
> >
> > I applied your fixes below.
> >
> > The output of the one-liner program is now 1.2345678E+07, as expected.
> >
> > The .00 instead of .01 problem still exists; source code coming soon.
>
> This program
>
> IDENTIFICATION DIVISION.
> PROGRAM-ID. numeds.
> DATA DIVISION.
> WORKING-STORAGE SECTION.
> 01 VARP9 PIC P9 VALUE 0.01.
> PROCEDURE DIVISION.
> DISPLAY "VARP9 should be .01"
> DISPLAY "VARP9 is " VARP9.
> END PROGRAM numeds.
>
> generates
>
> VARP9 should be .01
> VARP9 is .00
>
> As usual, it's COBOL, so it comes with a lecture:
>
> The variable
>
> 01 VARP9 PIC P9 VALUE 0.01.
>
> means that it is a NUMERIC DISPLAY variable, which is represented in
> memory as ASCII digits. There is but one '9' in the PICTURE, so it is a
> one-digit number. The prefix 'P', in the "P9", means that the actual
> value of the variable is scaled by 0.01 So, the value 0.01 is represented
> in memory by a single "1".
>
> If it were "PIC 9PPP", then 1,000 would be represented in memory as a
> single "1".
The following incremental patch should fix that (but otherwise untested).
--- gcc/cobol/parse.y.jj 2025-03-21 17:49:43.571440176 +0100
+++ gcc/cobol/parse.y 2025-03-21 20:15:24.852414777 +0100
@@ -4331,7 +4331,8 @@ value_clause: VALUE all LITERAL[lit] {
cbl_field_t *field = current_field();
auto orig_str = original_number();
REAL_VALUE_TYPE orig_val;
- real_from_string (&orig_val, orig_str);
+ real_from_string3 (&orig_val, orig_str,
+ TYPE_MODE (float128_type_node));
char *initial = NULL;
if( real_identical (&orig_val, &$value) ) {
@@ -6922,7 +6923,8 @@ cce_expr: cce_factor
cce_factor: NUMSTR {
/* ??? real_from_string does not allow arbitrary radix. */
// $$ = numstr2i($1.string, $1.radix);
- real_from_string (&$$, $1.string);
+ real_from_string3 (&$$, $1.string,
+ TYPE_MODE (float128_type_node));
}
;
The old code was just using _Float128 which has the IEEE quad precision,
but REAL_VALUE_TYPE in GCC actually has larger internal precision than that,
so if it isn't rounded to the IEEE quad precision first and builds REAL_CST,
it isn't the expected 0.0100000000000000000000000000000000002 but
0.009999999999...
Jakub