public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Bytes of long double - trouble . . .
@ 2023-02-08  8:48 Sergey Smith
  2023-02-08  9:09 ` henri.cloetens
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Sergey Smith @ 2023-02-08  8:48 UTC (permalink / raw)
  To: gcc-help

[-- Attachment #1: Type: text/plain, Size: 808 bytes --]


To:     gcc-help@gcc.gnu.org     
Dear GCC,  [ 8:2:23  ]
                  Like Woooew ! What is THIS!?  I installed Visual Studio Code, & your 32 bit C, Version 9.2.0. I ran :
   printf("\nOn THIS particular computer, long double is given %d bytes\n", sizeof(long double)); /* The Answer was: 12 bytes.
   THEN, I updated to C Version 12.2.0 and ran the same code, - ON THE SAME COMPUTER, - but NOW the answer is:  16 bytes !
 
    HOW can this happen if, as I understand it, - this function is supposed to assess a computer’s  *hardware* ?  I am on Windows 10 btw.
                                                                                       — Sergey.
 
С уважением,
Sergey Smith
sergey-16a5@mail.ru

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Bytes of long double - trouble . . .
  2023-02-08  8:48 Bytes of long double - trouble . . Sergey Smith
@ 2023-02-08  9:09 ` henri.cloetens
  2023-02-08 11:12   ` Jonathan Wakely
  2023-02-08 11:11 ` Jonathan Wakely
  2023-02-15 12:50 ` Dennis Clarke
  2 siblings, 1 reply; 5+ messages in thread
From: henri.cloetens @ 2023-02-08  9:09 UTC (permalink / raw)
  To: gcc-help

Dear Sergey,  добрий ден !

This is most likely because, on the machine you are using,
the type long double is emulated in software, and the way it is
emulated is different in both versions.

Best Regards,
С уважением,

Henri.


Quoting Sergey Smith <sergey-16a5@mail.ru>:

> To:     gcc-help@gcc.gnu.org    
> Dear GCC,  [ 8:2:23  ]
>                   Like Woooew ! What is THIS!?  I installed Visual  
> Studio Code, & your 32 bit C, Version 9.2.0. I ran :
>    printf("\nOn THIS particular computer, long double is given %d  
> bytes\n", sizeof(long double)); /* The Answer was: 12 bytes.
>    THEN, I updated to C Version 12.2.0 and ran the same code, - ON  
> THE SAME COMPUTER, - but NOW the answer is:  16 bytes !
>  
>     HOW can this happen if, as I understand it, - this function is  
> supposed to assess a computer’s  *hardware* ?  I am on Windows 10 btw.
>                                                                      
>                    — Sergey.
>  
> С уважением,
> Sergey Smith
> sergey-16a5@mail.ru




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Bytes of long double - trouble . . .
  2023-02-08  8:48 Bytes of long double - trouble . . Sergey Smith
  2023-02-08  9:09 ` henri.cloetens
@ 2023-02-08 11:11 ` Jonathan Wakely
  2023-02-15 12:50 ` Dennis Clarke
  2 siblings, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2023-02-08 11:11 UTC (permalink / raw)
  To: Sergey Smith; +Cc: gcc-help

On Wed, 8 Feb 2023 at 08:50, Sergey Smith wrote:
>
>
> To:     gcc-help@gcc.gnu.org
> Dear GCC,  [ 8:2:23  ]
>                   Like Woooew ! What is THIS!?  I installed Visual Studio Code, & your 32 bit C, Version 9.2.0. I ran :

What is "C"? That's not a compiler, what did you actually install? How
are you running it?

We can't help you with such vague, unclear descriptions of your question.

>    printf("\nOn THIS particular computer, long double is given %d bytes\n", sizeof(long double)); /* The Answer was: 12 bytes.
>    THEN, I updated to C Version 12.2.0 and ran the same code, - ON THE SAME COMPUTER, - but NOW the answer is:  16 bytes !
>
>     HOW can this happen if, as I understand it, - this function is supposed to assess a computer’s  *hardware* ?  I am on Windows 10 btw.

No, 'long double' is a C language type. The hardware has registers
that might be 32 bits, 64 bits, 80 bits or 128 bits wide. The 'long
double' type is implemented in the compiler to use the hardware in an
implementation defined way.

The most likely explanation is that your first program was compiled as
a 32-bit i686 program, where long double is 12 bytes, and your second
program was compiled as a 64-bit x86-64 program, where long double has
an extra 4 bytes of padding.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Bytes of long double - trouble . . .
  2023-02-08  9:09 ` henri.cloetens
@ 2023-02-08 11:12   ` Jonathan Wakely
  0 siblings, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2023-02-08 11:12 UTC (permalink / raw)
  To: henri.cloetens; +Cc: gcc-help

On Wed, 8 Feb 2023 at 09:10, <henri.cloetens@blueice.be> wrote:
>
> Dear Sergey,  добрий ден !
>
> This is most likely because, on the machine you are using,
> the type long double is emulated in software, and the way it is
> emulated is different in both versions.

I think the most likely is x86 vs x86-64.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Bytes of long double - trouble . . .
  2023-02-08  8:48 Bytes of long double - trouble . . Sergey Smith
  2023-02-08  9:09 ` henri.cloetens
  2023-02-08 11:11 ` Jonathan Wakely
@ 2023-02-15 12:50 ` Dennis Clarke
  2 siblings, 0 replies; 5+ messages in thread
From: Dennis Clarke @ 2023-02-15 12:50 UTC (permalink / raw)
  To: gcc-help

On 2/8/23 03:48, Sergey Smith wrote:
> 
> To:     gcc-help@gcc.gnu.org
> Dear GCC,  [ 8:2:23  ]
>                    Like Woooew ! What is THIS!?  I installed Visual Studio Code, & your 32 bit C, Version 9.2.0. I ran :
>     printf("\nOn THIS particular computer, long double is given %d bytes\n", sizeof(long double)); /* The Answer was: 12 bytes.
>     THEN, I updated to C Version 12.2.0 and ran the same code, - ON THE SAME COMPUTER, - but NOW the answer is:  16 bytes !
>   
>      HOW can this happen if, as I understand it, - this function is supposed to assess a computer’s  *hardware* ?  I am on Windows 10 btw.
>                                                                                         — Sergey.
>   

There is no x86 hardware ever that can do true 128-bit long double
floating point. The best you can hope for is the strange 10-byte
format that Intel made up as a way to extend precision a little bit.
Works pretty well for things like fused multiply add and such.

However there are various ways you can emulate the IEEE-754 floating
point stuff on x86 hardware and perhaps you really want the libquadmath
here. Regardless you *may* see the data type take a full 16 bytes and
yes that means six bytes are trash. They mean nothing. Unless you do
the software emulation goodness. Try :

/*
  * fp128_q.c  mess around with the libquadmath to see IEEE-754 2008
  *            floating point stuff sort of work in an emulated way
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
  *
  * https://www.gnu.org/licenses/gpl-3.0.txt
  */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <quadmath.h>
#include <float.h>
#include <fenv.h>

#define BUFFERSIZE 128

int main(int argc, char *argv[]){

     __float128 fp0, fp1, fp2, pi;
     const size_t buffer_size = BUFFERSIZE;
     char *buffer = calloc(buffer_size,sizeof(unsigned char));
     int num_chars;

#ifdef FLT_EVAL_METHOD
     printf ( "INFO : FLT_EVAL_METHOD == %d\n", FLT_EVAL_METHOD);
#endif

#ifdef DECIMAL_DIG
     printf ( "INFO : DECIMAL_DIG == %d\n", DECIMAL_DIG);
#endif

/* LDBL_DIG, FLT_DECIMAL_DIG, DBL_DECIMAL_DIG, LDBL_DECIMAL_DIG */
#ifdef FLT_DECIMAL_DIG
     printf ( "INFO : FLT_DECIMAL_DIG == %d\n", FLT_DECIMAL_DIG);
#endif

#ifdef DBL_DECIMAL_DIG
     printf ( "INFO : DBL_DECIMAL_DIG == %d\n", DBL_DECIMAL_DIG);
#endif

#ifdef LDBL_DECIMAL_DIG
     printf ( "INFO : LDBL_DECIMAL_DIG == %d\n", LDBL_DECIMAL_DIG);
#endif

#ifdef LDBL_DIG
     printf ( "INFO : LDBL_DIG == %d\n", LDBL_DIG);
#endif


     /* NOTE : floating point can NOT precisely represent the
      *        test values being used here. Such is life in
      *        the real world of floating point. Good luck.
      */
     fp0 = 36.584Q;

     printf ( "the sizeof(fp0) is %i\n", sizeof(fp0) );

     num_chars = quadmath_snprintf(buffer,
                                   buffer_size, "%40.36Qg", fp0);

     if ( num_chars > 0 ) {

         printf ("INFO : quadmath_snprintf formatted %i chars.\n",
                  num_chars);

     } else {

         fprintf(stderr,"FAIL : quadmath_snprintf failed.\n");
         return EXIT_FAILURE;

     }

     printf ("the value of fp0 is %s\n", buffer);

     fp1 =  7.812;

     num_chars = quadmath_snprintf(buffer,
                                   buffer_size, "%40.36Qg", fp1);

     if ( num_chars > 0 ) {

         printf ("INFO : quadmath_snprintf formatted %i chars.\n",
                  num_chars);

     } else {

         fprintf(stderr,"FAIL : wtf quadmath_snprintf failed.\n");
         return EXIT_FAILURE;

     }

     printf ("the value of fp1 is %s\n", buffer);

     fp2 = fp0 + fp1;

     num_chars = quadmath_snprintf(buffer,
                                   buffer_size, "%40.36Qg", fp2);

     if ( num_chars > 0 ) {

         printf("INFO : quadmath_snprintf formatted %i chars.\n",
                 num_chars);

     } else {

         fprintf(stderr,"FAIL : wat? quadmath_snprintf failed.\n");
         return EXIT_FAILURE;

     }

     printf("fp2 = fp0 + fp1 = %s\n", buffer);

     /* more than reasonable value for pi which is a few more
      * decimal digits past the stuff in math.h */
     pi = 3.1415926535897932384626433832795028841971693993751Q;

     num_chars = quadmath_snprintf(buffer,
                                   buffer_size, "%46.40Qe", pi );

     if ( num_chars > 0 ) {
         printf ("INFO : quadmath_snprintf formatted %i chars.\n",
                  num_chars);
     } else {
         fprintf(stderr,"FAIL : wat? quadmath_snprintf failed.\n");
         return EXIT_FAILURE;
     }

     printf("libquadmath says pi = %s\n", buffer);
     printf("the real thing is  ~= ");
     printf("3.1415926535897932384626433832795028841971693993...\n");

     free(buffer);
     return EXIT_SUCCESS;  /* or 42 if you prefer */

}


Be sure to link with -lquadmath and you should see :

$ gcc12 -g -O0 -Wl,-rpath=/usr/local/lib/gcc12,-enable-new-dtags
            -o fp128_q fp128_q.c -lquadmath

$ ./fp128_q
INFO : FLT_EVAL_METHOD == 0
INFO : DECIMAL_DIG == 21
INFO : FLT_DECIMAL_DIG == 9
INFO : DBL_DECIMAL_DIG == 17
INFO : LDBL_DECIMAL_DIG == 21
INFO : LDBL_DIG == 18
the sizeof(fp0) is 16
INFO : quadmath_snprintf formatted 40 chars.
the value of fp0 is    36.5840000000000000000000000000000015
INFO : quadmath_snprintf formatted 40 chars.
the value of fp1 is    7.81200000000000027711166694643907249
INFO : quadmath_snprintf formatted 40 chars.
fp2 = fp0 + fp1 =     44.396000000000000277111666946439074
INFO : quadmath_snprintf formatted 46 chars.
libquadmath says pi = 3.1415926535897932384626433832795027974791e+00
the real thing is  ~= 3.1415926535897932384626433832795028841971693993...


Works pretty well.  The only other option is to get an IBM POWER9
server which has real 128-bit goodness in hardware. Also an IBM
System Z type mainframe can do all that also. The RISC-V processor
specification also has the Q-extension for true 128bit floating
point but no one seems to have fabricated that. Yet. :)

-- 
Dennis Clarke
RISC-V/SPARC/PPC/ARM/CISC
UNIX and Linux spoken
GreyBeard and suspenders optional


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-02-15 12:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-08  8:48 Bytes of long double - trouble . . Sergey Smith
2023-02-08  9:09 ` henri.cloetens
2023-02-08 11:12   ` Jonathan Wakely
2023-02-08 11:11 ` Jonathan Wakely
2023-02-15 12:50 ` Dennis Clarke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).