I have noticed people complaining about how <math.h> uses up too much memory, in fact, so much so that it is virtually useless in the Atmega8. I'm thinking it would be fun to create a tiny math library, so I'm starting this topic to pose the following questions and ideas for feedback from the Arduino community:
Is it possible to replace the usual <math.h> with our own floating point package that defines only the most commonly used functions? These would be sqrt, sin, cos, log, exp. I am going to do some experiments to test the feasibility of this. It may turn out that just using floating point at all is the problem, not the library functions themselves.
If floating point itself is the problem, how about creating our own fixed point library? The idea here is to use integers (perhaps the 'long' type, which is signed 32 bits) to represent non-integer values. For example, the value 1000000 could represent 1, 500000 could represent 1/2, etc.
Another variation on this idea is to create a fraction class...
class fraction {
private:
long numerator;
long denominator;
public:
// blah blah blah
};
It would be easy to overload operators to add, subtract, etc. Gradually we could build up a library of trig functions, logarithm, sqrt, etc.
I am willing to take the lead on this project, but I thought I would put out feelers to see if anyone has any ideas or would like to help out. I propose that the goal should be to create something that would help solve a wide variety of real-world problems, with an emphasis on using as little program memory and SRAM as possible. A good design should allow users to use the parts of the code they want, but not have to pull in code they do not need.
Another thing that would be helpful would be for people to give examples of the kind of thing they would do if they had such a library. For example, I have seen a post where somebody wanted trig functions so they could calculate distances between points on the globe, given GPS data. What real world problems would you like to attack on Arduino, but can't, because you don't have floating point math?
OK, here is the result of my first experiment. I'm starting to see that it is the floating point library functions that seem to be using up a lot of space. The code here contains comments that show how the binary size varies as I start calling a few functions. I had to add the function DumpFloat so that the compiler optimizer would be forced to generate code for the floating point calculations I did. Without using the values calculated, the optimizer figures out that the calculations are not needed and does not generate any code at all for them. (Clever monkey!)
Anyway, I can now see for myself how any real-world attempt to use floating point math functions becomes impossible when your code size is limited to 7168 bytes!
/*
math_test.pde - Don Cross - http://cosinekitty.com
Experiment to see what the heck is wrong with floating point math in Arduino
that everyone keeps complaining about it.
*/
#include <math.h>
void DumpFloat (float x)
{
const unsigned char *p = (const unsigned char *) &x;
for (int i=0; i < sizeof(float); ++i) {
Serial.print (" ");
Serial.print (p[i], HEX);
}
Serial.println();
}
void setup()
{
Serial.begin (9600);
// 3494 bytes with no math.h function calls
// 4508 bytes with cos
// 4690 bytes with cos, sqrt
// 6288 bytes with cos, sqrt, log
float x = cos(0.7);
float y = sqrt(x) * log(x);
DumpFloat (x);
DumpFloat (y);
}
void loop()
{
}
/*
$Log: math_test.pde,v $
Revision 1.1 2006/12/26 22:34:00 dcross
Starting experimenting with binary sizes produced by using various math.h functions.
*/
It could still be useful to have a int math function, like successive substraction, powers, closest sqrt... I wonder if that's feasable with the limited space.
Finding the angle between two points requires arctan. This would be of use for example if someone had a (radial) robot arm on a wall and wanted to read a user with a line of sonar sensors on the wall. Maybe the example isn't that great because the resolution along the wall would be so crude, because you'd go through your budget fast at $25 a pop every four inches. (and a rude lookup table would work) but you get the idea.
The pow function is useful for generating things like gamma curves for mapping brightness of one device onto another. I used a sin function to dim some LED's up and down on a project but there are many other ways it could work.
I really think that math.h is the way to go though. The Atmega8 chips don't really have any reason to stay around because they're just as expensive as the 168's.