This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Code Composer, float.h, TMS320F2812

Other Parts Discussed in Thread: TMS320F2812

I've run into problems with a floating point test.

In the float.h that comes with Code Composer version 3.3, it defines epsilon to be:

FLT_EPSILON        1.192092896E-07F   /* SMALLEST X WHERE 1+X != 1 */

However, while running the following code on the TMS320F2812 device simulator, I arrive at an epsilon of half what is defined or 5.96046444E-08F.

float eps = 1.0f;
while( (1.0f + eps/2.0f) != 1.0f )
{
    eps/=2.0f;
}

Can TI confirm my numbers?

  • Kyle,

    I get the same answer as you.  However isn't it dividing by 2 one extra time since the reason it exited the loop was that it was equal to 1.0f

    John

  • Hi John,

    Thanks for your quick response.

    The previous code divides eps by two in the termination condition to look ahead for the value where 1+eps==1, so when the loop is exited, eps contains the smallest value such that 1+eps != 1.

    I modified the code to illustrate this better:

        float eps,lead_eps,val1;
        eps = 1.0f;
        lead_eps = 0.0f;
        val1 = 0.0f;

        printf("val1 != 1.0?  \n");
        while( val1 != 1.0f )
        {
            printf("yes: val1=%.17f...........lead_eps=%.17f.....eps=%.17f\n",val1, lead_eps,eps);
            eps/=2.0f;
            lead_eps = eps/2.0f;
            val1 = (1.0f + lead_eps);
        }
        printf("\nno : val1=%.17f...........lead_eps=%.17f.....eps=%.17f\n",val1,lead_eps,eps);
        printf("one plus eps: %.17f\none plus lead_eps=%.17f",1.0f+eps,1.0f+lead_eps);
        printf("\n\neps=%.17f",eps);

    my output:

    val1 != 1.0?  
    yes: val1=0.00000000000000000...........lead_eps=0.00000000000000000.....eps=1.00000000000000000
    yes: val1=1.25000000000000000...........lead_eps=0.25000000000000000.....eps=0.50000000000000000
    yes: val1=1.12500000000000000...........lead_eps=0.12500000000000000.....eps=0.25000000000000000
    yes: val1=1.06250000000000000...........lead_eps=0.06250000000000000.....eps=0.12500000000000000
    yes: val1=1.03125000000000000...........lead_eps=0.03125000000000000.....eps=0.06250000000000000
    yes: val1=1.01562500000000000...........lead_eps=0.01562500000000000.....eps=0.03125000000000000
    yes: val1=1.00781250000000000...........lead_eps=0.00781250000000000.....eps=0.01562500000000000
    yes: val1=1.00390625000000000...........lead_eps=0.00390625000000000.....eps=0.00781250000000000
    yes: val1=1.00195312500000000...........lead_eps=0.00195312500000000.....eps=0.00390625000000000
    yes: val1=1.00097656250000000...........lead_eps=0.00097656250000000.....eps=0.00195312500000000
    yes: val1=1.00048828125000000...........lead_eps=0.00048828125000000.....eps=0.00097656250000000
    yes: val1=1.00024414062500000...........lead_eps=0.00024414062500000.....eps=0.00048828125000000
    yes: val1=1.00012207031250000...........lead_eps=0.00012207031250000.....eps=0.00024414062500000
    yes: val1=1.00006103515625000...........lead_eps=0.00006103515625000.....eps=0.00012207031250000
    yes: val1=1.00003051757812500...........lead_eps=0.00003051757812500.....eps=0.00006103515625000
    yes: val1=1.00001525878906250...........lead_eps=0.00001525878906250.....eps=0.00003051757812500
    yes: val1=1.00000762939453125...........lead_eps=0.00000762939453125.....eps=0.00001525878906250
    yes: val1=1.00000381469726563...........lead_eps=0.00000381469726563.....eps=0.00000762939453125
    yes: val1=1.00000190734863281...........lead_eps=0.00000190734863281.....eps=0.00000381469726563
    yes: val1=1.00000095367431641...........lead_eps=0.00000095367431641.....eps=0.00000190734863281
    yes: val1=1.00000047683715820...........lead_eps=0.00000047683715820.....eps=0.00000095367431641
    yes: val1=1.00000023841857910...........lead_eps=0.00000023841857910.....eps=0.00000047683715820
    yes: val1=1.00000011920928955...........lead_eps=0.00000011920928955.....eps=0.00000023841857910
    yes: val1=1.00000011920928955...........lead_eps=0.00000005960464478.....eps=0.00000011920928955

    no : val1=1.00000000000000000...........lead_eps=0.00000002980232239.....eps=0.00000005960464478
    one plus eps: 1.00000011920928955
    one plus lead_eps=1.00000000000000000

    eps=0.00000005960464478

    my output comments:

    It is curious that while 1+2^-24 doesn't equal 1, it doesn't equal 1+2^-24 either, but rather 1+2^-23. I am sure it is just something I don't understand about floating point arithmetic.

  • Right, I missed the /2.0f in the condition.  I really don't know much about floating point either.  I will slide this over to the C2000 forum.  They should know if the value in float.h is correct.

    John

  • Thanks John.

  • John, Kyle,

    This seems to be a simulator issue.  I ran this on actual silicon with the following result.

    John - can you file an issue against the simulator?

  • Thanks Lori!
  • Yeah, thanks!

  • Honeywell requires a correction to this simulator issue if it truly exists and/or provide a determination of root cause and further information regarding the effects of this bug.  Is accuracy higher, in the simjulator, for example?  Note, we actually require the simulator to behave like the silicon in order to qualifiy our products, so a fix may be the only solution.  Without further information, we cannot explain the difference to our certification authorities.

    So, please provide a detailed explaination of the problem, the differences from simulator to silicon, and a date when a new release / patch will be provided.  This assumes that it is not fixed in a newer version already, of course.

    Regards,

    Brian Sellner
    Sr. Technical Manager
    Honeywell Aerospace
    11100 N. Oracle Rd.
    M/S M124
    Tucson, AZ 85737
    (520) 469-5227 - Office

  • Brian,

    I can see why this would be of significant concern to you.  Is your certification process tied to the simulator or is it something that can be run on hardware?  The F28x simulator is something that is being phased out and is not actively maintained.  For F28x instead the low cost development boards are recommended instead.

    Regards,

    John

  • We are tied to the simulator in some regards.  Switching to real hardware for all of our detailed tests posses some problems.

    To be honest, I find it a bit concerning that TI is phasing out support of a simulator for a part you still sell to customers. 

    We will discuss more internally to see if there are other ways to address this problem.  In the mean time, can we at least get a detailed analysis of the problem and the differences that will be seen from hw to simulator?  Also, I would like you to see if this is something that can be corrected as a patched version for us, with minimal impact on your side.  It would not have to be a formal version, as we could configure it internally.  Hopefully that would be a happy medium.

  • Brian, John,

    My apologies - I just noticed the 2812 comment.

    In my initial assessment I did not notice that this was for a fixed-point device (2812).  I tried the code with the fpu32 extensions enabled and a floating-point device.  

    I have rerun the code without fpu32 and the results were the same as the original post as shown below.

    We will need to investigate this a bit further.

  • Hi Lori,

     We are a bit off track here.  Let me reiterate our problem so we are all on the same page.  We are using Code Composer Version 3.3.38 to execute simulator test of our software.  In doing so, we discovered that the value of FLT_EPSILON defined in the Code Composer file Float.h is incorrect.  We believe the value should be '5.96046444E-08F.   We would like to know if you agree with our assessment or do you think we are incorrect.  In addition to this we would like you to provide rational used for by TI in determing the value of FLT_EPSILON in Code Composer.

  • Tim Kimble said:
    We would like to know if you agree with our assessment or do you think we are incorrect.

    You are incorrect.

    Tim Kimble said:
    In addition to this we would like you to provide rational used for by TI in determing the value of FLT_EPSILON in Code Composer.

     

    I’ll start with the ANSI standard definition for FLT_EPSILON.

    The difference between 1 and the least value greater than 1 that is representable in the given floating type.

    Side note on standards …  As described in http://processors.wiki.ti.com/index.php/TI_Compilers_and_Industry_Standards, the TI compiler adheres to the C89 standard.  That standard is not generally available online.  The C99 standard is generally available online.  The definition of FLT_EPSILON is identical in the two standards.

    So, the definition of FLT_EPSILON depends entirely on the floating point representation used, and nothing more.  Ignore rounding modes, accuracy, etc.  Thus, it is better to work this problem through in terms of the underlying representation.  Directly consider the binary digits used to represent that value.

    The next paragraph presumes you understand computer floating point representation, and you have good familiarity with the IEEE 754 standard for it.

    The TI compiler (and every other C compiler I know of) uses 32-bit IEEE 754 representation for the type float.  In that representation, here are the bits (written with hex) for the value 1.0: 0x3f800000.  The last 23 bits are the mantissa.  To get the next representable value, just add 1 to that mantissa.  So, the next representable value is: 0x3f800001.  Note the last hex digit changes from 0 to 1.  What is the floating point value for that set of bits?  Much fun math skipped over here gives you … 1.0000001192092896.  Subtract 1 from that, and you have FLT_EPSILON.

    Because this is based on representation, and every compiler I’ve seen uses 32-bit IEEE 754 for float, it stands to reason that other compilers would have the same value for FLT_EPSILON.  And indeed they do.  My laptop has gcc version 3.4.4, and it uses 1.19209290e-7F.  My MSVC version 9 uses 1.192092896e-07F.

    Thanks and regards,

    -George

  • George,

    Thank you for your quick and detailed response.  We will continue to look into the issue on our side.

    Tim

  • George,

     This is our problem.  Our test verify the math functions for each processor that we use.  I have outlined the test below:

     FLT_EPSILON = 1.192092896E-07F, Per the TI float.h file .

    and

    0x3F800000 = 1.0f

    Then:

    0x3F800001 = 1.0f + FLT_EPSILON

    Since FLT_EPSILON is the smallest value which can be represented then the following test would be correct

    0x3F800000 = 1.0f + FLT_EPSILON / 2.0f

    However, we get the following result from Code Composer which causes our test to fail.

    0x3F800001 = 1.0f + FLT_EPSILON / 2.0f

     Our test pass if we change FLT_EPSILON to:

    OUR_FLT_EPSILON = FLT_EPSILON  / 2.0f;

    Then

    0x3F800000=  1.0 + OUR_FLT_EPSILON  / 2.0f;

    Can you provide some insight into this for us, we are using the F2812 rts2800_ml.lib for all math functions.

    Tim

     

  • George,

     

    We found the following comments in the fs_add28 assembly code.

     

    ;*****************************************************************************

    *;       exp OP1 > exp OP2                                                    *

    *;  Test if the difference of the exponents is larger than 24 (precision of   *

    *;  the mantissa).                                                            *

    *;  Return OP1 as the result if OP2 is too small.                             *

    *;  Mantissa of OP2 must be right shifted to match normalization of OP1.      *

    *;  Add mantissas:  mant OP1 + mant op2                                       *

    *;*****************************************************************************

     

    *;*****************************************************************************

    *;       OP1 < OP2                                                            *

    *;  Test if the difference of the exponents is larger than 24 (precision of   *

    *;  the mantissa).                                                            *

    *;  Return OP2 as the result if OP1 is too small.                             *

    *;  Mantissa of OP1 must be right shifted to match normalization of OP2.      *

    *;  Add mantissas:  mant OP1 + mant OP2                                       *

    *;  If A = 0 then have gone beyond precision available                        *

    *;*****************************************************************************

    We believe this to be incorrect, the precision of the mantissa should be 23 and not 24.  Could you also provide also provide some insight into the value of 24

    Tim

  • Tim Kimble said:
    the precision of the mantissa should be 23 and not 24

    That is incorrect.  The mantissa is 24 bits.  Please see http://en.wikipedia.org/wiki/Binary32 .

    -George

  • Tim Kimble said:
    Since FLT_EPSILON is the smallest value which can be represented

    That is not how the standard defines FLT_EPSILON.

    Tim Kimble said:

    the following test would be correct

    0x3F800000 = 1.0f + FLT_EPSILON / 2.0f

    No, it isn't.  Round-off may or may not affect things.

    Look, my expertise on this subject has been exhausted.  I am not the best person for your questions.  Moreover, at this point, your questions are no longer specific to the TI compiler.  Any compiler which supports 32-bit IEEE 754 floating point has the exact same issues for the exact same reasons.  Therefore, I suggest you pursue your questions in some forum where such experts hang out.  I'm sorry I do not have any such forum to suggest.

    Thanks and regards,

    -George

  • Tim Kimble said:

    Since FLT_EPSILON is the smallest value which can be represented then the following test would be correct

    0x3F800000 = 1.0f + FLT_EPSILON / 2.0f

    As George indicated, the ANSI standard definition for FLT_EPSILON is: "The difference between 1 and the least value greater than 1 that is representable in the given floating type."

    Or: 1.0f + FLT_EPSILON - 1.0f = FLT_EPSILON, which is different from your test.

    I'm certainly not an expert in this either, but consider the following:

    #include <float.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main(int argc, char **argv)
    {
        int i;
        for(i = 1; i < 4; i++)
        {
            float myEPSILON = FLT_EPSILON / i;
            float result = 1.0f + myEPSILON - 1.0f;

            printf("FLT_EPSILON/%d of %.25f yields %.25f  %s\n",
                   i, myEPSILON, result, (result == myEPSILON ? "OK" : "Err"));
        }
    }

    It produces:

    FLT_EPSILON/1 of 0.0000001192092895507812500 yields 0.0000001192092895507812500  OK
    FLT_EPSILON/2 of 0.0000000596046447753906250 yields 0.0000001192092895507812500  Err
    FLT_EPSILON/3 of 0.0000000397364274817846308 yields 0.0000000000000000000000000  Err

    Notice that when using your suggested value of FLT_EPSILON/2, it does *NOT* satisfy the ANSI definition of FLT_EPSILON (even though it produces a difference) as it does not produce the same FLT_EPSILON/2 as the result once round-off and other factors are introduced.  (And at FLT_EPSILON/3 the value becomes too small a difference to represent, etc.)




  • We think we found our problem,

    Our tests assume a round to zero method is used, we found documentation in the TI lib that states round to nearest is used.  The test results support the round to nearest method as defined in the TI lib.  To correct our problem we will rewrite our test to determine which rounding method is used.   

    Thanks to everyone for providing input into this issue. 

  • Hi,

    I have a problem withe the float type: I used the same program :

    #include <stdio.h>
    #include <math.h>
    #include <float.h>

    void main ()
    {
    float eps,lead_eps,val1;
    eps = 1.0f;
    lead_eps = 0.0f;
    val1 = 0.0f;

    printf("val1 != 1.0? \n");

    while( val1 != 1.0f )
    {
    printf("yes: val1=%.17f...........lead_eps=%.17f.....eps=%.17f\n",val1, lead_eps,eps);
    eps/=2.0f;
    lead_eps = eps/2.0f;
    val1 = (1.0f + lead_eps);
    }
    printf("\nno : val1=%.17f...........lead_eps=%.17f.....eps=%.17f\n",val1,lead_eps,eps);
    printf("one plus eps: %.17f\none plus lead_eps=%.17f",1.0f+eps,1.0f+lead_eps);
    printf("\n\neps=%.17f",eps);
    }

    The simulation result:

    val1 != 1.0?
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f
    yes: val1=17f...........lead_eps=17f.....eps=17f

    no : val1=17f...........lead_eps=17f.....eps=17f
    one plus eps: 17f
    one plus lead_eps=17f

    eps=17f

    How Can I get the real result of float variables?