# 2023q1 Homework3 (quiz3)
contributed by < `Korin777` >
## 測驗四
```c
int ceil_log2(uint32_t x)
{
uint32_t r, shift;
x--;
r = (x > 0xFFFF) << 4;
x >>= r;
shift = (x > 0xFF) << 3;
x >>= shift;
r |= shift;
shift = (x > 0xF) << 2;
x >>= shift;
r |= shift;
shift = (x > 0x3) << 1;
x >>= shift;
return (r | shift | x >> 1) + 1;
}
```
* $\lceil log_{2}(x) \rceil$ 分為以下兩種情況:
1. `x` 是 2 的冪 : $\lceil log_{2}(x) \rceil$ 為位元中 1 所在的最高位位置
2. `x` 不是 2 的冪: $\lceil log_{2}(x) \rceil$ 為位元中 1 所在的最高位位置加一
* 透過二分搜尋來找出 1 所在的最高位位置
* `x--` 確保 `x` 的位元中 1 所在的最高位位置小於 $\lceil log_{2}(x) \rceil$,因此不管 `x` 是否為 2 的冪,位元中 1 所在的最高位位置加一就是 $\lceil log_{2}(x) \rceil$
* 當 `x` 為 1 時輸出應為 0 ,不過這個實作會輸出 1 ,因為 `x--` 後位元中 1 所在的最高位位置應該不為 0 , 下面的實作可以改善這個問題
```c
int ceil_log2(uint32_t x)
{
uint32_t r, shift;
int ceil = !((x & x-1) == 0);
r = (x > 0xFFFF) << 4;
x >>= r;
shift = (x > 0xFF) << 3;
x >>= shift;
r |= shift;
shift = (x > 0xF) << 2;
x >>= shift;
r |= shift;
shift = (x > 0x3) << 1;
x >>= shift;
return (r | shift | x >> 1) + ceil;
}
```
* `(x & x-1) == 0` 可以判斷 x 是否為 2 的冪,也就可以判別 $\lceil log_{2}(x) \rceil$ 的兩種情況, 因此找出 `x` 位元中 1 所在的最高位位置再加上 `!((x & x-1) == 0)` 就可以求得 $\lceil log_{2}(x) \rceil$
[題目連結](https://hackmd.io/@sysprog/linux2023-quiz3#%E6%B8%AC%E9%A9%97-3)