3

The libmath on a particular embedded system does not have functions like sin and cos due to missing fp-operation unit.

Is there some library around that provides the functions via look-up tables? I do not actually need 100% reliable values.

Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
Stasik
  • 2,568
  • 1
  • 25
  • 44
  • 1
    which embedded system exactly are we talking about? TI's DSPs have sin function implemented as a lookup table – BЈовић Feb 08 '13 at 07:45
  • Plenty standard libraries for embedded targets without an FPU include a complete standard math library using *software floating point* arithmetic - even for 8 bit targets. The performance hit can be relatively high, but whether that is an issue is dependent on the application and it is not normally a decision that the tool vendor could or should make. What is your target and toolchain? GNU libm certainly includes these functions so your library is either not that or a modified implementation. You may find that they are merely omitted or conditional compiled out in the header file? – Clifford Feb 09 '13 at 13:46

5 Answers5

2

Depending on the needed requirements for speed and precision, maybe you could create the functions needed by a simple lookup table, by writing a program to create the lookup table. Or use CORDIC.

wallyk
  • 56,922
  • 16
  • 83
  • 148
  • sounds good, but there is no "out of the box" solution constructing such tables? – Stasik Feb 08 '13 at 07:50
  • @Stasik: Really? It is not that hard. If you don't want to write code, use a spreadsheet, output as a CSV file, then copy and paste the comma separated values between initialiser braces `{...}` in your code. – Clifford Feb 09 '13 at 14:01
2

A better method for targets without hardware floating point is perhaps to use fixed-point and the CORDIC algorithm.

Anthony Williams' fixed-point maths library provides a complete analogue of the standard maths library for a fixed data type that is typically around 5 times faster than software floating-point on the same target. It is a C++ library, but so long as your compiler supports C++ that should not be a problem even if the rest of your code does not use C++ specific features. For the most part all you need to do to port code to use this library is to replace math.h with fixed.hpp and replace the type keywords float and double with the fixed type.

Clifford
  • 88,407
  • 13
  • 85
  • 165
1

If you do not have libraries for your system providing you sin/cos functions, or a lookup tables in memory, you can create one very easily.

Next matlab function will provide you sin(x) ([0,2*pi] range with 2*pi/100 step) in a c header myheader.h :

step=2*pi/100;
x=[0:step:2*pi];
y=floor(0.5 * 65535 * sin(x));

fd=fopen('myheader.h','wt');
fprintf(fd,'int16_t y[%d]={%g',length(y),y(1));
fprintf(fd,',\n %.9g',y(2:end));
fprintf(fd,'};\n');
fclose(fd);

The header looks like this :

int16_t y[101]={0,
 2057,
 4107,
 6140,
 8149,
 10126,
 12063,
 13952,
 15786,
 17558,
 19260,
 20887,
 22431,
 23886,
 25248,
 26509,
 27667,
 28714,
 29649,
 30466,
 31164,
 31738,
 32187,
 32509,
 32703,
 32767,
 32703,
 32509,
 32187,
 31738,
 31164,
 30466,
 29649,
 28714,
 27667,
 26509,
 25248,
 23886,
 22431,
 20887,
 19260,
 17558,
 15786,
 13952,
 12063,
 10126,
 8149,
 6140,
 4107,
 2057,
 -0,
 -2057,
 -4107,
 -6140,
 -8149,
 -10126,
 -12063,
 -13952,
 -15786,
 -17558,
 -19260,
 -20887,
 -22431,
 -23886,
 -25248,
 -26509,
 -27667,
 -28714,
 -29649,
 -30466,
 -31164,
 -31738,
 -32187,
 -32509,
 -32703,
 -32768,
 -32703,
 -32509,
 -32187,
 -31738,
 -31164,
 -30466,
 -29649,
 -28714,
 -27667,
 -26509,
 -25248,
 -23886,
 -22431,
 -20887,
 -19260,
 -17558,
 -15786,
 -13952,
 -12063,
 -10126,
 -8149,
 -6140,
 -4107,
 -2057,
 -0};
Clifford
  • 88,407
  • 13
  • 85
  • 165
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • Maybe you could post the output of this? I don't have matlab, as I expect is common. – wallyk Feb 08 '13 at 08:52
  • @wallyk octave is free. Anyway, I edited the question – BЈовић Feb 08 '13 at 09:00
  • If there's no FPU on the target platform, a more suitable way would be to scale these with an integer (and to round them). – Aki Suihkonen Feb 08 '13 at 11:54
  • @AkiSuihkonen right. fixed it – BЈовић Feb 08 '13 at 12:59
  • While at it, try int16_t for -xxxx (and notice there's no +32768) – Aki Suihkonen Feb 08 '13 at 13:00
  • @wallyk: You never needed Matlab or Octave (or SciLab or FreeMAT for that matter) to generate the table, you could as easily have written the generator in C (to run on the PC not the target obviously). – Clifford Feb 09 '13 at 13:36
  • It more memory efficient to generate a table for one quadrant only; values in the other three quadrants can be determined arithmetically from values in the first as described [here](http://en.wikipedia.org/wiki/Lookup_table#Computing_sines). You can then have either a smaller table, or greater precision. – Clifford Feb 09 '13 at 13:55
0

Jack Ganssle has an excellent article on optimising trig for embedded systems:

http://www.ganssle.com/approx/approx.pdf

Martin Thompson
  • 16,395
  • 1
  • 38
  • 56
0

I don't think it makes sense to provide such an library, as the are too many design choices and parametrizations compared to the difficulty of writing an own. I mean none of these are very difficult, but can't be provided as fits-for-all solution.

  • the parameters:

    • argument of sin/cos == (unsigned) vs (signed)
    • short,int,float, fixed point
    • range: limited (mod pi, mod 2pi)
    • is the argument radians, degrees or something else (e.g. 2pi==65536==0)
  • the values

    • float vs. fixed point vs. scaled integer
    • 1st quadrant only, complete or extended range (no modulo reduction of argument needed)
    • both sines & cosines, or just sine
  • requirements

    • code size
    • data size
    • execution speed
      • "constant" vs.
      • a lot of variation allowed
    • precision
      • minimize some least square metric
      • minimize some maximum error
      • minimize 1 - sin(x)^2 - cos(x)^2 error
  • method

    • direct a=LUT[b]
    • mirroring depending on quadrant: a=sign(b)*LUT[ b ^ mirror(b)]; // conceptual formula
    • CORDIC
    • 3rd or 5th degree Taylor polynomial
    • added (angular) precision using two LUT tables LUTA(x)=sin(x); LUTB(x)=sin(x/256) and formula for sum of angles
Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57