## 測驗 $\alpha -1$ 解釋上述程式碼運作原理 * st_rotate_left ```graphviz digraph st_rotate_left { graph [center=true, margin=0.01, nodesep=0.1, ranksep=0.2, width=2,ratio=.25]; node [fontname="Courier New",color="0.0 0.0 0.0",fixedsize=true,width=0.6,shape=circle,label="",fontsize="20"]; node [margin=0.02,fillcolor="lightgrey"]; edge [dir=none]; node [fillcolor="black"]; graph [style=invis]; subgraph cluster_Lower { Lower[label = "p"]; LowerL[label = "n"]; LowerM [style=invis]; LowerR [style=invis]; Lower -> LowerR [weight=100 style=invis]; Lower -> LowerM [weight=100 style=invis]; Lower -> LowerL; LowerLL[label = "l"]; LowerLM [style=invis]; LowerLR [style=invis]; LowerRM [style=invis]; LowerRR [style=invis]; LowerLLL[style=invis]; LowerLLM[style=invis]; LowerLLR[label = "l_r"] LowerL -> LowerLR [weight=100 style=invis]; LowerL -> LowerLL ; LowerL -> LowerLM [weight=100 style=invis]; LowerR -> LowerRR [style=invis]; LowerR -> LowerRM [weight=100 style=invis]; LowerLL ->LowerLLL[weight=100 style=invis]; LowerLL ->LowerLLM[weight=100 style=invis]; LowerLL ->LowerLLR } node [fillcolor="red"]; subgraph cluster_Upper { Upper[label = "p"]; UpperL[label = "l"]; UpperM [style=invis]; UpperR [style=invis]; UpperRM [style=invis]; UpperRR [style=invis]; Upper->UpperL; Upper->UpperM[weight=100 style=invis]; Upper->UpperR[style=invis]; UpperLL[style=invis]; UpperLM[style=invis]; UpperLR[label = "n"]; UpperR->UpperRM[style=invis]; UpperL->UpperLL[style=invis]; UpperL->UpperLM[style=invis]; UpperL->UpperLR; UpperRRR[label = "l_r"]; UpperRRL[style=invis]; UpperRRM[style=invis]; UpperLR->UpperRRL[style=invis]; UpperLR->UpperRRR; UpperLR->UpperRRM[style=invis]; } } ``` ## 測驗 $\alpha -2$ 撰寫時間量測程式碼 1. 引入資料結構 ```timespec```,實作計算時間消耗的函示 ```diff_in_second```: ```c struct timespec start, end; double cpu_time1, cpu_time2; static double diff_in_second(struct timespec t1, struct timespec t2) { struct timespec diff; if (t2.tv_nsec-t1.tv_nsec < 0) { diff.tv_sec = t2.tv_sec - t1.tv_sec - 1; diff.tv_nsec = t2.tv_nsec - t1.tv_nsec + 1000000000; } else { diff.tv_sec = t2.tv_sec - t1.tv_sec; diff.tv_nsec = t2.tv_nsec - t1.tv_nsec; } return (diff.tv_sec + diff.tv_nsec / 1000000000.0); } ``` 2. 量測 insert 與 remove 消耗時間: ```c clock_gettime(CLOCK_REALTIME, &start); for (long int j = 0; j < num; ++j) { treeint_insert(rand() % (num - 1)); } clock_gettime(CLOCK_REALTIME, &end); t1 = diff_in_second(start, end); ``` 其中 ```num``` 為需要 insert/remove 的節點總數。對應 remove 的部分: ```c clock_gettime(CLOCK_REALTIME, &start); for (long int k = 0; k < num; ++k) { int v = rand() % (num - 1); treeint_remove(v); } clock_gettime(CLOCK_REALTIME, &end); t2 = diff_in_second(start, end); ``` 3. 使用 numpy 與 matplotlib 繪製結果: ```python import numpy as np import matplotlib .pyplot as plt if __name__ == "__main__": output = np.loadtxt('data.txt', dtype='float').T X = output[0] fig, ax = plt.subplots(1, 1, sharey=True) ax.set_title('Time consumption', fontsize=16) ax.set_xlabel('numbers of insert/remove', fontsize=16) ax.set_ylabel('time (s)', fontsize=16) ax.plot(X, output[1], marker='+', markersize=3, label='insert') ax.plot(X, output[2], marker='*', markersize=3, label='remove') ax.legend(loc='upper left') plt.show() ``` 4. 實驗結果: * 硬體設備資訊 ``` MacBook Pro (16-inch, 2019) 處理器:2.3 GHz 8 核心 Intel Core i9 ``` ![](https://hackmd.io/_uploads/SJ6NHLZ22.png) ## 測驗 $\beta -1$ 觀察數值為 2 的冪的倍數時,其二進為表示法的最低 $n-1$ 的位元為 0。因此數值 $x$ 以 2 的冪做向上對齊時 (align up),考慮以下情況: ```align_up(120, 4)``` 輸出結果為 120 $\to$ 11110<font color="#f00">00</font> ```align_up(121, 4)``` 輸出結果為 124 $\to$ 11111<font color="#f00">00</font> ```align_up(122, 4)``` 輸出結果為 124 $\to$ 11111<font color="#f00">00</font> ```align_up(124, 4)``` 輸出結果為 124 $\to$ 11111<font color="#f00">00</font> 1. 120 已經是 ```align_up(120, 4)``` 的結果。 2. 121 做完 ```align_up(121, 4)``` 後為二進位 11111<font color="#f00">00</font>,既然是向上對齊,考慮加上對齊值 $2^n$ ,然後對對齊值低於 $n$ 的位元遮蔽: ```(121 + 4) &~ (4-1) = 124``` 4. ```(122 + 4) &~ (4-1) = 124``` 5. ```(123 + 4) &~ (4-1) = 124``` 6. ```(124 + 4) &~ (4-1) = 128```,然而 124 做 align_up(124, 4) 是 124。觀察 124 + 4 的二進位,其第 2 位元發生進位,為避免此情況,改寫為 `(124 + (4-1)) &~ (4-1) = 124` 完整程式碼: ```c #include <stdint.h> static inline uintptr_t align_up(uintptr_t sz, size_t alignment) { uintptr_t mask = alignment - 1; if ((alignment & mask) == 0) { /* power of two? */ return (((sz) + (mask)) & ~(mask)); } return (((sz + mask) / alignment) * alignment); } ``` ## 測驗 $\gamma -1$