Question

Came across this algorithm to compute the page offset for a given address.

 //naive solution:
int getAlignedValue(int pageSize, int valueToAlign)
{
    int index = valueToAlign/pageSize;
    return index * pageSize;
}

//faster solution:
int getAlignedValue_Fast(int pageSize, int valueToAlign)
{
    return valueToAlign & (~(pageSize-1));
}

The naive approach is straightforward and intuitive, but the faster solution only works if the page size is a power of 2. For instance,

pagesize = 8
address = 30
getAlignedValue(8,30) => 24
getAlignedValue_Fast(8,30) => 24

However, when the pagesize is not a power of 2, such as 10
pagesize = 10
address = 24
getAlignedValue(10,24) => 20
getAlignedValue_Fast(10,24) => 16 //wrong

My question is what property the faster approach uses when the page size is a power of 2 such that valueToAlign & (~(pageSize-1)) "happened to" return the correct alignment e.g. 24. In other words, from the bit comparison one by one, all I understood was that it somehow worked, but without understanding the math behind it.

//leading 0s are ignored
pagesize = 8 => 00001000, address = 30 => 00011110
=>
~(pagesize - 1) = ~(00000111) = > 11111000 
=>
 00011110
&11111000
----------
 00011000 = 24

Thank you very much.

Was it helpful?

Solution

If pageSize is a power of two (ie, it has only 1 bit set) then ~(pageSize - 1) (equivalently to ~pageSize + 1 and to -pageSize on most systems) still has that specific bit set, and all higher bits also get set:

pageSize     = 00001000  // bit k is set
// now the -1 will borrow through all rightmost zeroes and finally reset the 1
pageSize-1   = 00000111  // all bits < k are set
// inverting restores the original 1 and also sets all higher bits
~(pageSize-1)= 11111000  // all bits >= k are set

AND-ing by that aligns to pageSize, because, for example, being aligned to 8 means that no bits that are "worth less" than 8 are set. The mask leaves 8 (in this example) and all higher powers of two, but all lower powers of two (1, 2 and 4) are removed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top