On Fri, Mar 21, 2025 at 01:47:05PM -0500, Robert Dubner wrote:
> > -----Original Message-----
> > From: Robert Dubner <rdub...@symas.com>
> > Sent: Friday, March 21, 2025 14:23
> > To: Richard Biener <rguent...@suse.de>
> > Cc: gcc-patches@gcc.gnu.org; Jakub Jelinek <ja...@redhat.com>
> > 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

Reply via email to