当前位置:首页 >> 编程开发 >> Visual C++ >> 内容

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

时间:2015/5/19 21:37:26 作者:平凡之路 来源:xuhantao.com 浏览:

原来指望能够有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;
 int aq;   /* initial value irrelevant */

 if (partialres == 0) {
  /* 0/anything gives 0 */
  rtn = 0;
 } else if (partialres >= divisor) {
          /* fract16 values have the range -1.0 <= x < +1.0,  */
         /* so our result cannot be as high as 1.0.  */
         /* Therefore, for x/y, if x is larger than y, */
         /* saturate the result to positive maximum.   */
         rtn = 0x7fff;
 } else {
  /* nom is a 16-bit fractional value, so move */
  /* the 16 bits to the top of partialres. */
  /* (promote fract16 to fract32) */
  partialres <<= 16;

  /* initialize sign bit and AQ, via divs(). */
  partialres = divs(partialres, divisor, &aq);

  /* Update each of the value bits of the partial result */
  /* and reset AQ via divq().  */
  for (i=0; i<15; i++) {
   partialres = divq(partialres, divisor, &aq);
  }

  rtn = (fract16) partialres;
 }

 return rtn;

}

这个计算过程在不打开优化的情况下将需要500个cycle,在打开优化之后将只需要42个cycle!相比较于将fract16转换为float进行计算还是要快得多。

但是很显然,例子中给出的这个函数并没有考虑到符号位,比如计算0.2 / -0.4这样的式子时它将直接返回1,因而我们需要对它进行适当的修改。

fract16 saturating_fract_divide(fract16 nom, fract16 denom)
{
 int partialres;
 int divisor;
 fract16 rtn;
 int i;
 int aq;   /* initial value irrelevant */
 int sign = (nom ^ denom) & 0x8000;
 partialres = abs_fr1x16(nom);
 divisor = abs_fr1x16(denom);

 if (partialres == 0) {
  /* 0/anything gives 0 */
  rtn = 0;
 } else if (partialres >= divisor) {
    /* fract16 values have the range -1.0 <= x < +1.0,  */
    /* so our result cannot be as high as 1.0.  */
    /* Therefore, for x/y, if x is larger than y, */
    /* saturate the result to positive maximum.   */
    rtn = 0x7fff;
 } else {
     /* nom is a 16-bit fractional value, so move */
     /* the 16 bits to the top of partialres.     */
     /* (promote fract16 to fract32) */
     partialres <<= 16;

     /* initialize sign bit and AQ, via divs(). */
     partialres = divs(partialres, divisor, &aq);

     /* Update each of the value bits of the partial result */
     /* and reset AQ via divq().  */
     for (i=0; i<15; i++) {
      partialres = divq(partialres, divisor, &aq);
     }

     rtn = (fract16) (partialres);
     if(sign)
      rtn = negate_fr1x16(rtn);
 }

 return rtn;

}

优化之前需要522个cycle,优化之后需要50个cycle。

相关文章
  • 没有相关文章
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
  • 徐汉涛(www.xuhantao.com) © 2024 版权所有 All Rights Reserved.
  • 部分内容来自网络,如有侵权请联系站长尽快处理 站长QQ:965898558(广告及站内业务受理) 网站备案号:蒙ICP备15000590号-1