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中,先看看它的注释:

/***************************************************************************
*
* Function:  FLOAT_TO_FR16 -- Convert a floating-point value to a fract16
*
* Synopsis:
*
*       #include <fract2float_conv.h>
*       fract16 float_to_fr16(float x);
*
* Description:
*
*       The float_to_fr16 function converts a single precision, 32-bit IEEE
*       value into a fract16 number in 1.15 notation. Floating-point values
*       that cannot be converted to fract15 notation are handled as follows:
*
*           Return 0x7fffffff if x >= 1.0 or  NaN or +Inf
*           Return 0x80000000 if x < -1.0 or -NaN or -Inf
*           Return 0          if fabs(x) < 3.0517578125e-5
*
*       (Note that the IEEE single precision, 32-bit, representation
*       contains 24 bits of precision, made up of a hidden bit and 23
*       bits of mantissa, and thus some precision may be lost by converting
*       a float to a fract16).
*
* Algorithm:
*
*       The traditional algorithm to convert a floating-point value to 1.15
*       fractional notation is:
*
*           (fract16) (x * 32768.0)
*
*       However on Blackfin, floating-point multiplication is relatively
*       slow is emulated in software, and this basic algorithm does not
*       handle out of range results.
*
*       This implementation is based on the support routine that converts
*       a float to fract32, and then converts the fract32 into a fract16
*       by performing an arithmetic right shift by 16 bits. (It is possible
*       to avoid the shift by coding the function to "multiply" the input
*       input argument by 2^15 (rather than 2^31) but this approach can lead
*       to the loss of 1-bit precision when handling negative inputs).
*
*       The following is a C implementation of this function and is about
*       a third slower:

#include <fract2float_conv.h>

extern fract16
float_to_fr16(float x)
{

int temp;
fract32 result;

temp = *(int *)(&x);

if ((temp & 0x7f800000) >= 0x3f800000) {
result = 0x7fffffff;
if (temp < 0)
result = 0x80000000;
} else {
temp = temp + 0x0f800000;
result = *(float *)(&temp);
}

return (result >> 16);

}
*
*       WARNING: This algorithm assumes that the floating-point number
*       representation is conformant with IEEE.
*
* Cycle Counts:
*
*       31 cycles when the result is within range
*       30 cycles when the result is out of range
*       28 cycles when the input is 0.0
*
*       These cycle counts were measured using the BF532 cycle accurate
*       simulator and include the overheads involved in calling the function
*       as well as the costs associated with argument passing.
*
* Code Size:
*
*       76 bytes
*
* Registers Used:
*
*       R0 - the input argument
*       R1 - various constants
*       R2 - the exponent of the input argument or a shift amount
*       R3 - the mantissa of the input argument
*
* (c) Copyright 2006 Analog Devices, Inc.  All rights reserved.
*     $Revision: 1.3 $
*
***************************************************************************/

时间: 2024-10-29 11:48:21

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

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

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)中的浮点运算(10):fract16类型表示

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

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)中的浮点运算(12):fract16加减运算

由于减法实际可以看成加上一个负数,因此我们只需要看加法操作.fract16的加法运算由add_fr1x16函数完成: #pragma inline #pragma always_inline static fract16 add_fr1x16(fract16 __a, fract16 __b) { fract16 __rval = __builtin_add_fr1x16(__a, __b); return __rval; } 从这里可以看出我们实际可以使用__builtin_add_fr1x1

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)中的浮点运算(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)中的浮点运算(9):long double和float的比较

在默认情况下,vdsp认为double和float这两种类型是一样的,因此我们比较long double和float. 1.1 类型表示 下面是两种类型的数据表示:   float long double 字节数 4 8 符号位 1 1 指数位数 8 11 尾数位数 23 52 最小值 1.1754943508222875E-38F 2.2250738585072014E-308L 最大值 3.4028234663852886E+38F 1.797693134862315708E+308L 分辨

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中,在这个文件的开头说明了这个函数的用法: /*********************************************************