Checking if an Integer is an Exact Binary Power

Solomon E via Digitalmars-d digitalmars-d at puremagic.com
Mon Apr 25 12:21:38 PDT 2016


On Monday, 25 April 2016 at 16:53:20 UTC, Solomon E wrote:
> ...
>
> (x >>> 1) is equal to half of x or one less than half of x, or 
> a positive number if x is negative.
>
> ...

Obviously wrong explanation, sorry. (x >>> 1) is equal to half of 
x or half of one less than x, or a positive number if x is 
negative.

There are other parts in isPow2F where I'm not sure exactly what 
the bits are doing, such as how the compiler makes the result 
negative for (x & -x) at the bit and short min values, where in 
other expressions while learning D I've found an implicit cast to 
int that I worked around by casting back to the type I put in. (I 
guess that's the way it's supposed to be for compatibility with 
C/C++ expectations.) Also I skipped mentioning case x = 6 works 
too, not just cases over and under 6. It's just a sketch of a 
proof.

I would use the other function I wrote first, isPow2D, to be more 
sure of the logic, although it's not the most optimized, or I'd 
use a library function that promises to do the task for all types 
if I found one first, rather than the isPow2 variants I wrote and 
others wrote, and rather than popcnt. I'm more concerned with 
getting the application logic right when I program than 
optimizing for speed or bytes, until something is noticeably 
pausing or taking extra megabytes.

bool isPow2D(T)(T x)
{
     return (x > 0) && !(x & (x - 1));
}

Just now I tested popcnt against isPow2D and found that popcnt 
reports the number of bits set in a uint, regardless of popcnt's 
argument being a smaller size integer type or signed. That would 
make (popcnt( -(2^^31) ) == 1) yield true, which isn't what I 
want for an isPow2 function. popcnt is only documented to take 
uint or ulong, so that's not a bug in the library, only in my try 
at using it roughly.



More information about the Digitalmars-d mailing list