# 2016q3 Homework1 (CLZ) #### contributed by <andy19950> ### Count Leading Zero (CLZ) - 用來計算一筆資料前面有幾個零 - 實做方法 1.recursive 2.iteration 3.binary search technique 4.byte-shift version 5.Harley’s algorithm #### 首先來個 recursive 版本 ```clike= int clz_recur(uint32_t x, int size) { if(size == 0) return 0; // shift upper half down, rest is filled up with 0s uint16_t upper = (x >> size); // mask upper half away int loc = (int) ceil(log((double)size)/log((double)2)); uint16_t lower = (x & TABLE[loc]); return upper ? clz_recur(upper, size/2) : size + clz_recur(lower, size/2); } ``` - 原本程式碼算是個概念,我把傳入值加入了每次要檢查的 size - 取 lower 的方法是在 .h 檔定義一個 TABLE[] = {0x01, 0x03, 0x0F, 0xFF, 0xFFFF}; - 每次都把 size 取 log 以2為底,因為 C 只有 log 以 e 為底,所以我用換底公式實做以 2 為底 - 接下來就是遞迴到size = 0 的時候回傳,函式會把前面有幾個 0 通通加起來再回傳給 main #### 再來是 iteration 版本 ```clike= int clz_itera(uint32_t x) { int n = 32, c = 16; do { uint32_t y = x >> c; if (y) { n -= c; x = y; } c >>= 1; } while (c); return (n - x); } ``` - 這是參考老師給的程式碼,用 while 迴圈每次檢查 1 bit - 但這份程式碼還是把輸入資料切一半來處理,算是比較好的版本 #### 最後是 Harley's Algorithm ```clike= uint32_t clz_Harley(uint32_t x) { static const uint8_t Table[] = { 0xFF, 0, 0xFF, 15, 0xFF, 1, 28, 0xFF, 16, 0xFF, 0xFF, 0xFF, 2, 21, 29, 0xFF, 0xFF, 0xFF, 19, 17, 10, 0xFF, 12, 0xFF, 0xFF, 3, 0xFF, 6, 0xFF, 22, 30, 0xFF, 14, 0xFF, 27, 0xFF, 0xFF, 0xFF, 20, 0xFF, 18, 9, 11, 0xFF, 5, 0xFF, 0xFF, 13, 26, 0xFF, 0xFF, 8, 0xFF, 4, 0xFF, 25, 0xFF, 7, 24, 0xFF, 23, 0xFF, 31, 0xFF, }; /* Propagate leftmost 1-bit to the right */ x = x | (x >> 1); x = x | (x >> 2); x = x | (x >> 4); x = x | (x >> 8); x = x | (x >> 16); /* x = x * 0x6EB14F9 */ x = (x << 3) - x; /* Multiply by 7. */ x = (x << 8) - x; /* Multiply by 255. */ x = (x << 8) - x; /* Again. */ x = (x << 8) - x; /* Again. */ return (Table[x >> 26]); } ``` - 由於它實在是太博大精深了,等我搞懂了再來補充QQ --- ### 接下來就是效能分析拉 ![](https://i.imgur.com/YdtkZ4v.png) - recursive 版本明顯消耗更多時間 - iteration 跟 Harley 差不多,但Harley還是稍微好一點。 ---