• Visual DSP定点数(fract)使用指南


    fract数据类型(Fractional Data Type

    C类型

    用法

    fract16

    16位有符号定点数,1.15

    fract32

    32位有符号定点数1.31

    fract2x16

    16位有符号定点数

    这几个数据类型实际上并不是固有的数据类型,而是使用typedef语句将short定义成fract16,long定义成fract32fract2x16。因此,你不能直接通过fract16*fract16来得到正确的定点相乘结果。对于C++,有两个类”fract””shortfract”定义了基本的算术操作。以下仅谈在C中的操作。

    内建函数(Built-in Functions

    由于fract算术的特殊性,系统提供了一套接口用于实现这些运算,它们定义在fract.h文件中。所有在fract.h中的文件都被标记为“内联”的,所以如果开了编译器优化,内建函数将会被展开。下面给出的内建函数并不全,更多的请参考[1]

    fract16 内建函数

    fract16 add_fr1x16(fract16 f1, fract16 f2);

           执行16位加法(f1 + f2)

    fract16 sub_fr1x16(fract16 f1, fract16 f2);

           执行16位减法(f1 – f2)

    fract16 mult_fr1x16(fract16 f1, fract16 f2)

           执行16位乘法(f1 * f2),结果截短到16

    fract16 multr_fr1x16(fract16 f1, fract16 f2)

           执行16位乘法,结果舍入到16位。是否进位根据ASTAT寄存器的RND_MOD是否被设置。

    fract32 mult_fr1x32(fract16 f1, fract16 f2)

           执行16位乘法,返回32位结果。

    fract16 abs_fr1x16(fract16 f1)

           返回输入参数的绝对值,如0x8000返回0x7fff

    fract16 min_fr1x16(fract16 f1, fract16 f2)

           返回f1,f2的较小值

    fract16 max_fr1x16(fract16 f1, fract16 f2)

           返回f1,f2的较大值

    fract16 negate_fr1x16(fract16 f1)

           返回-f1

    fract16 shl_fr1x16(fract16 src, short shft)

           src作算术移位,shft为正则向左移,保留符号位,空的位用0填充;shft为负则向右移,符号扩展;

    fract32 内建函数

    fract32 add_fr1x32(fract32 f1,fract32 f2)

           返回f1 + f2

    fract32 sub_fr1x32(fract32 f1,fract32 f2)

           返回f1 – f2

    fract32 mult_fr1x32x32(fract32 f1,fract32 f2)

           返回f1*f2,运算的中间结果保存在40位的累加寄存器,然后舍入到32位。

    fract32 multr_fr1x32x32(fract32 f1,fract32 f2)

           和上一个函数一样,只不过提供了额外的舍入精度

    fract32 mult_fr1x32x32NS(fract32 f1, fract32 f2)

           提供不饱和的乘法f1 * f2,这个相对来说会快一些

    fract32 abs_fr1x32(fract32 f1)

           返回f1的绝对值

    fract32 min_fr1x32(fract32 f1, fract32 f2)

           返回f1, f2的较小值

    fract32 max_fr1x32(fract32 f1, fract32 f2)

           返回f1, f2的较大值

    fract32 negate_fr1x32(fract32 f1)

           返回-f1

    fract16 sat_fr1x32(fract32 f1)

           如果f1 > 0x00007fff,则返回0x7fff,如果f1< 0xffff8000,则返回0x8000,其他情况,返回f1的低16

    fract2x16 内建函数

    将两个fract16打包成fract2x16表示为{a,b}”a”为高半部,”b”为低半部

    fract2x16 compose_fr2x16(fract16 f1, fract16 f2)

    f1,f2打包成fract2x16的类型

    输入:2fract16

    输出:{f1, f2}

    fract16 high_of_fr2x16(fract2x16 f)

    返回f的高半部

    输入:{a, b}

    输出:a

    fract16 low_of_fr2x16(fract2x16 f)

    返回f的低半部

    输入:{a, b}

    输出:b

    fract2x16 add_fr2x16(fract2x16 f1,fract2x16 f2)

    输入:f1{a, b}, f2{c, d}

    输出:{a + c, b + d}

    fract2x16 sub_fr2x16(fract2x16 f1,fract2x16 f2)

    输入:f1{a, b}, f2{c, d}

    输出:{a – c, b – d}

    fract2x16 mult_fr2x16(fract2x16 f1,fract2x16 f2)

    输入:f1{a, b}, f2{c, d}

    输出:{trunc16(a*c), trunc16(b*d)}

    fract2x16 multr_fr2x16(fract2x16 f1,fract2x16 f2)

    输入:f1{a, b}, f2{c, d}

    输出:{round16(a*c), round16(b*d)}

    fract2x16 negate_fr2x16(fract2x16 f1)

    输入:f1{a, b}

    输出:{-a, -b}

    fract2x16 shl_fr2x16(fract2x16 f1,short shft)

    输入:f1{a, b} shft

    输出:{a << shft, b << shft}

    fract16 sum_fr2x16(fract2x16 f1)

    输入:f1{a, b}

    输出:a + b

    fract2x16 add_as_fr2x16(fract2x16 f1,fract2x16 f2)

    输入:f1{a, b}, f2{c, d}

    输出:{a + c, b – d}

    fract16fract2x16的一点注解

    当编译使用单数据fract16运算的程序时,编译器会尝试优化,寻找可以并行计算的情形,因此重写程序以显式使用fract2x16并不总是能产生性能提高。

    fract数据类型的应用(Application of Fractional Data Type)

    fract常量的表示

    要对一个fract类型(fract16, fract32)赋常量值应该使用r16,r32后缀。

    例如:

    要为fract16类型的变量a赋值0.5,那么可以使用

    a=0x4000a=0.5r16

    两种方式,显然,后者看起来更直观。

    分数与浮点数之间的转换

    VisualDSP++运行时库提供了高层次的支持用于fract与浮点数之间的转换。这些函数的声明包含在头文件fract2float_conv.h里。

    fract32 fr16_to_fr32(fract16);        //Deposits a fract16 to make a fract32

    fract16 fr32_to_fr16(fract32);        //Truncate a fract32 to make a fract16

    fract32 float_to_fr32(float);           //Convert a float to fract32

    fract16 float_to_fr16(float);           //Convert a float to fract16

    float fr16_to_float(fract16);    //Convert a fract16 to float

    float fr32_to_float(fract32);    //Convert a fract32 to float

    综合实例

    fract转换为float并输出

    #include <stdio.h>
    #include 
    <fract.h>
    #include 
    <fract2float_conv.h>

    int main( void )
    {
           fract16 x
    =0.4r16;
           
    float fx;

           fx 
    = fr16_to_float(x);
           printf(
    "x=%f\n", fx);

           
    return 0;
    }

    输出:

           x=0.399994

    fractfloat的时间花费对比

    代码很简单,这里不再费口舌:

    #include <stdio.h>
    #include 
    <fract.h>
    #include 
    <fract2float_conv.h>
    #include 
    <time.h>
    #define COUNT 10000

    int main( void )
    {
           
    int i;
           fract32 x, y, z;
           
    float fx, fy, fz;
           clock_t t1, t2;    

           
    //test fract,be sure that the sum won't overflow
           t1 
    = clock();
           x 
    = 0; y = 0; z = 0;
           
    for (i = 0; i < COUNT; i++)
           {
                  z 
    = add_fr1x32(z, mult_fr1x32x32NS(x, y));
                  x 
    = add_fr1x32(x, 0.000001r32);
                  y 
    = add_fr1x32(y, 0.000001r32);
           }
           t2 
    = clock();
           printf(
    "result:%f\n", fr32_to_float(z));
           printf(
    "fract operations cost:%uk Cycles\n", (t2 - t1) / 1000);

           
    //test float
           t1 
    = clock();
           fx 
    = 0; fy = 0; fz = 0;
           
    for (i = 0; i < COUNT; i++)
           {
                  fz 
    += fx * fy;
                  fx 
    += 0.000001;
                  fy 
    += 0.000001;
           }
           t2 
    = clock();
           printf(
    "result:%f\n", fz);
           printf(
    "float operations cost:%uk Cycles\n", (t2 - t1) / 1000);
           
    return 0;
    }

    输出(DEBUG模式)

           result:0.333131

           fract operations cost:360k Cycles

           result:0.333240

           float operations cost:5148k Cycles

    输出(RELEASE模式)

           result:0.333131

           fract operations cost:90k Cycles

           result:0.333240

           float operations cost:5018k Cycles

    这里可以看到性能的差异还是很大的。在RELEASE下,性能相差50倍以上。不过这里有一点值得注意,两个运算的结果并不完全一样,相差得有点大。这里没法给出详细的理论分析差异的原因,个人猜想是由于误差累积差成的。因此,在实际应用中,最好注意下不要这种连续累加的情况。使用multr_fr1x32x32结果会更接近一些,不过也差不了多少。

    扩展阅读(Further Reading)

    参考[1]有关于C++操作fract的详细细节,以及复数fract内建函数的使用,有兴趣的读者请自行了解。这些都在[1]Compiler->C/C++ Compiler Language->Compiler Built-In Functions章节。还有一些有关映射ETSI(European Telecommunications Standards Institute) fract函数到内建函数的资料,本人也没用过。

    参考(References

    [1]“Visual DSP++ 5.0 Compiler and Library Manual for Blackfin Processors”

  • 相关阅读:
    ubuntu 14.4 apache2 django
    github上的版本和本地版本冲突的解决方法
    Javascript能做什么 不能做什么。
    django 取model字段的verbose_name值
    Django在admin模块中显示auto_now_add=True或auto_now=True的时间类型列
    合并多个python list以及合并多个 django QuerySet 的方法
    摘抄
    Python 字符串拼接
    学习HTTP
    Django 自定义模板标签和过滤器
  • 原文地址:https://www.cnblogs.com/pheye/p/2042216.html
Copyright © 2020-2023  润新知