13

Tengo un código C que usa dobles. Quiero poder ejecutar el código en un DSP (TMS320). Pero el DSP no admite dobles, solo números de punto fijo. ¿Cuál es la mejor manera de convertir el código en punto fijo? ¿Hay una buena biblioteca C para números de punto fijo (implementados como enteros)?¿Cómo convierto un código C de punto flotante a punto fijo?

+3

Este es un tema bastante importante. Hay una gran discusión en esta pregunta SO: http://stackoverflow.com/questions/79677/whats-the-best-way-to-do-fixed-point-math. Casi todas las respuestas tenían algunos nuggets útiles. – mtrw

+1

Por curiosidad, ¿cómo representa el compilador DSP los puntos fijos? Como dos enteros? Por ejemplo, ¿cómo agregaría dos números de punto fijo? – chrisaycock

+0

Se representan como valores de 32 bits ('long'), con un desplazamiento implícito en el tipo. Por ejemplo, si tiene 16 bits después del punto ('_iq16'), representa el número de punto fijo 1.0 por el entero 65536 en el tipo subyacente. Para sumar y restar números de punto fijo del mismo tipo, puede usar las operaciones de entero estándar. La multiplicación necesita un cambio adicional para corregir la escala. – starblue

Respuesta

8

TI proporciona una biblioteca de punto fijo llamado "IQmath":

http://focus.ti.com/lit/sw/sprc990/sprc990.pdf

la conversión implica un análisis del código actual - para cada variable que necesita saber qué rango que puede contener, y lo que la precisión que necesita . Luego puede decidir en qué tipo almacenarlo. IQMath proporciona tipos de q30 con un rango de +/- 2 y una precisión de 0.0000000001 a q1 con un rango de ~ +/- 1 millón y una precisión de 0.5.

Para las operaciones que posiblemente puede desbordar el rango de las variables, es necesario agregar cheques por desbordamiento, y decidir cómo manejarlo - Pin It en el máximo, tienda con una escala diferente, generará un error, etc.

Realmente no hay forma de convertir a punto fijo sin realmente obtener una comprensión profunda del flujo de datos de su proceso.

5

La mayoría de las cadenas de herramientas DSP incluyen bibliotecas para la emulación de coma flotante en el software. Esto será lento, pero inicialmente debe compilar su código con soporte de coma flotante, luego haga un perfil para ver si solo hay unos pocos lugares que necesita convertir a punto fijo para obtener el rendimiento suficiente. También tendrá que tener las cosas de coma flotante ejecutándose para proporcionar una comparación a medida que realiza el envío al punto fijo, para asegurarse de no haber perdido nada en el proceso.

0

Hay algunas bibliotecas que pueden hacer esto por usted. Sin embargo, es más probable que la PSP de su dispositivo incluya algún tipo de biblioteca matemática. Debe ser documentado. Es probable que tengas que volver a escribir parte de tu código, porque las construcciones de control que usas al hacer una aritmética de coma flotante basada en primitivas pueden no tener sentido cuando usas la API provista por tu PSP.

Por ejemplo - es posible convertir este

double arraysum = 0.0; 
for (int i = 0; i < arraylen; i++) 
{ 
    arraysum += array[i]; 
} 

a este

psp_decimal_t arraysum; 
if (0 != psp_sum_elements(&array, arraylen, &arraysum)) 
{ 
    printf("error!"); 
} 
+0

El enlace está muerto, corrígelo. – Danijel

+0

Lamentablemente, no he podido encontrar ese contenido en ningún otro lado ni la persona que lo publicó. –

2

Si el código C utiliza dobles muy rara vez/escasamente, entonces usted podría ser capaz de utilizar una biblioteca de emulación de punto flotante sin hacer que su código C se ejecute de 10X a 100X más lento. Si no desea que se vea afectado el rendimiento y hay muchas operaciones de punto flotante, y conoce la escala y la precisión requeridas en cada operación aritmética y de almacenamiento para cada entrada realista, entonces es posible que pueda convertir cada operación aritmética, manualmente, a utilizó tipos de datos enteros escalados y operaciones. Pero analizar los requisitos de precisión es, en general, no trivial para el código de tipo DSP. Hay muchos capítulos de libros de texto de DSP y Métodos Numéricos sobre el tema.

+0

... elabore en la última oración, para que esto califique como útil. – jpinto3912

12

El siguiente código define un tipo Fixed, utilizando enteros como su representación interna. Las adiciones y sustracciones se realizan simplemente con los operadores + y -. La multiplicación se realiza utilizando la macro definida MULT.

#include <stdio.h> 
typedef int Fixed; 

#define FRACT_BITS 16 
#define FRACT_BITS_D2 8 
#define FIXED_ONE (1 << FRACT_BITS) 
#define INT2FIXED(x) ((x) << FRACT_BITS) 
#define FLOAT2FIXED(x) ((int)((x) * (1 << FRACT_BITS))) 
#define FIXED2INT(x) ((x) >> FRACT_BITS) 
#define FIXED2DOUBLE(x) (((double)(x))/(1 << FRACT_BITS)) 
#define MULT(x, y) (((x) >> FRACT_BITS_D2) * ((y)>> FRACT_BITS_D2)) 

Estaba usando el código anterior para representar fracciones en mi algoritmo de procesamiento de imágenes. Era más rápido que la versión que usaba dobles y los resultados eran casi exactamente los mismos.

+0

revise esta biblioteca también: [http://www.sf.net/projects/fixedptc](http://www.sf.net/projects/fixedptc) –

Cuestiones relacionadas