Vdsp(bf561)中的浮点运算(15):vdsp库的一个BUG

在写完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可以修正。

时间: 2024-09-19 08:52:00

Vdsp(bf561)中的浮点运算(15):vdsp库的一个BUG的相关文章

Vdsp(bf561)中的浮点运算(1):文档的说法

在vdsp提供的<VisualDSP++ 5.0 C/C++ Compiler and Library Manual for Blackfin Processors Revision 5.1, August 2008>中列出了vdsp支持的所有数据类型,其中与浮点有点的类型有: Type Bit Size Number Representation sizeof returns double 32 bits 32-bit IEEE single-precision 4 float 32 bit

Vdsp(bf561)中的浮点运算(11):fract16与float的转换

vdsp提供了两个函数用以实现fract16与float之间的相互转换: fract16 float_to_fr16 (float _x); float fr16_to_float (fract16 _x); 看看这两个转换函数到底做了什么. 1.1 float_to_fr16 这个函数的原始代码在Blackfin\lib\src\libc\runtime\fl2fr.asm中,先看看它的注释: /*************************************************

Vdsp(bf561)中的浮点运算(10):fract16类型表示

fract16是VDSP的另一种浮点类型,它使用1.15的格式: 最高位为符号位,其余为数据位,没有指数和尾数的概念. 最大值:+0.999969482421875 最小值:-1 分辨率:2-15 = 0.000030517578125 在blackfin里面使用fract类型进行计算可以获得最好的性能,但是要求在使用之前对需要进行计算的数据进行归一化,而且必须保证在计算过程中不会产生溢出. 在对数据归一化的时候,通常是需要进行浮点计算的,因此要产生很多额外的开销,如果使用fract进行的计算量

Vdsp(bf561)中的浮点运算(16):fract2x16类型

由于BF561内部带有两个16位的MAC,因此它将可以在一个周期内进行两个fract16类型的运算. 为适应这种特性,vdsp引入了一个称之为fract2x16的类型.它其实是定义为一个int类型的整数,但是其实际意义却是要用高低16位分别来表示两个fract16类型. typedef int _raw32; typedef _raw32 raw2x16; typedef raw2x16 fract2x16; 要查看fract2x16类型的值还是只能通过data register窗口,手动将类型

Vdsp(bf561)中的浮点运算(14):fract16除法

原来指望能够有div_fr1x16之类的函数来实现fract16的除法,但是很遗憾vdsp居然不直接提供这样的函数,让人颇为尴尬,估计是因为其CPU不直接提供fract除法的缘故.不过vdsp文档里面提供了一个做除法的例子: fract16 saturating_fract_divide(fract16 nom, fract16 denom) { int partialres = (int)nom; int divisor = (int)denom; fract16 rtn; int i; in

Vdsp(bf561)中的浮点运算(13):fract16乘法运算

vdsp提供了三种不同的方式进行fract16的乘法运算. 1.1 mult_fr1x16函数 这个函数定义为: #pragma inline #pragma always_inline static fract16 mult_fr1x16(fract16 __a, fract16 __b) { fract16 __rval = __builtin_mult_fr1x16(__a, __b); return __rval; } 从这里可以看出我们实际可以使用__builtin_mult_fr1x

Vdsp(bf561)中的浮点运算(8):float除法运算

1.1 Vdsp对float除法运算的处理 在vdsp下,可以很简单地用: float fdiv(float x, float y) { float r = x / y; return r; } 来完成浮点除法运算,编译器自动将里面的乘法操作转换为___float32_div的函数调用,这个函数的调用实现在libdsp/fpdiv.asm中,在这个文件的开头说明了这个函数的用法: /*********************************************************

Vdsp(bf561)中的浮点运算(7):float乘法运算

1.1 Vdsp对float乘法运算的处理 在vdsp下,可以很简单地用: float mul (float x, float y) { float r = x * y; return r; } 来完成浮点乘法运算,编译器自动将里面的乘法操作转换为___float32_mul的函数调用,这个函数的调用实现在libdsp/fpmult.asm中,在这个文件的开头说明了这个函数的用法: /********************************************************

Vdsp(bf561)中的浮点运算(6):float加减运算

一直以为float加减运算很简单,无非就是将之转换为__float32_add和__float32_sub这两个函数调用而已,然后用软件模拟进行加减运算.但真的如此简单吗?当一些让人不太舒服的条件出现的时候,还是如此吗? 1.1 Vdsp对float加减运算的处理 在vdsp下,可以很简单地用: float add(float x, float y) { float r = x + y; return r; } float sub(float x, float y) { float r = x