優化飽和加法運算

2021-07-02 15:17:43 字數 854 閱讀 5016

通常計算機上的加法運算是迴圈的,例如0x0001 + 0x7fff = 0x8000, 其中0x7fff是short型別的最大正值,0x8000是最小負值。假設我們是把兩個聲音相加,由於結果的符號反轉,將出現不連續,如果我們把上面的數當做q15定點小數來看的話,本來是正1(0x7fff),由於加了個很小的數(0x0001),結果卻變為了負1(0x8000)。

因此dsp晶元都支援飽和加法,當結果超出範圍的時候,就取範圍的上下限為結果:0x0001 + 0x7fff = 0x7fff。例如在5510晶元中,為了使用飽和加法只需要把狀態位:sata或satd設為1即可(sata和satd的具體含義請參考手冊)。這種位操作只能在彙編下進行,因此為了方便c語言程式設計,編譯器提供了偽函式_sadd和_ssub。使用這些偽函式的時候,編譯器會自動新增設定和清除飽和位的語句,例如:

a=_sadd(a,b)可能會編譯成

bset st3_sata ;設定飽和位

add t0, t1

bclr st3_sata ;清除飽和位

當幾個_sadd連續使用的時候,編譯器只設定和清除一次飽和位。但是當幾個_sadd呼叫中間還有一般的加法的話,就會設定和清除好幾次飽和位了。

例如c= _sadd(c,b); // 設定並清除一次

c= a+c;

c= _sadd(c,b); // 再設定並清除一次

如果在乙個迴圈中有多次這樣的交叉呼叫的話,飽和位將被設定和清除很多次,這樣顯然是浪費dsp資源的。因此盡量把飽和加減的呼叫集中,為了減少設定清除飽和位的次數,一些不需要飽和運算的加減也可以使用飽和運算。如果可以把整個函式都改寫為飽和加減運算的話,那麼乾脆在函式最前面新增asm(" bset st3_sata");手工設定飽和位,這樣程式中可以直接是用加減號運算。

使用移位和加法運算替代乘法運算

因為工作中遇到頻繁操作乘法運算導致用時過多的情況,特找了下替代方案,但實測效果並不理想,暫做記錄。include include include include define max nm a,b a b?a b define min nm a,b a b?a b define repeat num...

與或運算和加減運算

從數電位運算得角度康康加減運算,用c跑一跑 operation.cpp to understand the connection between and or and addition subtraction include using namespace std intmain add 64 to...

php array merge和加法陣列的區別

echo 索引陣列 n arr1 e w q arr2 a g h print r arr1 print r arr2 echo 當是索引陣列的時候 echo 加法 print r arr2 arr1 echo merge print r array merge arr2 arr1 echo 關聯陣...