13

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

+3

Это довольно большая тема. В этом SO-вопросе есть большая дискуссия: http://stackoverflow.com/questions/79677/whats-the-best-way-to-do-fixed-point-math. Почти все ответы имели некоторые полезные самородки. – mtrw 2010-12-06 16:20:15

+1

Из любопытства, как компилятор DSP представляет собой фиксированные точки? Как два целых числа? Например, как бы вы добавили два числа с фиксированной точкой вместе? – chrisaycock 2010-12-06 16:21:44

+0

Они представлены как 32-битные значения (`long`), причем сдвиг неяв в типе. Например, если у вас есть 16 бит после точки (`_iq16`), вы представляете число с фиксированной запятой 1.0 целым числом 65536 в базовом типе. Для добавления и вычитания чисел с фиксированной точкой одного типа вы можете использовать стандартные операции с целыми числами. Умножение требует дополнительной сдвига для коррекции масштабирования. – starblue 2014-01-09 13:44:48

ответ

8

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

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

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

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

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

5

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

0

Есть несколько библиотек, которые могут сделать это за вас. Скорее всего, 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!"); 
} 
+0

Ссылка мертва, пожалуйста, исправьте. – Danijel 2017-06-27 08:59:08

2

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

12

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

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