contributed by < baimao8437
>
jack81306
一開始 make 發現沒有 git hook的兩個檔案
從之前的作業複製過來 就可以 make 了
並將在 compute-pi 學習到的 makefile 簡化法 套用這個作業
原本也想學習 compute-pi 的 test_time.c 將所有算法寫在一起
再用 define 去分別執行 但在這裡 程式的關係更為複雜
所以先不要亂動好了~
先看懂 return 跟 ternary(?:) 的混合使用
運作原理:
c 初始值為0 代表所在層數(32-16-8-4-2) 運作到 c=3 時會開始回傳加總結果
magic 主要做的是在剩下兩個 bits 以後(c==3)判斷有幾個 0
x 一進入後判斷都是0的話就回傳32
再來分為 upper & lower 兩半
當 c!=3 檢查 upper 是否為0 不是0就代 upper 進下層 是0 就代 lower 進下層且回傳值會加上確定的 0 數 (16>>c)
當 c==3 檢查 upper 是否為0 此時 upper 剩下2bits
不是0 就回傳 magic[upper] 是0就回傳 2(upper=00) + magic[lower]
magic代表的就是最後有幾個0了 接著回傳 加上之前確定的0數 就是答案
運作原理:
y 的性質跟 recursive 的 upper 一樣 先判斷 upper 是否為 0
不為 0 就先把 n 扣掉已知不重要 bits 的個數 upper 範圍縮小一半再跑一次迴圈
等於 0 就往 lower 的地方縮小範圍去跑一次迴圈
直到 y 都是 0 了 等 c 跑完跳出迴圈
最後回傳 n - x (x皆為1 n為左邊數來第幾個不為零的數)
一半一半
運作原理:
每次比一半 若 x <= 0x0000ffff 表示確定有前面 16 位是 0
就把 x 往左 shift 再比一半 依此類推 只要確定前面有幾個 0 就好
直接做位移
運作原理:
跟 binary 類似的原理 每次砍半 利用直接位移的方式來檢查前面有幾個確定為 0
有找到確定為 0 時 就要把 x 往左 shift 檢查 lower 的前面有幾個 0
最後看第一位是否為 0 (x >> 31) 扣掉後即為答案
算第幾個位置是 leading 1
運作原理:
主要操作分為兩部份 第一部份較簡單 是在將第一個(左到右)不為0的後面 全部都變1 直接看數字就懂
至於這樣做的理由 等等解釋
第2部份就比較神奇了 我看不出這些操作是什麼道理 看一下數據
只取最前面6個數字當 index 然後去找 Table[index]
得到的數字是 右邊數來第幾個是 leading 1 (0 代表第一位)
神奇的來了 第2部份的操作到底再幹嘛呢 我不想理解了直接看數據
我將 ~ 當作 input 去看程式輸出 結果:
太神奇了傑克~ 32 個 input 剛好對應了不同的 index
那我合理的將這個算法理解為一個 Hash
那兩個操作部份的意義也很明顯了 第1部份是為了同化結果
e.g. 1001 & 1100 經過 stage 1 都會變成 1111
那第2部份的操作就是他對 stage 1 ouput 的 Hash Function 愈複雜的函數能將資料分的愈均勻
Table 中就是各 index 對應的輸出結果 右邊數來第幾個是leading 1(0是第一位)
那 hash 就是以空間換取時間的作法 所以花費時間可以很短 但空間花費相對大
可以看到 如影片中所說 byte & binary 所用 cycles 最少
harley 也相對平穩
使用原本寫好的工具 在 make run
後面加上 PROFILE=1
就會進入偵錯工具 順利用所有 method 跑完所有 32-bit 數值沒有錯誤
我覺得原本的 makefile 方式可以帶來非常大的便利性
只要加上不同的 define 就可以進行不同的操作
define 的用法又比上一個作業高上一層
我還沒想到有什麼更快更便利的方法來設計
但還是自己寫了一個能夠輸出不同位錯誤個數的測試方式
輸入make generrcsv
就會產生64*5表格 格式為
但是…還在思考圖像化要怎麼表示比較好…
其實還在理解如何應用…