Pages: [1]   Go Down
Author Topic: the map() function  (Read 854 times)
0 Members and 1 Guest are viewing this topic.
Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 819
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all,

I wonder... why is the map() function setup to use long ints?

I hacked mine (changed all the longs to floats) and it works the same.... except that it also now produces fractional results when necessary. Why would it be written with such a limitation?

In case anyone is interested is using this, edit the following files:

arduino-1.x.x/hardware/arduino/cores/arduino/WMath.cpp

Near the bottom, replace the map function with this code:

Code:
float map(float x, float x1, float x2, float y1, float y2)
{
  return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
}

Next, edit the file arduino-1.x.x/hardware/arduino/cores/arduino/Arduino.h (to change the header for map()):

Again, near the bottom, replace the declaration for map() with this code:

Code:
float map(float, float, float, float, float);

That's it. Now, map() will return exact values instead of values truncated to integers.

Or... if you're afraid to modify "stock" code, you can just ADD the code above and give it a different name such as "fmap()"...
« Last Edit: November 28, 2012, 09:56:24 pm by Krupski » Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13085
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Thank you for the post.

Why would it be written with such a limitation?

Bear in mind the memory limitations of the original Arduino.
Logged

Left Coast, CA (USA)
Online Online
Brattain Member
*****
Karma: 362
Posts: 17308
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Thank you for the post.

Why would it be written with such a limitation?

Bear in mind the memory limitations of the original Arduino.


And the speed penalty of using floating point math if integer math can do the job required. So yes to and thank you for the fmap() function, but it should never replace the existing map() function.

Lefty
Logged

Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 819
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Thank you for the post.

Why would it be written with such a limitation?

Bear in mind the memory limitations of the original Arduino.


And the speed penalty of using floating point math if integer math can do the job required. So yes to and thank you for the fmap() function, but it should never replace the existing map() function.

Lefty

I know... "speed penalty"... "code size penalty".... but have you ever written a program that just barely squeaked into the available memory? I haven't... and I've written a LOT of stuff in C and assembler (68HC11 assembler).

Have you ever had a program slow to a crawl because it had a floating point number in it? I have not.

I know "speed" and "code size" are stock arguments, but is there any reality to them?

I think the ONLY time that I ever explicitly used integer math in a function was implementing a special version of Bresenham's line draw algorithm (I modified it to generate points in the same direction as they are specified, rather than always from bottom to top or vice-versa). Since I needed to calculate many X-Y points in runtime, I used integers.

Other than that, I really don't care if my code takes a few more clock cycles to run.
Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13085
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

but have you ever written a program that just barely squeaked into the available memory?

Yes.  Several.  Going back to the 80386 processor.

I have an Arduino program that requires marking setup and loop with noreturn so it will fit.  It literal consumes every last byte of Flash.

That's kind of the point.  To get as much work as possible out of a hardware investment.

Quote
Have you ever had a program slow to a crawl because it had a floating point number in it?

Yes.

But the bigger issue with floating-point on AVR processors is the additional code from the emulation library.

Quote
I know "speed" and "code size" are stock arguments, but is there any reality to them?

There is for me.
Logged

Left Coast, CA (USA)
Online Online
Brattain Member
*****
Karma: 362
Posts: 17308
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I know "speed" and "code size" are stock arguments, but is there any reality to them?

Certainly at time there is. Say when writing a ISR function where you need to make the interrupt take as little time as possible so as not to possibly miss any other interrupts until my ISR completes and re-enables interrupts.

 The point is not that a fmap() function is not useful, just that it should never lead to the elimination of the exiting integer map() function, especially on a 8 bit microcontroller. There is room for both functions to exist. Which by the way, not being a C++ expert by any means, isn't there a way for a function to be written in C++ where it will work correctly no matter what variable type you call it with (or even variable number of arguments passed)? I seem to recall that such a C++ function would 'mangle' it's name into separate functions to handle each different argument case? Sounds like magic to me, I'll stick to as close to simple C as I can, thank you.  smiley-wink

Lefty
Logged

France
Offline Offline
Edison Member
*
Karma: 38
Posts: 1012
Scientia potentia est.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes just make a copy of it:

Code:
int map(int x, int x1, int x2, int y1, int y2)
{
  return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
}

float map(float x, float x1, float x2, float y1, float y2)
{
  return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
}

Or, maybe easier...
Code:
template <typename T> T map(T x, T x1, T x2, T y1, T y2);
template <typename T> T map(T x, T x1, T x2, T y1, T y2)
{
  return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
}

I just started learning about templates and overloaded functions, they are cool smiley-grin...But typeless languages are even better!
« Last Edit: November 29, 2012, 02:37:02 am by guix » Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
isn't there a way for a function to be written in C++ where it will work correctly no matter what variable type you call it with (or even variable number of arguments passed)?

Yeah it's called function overload. If you think about it, what does identify a function ? Not only its name, but its argument list too, both type and number of them. So if you write two functions with the same name but different argument list the compiler can select the correct one based on the actual parameters (i.e. the parameter list you specify when you call the function).

Look a Print::print() and Print::println() in hardware/arduino/cores/arduino.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 228
Posts: 14053
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
isn't there a way for a function to be written in C++ where it will work correctly no matter what variable type you call it with (or even variable number of arguments passed)?

Yeah it's called function overload.

or use a macro ?

#define map(x, x1, y1, x2, y2)  ( ( (x) - (x1) ) * ( (y2) - (y1) ) / ( (x2) - (x1) ) + (y1) )

but be aware macros can have side effects...
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Since abandoning #define NAMED_CONSTANT literal in favor of const datatype NAMED_CONSTANT = literal I tend to avoid macros whenever possibile. I like to give the compiler as much hints as possible about what my code actually means, to help it catch as many errors as possible.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 228
Posts: 14053
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I like to give the compiler as much hints as possible about what my code actually means
important point
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: