# 2020q3 Homework4 (quiz4) contributed by < ```howish``` > ## 測驗1 ```c= int hammingDistance(int x, int y) { return __builtin_popcount(x ^ y); } ``` gcc extension `__builtin_popcount` 計算了一個數字的二進位裡出現的 1 的個數,而兩個數字的XOR`x ^ y`正是將兩個數字的二進位中不同的地方計算成 1 ,相同的地方計算成 0 ,因此計算 x ^ y 的 1 的個數正是等於這兩個數字的 hamming distance ## 測驗2 ```c= typedef struct { int n; int **parent; int max_level; } TreeAncestor; TreeAncestor *treeAncestorCreate(int n, int *parents, int parentSize) { TreeAncestor *obj = malloc(sizeof(TreeAncestor)); obj->n = n; obj->parent = malloc(n * sizeof(int *)); // Allocate parents int max_level = 32 - __builtin_clz(n) + 1; for (int i = 0; i < n; i++) { obj->parent[i] = malloc(max_level * sizeof(int)); for (int j = 0; j < max_level; j++) obj->parent[i][j] = -1; } for (int i = 0; i < parentSize; i++) obj->parent[i][0] = parents[i]; // Get parent array for each element for (int j = 1;; j++) { int quit = 1; for (int i = 0; i < parentSize; i++) { obj->parent[i][j] = obj->parent[i][j + (-1)] == -1 ? -1 : obj->parent[obj->parent[i][j - 1]][j - 1]; if (obj->parent[i][j] != -1) quit = 0; } if (quit) break; } obj->max_level = max_level - 1; return obj; } ``` 考慮範例給的樹 ![樹](https://i.imgur.com/xT8OuCR.png) 這段程式碼實際上是造了一個 parent table,儲存了所有2密次 |Relative dist|1|2|4|8| |:-:|:-:|:-:|:-:|:-:| |Ancestors of n0|||| |Ancestors of n1|||| |Ancestors of n2|||| |Ancestors of n3|||| ## 測驗3 ```c= #define MSG_LEN 8 static inline bool is_divisible(uint32_t n, uint64_t M) { return n * M <= M - 1; } static uint64_t M3 = UINT64_C(0xFFFFFFFFFFFFFFFF) / 3 + 1; static uint64_t M5 = UINT64_C(0xFFFFFFFFFFFFFFFF) / 5 + 1; int main(int argc, char *argv[]) { for (size_t i = 1; i <= 100; i++) { uint8_t div3 = is_divisible(i, M3); uint8_t div5 = is_divisible(i, M5); unsigned int length = (2 << div3) << div5; char fmt[MSG_LEN + 1]; strncpy(fmt, &"FizzBuzz%u"[(MSG_LEN >> div5) >> (div3 << 2)], length); fmt[length] = '\0'; printf(fmt, i); printf("\n"); } return 0; } ``` 下表表示了`div3`與`div5`所有可能需要使用的index值,可知答案為 div5 → div3 → 2 時與所有 | `div3` | `div5` |`(8>>div5)>>(div3<<2)`| |:------:|:------:|:--------------------:| | 0 | 0 | 8 | | 0 | 1 | 4 | | 1 | 0 | 0 | | 1 | 1 | 0 | ## 測驗4 ```c= #define ffs32(x) ((__builtin_ffs(x)) - 1) size_t bitwise(size_t offset, size_t page_queues) { size_t blockidx; size_t divident = page_queues; blockidx = offset >> ffs32(divident); divident >>= ffs32(divident); switch (divident) { case 3: blockidx /= 3; break; case 5: blockidx /= 5; break; case 7: blockidx /= 7; break; } } ``` `__builtin_ffs` 這個函式計算了此數字的二進位表示法中第一個1出現在從右數來第幾個。`((__builtin_ffs(x)) - 1)` 就是計算了二進位表示法中最右邊有幾個0。 這意味著在此程式碼中5~6行直接去掉了除數與被除數的2冪次因數。故 `divident` 只可能是奇數,也就是 3, 5, 7 三種可能。