floating point computation error

2005-11-15
2013-03-12
  • Nicolas Wanner

    Nicolas Wanner - 2005-11-15

    Hi,

    I am using the daily build of SDCC 20051114 on win32 platform compiling a program for the mcs51 architecture.

    I got negative result for expf() function call. After some testing, it seems to be a local variable initialisation problem.

    The program ran on a real system based on AduC834 and on a simulator (MCS51).

    The compilation commands are :
    sdcc --model-large --xram-size 2048 --stack-size 128 -DOPT_SNAPSHOT -c main.c
    sdcc --model-large --xram-size 2048 --stack-size 128 -DOPT_SNAPSHOT main.rel o debug.hex

    There is the test program :

    #include <math.h>

    float      val1, val2, val3;

    void SetValue( void )
    {
       /* This one is needed to avoid compiler optimisation */
       val1 = 3.0e-6;
       val2 = -2490.0;
    }

    void main( void )
    {
       SetValue();

       /*
       ** (val2 * val1) = -7.47e-3
       ** expf( val2 * val1 ) returns -0.992558 which is wrong
       */
       val3 = expf( val2 * val1 );

       /*
       ** expf( -7.47e-3 ) still returns -0.992558
       */
       val3 = expf( -7.47e-3 );

       /*
       ** expf( -7.47e-3 ) now returns 0.992558 (right value).
       ** It seems to have a problem in the local variable initialisation in the
       ** library functions.
       */
       val3 = val2 * val2;
       val3 = expf( -7.47e-3 );

       while( 1 );
    }

    Did someone have the same problem?
    Is there a work around or an existing  patch?

    Tanks in advance

    Nicolas Wanner

     
    • Jesus Calvino-Fraga

      Did you recompile the libraries?  My test program is below, and this is the output I get:

      val1 =  0.000003000, val2 =  -2490.000000000
      val3 = expf( val2 * val1 ) =  0.992557716
      val3 = expf( -7.47e-3 ) =  0.992557716
      val3 = val2 * val2 = 6200100.000000000
      val3 = expf( -7.47e-3 ) =  0.992557716

      This was obtained running in actual hardware: Philips p89v51rd2.  It seems that if I don't make the variables volatile, the statement val3=val2*val2 is optimized out, but the result of expf is always correct.

      Jesus

      /* Test program begins here */
      #include <math.h>
      #include <stdlib.h>
      #include <stdio.h>

      #ifdef SDCC_mcs51
      #include <8051.h>
      void dummyint3 (void) interrupt 3 _naked {}
      #endif

      volatile float val1, val2, val3;

      void SetValue( void )
      {
         /* This one is needed to avoid compiler optimisation */
         val1 = 3.0e-6;
         val2 = -2490.0;
      }

      void main( void )
      {
         SetValue();

         /*
         ** (val2 * val1) = -7.47e-3
         ** expf( val2 * val1 ) returns -0.992558 which is wrong
         */
         val3 = expf( val2 * val1 );

         printf("val1 = %12.9f, val2 =  %12.9f\n", val1, val2);
         printf("val3 = expf( val2 * val1 ) = %12.9f\n", val3);

         /*
         ** expf( -7.47e-3 ) still returns -0.992558
         */
         val3 = expf( -7.47e-3 );
         printf("val3 = expf( -7.47e-3 ) = %12.9f\n", val3);

         /*
         ** expf( -7.47e-3 ) now returns 0.992558 (right value).
         ** It seems to have a problem in the local variable initialisation in the
         ** library functions.
         */
         val3 = val2 * val2;
         printf("val3 = val2 * val2 = %12.9f\n", val3);
         val3 = expf( -7.47e-3 );
         printf("val3 = expf( -7.47e-3 ) = %12.9f\n", val3);

         while( 1 );
      }

      #ifdef SDCC_mcs51
      unsigned char _sdcc_external_startup(void)
      {
        TR1=0;
        TMOD=(TMOD&0x0f)|0x20;
        PCON|=0x80;
        TH1=TL1=0xff; //112000 baud with 22MHz crystal
        TR1=1;
        SCON=0x52;

        return 0;
      }

      char getchar(void)
      {
        char c;
        while (!RI);
        RI=0;
        c=SBUF;
        return c;
      }

      void putchar(char c)
      {
        while (!TI);
        TI=0;
        SBUF=c;
        if (c=='\n') putchar('\r');
      }
      #endif

       
    • Nicolas Wanner

      Nicolas Wanner - 2005-11-30

      No I did not recompile the libraries. Should I do it?

      Is there a "makefile" to do that task?

       
      • Jesus Calvino-Fraga

        Either that or get a fresh snapshot.  Check for the makefiles in the \sdcc\lib\src folder. 

        >No I did not recompile the libraries. Should I do it?

        >Is there a "makefile" to do that task?

         
    • Nicolas Wanner

      Nicolas Wanner - 2005-12-01

      I got a fresh snapshot and it did not change anything.

      I installed SDCC on cygwin from the sources, recompiled the libraries with USE_FLOAT and I got the following result :

      val1 =  0.000003000, val2 = -2490.000000000
      val3 = expf( val2 * val1 ) = -0.992557907
      val3 = expf( -7.47e-3 ) =  0.992557907
      val3 = val2 * val2 = 6200100.000000000
      val3 = expf( -7.47e-3 ) =  0.992557907

      is that problem related to the hardware?

       
    • Jesus Calvino-Fraga

      Indeed there was a bug in the assembler implementation of expf() which I was not using.  It should be fixed now...

       

Log in to post a comment.