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.

CCS/TMS320F28379D: Accuracy of atof()

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Tool/software: Code Composer Studio

Hello TI World:

 Since CCS does not include an ftoa() function, and the sprint() function requires an excessive amount of stack space, one must create their own ftoa() function.

While testing the ftoa() function, it has been observed that the atof() function seems to not be as accurate as it should be.

For example, the result for atof(“-9196.013671875”) is -9196.01172 as shown in the image of the debug results below:

I would have expected that the first 7 digits (i.e. 9196.013) would be the same.

A difference of nearly 0.002 seems excessive.

Is that much of a difference reasonable for a 32 bit floating point number?

 Thank you,

Tim Ball

TDB Consulting

P.S. As you may know, the sprint() function using the “%g” format specifier works but “%f” crashes the system, even with a stack size of 0x400.

 

 

  • You only get about 8 digits of precision in a 32 bit float, so you are close to the limit. Try a 64bit float.

    Did you try strtod() or its cousins? That gives you much more control.

  • As you note, float has 32 bits, and for IEEE 32, FLT_DIG=6.  FLT_DIG basically tells you how many significant digits you can expect to be accurate before rounding occurs.

    However, in this case, your input is exactly representable, so there should be no rounding.

    However, I am not able to reproduce this problem.  Could you please show the memory contents of rFloat in hex format so I can check the bits?  What options are you using to compile this test case?

  • Please reply to the questions in the last post.

    Thanks and regards,

    -George

  • Since it has been while, I presume you have resolved your problem.  We would appreciate hearing how you resolved it.

    Thanks and regards,

    -George

  • Please accept my apologies for not responding sooner.

    The issue described exists for both atof() and strtof() as shown in the graphics, that include the hexadecimal values, below:

    Note too that the “Floating point precision accepted by compiler” is set to “all”:

    Thank you for any clues that might explain and resolve this issue,

    Tim Ball

    TDB Consulting

    Web: TDBConsulting.org

  • Please see response from March 5, 2019 2:22 PM.
  • I still cannot reproduce the error.  What compiler version are you using (it is not the same as the CCS version).  What command-line options are you using?

    The correct hex value should be 0xC60FB00E, so the value you get is off by two bits.

    Some notes:

    1. atof just calls strtod, so you only need to test one or the other
    2. the option --float_operations_allowed does not change precision in any way; it causes the compiler to emit an error if floating point operations are seen.
    3. The hex value in your screen capture agrees with the float value displayed by CCS, so it's not a bug in the expression viewer.

  • As indicated in CCS Help/About Code Composer Studio:
    Code Composer Studio
    Version: 7.2.0.00013
    (c) Copyright Texas Instruments, 2016. All rights reserved.

    Note that the same result is produced when compiling code for the F280049 as well as the F28379D

    Thank you for your time and efforts,

    Tim Ball

    TDB Consulting

  • The TI compiler version is not the same as the CCS version, as one version of CCS can deal with multiple versions of the compiler installed at once.

    To quickly find the TI compiler version:

  • That version is TI v18.1.3.LTS as shown below for the F280049 which is also for the F28379D having the same issue:

  • Thank you for the compiler version.  We are still missing the answer to ...

    Archaeologist said:
    What command-line options are you using?

    Please copy-n-paste that from the CCS Console view.  Copy the complete compiler invocation for one of the source files.

    Thanks and regards,

    -George

  • Okay, thank you for that information.  Unfortunately I am still unable to reproduce the problem.  I think I may need to see your source code.  What compiler options are you using to compile this program?  The easiest place to see the complete set of options is in the build console log.  Here is the test case I am using.  It should produce identical output on either the C28x or a host machine.

    #include <stdio.h>
    #include <stdlib.h>

    char *orig = "-9196.013671875";

    int main()
    {
        float f = atof(orig);
        double d = atof(orig);
        printf("%s\n\n", orig);
        printf("%a\n", f);
        printf("%a\n", d);
        printf("%.15f\n\n", f);

        float fp = -9196.013671875f;
        double dp = -9196.013671875;
        printf("%a\n", fp);
        printf("%a\n", dp);
        printf("%.15f\n", fp);
        printf("%.15f\n", dp);
    }

  • The information requested follows:

    'Building file: C:/RTC/TBAL_WS1/FreeRTOS/croutine.c'
    'Invoking: C2000 Compiler'
    "C:/ti/ccsv7/tools/compiler/ti-cgt-c2000_18.1.3.LTS/bin/cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 -Ooff --fp_mode=strict --include_path="C:/ti/ccsv7/tools/compiler/ti-cgt-c2000_18.1.3.LTS/include" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/c2000ware/common/include" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/c2000ware/headers/include" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/c2000ware/flash/include" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/include" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/parameters" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/general" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/drivers/utilities" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/drivers/CAN" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/drivers/fram" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/drivers/io" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/drivers/xcp" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/drivers/xcp/usr" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/drivers/xcp/cfg" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/hal/F2837x" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/drivers" --include_path="C:/RTC/TBAL_WS1/REDACTED/src/nvstorage" --include_path="C:/RTC/TBAL_WS1/REDACTED/src" --include_path="C:/RTC/TBAL_WS1/REDACTED" --include_path="C:/RTC/TBAL_WS1/FreeRtos/include" --include_path="C:/RTC/TBAL_WS1/FreeRtos/portable" --include_path="C:/RTC/TBAL_WS1/REDACTED/F021_API_F2837xD/include" --advice:performance=all --define=_FLASH --define=_INLINE --define=CPU1 --define=SYSCLK_MHZ=200 --define=OSCCLK_MHZ=20 --diag_warning=225 --diag_wrap=off --display_error_number --preproc_with_compile --preproc_dependency="FREERTOS/croutine.d" --obj_directory="FREERTOS" "C:/RTC/TBAL_WS1/FreeRTOS/croutine.c"
    'Finished building: C:/RTC/TBAL_WS1/FreeRTOS/croutine.c'

  • Thank you. Unfortunately I am still unable to reproduce the problem. I'll try it again when I can get my hands on some matching hardware, but so far I've seen nothing which would indicate that the problem is in the compiler. Could you please try running the example test case I posted above on your hardware? In your test case, have you made sure to include stdlib.h? What type does float32_t resolve to? (I assume "float," but perhaps not?) Is it possible that the value of rFloat has been tampered with in some way before it is printed, perhaps by a stray pointer write? Is it possible that the string constant passed to atof has been tampered with?
  • Hello Arch:

    Yes, I made sure that stdio.h was included. The data type float32_t is a float and the calculation was performed right after all required initialization was performed.

    I completed my work with that client and now have no hardware to test with.

    However, I informed one of the other engineers about the issue and I will forward this information to him.

    Thank you,

    Tim Ball

    TDB Consulting

  • I have asked for help from others in reproducing this problem.  I'll let you know how that turns out.

    Thanks and regards,

    -George

  • George:

    Thank you. That is greatly appreciated.

    Have a nice weekend,

    Tim Ball

    TDB Consulting

  • Timothy Ball said:
    For example, the result for atof(“-9196.013671875”) is -9196.01172 as shown in the image of the debug results below

    Since you are looking at the floating point values using the CCS debugger, not sure if you are are encountering the same problem as in CCS/TMS570LS3137: CCS Debug - Float value changes when losing focus on CCS. I.e. where the debugger seems to be changing the floating point value.

    In the debugger what is the Number Format set to?

  • With the help of my colleage, we have reproduced the problem.  The underlying problem is that TI's implementation of strtod (aka atof) uses a floating-point variable to accumulate the value of the input as it is read digit-by-digit.  As the number of significant digits rises to a certain point, as in your input with 13 significant digits, you'll eventually get roundoff in the intermediate accumulated value.  Indeed, the standard doesn't require strtod to get such values correct.  The C99 standard, section 7.20.1.3 "The strtod, strtof, and strtold functions" paragraph 9, under "Recommended practice", says:

    If the subject sequence has the decimal form and at most DECIMAL_DIG (defined in
    <float.h>) significant digits, the result should be correctly rounded. If the subject
    sequence D has the decimal form and more than DECIMAL_DIG significant digits,
    consider the two bounding, adjacent decimal strings L and U, both having
    DECIMAL_DIG significant digits, such that the values of L, D, and U satisfy L <= D <= U.
    The result should be one of the (equal or adjacent) values that would be obtained by
    correctly rounding L and U according to the current rounding direction, with the extra
    stipulation that the error with respect to D should have a correct sign for the current rounding direction.

    The short story is that you should only expect the return value of atof to be accurate to about DECIMAL_DIG decimal digits.

    I claim that the TI RTS is within the precision required by the standard.  Yes, as a QoI issue, it would be nice if we guaranteed the closest float representation for the decimal value considered in infinite precision, but this is not a bug.  Nonetheless, I have reported it as a bug (CODEGEN-6134) so that it can be considered for improvement.

  • Hello TI:

    Thank you for the update. I will forward your information to others.

    Appreciatively,

    Tim Ball

    TDB Consulting

    Web: http://TDBConsulting.org/

  • Hello Timothy,

    I recently got the requirement of conversion of received character data serially into floating point data so I am not sure from where to begin with. Could you please tell me how did you initialize the atof function in your code.

  • Hello TI:

    I did not initialize the atof() function, I just made sure all hardware was initialized (e.g.by calling InitPieVectTable(), InitSysCtrl(), __enable_interrupts(), etc.).

    Thanks for writing,

    Tim Ball

    TDB Consulting

    Web: TDBConsulting.org

  • Avichal:
    You can also use the strtod() function for a little bit more control.