2015-03-09 2 views
2

У меня есть алгоритм во встроенной системе, который должен вычислять sin (theta), sin (2 * theta), sin (3 * theta) и т. Д.) С арифметикой Q15 с фиксированной точкой. грех (тета) и соз (тета) генерируются с использованием LUT/интерполяция комбы, но я использую метод Чебышева для расчета более высокий порядка SINES, который выглядит следующим образом (псевдо-код):Переполнение с использованием метода неподвижной точки Чебышева

sinN1 = Comes from Q15 LUT/interp algorithm 
cosN1 = Comes from Q15 LUT/interp algorithm 

sinN2 = (cosN1*sinN1)>>14; 
sinN3 = (cosN1*sinN2)>>14 - sinN1; 
sinN4 = (cosN1*sinN3)>>14 - sinN2; 
.... 

Проблема в том, что при определенных условиях этот метод дает результат, который может переполнять переменную Q15. Например, давайте рассмотрим, когда тэта = 2,61697:

sinN1 (Q15) = int(2**15*sin(2.61697)) = 16413 
cosN1 (Q15) = int(2**15*cos(2.61697)) = -28361 
sinN2 = (-28361*16413)>>14 = -28412   # OK 
sinN3 = (-28361*-28412)>>14 - 16413 = 32768 # OVERFLOW BY 1 
.. 

Я никогда, кажется, перелива более чем МЗР или два. Кажется, это артефакт компаундирования квантования. Я использую процессор ARM Cortex M4, поэтому я могу добавить логику насыщения с относительно небольшим количеством инструкций, но я делаю много потокового DSP в реальном времени с очень низкими требованиями к задержкам, поэтому мне нужно сэкономить столько CPU, сколько я могу поэтому мне интересно, есть ли более элегантный способ справиться с этой проблемой.

+0

Возможно, вы можете использовать арифметику без знака, так как +/- будет определяться проверкой квадрантов. Могут быть другие способы оценки функции и/или настройки коэффи- циентов. Вы не указали фактическую функцию, которая оценивается? –

ответ

0

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

Инструкция SSAT будет насыщать ваш результат в любую позицию, которая вам нужна, стоит один цикл и должна быть легко доступна через встроенный компилятор __ssat. Поскольку вы неизбежно накапливаете ошибки с любой нецелочисленной арифметикой, я не уверен, что есть действительно что-то лучше, чем просто делать расчет и тратить один дополнительный цикл, чтобы убедиться, что он находится в зоне действия.


То, что я не могу достаточно работать, если вы можете получить его совершенно бесплатно, вмешиваются в бите (инлайн) в сборе, чтобы получить в дополнительном сдвиге в ssat, что внутреннее не выставляет, на основании того, что шаг коррекции умножения/FP является самым большим источником ошибок; что-то вроде (псевдо-сборки):

mul tmp, cosN1, sinN2 
ssat tmp, #16, tmp, asr #14 
sub sinN3, tmp, sinN1 

Что вы можете только безопасно уйти с, если вы можете гарантировать, чтобы никогда в конечном итоге с чем-то вроде sinN3 = 0 - (-32768). QSUB16 заманчиво заменить SUB, но параллельная операция будет делать странные вещи с верхним полусловом знаковых битов, и как только вы добавите инструкцию для маскировки или полуслова, чтобы исправить это, вы потеряли «бесплатно» "игра.

Смежные вопросы