I have the following define macros:
#define NHID 5
#define NENT 10
#define NOUT 4
#define NWEIS (NENT + 1) * NHID + (NHID + 1) * NOUT
So everytime that the compiler finds a "NWEIS", it will replace "NEWIS" for "(NENT + 1) * NHID + (NHID + 1) * NOUT". But that is not what I want. I want it replace "NWEIS" by the actual value = 79, without having to declare extra variables in the memory. Is there a decent way to do this?
Macro replacement is mostly1 an iterative process.
What you will get, following macro substitution is an expression with the constants. And any decent compiler will be able to fold those constants (evaluate them at compile time) to give you the single value of 79.
For example, consider the program:
#define NHID 5
#define NENT 10
#define NOUT 4
#define NWEIS (NENT + 1) * NHID + (NHID + 1) * NOUT
int main (void) { return NWEIS; }
here's the pre-processor output from gcc -E:
int main (void) { return (10 + 1) * 5 + (5 + 1) * 4; }
and here's the relevant assembler code line it generates with gcc -S (the return value is placed into the eax register):
movl $79, %eax
Having said that, there are precious few reasons to use macros any more since you have constant "variables", inline suggestions to the compiler, enumerated types and so forth, all things that macros used to be very useful for.
I still find myself reaching for macros for quick'n'dirty code of course, but that's mostly because I'm an old codger, forged in the early C days before we even had prototypes :-)
It may be worthwhile rethinking your use of them as well, since you can replace it with something like:
const int nhid = 5;
const int nent = 10;
const int nout = 4;
const int nweis = (nent + 1) * nhid + (nhid + 1) * nout;
A smart compiler should still be able to optimise the calculations away at compile time and you'll most likely find that the variables are available in the debugger for you, something that often doesn't happen with macros.
1 Full details can be found in the C++11 standard, section 16.3 Macro replacement.
Suffice to say there are certain uses of # and ## within a macro that prevent further replacement of that token (the former replaces the token with a character string literal and the latter combines multiple tokens into a different token).
Since you're not using those, it's irrelevant here.
The macros you are using do not cost you extra memory. You have already acheived what you want.
Let's look at what a reasonable compiler will do.
Suppose you have this code.
#define NHID 5
#define NENT 10
#define NOUT 4
#define NWEIS (NENT + 1) * NHID + (NHID + 1) * NOUT
int f()
{
return NWEIS;
}
A reasonable compiler will obviously expand it into:
int f()
{
return (NENT + 1) * NHID + (NHID + 1) * NOUT;
}
The next step will than be:
int f()
{
return (10 + 1) * 5 + (5 + 1) * 4;
}
As this arithmetic expression consist of hard-coded numbers (constant expression) only, the compiler can treat the whole thing as a constant too.
int f()
{
return 79;
}
Note that this function is so small, a reasonable compiler will try its best to in-line the function.
However, it is much more preferable to do this:
constexpr int NHID = 5;
constexpr int NENT = 10;
constexpr int NOUT = 4;
constexpr int NWEIS = (NENT + 1) * NHID + (NHID + 1) * NOUT;
Just use
const int NHID = 5;
const int NENT 10;
const int NOUT 4;
const int NWEIS = (NENT + 1) * NHID + (NHID + 1) * NOUT;
A good optimizer will substitute these values at compile-time and not place any variables in memory, unless you do something such as take their address. Then you have the type safety and scoping of C++ without the macro evilness.
(Upper case names are by convention reserved for macros, so you may want to rename them slightly)
Related
I'm using a C++ compiler but writing code in C (if that helps)
There's a series of numbers
(-1^(a-1)/2a-1)B^(2a-1)
A and X are user defined... A must be positive, but X can be anything (+,-)...
to decode this sequence... I need use exponents/powers, but was given some restrictions... I can't make another function, use recursion, or pow() (among other advanced math functions that come with cmath or math.h).
There were plenty of similar questions, but many answers have used functions and recursion which aren't directly relevant to this question.
This is the code that works perfectly with pow(), I spent a lot of time trying to modify it to replace pow() with my own code, but nothing seems to be working... mainly getting wrong results. X and J are user inputted variables
for (int i = 1; i < j; i++)
sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
}
You can use macros to get away with no function calls restriction as macros will generate inline code which is technically not a function call
however in case of more complex operations macro can not have return value so you need to use some local variable for the result (in case of more than single expression) like:
int ret;
#define my_pow_notemp(a,b) (b==0)?1:(b==1)?a:(b==2)?a*a:(b==3)?a*a*a:0
#define my_pow(a,b)\
{\
ret=1;\
if (int(b& 1)) ret*=a;\
if (int(b& 2)) ret*=a*a;\
if (int(b& 4)) ret*=a*a*a*a;\
if (int(b& 8)) ret*=a*a*a*a*a*a*a*a;\
if (int(b&16)) ret*=a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a;\
if (int(b&32)) ret*=a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a;\
}
void main()
{
int a=2,b=3,c;
c=my_pow_notemp(a,b); // c = a^b
my_pow(a,b); c = ret; // c = a^b
}
as you can see you can use my_pow_notemp directly but the code is hardcoded so only up to a^3 if you want more you have to add it to code. The my_pow is accepting exponents up to a^63 and its also an example on how to return value in case of more complex code inside macro. Here are some (normal) ways on how to compute powers in case you need non integer or negative exponents (but to convert it to unrolled code will be insanely hard without loops/recursion):
Power by squaring for negative exponents
In case you want to get away with recursion and function calls you can use templates instead of macros but that is limited to C++.
template<class T> T my_pow(T a,T b)
{
if (b==0) return 1;
if (b==1) return a;
return a*my_pow(a,b-1);
}
void main()
{
int a=2,b=3,c;
c=my_pow(a,b);
}
As you can see templates have return value so no problem even with more complex code (more than single expression).
To avoid loops you can use LUT tables
int my_pow[4][4]=
{
{1,0,0,0}, // 0^
{1,1,1,1}, // 1^
{1,2,4,8}, // 2^
{1,3,9,27}, // 3^
};
void main()
{
int a=2,b=3,c;
c=my_pow[a][b];
}
If you have access to FPU or advanced math assembly you can use that as asm instruction is not a function call. FPU usually have log,exp,pow functions natively. This however limits the code to specific instruction set !!!
Here some examples:
How to: pow(real, real) in x86
So when I consider your limitation I think the best way is:
#define my_pow(a,b) (b==0)?1:(b==1)?a:(b==2)?a*a:(b==3)?a*a*a:0
void main()
{
int a=2,b=3,c;
c=my_pow(a,b); // c = a^b
}
Which will work on int exponents b up to 3 (if you want more just add (b==4)?a*a*a*a: ... :0) and both int and float bases a. If you need much bigger exponent use the complicated version with local temp variable for returning result.
[Edit1] ultimative single expression macro with power by squaring up to a^15
#define my_pow(a,b) (1* (int(b&1))?a:1* (int(b&2))?a*a:1* (int(b&4))?a*a*a*a:1* (int(b&8))?a*a*a*a*a*a*a*a:1)
void main()
{
int a=2,b=3,c;
c=my_pow(a,b); // c = a^b
}
In case you want more than a^15 just add sub term (int(b&16))?a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a:1 and so on for each bit of exponent.
It is a series. Replace pow() based on the previous iteration. #Bathsheba
Code does not need to call pow(). It can form pow(x, 5 * i - 1) and pow(-1, i - 1), since both have an int exponent based on the iterator i, from the prior loop iteration.
Example:
Let f(x, i) = pow(x, 5 * i - 1)
Then f(x, 1) = x*x*x*x
and f(x, i > 1) = f(x, i-1) * x*x*x*x*x
double power_n1 = 1.0;
double power_x5 = x*x*x*x;
for (int i = 1; i < j + 1; i++)
// sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
sum += power_n1 / (5 * i - 1) * power_x5;
power_n1 = -power_n1;
power_x5 *= x*x*x*x*x;
}
While compiling simple cpp file I got an error. I want to write a function that changes celcius to farenheit.
double przelicznik(double n)
{
n = 1,8 * n + 32;
return n;
}
Also it doesn't give me a correct result.
The code is.
n = 1, (8 * n + 32)
The comma operator is a fairly uncommon mechanism where multiple expressions can be done in sequence.
correct code.
n = 1.8 * n + 32;
Not sure how to word this but, Is there any way to increment a macro?
I have several offset macros, the first defined offset must be zero, the next one must be 1, and so on.
If I need to add an offset macro to the middle of the list, it can be cumbersome to increment all the offsets below it manually.
//How can I turn this...
// v This number needs to increment by 1 (no matter the order)
#define OFFSET_X 0
#define OFFSET_Y 1
#define OFFSET_Z 2
#define OFFSET_W 3
//Into something like this... (order of macros swapped yet the numbering still goes from 0 to 3)
int num = 0;
#define OFFSET_Z num++ // = 0 (was 2)
#define OFFSET_Y num++ // = 1 (was 1)
#define OFFSET_X num++ // = 2 (was 0)
#define OFFSET_W num++ // = 3 (was 3)
With the original order,
#define OFFSET_X 0
#define OFFSET_Y (OFFSET_X + 1)
#define OFFSET_Z (OFFSET_Y + 1)
#define OFFSET_W (OFFSET_Z + 1)
or with the revised order in the second part of your post,
#define OFFSET_Z 0
#define OFFSET_Y (OFFSET_Z + 1)
#define OFFSET_X (OFFSET_Y + 1)
#define OFFSET_W (OFFSET_X + 1)
etc. Since all this gets evaluated at compile time, anyway, there's no perf hit.
Or you could write a code generator, if you're really bored, and have it generate the values for you.
Or just use an enum. This is what they're for, and they're treated as constants by the compiler, anyway - but you get compile-time error checking which is far less effective with macros.
BUT, a better solution may be constexpr added in C++11.
In any case, if you only have four of these, this is overkill.
Just use an enum:
enum class offsets {
X = 0,
Y = 1,
Z = 2,
W = 3
};
and don't sweat it. Want auto-increments? Even easier:
enum class offsets { X = 0, y, z, w };
for the same effect.
Note I've suggested an enum class, so the usage is offsets::X, offsets::Y etc.
In some cases you may prefer an constexpr std::array, which you could then iterate over (something you can't do with macros or enums).
In my code, I often use a formula that returns me an index into a 2D array:
cells[cellToMarkX + cellToMarkY * xSize]
// ...
if (cells[j + i * xSize] == 0)
//...
else if (cells[j + i * xSize] >= 5)
//..
cells[cellToMarkX + cellToMarkY * xSize] += 4;
I'm not sure if I should instead create some function like
getCell(int x, int y)
or should is this unnecessary and I should prefer to use a macro?
Particularly in the example you give, you might want to consider precomputing as well, as in:
int myindex = j + i * xSize;
if (cells[myindex] == 0)
....
else if (cells[myindex] >= 5)
but to answer your question more directly, a function call is not out of place here, particularly if you declare it with the inline attribute. In many cases, a good optimizing compiler will generate the same code regardless of whether you use a macro or a function, but that is of course implementation-dependent.
Personally, I'd prefer a function.
So here's the code which works. Posted it without any changes.
There is X and Y values which must be betwen 0 and 1024. tyleSize is 1024;
//for X
int loffx=accurate(curphisobj->x) + (rand() % 100) - 50; //some math, doent matter
loffx=max(loffx,1);
loffx=min(loffx,tyleSize);
//for Y
int loffy=accurate(curphisobj->y) + (rand() % 100) - 50;
loffy=max(loffy,1);
loffy=min(loffy,tyleSize-3);
But if I write it like this:
int loffy=min(max(accurate(curphisobj->y) + (rand() % 100) - 50,1),tyleSize - 2);
int loffx=min(max(accurate(curphisobj->x) + (rand() % 100) - 50,0),tyleSize);
I get loffx and loffy 1034, 1029, -5, - 2, all kinds of nombers uncut by max and min.
Is there something i dont know about C++ compiler, or there's some dumb mistake?
Make sure that you're actually using the min and max functions from <algorithm>, and not some macros defined elsewhere. For instance, the Windows header windef.h defines max like this:
#define max(a,b) (((a) > (b)) ? (a) : (b))
This won't work in your code because it potentially evaluates each argument twice, and rand by design returns a different result each time.
Try viewing the source after preprocessing to see if you're using the macros. You can turn off the Windows macros by defining NOMINMAX before including any headers.