How to increment a value using a C-Preprocessor in Objective-C? [duplicate] - iphone

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Can you make an incrementing compiler constant?
Example: I try to do this:
static NSInteger stepNum = 1;
#define METHODNAME(i) -(void)step##i
#define STEP METHODNAME(stepNum++)
#implementation Test
STEP {
// do stuff...
[self nextFrame:#selector(step2) afterDelay:1];
}
STEP {
// do stuff...
[self nextFrame:#selector(step3) afterDelay:1];
}
STEP {
// do stuff...
[self nextFrame:#selector(step4) afterDelay:1];
}
// ...
When building, Xcode complains that it can't increment stepNum. This seems logical to me, because at this time the code is not "alive" and this pre-processing substitution stuff happens before actually compiling the source code. Is there another way I could have an variable be incremented on every usage of STEP macro, the easy way?

It seems to me that the fundamental problem is having these numbered variables, which are really just a poor man's array. An array would be the idiomatic way to do this in Objective-C.

Not a chance that will work. For a start, stepNum isn't a preprocessor macro so the preprocessor just thinks of it as a load of characters. Explicitly naming the steps would definitely be a good thing. Your macro doesn't save much typing and obfuscates the code, even if you could get it to work.
Anyway, this is the wrong way to do what you want. You actually seem to be reinventing program control flow.
ETA: It occurs to me that my answer to your other question might help here. You manually number all of your methods, but then put all their selectors in an array. You then iterate through the array and the order is determined by the order you put them in the array.

Related

Using all CPUs on CENT OS to run a c++ program

Hi and thanks for the help. I have been running a program that has many functions with for loops that iterate over 10000 times. I have been using "#pragma omp_set_num_threads();" to use all the CPUs of my CENT OS device. This seems to work fine for all functions i have in my program except one. The function it doesnt work on is something like this:
void move_check()//function to check if "molecule obj" is in space under consid
{
for(int i = 0 ; i < NM ; ++i)//NM-no of "molecules"
{
int bounds;
bounds = molecule_obj.at(i).check(dom_x,dom_y,dom_z);
////returns status of molecule
////molecule is a class that i have created and molecule_obj is an obj of that class.
if(bounds==1)
{
molecule_obj.erase(molecule_obj.begin()+i);
i -= 1;
NM -= 1;
}
}
}
Can I use pragma for this? If not what other alternative do i have?
As the above function is the one that seems to be consuming the most time, i would like to utilize all the CPUs to execute it. How do i go about doing that?
Thanks a lot.
Yes, in principle you can use an OpenMP pragma, just add
#pragma omp parallel for
before the for loop.
You have to make sure that it is save to use the methods of your molecule_obj in parallel. I cannot know if they are but I assume the following:
molecule_obj.at(i).check(dom_x,dom_y,dom_z); really works with one specific molecule and does depend any others. That is fine than.
But the erase function most likely is not, dependent on how you store the entries. If you use something like std::list, std::vector erasing an element during the loop would lead to invalid iterators, wrong trip counts, etc.
I suggest that you replace the removal of the entry in the loop by just marking it for removal. You can add a special flag to each molecule for that.
Then after the completion of the parallel loop you can go over the list once in serial and actually remove the marked entries.
Just another suggestion: make a clearer distinction between one molecule and the list of molecules. It would improve the understandability of your code.

What is "super" in Objective-C? ( self != super )?

I've read the question below, and the story SEEMS simple:
What exactly is super in Objective-C?
Yet ...
- (id) init
{
NSLog(#"self=%p, super=%p", self, super);
}
That prints out "self=0xa83dc50, super=0xbfffe8d0". The addresses are NOT THE SAME???!?!?
That second address seems like a "special value" or something. What does it mean?
Thanks to bbum for pointing out that this value is the stack address of a special struct used by the compiler to implement the "super" behavior.
I can call [super init] and the call seems to work, or at least, nothing explodes ... not immediately. Calling [((id)0xbfffe8d0) init] fails hard with EXC_BAD_ACCESS.
Then there is the REALLY WEIRD part.....
I've got a piece of code that for no explainable reason throws a "NSGenericException: collection was mutated while being enumerated" exception. Inside a DIFFERENT object (basically a wrapper that has a pointer to the NSEnumerator), commenting out the call to "[super init]" causes the exception to not happen. If I could, I'd put out a $$$ reward for an answer to THAT mind-bender.
"id sups = (id)0xbfffe8d0" ... that also leads to "collection is modified." ... WTF? Ok, so I'm posting a 2nd question for that bizzariotity ...
I originally came here with one of those "bizarre symtoms" bugs, that turned out to be entirely unrelated (typical for such things): Does casting an address to (id) have side-effects??? Is Address 0xbfffe8d0 special? (fixed: issue was with _NSCallStackArray)
However, the content above the line is still valid, and the response still excellent. Read it if you want to understand ObjC just a little bit deeper.
You are messing with the man behind the curtain and he is punishing you for it... :)
super is a bit of compiler magic, really. When you say [super doSomething], the compiler will emit a call to objc_msgSendSuper() instead of objc_msgSend(). Most of the time -- there are some special cases.
In general, you should treat super as only a target for method calls. It should never be stored anywhere and should never be considered anything but that target expression for messaging.
In fact, uses of super that involve storage should likely be flagged by the compiler.
In terms of your bug, that sounds an awful lot like there is either corruption of memory, an over-release, and/or concurrency going on. You'll need to provide more code related to the enumeration and other relevant code to deduce further.

How to deallocate memory on the iPhone?

This is probably a very silly and simple question to most of you, but I have the following code creating a temporary array within a function, at the end of the function i need to release the memory. Here is the code:
double *FFTOut;
//FFT Out removes the alternative zeros added in the earler phase (before the FFT)
FFTOut = (double *)malloc((CFArray1Size)* sizeof(double));
So the pointer FFTOut is to a block of memory, I have tried the following...
[FFTOut release];
and...
[FFTOut dealloc];
Neither of which work. I'm sorry to post such a trivial question, but i can't seem to find the answer to this? Unless I am allocating the memory incorrectly in the first place, but I don't think this is the case?
Many Thanks
If you malloc, you have to use free().
release is for objective-c object that you've either new'd or alloc'd.

math function "Log ()"

Is there a way to implement the math function Log() into an equation with an iphone app? im working on right now that without the log function requires about 400 + if and else if statements. I have already wrote out these if and else if statements. half of them work and the other half keeps returning 0.00 . after HOURS of trying to find the problem and compare it to the part that does work i can still not figure it out. i know i can do simple math (add, subtract, divide, mulitply, etc), but i havnt found anything searching forums, google, etc that tells me how to add a Log function. if i could do this i can cut my code down from like 500 lines to about 40 tops. can anyone help me with this or at least point me in the right direction as to where i can find a thread or tutorial on this?
I already fixed Shaun's example code posted in his answer, but just to be perfectly clear, there were two issues at work:
First, he wasn't including <math.h> and using log from the system math library.
Second, he omitted the multiplication operator in the expression .19077f(logf(abNeckFactor)); we often write mathematics this way, but it is not syntactically valid C (or Obj-C) code.
Shaun, I would advise you to spend some more time reading up on what's available in C and Objective-C; an enormous amount of functionality is present in the language, and a few hours spent learning about what's already done for you will spend you many, many hours of searching for things in the future.
Note also that the log function is the base-e logarithm. Many people in technical fields outside of mathematics and computing use log to refer instead to the base-10 logarithm; if that's what you need, you will want to call log10( ) -- or log10f( ) -- instead.
#import <math.h>
// ...
double someLog = log(someDouble);
(Note: I used double/log here, but you might consider using float/logf if speed is an issue as they could be faster on the iPhone (IIRC).)
I know you've already got the answer to your question, but here's way of not having to write tons of if, else if, else if, .... else, for future reference.
Store the answers in an array.
For instance you could define an array of arrays that looks like this:
[(min, max, value),(min, max, value),...]. Then loop through the array.
arr = {{min, max, value}, {min, max, value}, ...}
for i in range(0, arr.length)
if(arr[i][min_i] < x && x < arr[i][max_i]) {return arr[val_i]}
There is probably a way figuring how to map the x to a index of an array like x/(max-min) so that log(x) would be arr[x/(max-min)]. But my point is, it is alot cleaner to have an array or dictionary and search through it than having a bunch of if, else if, else if, ... statements.

iPhone accelerometer:didAccelerate: seems to not get called while I am running a loop

An accelerometer related question. (Sorry the formatting may not look right, its the first time I am using this site). I got the accelerometer working as expected using the standard code
UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = 0.1; //I also tried other update values
I use NSLog to log every time the accelerometer:didAccelerate: method in my class is called. The function gets called as expected and everything works fine till here.
However, when I run a loop, the above method doesn't seem to get called. Something like this
float firstAccelValue = globalAccel; //this is the x-accel value (stored in a global by the above method)
float nextAccelValue = firstAccelValue;
while (nextAccelValue == firstAccelValue){
//do something
nextAccelValue = globalAccel; // note globalAccel is updated by the accelerometer method
}
The above loop never exits, expectedly since the accelerometer:didAccelerate: method is not getting called, and hence globalAccel never changes value.
If I use a fixed condition to break the while loop, I can see that after the loop ends, the method calls work fine again.
Am I missing something obvious here? Or does the accelerometer method not fire when certain processing is being done?
Any help would be greatly appreciated! Thanks!
(Don't compare float with ==.)
The CPU is occupied by the loop and has no time to give you the updated accelerator value.
Since -accelerometer:didAccelerate: is called everytime the acceleration changes, why not just use if?
// in -accelerometer:didAccelerate:
if (fabs(nextAccelValue - firstAccelValue) < 0.0001) {
// do something
nextAccelValue = globalAccel;
}
Thanks much for that! (About the float comparison, yes I understand, it was just an example).
Actually, what I want to do is this: After a button is pressed, I want to obtain the accelerometer value (firstValue) and then wait until it changes (to say a particular value relative to firstValue) and then proceed to do some tasks. As such I was using the while loop. (The loop I show just waits until it changes, but I can put the exact change condition required once it works).
From your answer, I understand that I can perform the task in the -accelerometer:didAccelerate: function itself (since it has access to all the data it needs, I can make it access a variable indicating whether the button was pressed). Thanks very much for that. I guess I can make it work in this way.
But just curious - is there a way to do it otherwise? If too much processing is hogging the CPU, can I force it to update accelerometer somehow? The loop hogging the CPU itself is low priority since it was just my way of waiting until the value changes.
Thanks again!