Arduino Forum

Development => Suggestions for the Arduino Project => Topic started by: kibergus on Dec 23, 2011, 07:06 pm

Title: min, max, abs.. are macroses?
Post by: kibergus on Dec 23, 2011, 07:06 pm
Why on the earth these functions are defined as macros:

Code: [Select]
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
//#define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))


This is dangerous and leads to strange behavior when you supply calculated values to these functions because values are calculated twice. They definitely must be rewritten as inline functions. This would make them much more robust and much faster.

I can write appropriate patch if you want.


Moderator edit: [code] [/code] tags added.
Title: Re: min, max, abs.. are macroses?
Post by: kibergus on Dec 23, 2011, 08:29 pm
I understand, that it is not possible to write in ANSI C, but current implementation do not conform to C99 or C89 because abs must be a function. And these macro prevent form defining good overloaded functions from C++ std:: namespace.
And I'm sure that these macroses do much more harm than good: they behave differently than functions with the same names on other platforms. They look like functions but the do not work like functions. It means that someone not familiar to arduino is unable to read/write programs with these macroses.
Title: Re: min, max, abs.. are macroses? WTF
Post by: Jantje on Dec 23, 2011, 09:18 pm
kirbergus
I don't mind a good discussion but please watch your language. Definitely if you make statements which are not solid.
1) your language:
It is not macroses but macros
You do not use WTF. Definitely not in a title.
2) the "must be a function"
The C89 standard you refer to is more commonly known as ANSI C. ANSI C was officially released in 1989. I have been programming in C from 1991 till 2000 for my living. In all those years I used a define for max. It is new to me that this must be a function. If you are sure that ANSI C  states that max must be a function please tell me where this is stated.
The C99 is the newest version of C. The compiler used by the Arduino team is (like most other C compilers) not 100% compliant with C99. As far as I know there is no statement that max must be a function. Please state where it states min max and abs  must be functions. Also refer to where it states all C compilers must comply to C99.
3) No macros but Inline
You state that these macros must be rewritten as inline. Inline is new in C99. It comes from C++. Inline is class related and on a AVR you do not want to have classes for something as basic as integers.
4) why a macro?
A macro has a great advantage. That is, it works with any type that implements the methods you use. So you do not need a maxint maxlong maxstring.....
5) You are right there is a risk with macros
On the content you are right that
Code: [Select]
MyNumber=5;
max(++MyNumber);
will result in MyNumber being 7 and not 6;  This is however a design decision that has been taken a long time ago on very good ground by people that didn't know about Arduino because it simply didn't exist yet. So blaming Arduino is not the way to go. It has been like this for decades now. I feel no sense of urgency.
6) overloaded functions from C++ std
I see no reason why you could not overload. You can use the #undef instructions if you want.

My advice: before you post again read this article:http://www.catb.org/~esr/faqs/smart-questions.html (http://www.catb.org/~esr/faqs/smart-questions.html)
If you do not comply to these rules I will no longer respond on your posts.
Best regards
Jantje
Title: Re: min, max, abs.. are macroses? WTF
Post by: kibergus on Dec 23, 2011, 11:06 pm

kirbergus
I don't mind a good discussion but please watch your language. Definitely if you make statements which are not solid.
1) your language:
It is not macroses but macros
You do not use WTF. Definitely not in a title.

Thanks. I was a little bit upset that I have to reinvent standard library. I've corrected errors.

2) the "must be a function"
The C89 standard you refer to is more commonly known as ANSI C. ANSI C was officially released in 1989. I have been programming in C from 1991 till 2000 for my living. In all those years I used a define for max. It is new to me that this must be a function. If you are sure that ANSI C  states that max must be a function please tell me where this is stated.
The C99 is the newest version of C. The compiler used by the Arduino team is (like most other C compilers) not 100% compliant with C99. As far as I know there is no statement that max must be a function. Please state where it states min max and abs  must be functions. Also refer to where it states all C compilers must comply to C99.

I didn't want to say that max must be a function accordingly to standard. Only abs must, in ANSI C too. I wanted to say that today in 2011, nearly in 2012 there is no need to put user right at the edge of a pit, even if you warn him. Look at this macro:

define sq(x) ((x)*(x))

It squares a variable. Why you would ever like to use it? If you have a single variable x it is easier and shorter to write x*x. But if you have a big statement which you would like to square it is very handy just to put it inside sq(). If sq was a function it would be computationally efficient too.
So if you see that using sq()would ease your life you nearly definitely going to make a mistake. This macro pushes user to a wrong way.

3) No macros but Inline
You state that these macros must be rewritten as inline. Inline is new in C99. It comes from C++. Inline is class related and on a AVR you do not want to have classes for something as basic as integers.

inline has nothing with classes. inline is just a hint for compiler that you would like to inline the function, nothing more. Using inlined function for integer does not convert them to classes.

4) why a macro?
A macro has a great advantage. That is, it works with any type that implements the methods you use. So you do not need a maxint maxlong maxstring.....

Actually this macro works only with different types of integers, float, double, pointers which can be implicitly converted to void*. If you have operator< defined for other type you are already using C++ and you can use templates which are much better then macro in this situation.

5) You are right there is a risk with macros
On the content you are right that
Code: [Select]
MyNumber=5;
max(++MyNumber);
will result in MyNumber being 7 and not 6;  This is however a design decision that has been taken a long time ago on very good ground by people that didn't know about Arduino because it simply didn't exist yet. So blaming Arduino is not the way to go. It has been like this for decades now. I feel no sense of urgency.

If you look at main arduino.cc page you ca read "It's intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments". Time has changed, programming languages has changed.This design decision was made "a long time ago on very good " old ground. Artists, designers, hobbyists do not need carefully documented well known rakes. 20 years ago it was the best solution but now we have more fool proof programming technologies. Which are still as efficient as old ones. They can be even more efficient in some cases.

6) overloaded functions from C++ std
I see no reason why you could not overload. You can use the #undef instructions if you want.

Thanks for the hint. I've did it for my building environment.
Title: Re: min, max, abs.. are macroses? WTF
Post by: bperrybap on Dec 26, 2011, 05:47 am

4) why a macro?
A macro has a great advantage. That is, it works with any type that implements the methods you use. So you do not need a maxint maxlong maxstring.....


But macros also can have issues and create some intended consequences that functions do not.

Consider this example:

Code: [Select]
bar = sq(foo++);

How much is foo incremented?
foo is incremented twice when sq() is a macro and if it is a function then it is incremented only once
as most people would probably expect.

Other unexpected things happen if the data is not a simple variable type and is a function.
Consider this example:

Code: [Select]

bar = abs(foo());


The function foo() will be called multiple times if abs() is a macro vs only once if it is a function.
If foo() has the potential to return different values on each call, then the results become unpredictable.
When abs() is a macro, consider the case when the first call to foo() returns a negative value and
the second time it returns  a positive value.
In this case the final result from abs() will be negative which nobody would expect from an abs() "function".

So there is a functional difference that can create non obvious issues when these "functions" are
implemented as macros vs real functions.

--- bill

Title: Re: min, max, abs.. are macroses?
Post by: maniacbug on Dec 26, 2011, 02:12 pm
Yah, I agree with the OP.  Macros like these should have gone out with bell-bottoms. They conflict with the ::abs and friends definitions, and they lead to unexpected side-effects.  Yes we could work around it with #undefs.  You can work around many problems, that doesn't make it NOT a problem.
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Dec 27, 2011, 12:45 am

If they are not macros, how should they be implemented?  Templates?  Inline-functions?
Title: Re: min, max, abs.. are macroses?
Post by: maniacbug on Dec 27, 2011, 01:13 am

If they are not macros, how should they be implemented?  Templates?  Inline-functions?


The idea is to get them out of the pre-processor and into the compiler.  So the basic answer to that question is "anything parsed by the compiler".

A classic implementation is this:
Code: [Select]

template<typename T>
  const T&
  max(const T& a, const T& b)
  { return (a > b) ? a : b; }


This has the interesting side effect of requiring the types to be identical, which safeguards against accidentally comparing disparate types, which gives the compiler permission to get funky on your types (er, I mean, implicitly convert them on you), which can lead to unpredictable results.  If that's overly pedantic, max() can be declared with two types, in which case it will behave more like normal.

Leaving it in the pre-processor means you rob files from defining it another namespace, or even as a method in a class! 

Try compiling this:

Code: [Select]

class wtf
{
  int max(void)
  {
    return 1;
  }
};

void setup(void)
{
  wtf w;
  Serial.print(w.max());
}


You get this helpful error...

Code: [Select]

sketch_dec26a.cpp:6:15: error: macro "max" requires 2 arguments, but only 1 given
sketch_dec26a.cpp:15:22: error: macro "max" requires 2 arguments, but only 1 given
sketch_dec26a:2: error: function definition does not declare parameters
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Dec 27, 2011, 03:46 am

The risk is that existing C source files will no longer compile.  But, as far as I can tell, nothing in the core is effected and none of the libraries available from this tool are effected...

http://arduino.cc/forum/index.php/topic,63215.0.html

Any other C source files to worry about?
Title: Re: min, max, abs.. are macroses?
Post by: kibergus on Dec 29, 2011, 07:05 pm
This is what I currently use in my project. Including this file from C++ source would result in undefining macros and defining appropriate templates. Including from C source should have no effect because of macro guards.
It uses some C++11 features so -std=gnu++0x flag should be passed to gcc. It also calls gcc specific abs realizations for floating point types so it is not possible to use this with compiler other than gcc.
I've also defined new and delete operators. As far as I understand they are already defined in latest arduino. So you may need to remove them to compile your project.

P.S. Using it shouldn't have any impact on program size or speed if you are using macros only with single variables.
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Dec 29, 2011, 08:26 pm

No round?  Did you exclude it on purpose?


You allow the parameters to be different types.  You're not concerned about the possibility of implicit type-conversions?


Quote
It uses some C++11 features so -std=gnu++0x flag should be passed to gcc.


I suspect that will not happen.


Quote
P.S. Using it shouldn't have any impact on program size or speed if you are using macros only with single variables.


In my testing it does.  In some cases this...

Code: [Select]
template <class T> const T& minT ( const T& a, const T& b )
{
  return( (a<b) ? a : b );
}


Produces less code the the min macro.
Title: Re: min, max, abs.. are macroses?
Post by: kibergus on Dec 29, 2011, 09:51 pm

No round?  Did you exclude it on purpose?

In my version of arduino library round is commented out:
Code: [Select]

//#define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

So I didn't include it.

You allow the parameters to be different types.  You're not concerned about the possibility of implicit type-conversions?

Right. That's how it is done in gcc's library:
Code: [Select]

  template<typename _Tp>
    inline const _Tp&
    max(const _Tp& __a, const _Tp& __b)
    {
      // concept requirements
      __glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
      //return  __a < __b ? __b : __a;
      if (__a < __b)
return __b;
      return __a;
    }

So I think C++ standard allows to have different types here. At first version I didn't allow to have different types but I've got weird errors nearly identical types. Default C++ types have quite logical type conversion rules and class constructors in most cases should be defined as explicit so as to prohibit implicit type conversions. So if your classes are well written you should not be aware of implicit type conversions much.

Quote
It uses some C++11 features so -std=gnu++0x flag should be passed to gcc.


I suspect that will not happen.

C++11 is cool. Using it for my project allows me to spend less time and write more readable code. And I really need it for implementing good mixin design patterns. If you use makefiles you can add compiler flag easily. I do use makefiles because I'm used to vim.

I think, that you can find C++99 compliant solutions here:
https://github.com/maniacbug/StandardCplusplus
or here:
http://andybrown.me.uk/ws/2011/01/15/the-standard-template-library-stl-for-avr-with-c-streams/
But unfortunately I didn't succeeded in compiling these libraries today.

Quote
P.S. Using it shouldn't have any impact on program size or speed if you are using macros only with single variables.

In my testing it does.  In some cases this...
Code: [Select]
template <class T> const T& minT ( const T& a, const T& b )
{
  return( (a<b) ? a : b );
}

Produces less code the the min macro.

Well, it shouldn't if you pass single variable to macro which is an advised way to use macro. And it easily can be faster and consume less memory if you pass expressions in-to macro.
Title: Re: min, max, abs.. are macroses?
Post by: PatrickPijnappel on Jan 02, 2012, 12:56 pm
I personally just yesterday ran into the problems mentioned above.

Code: [Select]
int value = constrain(Serial.readByte(), 0, 5);

Anyway, I would just add that:
a) I am strongly in favor of replacing these macros by something better, if at all feasible.
b) If they end up not being replaced, I would at least suggest that they are properly documented and warned about in the reference. I had to look in the source files to find out.
Title: Re: min, max, abs.. are macroses?
Post by: bperrybap on Jan 02, 2012, 07:53 pm
The real problem with the macros isn't that they are macros but that they are too simplistic.
gcc provides a way to declare and use locals as well as extract the data types of
the arguments to declare the locals inside the macros.

This only works for gcc as it is a gcc extension.
Does anybody use anything else...  :)

But it provides a very simple way to create macros that work properly and
will work for both C and C++

So for example this is better definition of max() that is still a macro:
Code: [Select]

#define max(a,b) \
       ({ typeof (a) _a = (a); \
           typeof (b) _b = (b); \
         _a > _b ? _a : _b; })


And a few others:
Code: [Select]

#define min(a,b) \
       ({ typeof (a) _a = (a); \
           typeof (b) _b = (b); \
         _a < _b ? _a : _b; })

Code: [Select]

#define abs(x) \
       ({ typeof (x) _x = (x); \
          _x > 0 ? _x : -_x; })

Although I would probabaly want to take a closer look at abs() to see if it is better to use >= vs >
i.e. does -0 create some problems?

etc...
So this could also easy be used for constrain() and round()

For my C entrenched brain it seems a whole lot easier than all the
template and class foo.

--- bill
Title: Re: min, max, abs.. are macroses?
Post by: pYro_65 on Jan 03, 2012, 07:31 am
that looks like a good fix, but IMO it is more obfuscated than a direct template.

As an object orientated programmer, templates are a natural choice.

Leaving bugs in software and expecting novice's to know the in's and out's of #define's is quite silly. since this thread stated there have been a number of threads with confused posters as to why an operation is done multiple times and undocumented when using arduino core functionality.

People having to learn the basics of templates is far more beneficial than, rare case #define logic

Title: Re: min, max, abs.. are macroses?
Post by: westfw on Jan 03, 2012, 08:06 am
Quote
having to learn the basics of templates

I personally would prefer that Arduino NOT become overly full of C++isms.
Title: Re: min, max, abs.. are macroses?
Post by: pYro_65 on Jan 03, 2012, 08:21 am
The only difference to an end user is calling functions where parameters go in '<>' rather than '()', This is incredibly simple even for a novice.

I don't see how the bugs imposed on #defines are a trade off for secure guaranteed execution of a well defined template.
This would save mass amounts of headaches.

C is great but C++ is better*



*this is my own opinion, Moved from C to C++ and never looked back.
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Jan 03, 2012, 08:26 am
Quote
This only works for gcc as it is a gcc extension. Does anybody use anything else...


Good question.  The Arduino folks are trying to add support for more processor types (like ARM).  There is a possibility that a non-GCC compiler may come into play.
Title: Re: min, max, abs.. are macroses?
Post by: bperrybap on Jan 03, 2012, 08:40 am


I don't see how the bugs imposed on #defines are a trade off for secure guaranteed execution of a well defined template.
This would save mass amounts of headaches.


I believe that a final solution needs to work for both C and C++

There are no "bugs imposed on #defines"
The existing bugs in the min/max/abs() macros are there because the implementation is too simplistic
and silently generates unintended code.
It is no different than having a bug in your  main line code.
The solution is to simply fix the code.
These simplistic macros started showing up in the early to mid 80s and I've hated them
ever since. They go back to the days before there was much optimization, before function prototypes
and even inline functions and were an attempt to generate faster code.

About macros in general:
there are some things that you can do with macros that cannot be done in any other way.

--- bill
Title: Re: min, max, abs.. are macroses?
Post by: pYro_65 on Jan 03, 2012, 08:54 am
Technically unexpected behaviour is a bug.
Documentation specifying the 'unexpected behaviour' makes it an 'undefined behaviour' and explicitly leaves it to the programmer to investigate, this however is not the case.

Vastly different to having an explicitly defined error in your own code.

However I agree, the solution needs to be workable in C & C++.

that is as easy as a #ifdef  for the C++ define, which leaves reason to provide a safer version when possible.
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Jan 03, 2012, 08:57 am
Quote
However I agree, the solution needs to be workable in C...


Why does the solution need to work in C ?
Title: Re: min, max, abs.. are macroses?
Post by: pYro_65 on Jan 03, 2012, 09:04 am
Quote
Why does the solution need to work in C ?


Haha, it doesn't. GCC is capable of both. I'm only trying to conform to the masses that do not want to migrate to C++

My main point at this stage is whatever comes out of this, the macros as is now should be rolled up and smoked. I would prefer using long winded template meta programming for replacing everything 'macro' that inline functions cannot do, but I assume this would receive negative responses too.
Title: Re: min, max, abs.. are macroses?
Post by: bperrybap on Jan 03, 2012, 09:07 am

Quote
This only works for gcc as it is a gcc extension. Does anybody use anything else...


Good question.  The Arduino folks are trying to add support for more processor types (like ARM).  There is a possibility that a non-GCC compiler may come into play.



Really? What other no cost ARM compiler is out there
that works as well as gcc? Is there one?
Title: Re: min, max, abs.. are macroses?
Post by: bperrybap on Jan 03, 2012, 09:19 am

Technically unexpected behaviour is a bug.
Documentation specifying the 'unexpected behaviour' makes it an 'undefined behaviour' and explicitly leaves it to the programmer to investigate, this however is not the case.

Vastly different to having an explicitly defined error in your own code.

However I agree, the solution needs to be workable in C & C++.

that is as easy as a #ifdef  for the C++ define, which leaves reason to provide a safer version when possible.


The C language has alot of unexpected behaviors that do not qualify as bugs as there
are many folks that are not intimately familiar with many of the low level details around
precedence, char type handling and promotion.

In this case I did say it was a bug.
No different than a math library generating an incorrect sine value or floating point calculation.
The bug just happens to be in system supplied code rather than a users code.

There is no need to punish the C code in favor of C++ when looking for solutions
especially when, as I've shown, it is possible to write better macros that work
properly for both C and C++


--- bill

Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Jan 03, 2012, 09:20 am

@bperrybap:  Are you claiming that the Arduino folks, for the foreseeable future, will only be using GCC?
Title: Re: min, max, abs.. are macroses?
Post by: pYro_65 on Jan 03, 2012, 09:40 am
I also have not seen any modern free optimising compilers that do not support C++ apart from non standard implementations. I'm sure they exist, but are their optimisations worth a grain of salt.
Title: Re: min, max, abs.. are macroses?
Post by: bperrybap on Jan 03, 2012, 09:44 am


@bperrybap:  Are you claiming that the Arduino folks, for the foreseeable future, will only be using GCC?



No. I have no information either way.

But given the low cost availability and realibility of gcc for so many different platforms including
ARM, it seemed like a natural fit.

I also read a thread over on the diydrones site about ardupilot from back in Sep 2011.
There was some Arduino and Atmel bashing going on.
Massimo Banzi made a comment about having an ARM environment with gdb up and working with a new IDE
prototype.

http://diydrones.com/profiles/blogs/arm-arduino-coming?id=705844%3ABlogPost%3A645017&page=4#comments (http://diydrones.com/profiles/blogs/arm-arduino-coming?id=705844%3ABlogPost%3A645017&page=4#comments)

Seems to at least "smell" like gcc is going to be solution for the foreseeable future.

--- bill
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Jan 12, 2012, 09:18 am
I believe that a final solution needs to work for both C and C++


Why for C?
Title: Re: min, max, abs.. are macroses?
Post by: bperrybap on Jan 12, 2012, 09:48 am

I believe that a final solution needs to work for both C and C++


Why for C?



Why create a C++ only solution?

Not everything in Arduino is C++
There is core code that is C and there are some libraries that use C++ wrappers on top of C code.


Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Jan 12, 2012, 09:57 am
Why create a C++ only solution?


At this point, there is no reason not to.


Quote
Not everything in Arduino is C++ ... There is core code that is C


The list is short...
  WInterrupts.c
  wiring.c
  wiring_analog.c
  wiring_digital.c
  wiring_pulse.c
  wiring_shift.c

Quote
and there are some libraries that use C++ wrappers on top of C code.


The list is even shorter...
  twi.c


None of those modules use the macros in question.


Why does the solution need to work for C?
Title: Re: min, max, abs.. are macroses?
Post by: bperrybap on Jan 13, 2012, 12:35 am
While the code that is provided by the Arduino development environment,
(core code and libraries), does not have any C code that currently uses these macros

At this point, there is no reason not to.

seems to a bit of an overstatement with respect to creating a C++ only solution.

Quote

Why does the solution need to work for C?


So that it can be finally be put to bed rather than having to revisit this again
in the future when something in a C module "breaks".
Maybe it is a 3rd party library, or heaven forbid some
new C code in say the Due C core code wants/needs to use these type of macros.

IMHO, this kind of stuff really should be done by the compiler and LibC people rather than being done
in individual projects.

Of course, another approach, which would carry on in the seemingly odd, IMHO, Arduino/Wiring Language
"Re-Inventing the Wheel Syndrome", would be to create new Class/Macro/Template "functions"
with names like Min(), Max(), Abs(), Constrain(), and Round() that do what the old functions/macros
did.

But even if you do that, you still need to fix the existing min()/max() ... macros.

--- bill
Title: Re: min, max, abs.. are macroses?
Post by: maniacbug on Jan 13, 2012, 06:45 am

But even if you do that, you still need to fix the existing min()/max() ... macros.


Simple solution would be to wrap the old-school stuff in the #else of #ifdef __cplusplus.  That way, the modern folks can have a well-behaved compiler-driven solution, and people who for some reason like C *and* Arduino, can have something that works.

Moreover, the focus in Arduino is folks who are new to all this.  These folks will not need C, and they are more likely to be tripped up by accidentally using 'max' somewhere in their code and getting arcane error messages.  I think it's fair to say that anyone using C on Arduino knows what they're doing, and can pull in a C implementation of min/max without any problem.
Title: Re: min, max, abs.. are macroses?
Post by: westfw on Jan 13, 2012, 09:51 pm
I guess the chief danger is that a user's Arduino habits would suddenly cause them to write non-working code in a C environment.  A C++ only solution would cause C++ to behave differently than C (silently.  Invisibly.)

Quote
this kind of stuff really should be done by the compiler and LibC people

Agreed.  It looks as though "abs" has already been handled by the compiler.

Quote
"The ISO C90 functions abs, cos, exp, fabs, fprintf, fputs, labs, log, memcmp, memcpy, memset, printf, putchar, puts, scanf, sin, snprintf, sprintf, sqrt, sscanf, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp, strncpy, strpbrk, strrchr, strspn, strstr, vprintf and vsprintf are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function). All of these functions have corresponding versions prefixed with __builtin_."

http://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Other-Builtins.html
Title: Re: min, max, abs.. are macroses?
Post by: Jantje on Jan 15, 2012, 12:59 am
maniacbug
Quote
Simple solution would be to wrap the old-school stuff in the #else of #ifdef __cplusplus.  That way, the modern folks can have a well-behaved compiler-driven solution, and people who for some reason like C *and* Arduino, can have something that works.

I agree this is a solution. I would like to share this thought:
This solution will create situations where code works  in one situation and it doesn't in another. Newbies will not realize they moved their code from C++ to C (or the other way around) and will be completely puzzled. At that point in time there will only be a very small number of people who still know macro behavior and the specific Arduino implementation.
And then I ask myself (without implying an answer) What is worse? A commonly known drawback with little consequences or a rare unknown drawback with little consequences?

Best regards
Jantje
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on May 28, 2012, 07:52 am

The code in Reply #7 (http://arduino.cc/forum/index.php/topic,84364.msg634416.html#msg634416) is out.  It requires both parameters to be the same datatype.  New users have enough problems with datatypes.  Forcing them to learn typecasting makes the pain even worse.

The code in Reply #9 (http://arduino.cc/forum/index.php/topic,84364.msg636881.html#msg636881) is out.  It does not compile with the GCC version that ships with Arduino nor with the latest WinAVR.

The code in Reply #11 (http://arduino.cc/forum/index.php/topic,84364.msg637001.html#msg637001) has the same problem as the code in Reply #7.  

Which leaves the macro in Reply #13 (http://arduino.cc/forum/index.php/topic,84364.msg640438.html#msg640438) and inline functions.  abs works very nicely as an inline function.  min and max not so much (too many combinations).  At this point, the only one left standing is the macro in reply #13.


A few points of interest: The code generation varies a bit and is not consistent.  Sometimes the "old" macro produces slightly better code.  Sometimes the template does.  Sometimes the "new" macro does.  Basically, all the solutions have at least one code generation quirk.  The random function appears to include an exception handler stack frame for some reason (lots of unnecessary code).  The round macro fails to work correctly for values past ±8388609.  The GCC / Libc round function works correctly.
Title: Re: min, max, abs.. are macroses?
Post by: odometer on May 28, 2012, 09:15 am
If you don't mind my asking:

Why are these macros defined at all?
Isn't it more difficult to have to remember the "gotchas" of working with macros than it is to write your own code for these things when you need it?
We're not talking about anything fancy here. I mean, how hard is it to write something like this? x = (y>=0?y:-y);

As for squaring, is there any reason for the compiler not to handle y = pow(x,2) by using the obvious optimization?
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on May 28, 2012, 09:58 am

There is no point contemplating why they exist.  There is a non-zero number of users who have used them so they cannot be removed.
Title: Re: min, max, abs.. are macroses?
Post by: maniacbug on May 29, 2012, 12:01 am
And if they annoy you, you can always #undef them out so they don't annoy again.
Title: Re: min, max, abs.. are macroses?
Post by: kf2qd on Jun 01, 2012, 05:55 pm
A problem with implementing them as a function is STACK USAGE - Will they use more stack space (only 2K RAM, remember?) as a function or as a macro?

Stack is much more limited than is program memory. While it might be good to optimize for FLASH usage, you must not forget limited RAM.
Title: Re: min, max, abs.. are macroses?
Post by: Coding Badly on Jun 02, 2012, 12:36 am
A problem with implementing them as a function is STACK USAGE - Will they use more stack space (only 2K RAM, remember?) as a function or as a macro?


For normal# functions with a few bytes of parameters (like min(int,int)) only the return address is pushed on the stack (two bytes).  The parameters are passed in registers.

For inline functions the code is inserted at the call-point so not even the return address is pushed.

Quote
Stack is much more limited than is program memory. While it might be good to optimize for FLASH usage, you must not forget limited RAM.


In terms of SRAM usage, there is essentially no difference in the choices discussed here.  The optimizer occasionally makes a minor mistake leading to one or two bytes unnecessarily being pushed but that behaviour seems to be independent of the implementation.


# As opposed to inline functions.
Title: Re: min, max, abs.. are macroses?
Post by: pYro_65 on Jun 02, 2012, 05:01 am
I don't see a real problem with using the macros I just wish the reference would say they are macros and also have an example of how the usage may fail so people can avoid it without having in-depth c/c++ knowledge.

The biggest drawback of these macros is the inability to use those macro names in your own code. A range class for example would benefit from members named min & max over something like LowVal and HighVal for example.
Title: Re: min, max, abs.. are macroses?
Post by: kf2qd on Jun 04, 2012, 05:30 pm


The biggest drawback of these macros is the inability to use those macro names in your own code. A range class for example would benefit from members named min & max over something like LowVal and HighVal for example.


That's a problem with any language except for Forth. Reserved keywords and such are an issue with any language. Only Forth allows you to redefine a WORD without damaging the code that used the old version.