contributed by < w96086123
>
為求 的開根號,可利用 Digit-by-digit calculation 的方式取得。
可將 拆分為由 n 個整數之和:
將此展開之後可得:
因此可知 即為所求。
目的是從試著找出所有 ,因此由 n 試到 0 並且因為 只有兩種可能 ,因此求 時只須試驗 ,即可知道 的值。
由於每輪計算 的成本過高,因此改為利用上輪的差值 減去 可得
也就是紀錄上一輪的 來調整。
拆分 可得上述的 和 ,並且藉由位元運算推出下一輪
由上述可知 AAAA
為 2 ,BBBB
為 1 。
__builtin_clz
此函數在 \lib\math\int_sqrt.c
。
找到 int_sqrt
被用在 rwb_arm_timer
中,而 rwb_arm_timer
的路徑是 \block\blk-wbt.c
。
此函數 rwb
代表的是 request write back
,因此可以知道它是一個寫入的函數。
此函數主要想要判斷是否有需要提昇寫入速度,若有需要則使用調整 window size 的方法進行提昇,且調整方法為透過 Fast inverse square root 。
但為何要使用 8 與 4 這樣狀況無法得知,只能猜測可能是基於實驗過後的結果所得出的結論。
主要想法為想要使用 bitwise 的方式進行除法運算,但 10 不是 2 的冪次,因此無法直接使用,所以此方法想把 in 改變成 ,後使用右移三位取得 。
但 in 無法使用直接轉成 ,因此使用逼近法取得數值 q = (q >> 8) + x
。
根據上述的計算過程,可得知要取得商數只需要將 q
右移三位即可,因此 CCCC
為 3 。
則想要取得餘數可利用餘數定理取得,((q & ~0x7) + (*div << DDDD))
則為 ,因此 即為餘數。
主要作法與 __builtin_clz
相似,尋找 MSB 的數值以取得以 2 為底的對數整數。
以長度為 32 位元的為例,若 i
大於 代表前 16 位元中含有 bit 為 1 ,以此類推可得以下程式:
由於此方法可以直接使用 __builtin_clz
代替,因此也可得以下程式:
shift
用來記錄當下 msb 的值,並且使用 r
進行 shift
的累加,以取得 ilog2
的數值。在這過程中,需要注意到我們要取得的是上限值,因此在一開始進行 -1
,主要為了處理 x
剛好為 2 的指數次方狀況。如果沒有做此動作,在輸出時會因為回傳的 +1
而比正確答案多一。
可以在進行運算前,先進行判斷是否 x 為 0 ,若是則改為 1 。後續處理方式一樣,程式碼如下。