Jump to content

Noob question: Floating Point

Recommended Posts

Hello!  I'm an Arduino old timer, been working with it for years, but I am new to this platform.


I bought one of the new 'Connected Launchpads' with the ARM Cortex M4 (TM4C1294NCPDTI) microcontroller.  Part of what tempted me to try this one is that it is supposed to have floating point support in the processor hardware.  (Correct?)


I have been working on a celestial clock that calculates sunrise, sunset, moonrise, set, phase, precise angles in the skies, tides, and various other astrological events, and displays it on a small LCD.  It uses a cheap GPS module for the user's location and accurate time.  And it uses a MP3 module to announce things. This was wayyyyyy to much floating point math and string manipulation for the 16MHz 8-bit Arduino to perform in any timely manner.


I've been skimming thru the documentation and these forums and have seen little mention of the floating point support.  Do the Energia and Code Composer compilers handle and optimize for this automatically?  Or will I have to jump thru a hoop or two?  Can someone please aim me in the direction of some more detailed documentation or examples?


P.S.  Yes, I will be sharing this project and it's code when I get a little further along with it!



Link to post
Share on other sites

Energia enables it automatically.  Just use "float" and the -lm (libm, i.e. math library) is also automatically linked by Energia, so the trigonometric functions are there.  I think they're suffixed by 'f', i.e. sinf, cosf, etc?


Be sure to #include <math.h> at the top of your sketch or any other code files that use them.


You do want to use 'float' and not 'double' here, as 'float' is 32-bit Single-Precision which is the only type supported by the Cortex-M4F's built-in FPU.


Perusing math.h (found in energia-0101E0012/hardware/tools/lm4f/arm-none-eabi/include/math.h if you're curious), lots of crud but here's a bit of a list of functions I believe:

/* Single precision versions of ANSI functions.  */

extern float atanf _PARAMS((float));
extern float cosf _PARAMS((float));
extern float sinf _PARAMS((float));
extern float tanf _PARAMS((float));
extern float tanhf _PARAMS((float));
extern float frexpf _PARAMS((float, int *));
extern float modff _PARAMS((float, float *));
extern float ceilf _PARAMS((float));
extern float fabsf _PARAMS((float));
extern float floorf _PARAMS((float));

#ifndef _REENT_ONLY
extern float acosf _PARAMS((float));
extern float asinf _PARAMS((float));
extern float atan2f _PARAMS((float, float));
extern float coshf _PARAMS((float));
extern float sinhf _PARAMS((float));
extern float expf _PARAMS((float));
extern float ldexpf _PARAMS((float, int));
extern float logf _PARAMS((float));
extern float log10f _PARAMS((float));
extern float powf _PARAMS((float, float));
extern float sqrtf _PARAMS((float));
extern float fmodf _PARAMS((float, float));
#endif /* ! defined (_REENT_ONLY) */
/* Other single precision functions.  */

extern float exp2f _PARAMS((float));
extern float scalblnf _PARAMS((float, long int));
extern float tgammaf _PARAMS((float));
extern float nearbyintf _PARAMS((float));
extern long int lrintf _PARAMS((float));
extern _LONG_LONG_TYPE llrintf _PARAMS((float));
extern float roundf _PARAMS((float));
extern long int lroundf _PARAMS((float));
extern long long int llroundf _PARAMS((float));
extern float truncf _PARAMS((float));
extern float remquof _PARAMS((float, float, int *));
extern float fdimf _PARAMS((float, float));
extern float fmaxf _PARAMS((float, float));
extern float fminf _PARAMS((float, float));
extern float fmaf _PARAMS((float, float, float));

extern float infinityf _PARAMS((void));
extern float nanf _PARAMS((const char *));
extern int finitef _PARAMS((float));
extern float copysignf _PARAMS((float, float));
extern float logbf _PARAMS((float));
extern int ilogbf _PARAMS((float));

extern float asinhf _PARAMS((float));
extern float cbrtf _PARAMS((float));
extern float nextafterf _PARAMS((float, float));
extern float rintf _PARAMS((float));
extern float scalbnf _PARAMS((float, int));
extern float log1pf _PARAMS((float));
extern float expm1f _PARAMS((float));

#ifndef _REENT_ONLY
extern float acoshf _PARAMS((float));
extern float atanhf _PARAMS((float));
extern float remainderf _PARAMS((float, float));
extern float gammaf _PARAMS((float));
extern float lgammaf _PARAMS((float));
extern float erff _PARAMS((float));
extern float erfcf _PARAMS((float));
extern float log2f _PARAMS((float));
#if !defined(__cplusplus)
#define log2f(x) (logf (x) / (float_t) _M_LN2)
extern float hypotf _PARAMS((float, float));
#endif /* ! defined (_REENT_ONLY) */

extern float dremf _PARAMS((float, float));
extern void sincosf _PARAMS((float, float *, float *));
extern float gammaf_r _PARAMS((float, int *));
extern float lgammaf_r _PARAMS((float, int *));

extern float y0f _PARAMS((float));
extern float y1f _PARAMS((float));
extern float ynf _PARAMS((int, float));
extern float j0f _PARAMS((float));
extern float j1f _PARAMS((float));
extern float jnf _PARAMS((int, float));


/* Useful constants.  */

#define MAXFLOAT        3.40282347e+38F

#define M_E             2.7182818284590452354
#define M_LOG2E         1.4426950408889634074
#define M_LOG10E        0.43429448190325182765
#define M_LN2           _M_LN2
#define M_LN10          2.30258509299404568402
#define M_PI            3.14159265358979323846
#define M_TWOPI         (M_PI * 2.0)
#define M_PI_2          1.57079632679489661923
#define M_PI_4          0.78539816339744830962
#define M_3PI_4         2.3561944901923448370E0
#define M_SQRTPI        1.77245385090551602792981
#define M_1_PI          0.31830988618379067154
#define M_2_PI          0.63661977236758134308
#define M_2_SQRTPI      1.12837916709551257390
#define M_SQRT2         1.41421356237309504880
#define M_SQRT1_2       0.70710678118654752440
#define M_LN2LO         1.9082149292705877000E-10
#define M_LN2HI         6.9314718036912381649E-1
#define M_SQRT3 1.73205080756887719000
#define M_IVLN10        0.43429448190325182765 /* 1 / log(10) */
#define M_LOG2_E        _M_LN2
#define M_INVLN2        1.4426950408889633870E0  /* 1 / log(2) */

Not exactly sure how much of that is visible to Energia sketches as there's a rat's nest of #ifdef's and crap in there, but the constants certainly should be available too.

Link to post
Share on other sites

If you can get by with fixed point you might also look at the IQMath library.

Nothing wrong with floating point, but an option worth being aware of if need more speed.

Disclaimer - I haven't used the IQMath library.  

It is part of TI's Tivaware drivers, I do not know if it has been integrated into Energia or if there would be difficulties in doing so.

Link to post
Share on other sites

Since this is for a celestial clock, most of the calculations need to be performed only once per day, and I can stagger different ones at different times, and even break them into steps to be performed at separate times.  I had to do that with the poor lil' old Arduino, and even then my clock would freeze up for a few seconds when performing some of them.  I'm sure single precision floating point shall be enough for my needs.  I doubt I can adapt to fixed point for these calculations but I may tinker with that.  I'm definitely gonna try a few things and perform some benchmarks and speed comparisons.  I'm a stickler for efficiency.  I'll report back with my findings!

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...