contributed by < Brianpan
>
mpi_t[1]的理由: 根據03/04課堂筆記將mpi_t定義為一個元素的陣列,在編譯時便可確保 mpi_t
始終會佔據一個 struct 的空間。而使用陣列的形式而非指標,即可不需要再額外分配記憶體
上取整數的商, 此計算方法是利用餘數定義
同時加上d-1
(2d -1)/d的商數仍是1故這個方法成立
詳細步驟參見
此程式每個區塊我們最大利用的空間為31位元
因此我們的INTMAX會是0x7ffffff
mpi_set_u64的邏輯是
略過初始化和清理區域變數
乘法的主要邏輯是這個雙層迴圈
乘數和被乘數以區塊為單位相乘得到的結果再放置到相應的位置
舉個例子 n = 0, m = 1
先將對應區塊的乘積算出, 也就是變數r,使用uint64_t是因為兩個31位元大小乘法必須使用64位元存放
c變數為進位的數值
再來是填格子,把乘積放到對應的位置
k從m+n開始算起,因為至少會從m+n位開始填
可以想成指數乘法
繼續條件是考慮是否有進位或是仍有數值沒處理
利用的函式:
mpi_sizeinbase: 計算需要多少個位元, 8 -> 結果為三
mpi_mul_2exp:取得 ->這裡的x是1
mpi_testbit:比較某個索引的值是否是1
mpi_setbit:設置特定位元至某個索引
mpi_sub: mpi減法運算
主要程式邏輯可以想成直式除法
的用意是上一輪結束後要和新一輪位數合併
至於使用1的理由是我們是以二進位表示法的除法
接著判斷被除數的新加進來的最右位是否存在
存在就設置位元
第二個if是直式除法的核心邏輯
如果現在被除數的值比除數大,減掉被除數, 並設置商在該i位元為一
比起十進位簡化很多,因為二進位除法一個位數的商只有0或1兩種可能
用的是輾轉相除法的定義解
透過利用硬體的word大小, 一次進行以word大小的區塊做操作
本題是一次比較sizeof(long)長度的字串是否包含要找尋的目標字元
函數定義: void *memchr_opt(const void *str, int c, size_t len)
找到出現字元c的指標位置,如果沒有回傳NULL
改進的方法是利用SWAR技巧一次比較一個word大小
本題是比較sizeof(long)
DETECT_CHAR呼叫DETECLT_NULL(X^mask)判斷X和mask是否有位元組相符
用XOR比較的理由是如果位元組相同回傳0x00
接著解構DETECT_NULL巨集
: 如果某個位元組是0x00相減過後為0xFF
: 取一補數後0x00會變為0xFF
:如果該字元是0x00前面兩個操作結束後的最高位是1
詳見整理筆記
建立coroutine後要更改狀態是可排程ENV_RUNNABLE
排程coroutine使用attempts + 1
避免重複在試同一個coroutine
coro_yield: 讓出資源給其他coroutine
搶佔coroutine就是讓出現在的資源給其他coroutine
CRC 計算時,不是使用標準的數字除法,而是透過 XOR 運算來模擬二進位多項式的除法
在計算 CRC 時,使用資料的多項式去除以預先指定的 CRC 多項式,取餘數作為校驗碼。例如,給定資料 11010101(8-bit),若用 0x1EDC6F41 來除,就會得到一個 32-bit 餘數,這就是 CRC32 的值。
在編譯器最佳化的運作下(cmov)使用三元運算子會有更好的效率
題目是要計算32位元組長度的CRC校驗碼產生
利用godbolt程式碼來改寫
最外層迴圈i是執行16組的預設資料
內迴圈j是每4個位元為一組
(crc & 1):檢查LSB是否為一
-(int)(crc & 1): 如果為一,取負數的32位元組表示是0xffffffff相當於所有的位元為一
AAA: 0xc38d26c4
BBB: 0xd3d3e1ab
CCC: 0xe330a81a
DDD: 0xf36e6f75
沒有修過信號與系統 先跳過 @@
主要程式碼邏輯透過下圖的描述建立一個TCP伺服器
socket() -> bind() -> listen() 在 event loop之前完成
accept()則是在event loop去取得新連接
中間有一段ioctl使得連結不是blocking
原因如註解所說斷開的連結仍可以讀取, 所以之後的read呼叫可能會卡住
主要的改動是多一個結構體userinfo的陣列存取使用者名稱
在每一次accept()之後給使用者發送訊息輸入使用者名稱
並且透過set_userinfo去判斷儲存使用者名稱
並在廣播訊息的時候把發訊息的使用者名稱透過snprintf再寫給建立連接的其他檔案描述子