Features of the mql5 language, subtleties and tricks - page 116

 
Ilya Malev:

(tired) if that were the problem, the error "'k' - redefinition; different type modifiers" would pop up, but it's not on the screenshot. So the compiler doesn't care and it's not the issue.

Well, well...

 
Alexey Navoykov:

Well, well...

Well, try compiling it yourself. If you're not too lazy to write posts on this topic on the forum, you should be too lazy to put it into an editor and press F7. It's much faster.

 

Fast way to calculate the binary logarithm of an integer. Works 3-5 times faster than MathLog.

int log2(ulong n)
{
  if (n==0) return -1;
  
  #define  S(k) if (n >= (ulong(1)<<k)) { i += k;  n >>= k; }
  
  int i=0;  S(32);  S(16);  S(8);  S(4);  S(2);  S(1);  return i;
  
  #undef  S
}
 
Will an EA written in MQL5 work on an MT4 terminal? I read somewhere that it will work.
 
Alexey Navoykov:

Fast way to calculate binary logarithm of an integer. Works 3-5 times faster than MathLog.

I use a function like this (pure shamanism, but it works):

static const uint ulLogTable[64] = 
{
0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63 
};


uint _FastLog2(ulong ulInput)
{
   ulInput |= ulInput >> 1;
   ulInput |= ulInput >> 2;
   ulInput |= ulInput >> 4;
   ulInput |= ulInput >> 8;
   ulInput |= ulInput >> 16;
   ulInput |= ulInput >> 32;
  
   return(ulLogTable[(uint)((ulInput * 0x03f6eaf2cd271461) >> 58)]);
};

Both functions give the correct same answer, I found no errors.

It's interesting to compare the speed of operation. My version has slightly less shift and addition operations, but there's multiplication at the end. Alexey's version has slightly more shift and addition operations, but no multiplication. How is it faster ?

 
Comments not related to this topic have been moved to "Any questions from newbies on MQL4, help and discussion on algorithms and codes".
 
Comments not related to this topic have been moved to "Any questions from newbies on MQL4, help and discussion on algorithms and codes".
 
Georgiy Merts:

My version has slightly fewer shift and addition operations, but not multiplication. Alexey's version has slightly more shift and addition operations, but no multiplication. How is it faster?

I have a maximum of 6 shift and addition operations (binary search).Shift (ulong)1<<k doesn't count, because it's a constant. The only thing is that we also check the condition. But there are always 6 operations, plus multiplication, plus one more shift and access to the managed array (i.e. index check). So your version will obviously be slower by speed :).

And your version of course looks mysterious.)

p.s. I've got an assumption, that if my code could be unwrapped into a chain of comparisons via if-else, getting rid of all the arithmetic operations, it would speed things up tremendously. But it'd be a big mess of code. If only one could use recursion in macros...

 
Georgiy Merts:

It is interesting to compare the speed.

The log2 variant is faster.

#property strict
#define    test(M,S,EX)        {uint mss=GetTickCount();uint nn=(uint)pow(10,M);for(uint t12=0;t12<nn;t12++){EX;} \
                                printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}

int log2(ulong n){
  if (n==0) return -1;
  #define  S(k) if (n >= (ulong(1)<<k)) { i += k;  n >>= k; }
  int i=0;  S(32);  S(16);  S(8);  S(4);  S(2);  S(1);  return i;
  #undef  S}


static const uint ulLogTable[64] = {
0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63 };

uint _FastLog2(ulong ulInput){
   ulInput |= ulInput >> 1;
   ulInput |= ulInput >> 2;
   ulInput |= ulInput >> 4;
   ulInput |= ulInput >> 8;
   ulInput |= ulInput >> 16;
   ulInput |= ulInput >> 32;  
   return(ulLogTable[(uint)((ulInput * 0x03f6eaf2cd271461) >> 58)]);};

void OnStart(){
  srand(GetTickCount());
  ulong n,n1;
  test(8,"MathLog",n=rand()*rand();n1=ulong(MathLog(n)/MathLog(2)))
  test(8,"log2",n=rand()*rand();n1=log2(n);)
  test(8,"_FastLog2",n=rand()*rand();n1=_FastLog2(n))}


 
Ilya Malev:

So the log2 option is faster.


Got it.

Replacing my function.

Reason: