在寫完fract除法之後,偶然發現在vdsp的一個頭文件中提供了fract16除法運算的函數,這個文件就是VisualDSP 5.0\Blackfin\include\fract_math.h:
/* Produces a result which is the fractional division of f1 by f2. Not a builtin
* as written in C code. */
#pragma inline
#pragma always_inline
static fract16 div_s(fract16 _a, fract16 _b) {
int x = (int)_a;
int y = (int)_b;
fract16 rtn;
int i;
int aq;
if (x==0) {
rtn = 0;
}
else if (x>=y) {
rtn = 0x7fff;
}
else {
x <<= 16;
x = divs(x, y, &aq);
for (i=0; i<15; i++) {
x = divq(x, y, &aq);
}
rtn = (fract16) x;
}
return rtn;
}
這個內聯函數和vdsp文檔中提供的示例函數完全一樣,也就是說,它存在一個《Vdsp(bf561)中的浮點運算(14):fract16除法》中提到的缺陷,如果你用它計算一個正的小數和一個負的小數的除法,它將毫不客氣地返回1。
比如用它計算 0.2 / -0.4,這個是不應該出現飽和的!
出現這個問題的原因在於
int x = (int)_a;
int y = (int)_b;
然後就進行了x和y的比較,由於進行的是整數的比較,正數顯然永遠大於負數,所以就造成了這樣的問題。
以0.2 / -0.4為例:
0.2轉換為以十六進制表示的數為0x1999,而-0.4則為0xCCCC,當這兩個值賦給x和y後分別變成了0x00001999和0xffffcccc,也就是6553和-13108,哈哈,正數大於負數,小學生都知道!
期待下一個update可以修正。