[英]32-bit multiplication through 16-bit shifting
我正在使用移位和加法編寫一個軟乘法函數調用。 現有的函數調用如下:
unsigned long __mulsi3 (unsigned long a, unsigned long b) {
unsigned long answer = 0;
while(b)
{
if(b & 1) {
answer += a;
};
a <<= 1;
b >>= 1;
}
return answer;
}
雖然我的硬件沒有倍增器,但我有一個硬移位器。 移位器一次最多可以移位16位。
如果我想充分利用我的16位移位器。 有關如何調整上述代碼以反映我的硬件功能的任何建議? 給定的代碼每次迭代僅移位1位。
16位移位器可以一次將32位無符號長值移位16個位置。 sizeof(無符號長整數)== 32位
移位多位的能力不會有多大幫助,除非你有硬件乘法,比如說8位x 8位,或者你可以負擔得起一些RAM / ROM(例如)4位乘4位乘以查找。
通過交換參數以使乘數更小,可以幫助直接轉換和添加(正如您所做)。
如果您的機器通常更快地執行16位操作,那么一次將32位“a”視為“a1:a0”16位,類似地“b”,您可能可以將某些周期相同。 你的結果只有32位,所以你不需要做'a1 * b1' - 雖然其中一個或兩個可能都是零,所以勝利可能不大! 此外,您只需要16位'a0 * b1',因此可以完全16位 - 但如果b1(假設b <= a)通常為零,那么這也不是一個大贏家。 對於'a * b0',你需要一個32位'a'和32位加'answer',但你的乘數只有16位...這可能有助於也可能沒有幫助。
跳過乘數零的運行可能會有所幫助 - 取決於處理器和乘數的任何屬性。
FWIW:做一個神奇的'a1 * b1','(a1-a0)*(b0-b1)','a0 * b0',並根據我的小經驗,通過輪班,加法和減法合成結果是絕對的噩夢......'(a1-a0)','(b0-b1)'的標志及其產品必須得到尊重,這使得看起來像一個可愛的伎倆有點混亂。 當你完成它以及添加和減去時,你必須有一個強大的緩慢乘法,以使它全部值得! 當乘以非常非常長的整數時,這可能會有所幫助......但是內存問題可能占主導地位...當我嘗試它時,這是一種令人失望的事情。
使用16位移位可以幫助您使用以下方法進行小幅度的增強:
(U1 * P + U0) * (V1 * P + V0) = = U1 * V1 * P * P + U1 * V0 * P + U0 * V1 * P + U0 * V0 = = U1 * V1 * (P*P+P) + (U1-U0) * (V0-V1) * P + U0 * V0 * (1-P)
假設P是2的方便冪(例如,2 ^ 16,2 ^ 32),因此乘以它是快速移位。 這減少了從4到3的較小數字的乘法,並且遞歸地,對於非常長的數字,O(N ^ 1.58)而不是O(N ^ 2)。
這種方法被命名為Karatsuba的乘法 。 這里描述了更多高級版本。
對於較小的數字(例如8乘8位),如果你有足夠的快速ROM,下面的方法很快:
a * b = square(a+b)/4 - square(a-b)/4
如果要將int(square(x)/4)
制成表格,則無符號乘法需要1022個字節,有符號乘法需要510個字節。
基本方法是(假設換1): -
取決於你的硬件......
但你可以試試: -
然后 :-
union Data32
{
unsigned long l;
unsigned short s[2];
};
unsigned long shiftleft32(unsigned long valueToShift, unsigned short bitsToShift)
{
union Data32 u;
u.l = valueToShift
u.s[0] <<= bitsToShift;
u.s[0] |= (u.s[1] >> (16 - bitsToShift);
u.s[1] <<= bitsToShift
return u.l;
}
然后反過來換右轉
上面的代碼正在以傳統方式,我們在小學學習的方式成倍增加:
EX:
0101
* 0111
-------
0101
0101.
0101..
--------
100011
當然,如果你沒有乘法運算符或1位移位器,你就無法接近它! 但是,您可以通過其他方式執行此操作,例如循環:
unsigned long _mult(unsigned long a, unsigned long b)
{
unsigned long res =0;
while (a > 0)
{
res += b;
a--;
}
return res;
}
它很實用,但它滿足您的需求,無論如何,如果你有更多的約束(比如計算時間......),你可以考慮其他方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.