# 2020q3 Homework3 (quiz3) contributed by < `carlhutant` > [TOC] ## 測驗 1 ``` c= int asr_i(signed int m, unsigned int n) { const int logical = (((int) -1) OP1) > 0; unsigned int fixu = -(logical & (OP2)); int fix = *(int *) &fixu; return (m >> n) | (fix ^ (fix >> n)); } ``` 程式流程如下: 1. 測試平台上有號數 ASR 是否行為正確 2. 測試輸入值正負號 3. 產生修正值 4. 修正值透過 or 修正原始值 shift 後新增的 bits 將 -1 向右 shift 後有無變號可知道 ASR 是否行為正確 `OP1 = (b) >> 1` 在 "ASR 不行為正確" 與 "輸入值為負" 時進行修正,fixu 為 -1 ,否則為 0 `OP2 = (c) m < 0` 將 fix 右側 設為 0 ,只留下左側 shift 數的 1 ,這樣 or 在一起後就會矯正 shift 補 0 的錯誤 ## 測驗 2 ```c= bool isPowerOfFour(int num) { return num > 0 && (num & (num - 1))==0 && !(__builtin_ctz(num) OPQ); } ``` 若是 4 的冪次方,從右側開始在遇到 1 之前的 0 必須為偶數個,也就是 LSB 須為 0 `OPQ = (f) & 0x1` ## 測驗 3 num 若非 0 ,則必須進行 : 1. 消除所有 LSB 的 1 2. 向右 shift 到最高位的 1 來到 LSB `AAA = (a) __builtin_popcount(num)` `BBB = (b) __builtin_clz(num)` ## 測驗 4 ```c= #include <stdint.h> uint64_t gcd64(uint64_t u, uint64_t v) { if (!u || !v) return u | v; ``` 處理其中一者為 0 的情況 ```c=4 int shift; for (shift = 0; !((u | v) & 1); shift++) { u /= 2, v /= 2; } ``` 將兩者的公因數 2 都先提出來,存在 shift ```c=8 while (!(u & 1)) u /= 2; do { while (!(v & 1)) v /= 2; ``` 因為 2 被提出來了,接下來產生的公因數不會有 2 的成分,因此只要是偶數都可以 shift right 消除 ```c=13 if (u < v) { v -= u; } else { uint64_t t = u - v; u = v; v = t; } } while (XXX); ``` 減法結果存在 v ,會先變成 0 `XXX = (b) v` ```c=21 return YYY; } ``` 減出 0 時,減數會是公因數,再補上先前提出來的 2 `YYY = (e) u << shift` ## 測驗 5 ```c= #include <stddef.h> size_t improved(uint64_t *bitmap, size_t bitmapsize, uint32_t *out) { size_t pos = 0; uint64_t bitset; for (size_t k = 0; k < bitmapsize; ++k) { bitset = bitmap[k]; while (bitset != 0) { uint64_t t = KKK; int r = __builtin_ctzll(bitset); out[pos++] = k * 64 + r; bitset ^= t; } } return pos; } ``` 找出最小的 1 的位置,寫入 out 移除那個 1 再重複步驟 `KKK = (e) bitset & -bitset` 因為在 two's compliment 與自己的負數做 and 會全是 0 除了最小 1 的位置會是 1 再與 bitset 做 exclusive or 就可移除最小的 1
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up