• TI Thinks Resolved

Compiler/F28M36H53B2: Odd behavior of sin function with float vs double

Part Number: F28M36H53B2

Tool/software: TI C/C++ Compiler

Hi,

I came across a odd problem regarding the use of the double sin(double) function from the RTS2800 FPU library. When I use a single precision float as input and output of the function, I sporadically get a +Inf at the output of the function. My input is linearly increasing between 0 and 2*PI. When I use the float sinf(float) function, the problem disappears. I am using  TI v15.12.3.LTS. Any thoughts about this problem?

  • Can you give us an example of x where sin(x)==+Inf but sinf(x)!=+Inf?

    Are you using --fp_mode=strict?

    Are you using --tmu_support?
  • In reply to Archaeologist:

    I am using --fp_mode=strict.
    I am not using --tmu_support.
    As far as giving you a specific example, it seems to happen very sporadically for various inputs. I used to use the exact same code on a Delfino F28335 (which I ported to the Concerto) and the problem never manifested there.
  • In reply to Cedric 40627:

    Are you saying that the result from a given sin(x) changes from one run to the next?
    Also, are you using --abi=eabi?
  • In reply to Archaeologist:

    I am not using eabi. I am using legacy coff.
    What I meant is that I could not pinpoint the exact values for when it happens. In my application (motor control) I generate a ramp signal from 0 to 1 which I then multiply by 2*PI (i.e. I have 0 to 6.283185307) that is the input to sin() function. The ramp generator is from controlSUITE (rampgen.h), the value coming from the ramp generator are as expected. As I said, I have used this code on a Delfino without any problem. Since the output of sin is sporadically +inf, it messes up the following control calculations, resulting in an incorrect PWM duty cycle. That's how I first notice the problem, and as I said, with no regular pattern.
  • In reply to Cedric 40627:

    Are you sure you have no stray divide by zero's? Can you provide us with a table of which rampgen outputs cause +inf?

    I would suggest that you simply store the last two PWM outputs and extrapolate when sin() is infinity.

    Also a lookup table would be much faster. 8^)
  • In reply to Keith Barkley:

    I don't have any division in my code. I need to use the sin function as values are pretty much continuous data. Is there a macro to detect +inf values in the compiler ?
    The error is consistently replicable whenever I switch between sinf and sin. Could it be an issue of casting from float to double or vice versa?
  • In reply to Cedric 40627:

    In COFF, float and double are both 32-bit floating-point types. In theory, sin(x) and sinf(x) should be identical. Libraries like the RTS2800 FPU library replace the default RTS library math functions (e.g. sin(x)) with their own faster versions. However, to date they have typically only bothered to replace the double-typed functions (e.g. sin(x)) and not the newer C99 functions (e.g. sinf(x), sinl(x)). What's probably happening is that your sin(x) results come from the RTS2800 FPU library replacement, and your sinf(x) results come from the default RTS library. The compiler team maintains the default RTS library (rts2800_fpu32.lib). As the bug does not appear in the compiler team's version, you're going to have to ask your question in the C2000 forum.
  • In reply to Cedric 40627:

    You mean like:

    #define SIN_BLEW_UP(s) (abs(s) > 1.00000001)

    or

    #define SIN_IS_INF(s) (s == inf)
    which might not work depending on how (or whether!) the ti compiler will let you enter an infinity.
  • In reply to Keith Barkley:

    Okay. Thank you for your inputs.
  • In reply to Cedric 40627:

    Is the input to the sin function variable that you control or is it an output from an observer? If it is an output from an observer, you most likely have a division within and if dievide by zero happens, your output will go to +-inf. And because you are in control loop, everytheing else will also become +-inf.

    Make sure you catch any dived by zero events first.