Return Positive value of a number - page 2

 
number *= ((int)(number-1)|1) % 2;
 
It should also be possible to do a bit arithmetic operation like this:


For an integer of 32 Bit.
number = number & 0x7FFFFFFF;
or as bitshift:
number = ((number << 1) >> 1);
 

For what it's worth I did a few tests to get the performance of all proposed solutions.

class CStopwatch
  {
protected:
   ulong             m_ticks;
public:
   void              Start() { m_ticks=GetMicrosecondCount(); }
   void              Stop() { m_ticks=GetMicrosecondCount()-m_ticks; }
   ulong             Ticks() { return m_ticks; }
  };

int OnInit()
  {
   CStopwatch watch;

   watch.Start();
   for(int i=-10000000; i<10000000; i++)
     {
      double num=i*0.1;
      //num=MathSqrt(MathPow(num,2)); // 1800000
      //num *= ((int)(num-1)|1) % 2; // 461000
      //num=num*(-1 + (2 * (num > -1))); // 386000
      //num=MathSqrt(num*num); // 239000
      //num=(num<0 ? -num : num); // 146000
      //num=(num < NULL) ? num * -1 : num; // 146000
      //num=num * ((num < NULL) ? -1 : 1); // 100000
      //if(num<0) num=num*-1; // 90000
      //if(num<0) num=-num; // 90000
      //num=MathAbs(num); // 61000
      //num = -num; // 60000
      //int n = ~i + 1; // 83000
      //int n = (i << 1) >> 1; // 67000
      //int n = i & 0x7fffffff; // 60000
      /*nop*/; // 60000
     }
   watch.Stop();
   Print("ticks: ",watch.Ticks());
   return INIT_FAILED;
 }

Performance is added as comment behind the appropriate statement. Bit manipulation works only on integers so the last 3 statements are somewhat out of league, but you'll get the impression. Fastest working solution is MathAbs().

 
number = MathAbs(number);
or 
number = number*(number>=0) -number*(number<0); 

 
Thank you lippmaje for performing the test.

I am not sure if all statements are true and I haven't tested them, but I question one of them being able to perform the task.

      //num = -num; // 60000

Next to the fact the ternary operator gets outperformed by an if statement. This could let me derive the compiler is optimizing somehow the code to something totally different from the if statement coded.

Also interesting is that two of the bit operations are as fast as the NOP, and slightly faster then MathAbs.

Also the type of usage of the ternary operator has massive influence in the optimization.


      //num=(num<0 ? -num : num); // 146000
      //num=(num < NULL) ? num * -1 : num; // 146000
      //num=num * ((num < NULL) ? -1 : 1); // 100000

Which leads me to the conclusion, the first two statements are not being optimized as they should be.

Would it be possible to do a measurment with this statement:

Just to see if it is the multiplication itself.

num=num & ((num < NULL) ? 0x7fffffff : 0xffffffff); // 100000
 
      //num = -num; // 60000

This one works only if the value is known to be negative, same as with

      //int n = ~i + 1; // 83000

So in the sense of OP's question both are not valid solutions.

Same with clearing the highest bit, that wouldn't work for all integer values.

Without the code we can only speculate what's going on at machine level. 

      int n=i & ((i < NULL) ? 0x7fffffff : 0xffffffff); // 70000
 
True. Interesting to see the result. So it takes 10k units for the ternary operator.
Thank you
Why would clearing the MSB not work for all integer values? Maybe, are you referring to different types? Like char, short and long?

That's true and it cannot be managed generally without imposing additional operations. But the bit shift will always work, no matter the size.

Btw, when using a union to convert a double to a long or a float to an int, bit shift and MSB would work as well. The sign bit is the same.

To bad mql does not allow cast to void.
 
So the multiplication needs 30k units more than the AND bit operation.
 
If I had, say, -1, how do I get to 1 by clearing the highest bit? Clearing the sign would work for doubles, provided you use a union, but integers?
 
You are right. It's Two`s complement. So the correct statement would have been

int n = ~i + 1; // 83000
Reason: