Which is faster: (i == 0) or (i < 1) - actionscript-3

I recently heard that:
//This:
val1 * 0.5;
//Is faster than this:
val1 / 2;
So I wonder if there is anything else like that, and so I ask:
var val1:uint = 0;
//Is This:
if (val1 == 0)
//faster than this?:
if (val1 < 1)

Why? Whichever you do, the compiler will optimise it on whatever platform you are currently compiling on.
If you need to check if it's 0, use (i == 0), if you want to know if it's less than zero, use that one instead. Write what you would read out loud.
Tiny things like this won't make anything faster, and you should be worried about readability and clean design rather than which tiny operation is faster.
And even if it doesn't do any logical changes, chances are on your platform, both will perform in one CPU cycle.

Related

Pros and Cons of i != n vs i < n in an int for loop

What are the pros and cons of using one or the other iteration functions ?
function (int n) {
for (int i = 1; i != n; ++i) { ... }
}
vs
function (int n) {
for (int i = 1; i < n; i++) { ... }
}
I think the main argument against the first version is that it is a much less common idiom.
Remembering that code is read more often than it is written, it does not make sense to use a less familiar form of for loop if there isn't a very clear advantage to doing so. All it achieves is distracting anyone working on the code in future.
So primarily for code maintenance reasons (by others as well as the original coder) I would favour the more common second format.
The version with < will work correctly if n is less than 1. The version with != will go into an infinite loop (well, probably not infinite, as integer variables wrap around in most languages).
Using < also generalizes better. E.g.
for (i = start; i < end; i += increment)
This will work even if end - start is not a multiple of increment.
The first one is quite dangerous and could cause an infinite loop.
If n is ever less than 1, the loop will never exit.
Also if something changes i inside the loop, so that it skips the value of n, then again the loop will never exit.
Edit: OK to be more precise when I say never exit, it will ultimately exit one way or another, but it won't be in the manner most sane developers expect. I can just imagine the look on the poor guy that debugs your code that calls the database 2 billion times.

Can someone translate this C++ into AS3?

This code stores the sqrt() of the numbers from 0 to 4095 in a table, and I would like to translate it into Actionscript 3.
unsigned short int_sqrt_x1024[4096];
for (int i=0; i<sizeof(int_sqrt_x1024)/sizeof(int_sqrt_x1024[0]); i++)
int_sqrt_x1024[i] = (int)(sqrtf((float)i + 0.5f) * 1024.0f);
I've done it halfway, but the 'sizeof' parts got me, I havent got a clue what to do with those!
So based on your suggestions I've come up with this, what do you think???:
var int_sqrt_x1024:Vector.<uint> = new Vector.<uint>(4096,true)
for (var i:int = 0; i < int_sqrt_x1024.length; i++)
int_sqrt_x1024[i] = Math.sqrt( i + 0.5) * 1024;
You can find the definition of sizeof HERE. To the best of my knowledge, there is no analogous operator in AS3. I have never encountered anything like it in documentation, and searches reveal nothing.
In fact, the closest thing I can find to it is the completely unrelated ByteArray, which I can guarantee would not achieve the same end, as one is an advanced data type and the other is an operator. Their usages aren't even similar.
I am curious, what is the goal of this code? Perhaps there is another way to achieve the same end. (And apparently from reading comments, there is actually a better way.)
EDIT: See Basic's comment below...there may be something similar.
Sorry, I can't provide a translation since I don't know Actionscript, but I think this will help you out too:
The C sizeof-Operator returns the size in bytes of its argument. This is not something you need to concern yourself with in a "managed" language like Actionscript. What the C code you posted (I don't really see anything in it that would necessarily make it C++) does, is iterating through the loop (size_of_the_array_in_bytes / size_of_one_array_element_in_bytes) times. In your case, that complicated expression would simply evaluate to 4096.
In other worlds, make a loop that executes the store of the square root 4096 times.
The C-code you're using as a basis seems to be pretty poorly written. I can't seem to find a reason one would use such a complicated, verbose and unreadable way to fill a simple lookup table. IMO, it should be something like this:
#define LOOKUPTABLE_LENGTH 4096
unsigned short int_sqrt_x1024[LOOKUPTABLE_LENGTH];
for (int i=0; i<LOOKUPTABLE_LENGTH; i++)
int_sqrt_x1024[i] = (int)(sqrtf((float)i + 0.5f) * 1024.0f);
Much more readable, no?

Simplifying if statement logic

I have seperated out a test to determine if two schedule items overlap because of the unreadability of it.
Is there any application to assist in simplifying a logic statement?
Example: (originally a faulty example, but exposes reasons I request this)
if (x < y && y < z && x < z)
could be reduced to
if (x < y && y < z)
My code is:
return (shift.Start <= shift2.Start && shift.End >= shift2.End) || (shift2.Start <= shift.Start && shift2.End >= shift.Start)
I would love to make that simpler, and I believe it's possible, just unsure how.
Seeing as this is really language agnostic, even converting to a different script to find possibilities would be nice, no need for it to be in C# for instance.
Kill the duplicate logic and you'll kill two birds with one stone. You'll get DRY, and you'll get a function name (the rich man's comment):
class Shift:
def encompasses(other_shift)
self.start <= other_shift.start && self.end >= other_shift.end
...
return shift1.encompasses(shift2) || shift2.encompasses(shift1)
Be very, very careful with these kinds of changes. They might seem straightforward at inital glance, and boolean logic (and DeMorgan's laws) are not too hard to grasp, but there are often potential gotchas when you look at individual cases:
For example: if (x < y && y < z) could be simplified to if (x < z)
This is not correct, if (x < z), y might still be greater than z. That state would not pass your original tests.
Although x < y && y < z implies x < z (< is transitive), the reverse is not true so the expressions are not equivalent. Indeed if y were defined as, say, Integer y = null, then the former may even cause an NPE in Java, or UNKNOWN in SQL.
When it comes to complex logic statements, you're usually best off with formatting your code in a readable manner than attempting some premature optimization (root of all evil, etc.)
For example:
return (shift.Start <= shift2.Start && shift.End >= shift2.End) || (shift2.Start <= shift.StartTime && shift2.End >= shift.Start)
Can, for readability and maintainability, be refactored to:
bool bRetVal = false;
bRetVal = ( ( (shift.Start <= shift2.Start)
&& (shift.End >= shift2.End))
|| ( (shift2.Start <= shift.StartTime)
&& (shift2.End >= shift.Start)))
return bRetVal;
Most places maintain a coding standard that defines something like the above for large logic blocks. I'd much rather maintain a few extra lines of code that can be read and understood than a one line monstrosity.
Is there any application to assist in simplifying a logic statement?
I didn't see anyone addressing this part of the question, So I'll take a stab and see what discussion occurs.
There are techniques for working with boolean logic. Back in my college days (BSEE) we used Karnaugh maps. Basically, you can take a very complex arbitrary truth table and determine a correct and optimized logical expression. We used this to reduce the number of logic gates in a circuit, which is analogous to simplifying a complex if statement.
Pros:
You can implement/optimize a very complex and arbitrary truth table relatively easily.
Cons:
The resulting logic usually bore little resemblance to the intent of the truth table. As others have suggested, this is "unreadable".
A change to a single cell of the truth table would often result in a completely different expression. A simple design tweak becomes a re-write, so it's unmaintainable.
Non-optimized logic is a lot cheaper than it used to be, while the design costs are the same.
Ultimately, the most critical thing is the correctness of the truth table/logic expression. An error means your program won't work right. No application or design technique will help if you don't properly understand the definition of the logic that needs to be implemented.
In my opinion, few real-world problems are sufficiently complex to truly benefit from this type of technique, but it does exist.
You need to be really careful when doing this... the example you gave, for example, simply isn't true...
if x = 1, y = 2, and z = 2, then x < y = true, and x < z = true, but y < z = false.
For this type of reasoning, you really want to go for code readability in these circumstances and not worry about the most efficient code that you can get.
Assuming Start and StartTime are actually supposed to be the same field, your condition boils down to
(a <= b && c >= d) || (b <= a && d >= c)
We can turn this into
(a <= b && d <= c) || (b <= a && c <= d)
but this still doesn't look like it simplifies much.
Sometimes you can wrap statements such as:
shift.Start <= shift2.Start && shift.End >= shift2.End
Into a boolean function to make it more readable such as:
function ShiftWithinValidRange //(terrible name here, but you get the idea)
{
return (shift.Start <= shift2.Start && shift.End >= shift2.End);
}
Not only is this dangerous, but it often leads to harder to maintain code. Boolean logic is easier to understand when broken down into specific steps. Condensing the logic will often lead to harder to understand logic.
i.e. in your example, why are we checking if x < z , when what we really want to know is x < y && y < z?
The simplest solution is often the best one. Condensing your logic into 'cooler' but less readable code is not good in the long run.
I don't have a general solution for you, but if I use Lisp syntax it looks a lot simpler to me:
(and (< x y)
(< y z)
(< x z))
Then notice that the first two clauses:
(and (< x y)
(< y z))
can be combined into:
(and (< x y z))
So the full expression now looks like:
(and (< x y z)
(< x z))
Now it's obvious that the second one is redundant, so it's down to:
(and (< x y z))
or simply:
(< x y z)
which in C-syntax is:
(x < y && y < z)
I think Wayne Conrad's answer is the right one, but for entertainment purposes only, here's another way to say it (I think):
(long) shift.Start.CompareTo(shift2.Start) * (long) shift.End.CompareTo(shift2.End) <= 0
Is this actually faster? I don't know. It's certainly harder to read.

Loop termination conditions

These for-loops are among the first basic examples of formal correctness proofs of algorithms. They have different but equivalent termination conditions:
1 for ( int i = 0; i != N; ++i )
2 for ( int i = 0; i < N; ++i )
The difference becomes clear in the postconditions:
The first one gives the strong guarantee that i == N after the loop terminates.
The second one only gives the weak guarantee that i >= N after the loop terminates, but you will be tempted to assume that i == N.
If for any reason the increment ++i is ever changed to something like i += 2, or if i gets modified inside the loop, or if N is negative, the program can fail:
The first one may get stuck in an infinite loop. It fails early, in the loop that has the error. Debugging is easy.
The second loop will terminate, and at some later time the program may fail because of your incorrect assumption of i == N. It can fail far away from the loop that caused the bug, making it hard to trace back. Or it can silently continue doing something unexpected, which is even worse.
Which termination condition do you prefer, and why? Are there other considerations? Why do many programmers who know this, refuse to apply it?
I tend to use the second form, simply because then I can be more sure that the loop will terminate. I.e. it's harder to introduce a non-termination bug by altering i inside the loop.
Of course, it also has the slightly lazy advantage of being one less character to type ;)
I would also argue, that in a language with sensible scope rules, as i is declared inside the loop construct, it shouldn't be available outside the loop. This would mitigate any reliance on i being equal to N at the end of the loop...
We shouldn't look at the counter in isolation - if for any reason someone changed the way the counter is incremented they would change the termination conditions and the resulting logic if it's required for i==N.
I would prefer the the second condition since it's more standard and will not result in endless loop.
In C++, using the != test is preferred for generality. Iterators in C++ have various concepts, like input iterator, forward iterator, bidirectional iterator, random access iterator, each of which extends the previous one with new capabilities. For < to work, random access iterator is required, whereas != merely requires input iterator.
If you trust your code, you can do either.
If you want your code to be readable and easily understood (and thus more tolerant to change from someone who you've got to assume to be a klutz), I'd use something like;
for ( int i = 0 ; i >= 0 && i < N ; ++i)
I always use #2 as then you can be sure the loop will terminate... Relying on it being equal to N afterwards is relying on a side effect... Wouldn't you just be better using the variable N itself?
[edit] Sorry...I meant #2
I think most programmers use the 2nd one, because it helps figure out what goes on inside the loop. I can look at it, and "know" that i will start as 0, and will definitely be less than N.
The 1st variant doesn't have this quality. I can look at it, and all I know is that i will start as 0 and that it won't ever be equal to N. Not quite as helpful.
Irrespective of how you terminate the loop, it is always good to be very wary of using a loop control variable outside the loop. In your examples you (correctly) declare i inside the loop, so it is not in scope outside the loop and the question of its value is moot...
Of course, the 2nd variant also has the advantage that it's what all of the C references I have seen use :-)
In general I would prefer
for ( int i = 0; i < N; ++i )
The punishment for a buggy program in production, seems a lot less severe, you will not have a thread stuck forever in a for loop, a situation that can be very risky and very hard to diagnose.
Also, in general I like to avoid these kind of loops in favour of the more readable foreach style loops.
I prefer to use #2, only because I try not to extend the meaning of i outside of the for loop. If I were tracking a variable like that, I would create an additional test. Some may say this is redundant or inefficient, but it reminds the reader of my intent: At this point, i must equal N
#timyates - I agree one shouldn't rely on side-effects
I think you stated very well the difference between the two. I do have the following comments, though:
This is not "language-agnostic", I can see your examples are in C++ but there
are languages where you are not allowed to modify the loop variable inside the
loop and others that don't guarantee that the value of the index is usable after
the loop (and some do both).
You have declared the i
index within the for so I would not bet on the value of i after the loop.
The examples are a little bit misleading as they implictly assume that for is
a definite loop. In reality it is just a more convenient way of writing:
// version 1
{ int i = 0;
while (i != N) {
...
++i;
}
}
Note how i is undefined after the block.
If a programmer knew all of the above would not make general assumption of the value of i and would be wise enough to choose i<N as the ending conditions, to ensure that the the exit condition will be eventually met.
Using either of the above in c# would cause a compiler error if you used i outside the loop
I prefer this sometimes:
for (int i = 0; (i <= (n-1)); i++) { ... }
This version shows directly the range of values that i can have. My take on checking lower and upper bound of the range is that if you really need this, your code has too many side effects and needs to be rewritten.
The other version:
for (int i = 1; (i <= n); i++) { ... }
helps you determine how often the loop body is called. This also has valid use cases.
For general programming work I prefer
for ( int i = 0; i < N; ++i )
to
for ( int i = 0; i != N; ++i )
Because it is less error prone, especially when code gets refactored. I have seen this kind of code turned into an infinite loop by accident.
That argument made that "you will be tempted to assume that i == N", I don't believe is true. I have never made that assumption or seen another programmer make it.
From my standpoint of formal verification and automatic termination analysis, I strongly prefer #2 (<). It is quite easy to track that some variable is increased (before var = x, after var = x+n for some non-negative number n). However, it is not that easy to see that i==N eventually holds. For this, one needs to infer that i is increased by exactly 1 in each step, which (in more complicated examples) might be lost due to abstraction.
If you think about the loop which increments by two (i = i + 2), this general idea becomes more understandable. To guarantee termination one now needs to know that i%2 == N%2, whereas this is irrelevant when using < as the condition.

for-loop mechanism efficiency tips

As I am using for-loops on large multi-dim arrays, any saving on the for-loop mechanism itself is meaningful.
Accordingly, I am looking for any tips on how to reduce this overhead.
e.g. : counting down using uint instead of int and != 0 as stop instead of >0 allows the CPU to do less work (heard it once, not sure it is always true)
One important suggestion: move as much calculation to the outer loop as possible. Not all compilers can do that automatically. For eample, instead of:
for row = 0 to 999
for col = 0 to 999
cell[row*1000+col] = row * 7 + col
use:
for row = 0 to 999
x = row * 1000
y = row * 7
for col = 0 to 999
cell[x+col] = y + col
Try to make your loops contiguous in memory, this will optimize cache usage. That is, don't do this:
for (int i = 0; i < m; i++)
for (j = 0; j < n; j++)
s += arr[j][i];
If processing images, convert two loops to one loop on the pixels with a single index.
Don't make loops that will run zero times, as the pipeline is optimized to assume a loop will continue rather than end.
Have you measured the overhead? Do you know how much time is spent processing the for loops vs. how much time is spent executing your application code? What is your goal?
Loop-unrolling can be one way. That is:
for (i=0; i<N; i++) {
a[i]=...;
}
transforms into:
for (i=0; i<N; i+=4) {
a[i]=...;
a[i+1]=...;
a[i+2]=...;
a[i+3]=...;
}
You will need special handling when N is not a multiple of 4 in the example above.
First, don't sweat the small stuff. Details like counting up versus counting down are usually completely irrelevant in running time. Humans are notoriously bad at spotting areas in code that need to be sped up. Use a profiler. Pay little or no attention to any part of the loop that is not repeated, unless the profiler says otherwise. Remember that what is written in an inner loop is not necessarily executed in an inner loop, as modern compilers are pretty smart about avoiding unnecessary repetition.
That being said, be very wary of unrolling loops on modern CPUs. The tighter they are, the better they will fit into cache. In a high-performance application I worked on last year, I improved performance significantly by using loops instead of straight-line code, and tightening them up as much as I could. (Yes, I profiled; the function in question took up 80% of the run time. I also benchmarked times over typical input, so I knew the changes helped.)
Moreover, there's no harm in developing habits that favor efficient code. In C++, you should get in the habit of using pre-increment (++i) rather than post-increment (i++) to increment loop variables. It usually doesn't matter, but can make a significant difference, it doesn't make code less readable or writable, and won't hurt.
This isn't a language agnostic question, it depends highly on not only language, but also compiler. Most compilers I believe will compile these two equivalently:
for (int i = 0; i < 10; i++) { /* ... */ }
int i = 0;
while (i < 10) {
// ...
i++;
}
In most languages/compilers, the for loop is just syntactic sugar for the later while loop. Foreach is another question again, and is highly dependant on language/compiler as to how it's implemented, but it's generally less efficient that a normal for/while loop. How much more so is again, language and compiler dependant.
Your best bet would probably be to run some benchmarks with several different variations on a theme and see what comes out on top.
Edit: To that end, the suggestions here will probably save you more time rather than worrying about the loop itself.
BTW, unless you need post-increment, you should always use the pre-increment operator. It is only a minor difference, but it is more efficient.
Internally this is the difference:
Post Increment
i++;
is the same as:
int postincrement( int &i )
{
int itmp = i;
i = i + 1;
return itmp;
}
Pre Increment
++i;
is the same as:
int preincrement( int &i )
{
i = i + 1;
return i;
}
I agree with #Greg. First thing you need to do is put some benchmarking in place. There will be little point optimising anything until you prove where all your processing time is being spent. "Premature optimisation is the root of all evil"!
As your loops will have O(n^d) complexity (d=dimension), what really counts is what you put INTO the loop, not the loop itself. Optimizing a few cycles away in the loop framework from millions of cycles of an inefficient algorithm inside the loop is just snake oil.
By the way, is it good to use short instead of int in for-loop if Int16 capacity is guaranteed to be enough?
There is not enough information to answer your question accurately. What are you doing inside your loops? Does the calculation in one iteration depend on a value calculated in a previous iteration. If not, you can almost cut your time in half by simply using 2 threads, assuming you have at least a dual core processor.
Another thing to look at is how you are accessing your data, if you are doing large array processing, to make sure that you access the data sequentially as it is stored in memory, avoiding flushing your L1/L2 cache on every iteration (seen this before on smaller L1 caches, the difference can be dramatic).
Again, I would look at what is inside the loop first, where most of the gains (>99%) will be, rather than the outer loop plumbing.
But then again, if your loop code is I/O bound, then any time spent on optimization is wasted.
I think most compilers would probably do this anyway, stepping down to zero should be more efficient, as a check for zero is very fast for the processor. Again though, any compiler worth it's weight would do this with most loops anyway. You need to loo at what the compiler is doing.
There is some relevant information among the answers to another stackoverflow question, how cache memory works. I found the paper by Ulrich Drepper referred to in this answer especially useful.