Ok, we all have had the need for an increment accumulator from time to time, for whatever reasons.
So, am i right in thinking that , at the cost of some bits in an increment variable( to allow for overhead; lets say we using a uint32_t ), i can wrap around A VARYING DYNAMIC counting increment, by AND'ing it (&) with the limit desired ?!
Ill try to exemplify it.
// Limit for WholePhasePeriod=1023
PhaseOutput = PhaseIncrm & 1023'
If PhaseIncrm==1025 then the result would be a 1 ( allowing for the 0 in an index as well ; i.e. 1024 == 0, 1025 ==1, )
Are there any caveats in this method that you might be aware ?!
Or any advices regarding any other similar methods that might be useful to know ?!
You can try the modulus of the variable :
limitedNumber = unlimitedNumber%1023;
This % ampersand operator gives the remainder after the input is divided by the modulus.
Thanks.
Which one would be faster after compile though ?!
As one of my main concerns is keeping track of a dynamic increment accumulator , "likkle" tricks like this allow me to optimize massively the precision of my current project, while not sacrificing in performance/time.
Bitwise operators make life so much simpler...
A bit wise and is much faster than a division or modulo operation . Note that the % trick only works as long as the unlimited number is below the maximum value for that data type.
Yeah, thats what i thought.
Sometimes you cant "run and hide" from using the modulo operator, but this time the AND will suit me perfectly. Specially as it makes it easier with the way the index needs to be ( N-1), to allow the use of 0 in calculations. Saves me a whole lot of worry, as the overflow jump in a shift register does influence the precision in not wrapping around the accumulator.
iyahdub:
Which one would be faster after compile though ?!
Unless you are really, really performance-critical, it won't matter. I'm not in favor of optimisation just for the sake of it, and I've seen many cases where premature or excessive optimisation has sacrificed clarity/robustness/generality for the sake of an inconsequential performance gain.
iyahdub:
Which one would be faster after compile though ?!
Unless you are really, really performance-critical, it won't matter. I'm not in favor of optimisation just for the sake of it, and I've seen many cases where premature or excessive optimisation has sacrificed clarity/robustness/generality for the sake of an inconsequential performance gain.
I know where you coming from... But i'm one of those that likes to know different methods, their weaknesses and strengths. Lets say it is for a cycle-eating signal processing purpose.
I am usually thoughtful about portability, clarity, and practical as much as i can. But in this case, im just trying to improve performance ...
Arduino language abstract layer is already slow in that sense, so in this case i am forced to optimize as much as possible . Thats where the "likkle" old school tricks comes into action. Of course Java developers would find this MAD... They would just add another gigabyte layer of abstraction lol
Grumpy_Mike:
Yes but here the best solution is also the fastest.
I'd dispute 'best'. It's not the most obvious or general solution and only works correctly when the divisor is a power of two.
I also wonder whether modern compilers are smart enough to reduce the modulus operation to the same thing, when applicable. It's my experience that human optimisation is best done at the architectural and algorithmic level; optimising down in the weeds is usually best left to the compiler.
Grumpy_Mike:
Come on it is blindingly obvious. But maybe that is because of my hardware background.
Is it blindingly obvious that this is correct?
PhaseOutput = PhaseIncrm & PhaseLength;
It's only 'obvious' if you use numeric literals, at which point you are inevitably duplicating magic numbers in your code, which is always undesirable. (It also raises the issue of how obvious it is to somebody maintaining the other definitions of that magic number out of sight of this code fragment that the value needs to be a power of two).
Grumpy_Mike:
Yes I did say that.
Your post said that, but your code didn't. Don't you consider it significant that you needed to point out that caveat? I do.
Regarding the powers of two- It is to keep the phase increment of a LUT, so methodology tradition has it as a power of two anyway(powers of 8, majority).
And i love the power of the modulo operator( using it in a proof of concept Caesar cipher im developing, more as an exercise into basic cryptography and prime numbers relations)...
But in this specific case, the bitwise operator will do me just fine. Im told that is not always compiler friendly when passed a variable in C ( can anyone confirm this?!), but with the Arduino seems to compile as expected.
As i said, i love to dig deeper into the tricks that can help ( or not!!) optimize things, be it performance or code.
This is a case where replacing so called magic numbers with variables is not at all appropriate. Don t just take a doctrin and follow it blindly, think about what it means and how you would use it.
In the case of non powers of two numbers this method is faster and safer than the use of the mod operation.
Val ++;
if(Val >= limit) Val = 0;
Im told that is not always compiler friendly when passed a variable in C ( can anyone confirm this?!)
The only people who tell you that are pranoid code zealots.
Grumpy_Mike:
This is a case where replacing so called magic numbers with variables is not at all appropriate. Don t just take a doctrin and follow it blindly, think about what it means and how you would use it.
I'm not following a doctrine blindly, I'm using a practice because it is sensible and desirable to do so. Not embedding magic numbers in the code and not replicating the definitions of those numbers are basic steps to producing clear and maintainable code. A coding trick that requires you to use magic numbers goes against that good practice. It might be appropriate in some specific situations but it is not a generally good thing to do. Using that trick without good reason is IMO premature optimisation; it's compromising the code to achieve a small performance gain that in most situations would be negligible.
Well to me it is a natural way to do things, just like you would in hardware. I guess that sort of thing will always be the gulf between a hardware and a software orientated person.
I am happy doing it that way and in 40 years it has not got me into any trouble. I am not doing the optimising for the compiler I am writing clean and sucenct code.
I have known other people who disagree with this. The funny thing is that the code they write is very obscure.
Im not sure that my opinion counts as much, but i guess that embedded design was all about working with the limitations ?
Usually hardware wise.?! A concept anyone who is coming from a software programming background has difficulty to grasp unless they have had some interaction with hardware before.
Now code portability , clarity and maintenance are sacrifices i dont mind making, if that helps me achieve what i need. That is harder as direct hardware registers manipulation is often needed.
Plus, even now, code size limitations are quite present, if you need to do some real crunching-numbers. Thats where itis good to know the tricks...
I agree with you, but also am forced to agree with the hardware quirks s well
Thanks for your insight, guys !
on the subject of MAGIC NUMBERS
Most compilers compile the same code if you use x/3. But isnt it good to know how it does it ?! Doesnt that add to your arsenal of tools available to solve problems ?!
// Crazy as this might sound, but the method below indeed does divide by 3.
// All it needs for doing so is a single 64 bit multiplication and a shift
// (multiplications might be 3 to 4 times faster than divisions
// on your CPU). In a 64 bit application this code will be a lot faster than
// in a 32 bit application (in a 32 bit application multiplying two 64 bit
// numbers take 3 multiplications and 3 additions on 32 bit values)
// - however, it might be still faster than a division on a 32 bit machine.
// It only works for constant numbers. Why ?!
// You always need to know the magic number (here 0xaaaaaaab,
// 0b1010 1010 1010 1010 1010 1010 1010 1011 ; 2,863,311,531 decimal)
// and the correct operations after the multiplication (shifts and/or additions
// in most cases)and both is different depending on the number you want to divide
// by (and to calculate both take too much CPU time, on the fly (that would be
// slower than hardware division). However, it's easy for a compiler to
// calculate these during compile time
static inline uint32_t div3 (
uint32_t bdivided
) {
return (uint32_t)(((uint64_t)0xaaaaaaabULL * bdivided) >> 33);
}
void setup() {
// put your setup code here, to run once:
Serial.begin (115200);
}
void loop() {
// put your main code here, to run repeatedly:
uint32_t test=1000;
uint32_t avar=div3(test);
Serial.println(avar);
delay(500);
}
But in this specific case, the bitwise operator will do me just fine. Im told that is not always compiler friendly when passed a variable in C ( can anyone confirm this?!), but with the Arduino seems to compile as expected.