Alexey Kardashevskiy <a...@ozlabs.ru> writes:

> On 02/24/2015 12:59 AM, Markus Armbruster wrote:
>> Alexey Kardashevskiy <a...@ozlabs.ru> writes:
>>
>>> This adds a helper to get closest bigger power-of-two value.
>>>
>>> Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru>
>>> ---
>>> Changes:
>>> v2:
>>> * s/up_pow_of_two/pow2ceil/
>>> ---
>>>   include/qemu-common.h | 2 ++
>>>   util/cutils.c         | 9 +++++++++
>>>   2 files changed, 11 insertions(+)
>>>
>>> diff --git a/include/qemu-common.h b/include/qemu-common.h
>>> index 644b46d..ae29748 100644
>>> --- a/include/qemu-common.h
>>> +++ b/include/qemu-common.h
>>> @@ -417,6 +417,8 @@ static inline bool is_power_of_2(uint64_t value)
>>>
>>>   /* round down to the nearest power of 2*/
>>>   int64_t pow2floor(int64_t value);
>>> +/* round up to the nearest power of 2*/
>>> +int64_t pow2ceil(int64_t value);
>>>
>>>   #include "qemu/module.h"
>>>
>>> diff --git a/util/cutils.c b/util/cutils.c
>>> index dbe7412..ecaa440 100644
>>> --- a/util/cutils.c
>>> +++ b/util/cutils.c
>>> @@ -483,6 +483,15 @@ int64_t pow2floor(int64_t value)
>>>       return value;
>>>   }
>>>
>>> +/* round up to the nearest power of 2*/
>>> +int64_t pow2ceil(int64_t value)
>>> +{
>>> +    if (!is_power_of_2(value)) {
>>> +        value = 0x8000000000000000ULL >> (clz64(value) - 1);
>>> +    }
>>> +    return value;
>>> +}
>>> +
>>>   /*
>>>    * Implementation of  ULEB128 (http://en.wikipedia.org/wiki/LEB128)
>>>    * Input is limited to 14-bit numbers
>>
>> pow2ceil(INT64_MIN) = INT64_MIN.  Should be 1.
>>
>> pow2ceil(INT64_MAX) = INT64_MIN.  Garbage.
>>
>> Related: "round down to the nearest power of 2" is defined only for x >
>> 0, but our pow2floor(x) happily returns garbage then.
>>
>> In particular we return 0x8000000000000000ULL >> 64 when value is 0,.
>> Undefined behavior.
>>
>> Here's how I'd do these functions:
>>
>> int64_t pow2floor(int64_t value)
>> {
>>      assert(value > 0);
>>      return 0x8000000000000000u >> clz64(value);
>> }
>>
>> int64_t pow2ceil(int64_t value)
>> {
>>      assert(value <= 0x4000000000000000)
>>      if (value <= 1)
>>      return 1;
>>      return 0x8000000000000000u >> (clz64(value - 1) - 1);
>> }
>>
>
>
> I've read the whole thread, that was cool :)

I indulged in a bit of language lawyering, glad you liked it.

> Do you want me to repost your versions as a patch? I do not feel I
> should since it is totally yours but I can :)

I'll post a patch fixing the existing pow2floor().  I prefer not to add
pow2ceil() without a user.  If you have one, I suggest you do your
patches on top of mine.

Reply via email to