Как мне преобразовать код C с плавающей запятой в код с фиксированной запятой?

StackOverflow https://stackoverflow.com/questions/4368396

Вопрос

У меня есть код на языке Си, который использует удвоения.Я хочу иметь возможность запускать код в DSP (TMS320).Но DSP не поддерживает удвоения, только числа с фиксированной запятой.Каков наилучший способ преобразовать код в формат с фиксированной запятой?Существует ли хорошая библиотека C для чисел с фиксированной запятой (реализованная в виде целых чисел)?

Это было полезно?

Решение

Ti предоставляет библиотеку фиксированной точки под названием «IQMath»:

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

Преобразование включает в себя анализ вашего текущего кода - для каждой переменной вам нужно знать, какой диапазон он может удерживать, и какую точность им потребности. Тогда вы можете решить, какой тип хранится. IQMath предоставляет типы из Q30 с диапазоном +/- 2 и точность 0,0000000001 до Q1 с диапазоном ~ +/- 1 миллиона и точностью 0,5.

Для операций, которые могут переоценить диапазон переменных, вам нужно добавить проверки для переполнения и решать, как обрабатывать его - прикрепите его в Max, храните с другой шкалой, поднимите ошибку и т. Д.

На самом деле нет никакого способа преобразовать в фиксированную точку, не находящее глубокое понимание данного данных вашего процесса.

Другие советы

Следующий код определяет фиксированный тип, используя целые числа в качестве внутреннего представления. Дополнения и вычитания выполняются просто с + и - операторы. Умножение выполняется с использованием определенного 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) )

Я использовал вышеуказанный код для представления фракций в моем алгоритме обработки изображений. Это было быстрее, чем версия, которая использовала двойные разум, и результаты были почти точно такими же.

Большинство наборов инструментов DSP включают библиотеки для эмуляции с плавающей запятой в программном обеспечении.Это будет медленно, но вы должны изначально создать свой код с поддержкой операций с плавающей запятой, затем профилировать, чтобы посмотреть, есть ли всего несколько мест, которые вам нужно преобразовать в операции с фиксированной запятой, чтобы получить достаточную производительность.Вам также нужно будет запустить функцию с плавающей запятой, чтобы обеспечить сравнение при переносе на фиксированную точку, чтобы убедиться, что вы ничего не потеряли в процессе.

Если код C использует удваивания очень редко / не редко, вы можете использовать библиотеку эмуляции с плавающей точкой, не вызывая вашего C-кода, чтобы запустить 10x до 100x медленнее. Если не хочу, чтобы этот удар производительности и существует много операций с плавающей запятой, и вы знаете масштаб и точность, необходимые при каждом арифметическом и хранилище операции для каждого реалистичного ввода, тогда вы сможете преобразовать каждую арифметическую операцию, вручную, чтобы Используются масштабированные целочисленные типы данных и операции. Но анализ точных требований является, в целом, нетривиальный для кода типа DSP DSP. Есть много DSP и численные методы главы учебников по теме.

Есть несколько библиотек, которые могут сделать это для вас. Однако, скорее всего, PSP для вашего устройства должен включать в себя какую-то математическую библиотеку. Это должно быть задокументировано. Скорее всего, вам придется перезаписать свой код, поскольку конструкции управления, которые вы используете при примитивной арифметике с плавающей запятой, могут не иметь смысла при использовании API, предоставленной вашим PSP.

Например - вы можете преобразовать это

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

к этому

psp_decimal_t arraysum;
if (0 != psp_sum_elements(&array, arraylen, &arraysum))
{
    printf("error!");
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top