Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Операции с плавающей точкой без FPU
Форум разработчиков электроники ELECTRONIX.ru > Цифровая обработка сигналов - ЦОС (DSP) > Алгоритмы ЦОС (DSP)
sigmaN
Интересно, а можно ли на целочисленном DSP с запасом производительности(скажем в 3-5 раз) зарулить вокодер на плавающей точке?

И вообще, каков overhead, так сказать, FP операций на проце без FPU?
Страдает ли точность вычисления?
Что нужно для подобных "извращений"?
Может быть есть какая-то библиотека виртуального FPU, так сказать?
DSP Техас 55 серии.
fontp
Можно, только не в 3-5, а скорее раз 8-10
Для этого обычно строят библиотеки "короткого" нестандартного FP
Чтобы удобно (т.е. быстро) было работать. Слово мантисы + слово экспоненты
И никаких проверок на потерю точности - с ними всё равно нечего делать в риал-тайме
Ещё они должны быть inline, иначе труба
Такие библиотеки есть. Можете и сами написать умножение деление сложение и вычитание.
Преобразование типа из/в int и float можно где-нибудь найти на С
Если Вы хотите приспособить к SPEEX без переписывания, то проблемы всё равно останутся.
Во-первых операторами можно оформить только в СPP, в С это функции/ SPEEX это С, а значит...
Во-вторых в чужих проектах используются стандартные математические библиотеки math.h,
а это уж точно прийдётся самому писать под новый тип новую реализацию - sin, sqr, и что там ещё есть в SPEEX
sigmaN
Цитата(fontp @ Apr 3 2008, 13:29) *
Можно, только не в 3-5, а скорее раз 8-10


Да уж... труба дело :-)
Неужели всё-таки придется окунуться в математику и переписывать некоторые алгоритмы на целочисленную модель.
А есть где-нибудь мануальчики как это обычно делается.
Ну там, начиная от анализа существующего FP алгоритма и так далее чтобы на выходе был ФТ алгоритм.

Видимо от этого никуда не деться....:-(
fontp
Цитата(sigmaN @ Apr 3 2008, 16:57) *
Да уж... труба дело :-)
Неужели всё-таки придется окунуться в математику и переписывать некоторые алгоритмы на целочисленную модель.
А есть где-нибудь мануальчики как это обычно делается.
Ну там, начиная от анализа существующего FP алгоритма и так далее чтобы на выходе был ФТ алгоритм.

Видимо от этого никуда не деться....:-(


Если никуда не деться... Могу посоветовать AN EE-185 для BF
Там хоть преобразование типов есть на С, операции на асемблере (делать самому, если не знать его ассемблера, чтобы использовать как прототип), ну и вообще по тексту описание
FastFloat16 или FastFloat32
Это на www.analog.com Application Note
Как у ti c такими библиотеками - не знаю, возможно, что и есть
Математику, в смысле, стандартные функции с нужной точностью - самому


Потом грамотно целый класс в С++ накропать
Типа c таким прототипом
http://www.koders.com/cpp/fid5E90955711BFB...C383C.aspx#L103

Потом все модули SPEEX переименовать в cpp, компилировать и править ошибки :-)
DRUID3
Цитата(fontp @ Apr 3 2008, 16:33) *
Если никуда не деться... Могу посоветовать AN EE-185 для BF
Там хоть преобразование типов есть на С, операции на асемблере (самому, если не знать его ассемблера, чтобы использовать как прототип), ну и вообще по тексту описание
FastFloat16 или FastFloat32
Это на www.analog.com Application Note
Как у ti c такими библиотеками - не знаю, возможно, что и есть
Математику, в смысле, стандартные функции с нужной точностью - самому
Потом грамотно целый класс в С++ накропать
Типа c таким прототипом
http://www.koders.com/cpp/fid5E90955711BFB...C383C.aspx#L103

Потом все модули SPEEX переименовать в cpp, компилировать и править ошибки :-)

07.gif Я еще speex не собирал, и вот заинтересовался темой. Но...

во-первых - помниЦЦо в VDSP++ есть float для целочисленных процессоров. В чем проблема? На Bf все будет летать и так. Что надо переписывать? Я кода-то с float алгоритмы переносил на fix так и то вспоминать не хочу больше... а если еще самому мутить матлибу (пусть и "быстрый float")- это ошибки человека + ошибки принципиальные - ну как в fix с масштабированием.

во-вторых - насколько я понимаю Linuxовый Speex для bf - целочисленный...и он вполне собираеЦЦо...??? Есть целочисленный вход/выход, в портах для TMS и BF используются типы данных на основе int. ... Что еще надо для души?

Ну и в-тетьих, если так хочеЦЦо float - то у AD есть серия дешевых SHARKов, они собственно для того и создавались что-бы не ломая голову применять акадэмические(книжные) алгоритмы. Тем более что их производительности хватит еще на корзинку таких speexов...

P.S.: собственно мне не понравился подход... не хочу чтобы медаппаратуру, например, даже для зубного кабинета, разрабатывали так...
fontp
Цитата(DRUID3 @ Apr 3 2008, 18:24) *
07.gif Я еще speex не собирал, и вот заинтересовался темой. Но...
во-первых насколько я помню в VDSP++ есть float для целочисленных процессоров. В чем проблема? На Bf все будет летать и так. Что надо переписывать? Я кода-то с float алгоритмы переносил на fix так и то вспоминать не хочу больше...а если еще самому мутить матлибу - это ошибки человека + ошибки принципиальные - ну как в fix с масштабированием.
во-вторых - насколько я понимаю Linuxовый Speex для bf - целочисленный...и он вполне собираеЦЦо...??? Есть целочисленный вход/выход, в портах для TMS и BF используются типы данных на основе int. ... Что еще надо для души?


Он хочет VBR, jitter buffer и эхоподавитель
А все эксперементальные, недоделаные фичи в SPEEX - float, что в общем-то правильно. Зачем вылизывать алгоритмы, которые ещё десять раз будут переделаны?

Порты BF и TMS int но он их не хочет ;-) В стандартном float32 ни BF ни TMS sPEEX с прибабахами не потянут
Вообще-то float всегда это больше fast prototyping - типа для лохов. Но человек хочет повозиться с прибабахами. Я так понимаю

Быстродействие int на BF я проверял
http://electronix.ru/forum/index.php?showt...36206&st=15
На tms помедленей, упомянуто там же
sigmaN
Цитата(fontp @ Apr 3 2008, 17:31) *
Он хочет VBR, jitter buffer и эхоподавитель
А все эксперементальные, недоделаные фичи в SPEEX - float, что в общем-то правильно. Зачем вылизывать алгоритмы, которые ещё десять раз будут переделаны?

Порты BF и TMS int но он их не хочет ;-) В стандартном float32 ни BF ни TMS sPEEX с прибабахами не потянут
Вообще-то float всегда это больше fast prototyping - типа для лохов. Но человек хочет повозиться с прибабахами. Я так понимаю

Быстродействие int на BF я проверял
http://electronix.ru/forum/index.php?showt...36206&st=15
На tms помедленей, упомянуто там же

Правильно понимаете.
Мне очень нужны именно эти фичи - без VBR и эхоподавления никак мне не жить.
На int там действительно только кодер/декодер - этого мало для решения моей задачи.
То, что типа для лохов - это тоже верно, но щас важнее чтоб по быстрому всё заработало и запахло капустой :-)
Потом следующую версию забабахаю на ФТ(если получится).
Есть ведь TMS320F28335 c FPU - вот на нем всё это без переделок пойдет. Просто жрет он очень много! Это меня и насторожило.

То, что тема это гнилая(мутить алгоритм ПТ на процах ФТ) - и ежу понятно, хотелось просто это ещё раз услышать. smile.gif

Вообще Speex очень хорош!
Я на PC провел испытания качества на низких битрейтах - просто сказка!
Нужно будет взяться и разрулить как-нибудь всё на ФТ.
DRUID3
Цитата(fontp @ Apr 3 2008, 17:31) *
Он хочет VBR, jitter buffer и эхоподавитель
А все эксперементальные, недоделаные фичи в SPEEX - float, что в общем-то правильно. Зачем вылизывать алгоритмы, которые ещё десять раз будут переделаны?

Порты BF и TMS int но он их не хочет ;-) В стандартном float32 ни BF ни TMS sPEEX с прибабахами не потянут
Вообще-то float всегда это больше fast prototyping - типа для лохов. Но человек хочет повозиться с прибабахами. Я так понимаю

Быстродействие int на BF я проверял
http://electronix.ru/forum/index.php?showt...36206&st=15
На tms помедленей, упомянуто там же

lol.gif Ну спасибо...так перечеркнуть все мои надежды на SHARC. К стати, они его не даром для музыки и радиолюбителей позиционируют, ибо это еще и low digital noise in superlongest accumulation operation biggrin.gif .
а так, по кодеку, вобщем ясно... Кстати, я тут недавно заинтересовался нелинейными системами, а там чем больше точность тем больше матриц матриц которые матрицы матриц biggrin.gif ...может попробую bf561 тем более и луникс для него оказываеЦЦо есть. Если правильно распределить потоки - то в среднем можно на суммарнуй 1 Гигатакт расчитывать....уж если он speex float не потянет, то даже не знаю... wacko.gif
Stanislav
Цитата(sigmaN @ Apr 3 2008, 14:21) *
Интересно, а можно ли на целочисленном DSP с запасом производительности(скажем в 3-5 раз) зарулить вокодер на плавающей точке?
Нельзя.
Цитата(sigmaN @ Apr 3 2008, 14:21) *
И вообще, каков overhead, так сказать, FP операций на проце без FPU?
Примерно два порядка.
Цитата(sigmaN @ Apr 3 2008, 14:21) *
Страдает ли точность вычисления?
Относительно чего?
Цитата(sigmaN @ Apr 3 2008, 14:21) *
Что нужно для подобных "извращений"?
Быть "извращенцем".
Цитата(sigmaN @ Apr 3 2008, 14:21) *
Может быть есть какая-то библиотека виртуального FPU, так сказать?
DSP Техас 55 серии.
Библы есть какие-то, конечно, в т.ч., и стандартные. Только зачем они Вам? Компилятор плывучку поддерживает и для целочисленных DSP, а для нормальной плавающей точки нужно брать и процессор соответствующий.
sigmaN
Цитата(Stanislav @ Apr 3 2008, 17:59) *
Нельзя.
Примерно два порядка.
Относительно чего?
Быть "извращенцем".
Библы есть какие-то, конечно, в т.ч., и стандартные. Только зачем они Вам? Компилятор плывучку поддерживает и для целочисленных DSP, а для нормальной плавающей точки нужно брать и процессор соответствующий.


Ясно всё.
В общем нужно детальнее разбираться в алгоритмах работы нужных мне фич и не обращать внимание на плывучку, как вы говорите.
Точность Относительно чего? Ну я имел ввиду относительно DSP с FPU. Но, понятно, вопрос дурацкий на самом делеsmile.gif

А можно какие-нибудь подсказки по методике перевода алгоритма на целочисленные вычисления?
Я, честно говоря, пока четко себе не представляю сам процесс.... sad.gif
Stanislav
Цитата(sigmaN @ Apr 3 2008, 21:13) *
В общем нужно детальнее разбираться в алгоритмах работы нужных мне фич и не обращать внимание на плывучку, как вы говорите.
Строго говоря, вычисления лучше делать не в целых числах, а в числах с фиксированной точкой (fixed point arithmetics). Попробуйте погуглить - найдёте немало интересного. Кроме того, на сайтах AD и TI есть много статей, аппнотов и мануалов, посвящённых данному вопросу.
Однакож, и "плавающие" DSP никто не запретил юзать. smile.gif Попробуйте-ка найти приличный fixed-point DSP за такую цену. wink.gif

Цитата(sigmaN @ Apr 3 2008, 21:13) *
...А можно какие-нибудь подсказки по методике перевода алгоритма на целочисленные вычисления?
Я, честно говоря, пока четко себе не представляю сам процесс...
Выше уже написал. Программирование в числах с фиксированной точкой требует большой аккуратности - постоянно приходится считаться с возможностью как переполнения, так и значительной потери точности на операциях разного рода. Это программист должен постоянно помнить, и нормировать и масштабировать не покладая рук. В целом, конечно, с приобретением должного опыта эти вещи будут получаться автоматически.

Есть и хитрости более "высокого порядка". Например, во многих вокодерах для параметрического оценивания используется рекурсивный алгоритм Левинсона-Дарбина, который весьма чувствителен к усечению разрядов. Заменив его на немного менее эффективный вычислительно метод LeRoux (Schur recursion), получим гораздо большую устойчивость решения для DSP с фиксированной точкой.
Кроме того, часть вычислений (не менее 10-20%) придётся писать на АСМе, потому что ЯВУ не поддерживают многие полезности архитектур DSP.

ЗЫ. А вообще, посмотрите стандарты. Алгоритмы работы вокодеров создаются обычно так, чтобы их легко можно было реализовать в целочисленном процессоре.
ЗЗЫ. А почему именно SPEEX? Послушал сэмплы на сайте speex.org - не понравилось мне звучание, особенно при малых битрейтах. Тот же G723.1 звучит заметно лучше, да и и MELP при 2400 бит/с ему точно не уступает...
fontp
Цитата(Stanislav @ Apr 3 2008, 22:38) *
ЗЗЫ. А почему именно SPEEX? Послушал сэмплы на сайте speex.org - не понравилось мне звучание, особенно при малых битрейтах. Тот же G723.1 звучит заметно лучше, да и и MELP при 2400 бит/с ему точно не уступает...


SPEEX CELP и звучит как CELP. Как G723.1 на 5.3 кб/cек. А MELP звучит конечно великолепно для 2.4кб/сек, но в целом так себе, если с потоком не париться

В варианте VBR SPEEX по идее должен, как говорят авторы, звучать лучше большинства стандартных.
Верю. Есть правда и стандарты VBR - тот же G726.2 AMR-NB

C другой стороны переменный битовый поток порождает свои проблемы - с тем же буфером джитера и всё такое. SPEEX "просто сказка" в том смысле, что там есть много чего нахаляву. Дело не только в том, что он open source, но и в том, что там много всяких дополнительных вкусностей. На вкус и цвет..., пусть расцветают все цветы..., у SPEEX есть тоже свои достоинства

Потом речь идёт не о том, чтобы "сделать", а о том, чтобы портировать готовое. Т.е. на С и если говорить о sPEEX vbr - то во float.

Во float по нормальному, вообще-то лучше использовать float процессор. И действительно, стандартный IEEE float тянет примерно два порядка быстродействия на процессоре FIXED
Или пользоваться суррогатными типами если нужно сделать за так и быстро :-) Тянет примерно один порядок
Пацан спросил-пацан ответел :-)
Stanislav
Цитата(fontp @ Apr 4 2008, 10:21) *
SPEEX CELP и звучит как CELP. Как G723.1 на 6.3 кб/cек.
Не знаю, может, сэмплы неудачные, но по мне, так SPEEX 6 кб/с звучит значительно хуже G 723.1 5.3 кб/с.

Кроме того, G723.1 - это не CELP, которым, как известно, является FS-1016, и SPEEX очень похож на него. У G723.1 формирование адаптивной кодовой книги производится иным способом.


Цитата(fontp @ Apr 4 2008, 10:21) *
...А MELP звучит конечно великолепно для 2.4кб/сек, но в целом так себе, если с потоком не париться
Мне показалось, что никак уж не хуже SPEEX на нижнем битрейте.

Цитата(fontp @ Apr 4 2008, 10:21) *
В варианте VBR SPEEX по идее должен, как говорят авторы, звучать лучше большинства стандартных.
Интересно, а за счёт чего он будет звучать лучше, скажем, того же FS-1016?
Ну, а на VBR можно переделать любой вокодер. С уменьшением устойчивости к ошибкам передачи, естественно.

Цитата(fontp @ Apr 4 2008, 10:21) *
...C другой стороны переменный битовый поток порождает свои проблемы - с тем же буфером джитера и всё такое. SPEEX "просто сказка" в том смысле, что там есть много чего нахаляву. Дело не только в том, что он open source, но и в том, что там много всяких дополнительных вкусностей. На вкус и цвет..., пусть расцветают все цветы..., у SPEEX есть тоже свои достоинства
С этим спорить не буду. Нахаляву оно, конечно, слаще...
Не подумайте, что я отношусь неодобрительно к SPEEX проекту - наоборот, считаю его очень полезным. Только вот "до кондиции" ему ещё далековато...

Цитата(fontp @ Apr 4 2008, 10:21) *
Потом речь идёт не о том, чтобы "сделать", а о том, чтобы портировать готовое. Т.е. на С и если говорить о sPEEX vbr - то во float.
Ага, и при этом головой абсолютно не думать. Лафа, паньмаешш, мечта "имбедецила". biggrin.gif

Цитата(fontp @ Apr 4 2008, 10:21) *
...Или пользоваться суррогатными типами если нужно сделать за так и быстро :-) Тянет примерно один порядок.
А один порядок - это сколько?
По-моему, даже любой суррогатный тип уменьшит быстродействие DSP на типовых операциях значительно более 8-10 раз.
fontp
Цитата(Stanislav @ Apr 4 2008, 11:30) *
Не знаю, может, сэмплы неудачные, но по мне, так SPEEX 6 кб/с звучит значительно хуже G 723.1 5.3 кб/с.

Кроме того, G723.1 - это не CELP, которым, как известно, является FS-1016, и SPEEX очень похож на него.


Мне показалось, что никак уж не хуже SPEEX на нижнем битрейте.

Интересно, а за счёт чего он будет звучать лучше, скажем, того же FS-1016?


С 6.3 я погорячился, исправил на 5.3 ещё до Вашего поста.
G723.1 (5.3) - это ACELP, c FS-1016 одного поля ягода. "A" в ACELP влияет на скорость поиска,
но не на размер таблицы, а значит качество звучания
Слушать SPEEX нужно в соответствующем диапазоне > 4.8. На нижнем диапазоне 2.4 его лучше вообще не слушать.

Вообще-то главным образом качество CELP зависит от того как сделан поиск по стохастической кодовой книге - с разорваной обратной связью или без разорваной (разница между G729 и G729A)
Т.е. полный перебор или декомпозиция "переборов"
При одинаковых битрейтах качество зависит ещё от тщательности и развесистости векторного квантования.Не знаю уж, где оно лучше исполнено.
А так всё примерно одинаково (FS1016, SPEEX, G723/1 - 5.3) - линейные предсказания, спектральные пары, кодовые книги и т.д. Примерно одна фигня

Цитата(Stanislav @ Apr 4 2008, 11:30) *
А один порядок - это сколько?
По-моему, даже любой суррогатный тип уменьшит быстродействие DSP на типовых операциях значительно более 8-10 раз.


Да ладно. Посмотрите как написано в FastFloat16 в соответствующем EE185 для BF
Мантиссы умножил, порядки сложил - вот и умножение
Нормализовал операнды к большему порядку, сложил мантиссы - вот и сложение
Или деление. Фигня. Нормализация и целочисленное деление.
Нормализация у BF - это две операции, норм и шифт. На ADSP2105, понятно, ничего не получится, нет там аппаратной нормализации :-)
Всё инлайн. Без проверок переполнения и потери точности. В 10 раз даже много.
Нет, ну за три такта тоже не получится, конечно
Относительная точность - лучше 10**-4. Но это относительная точность, не абсолютная, как у fixed16.
Практически всегда достаточно такой, чего нельзя сказать про fixed16
sigmaN
Господа, ну послушайте не сэмплы с сайта, которые действительно ужасно звучат(они просто закодированы/раскодированы на стандартных настройках кодера), а проведите эксперимент самостоятельно. VBR дает обалденное качество на 4Кб/с, по сравнению с другими!
Ну может быть посоветуйте что-нибудь, чтобы было не хуже GSM по субъективным оценкам пользователей, но на скорости не более 4.5.
Задача вообще решаема?
GSM очень расточителен(целых 13Кб/с!)

Да, халява это приятно всегда.
Блин, а этот шарк аж 370мА захавывает - это очень много для меня(батарейка мобилы просто умрет за часок-другой).
fontp
Цитата(sigmaN @ Apr 4 2008, 12:50) *
Господа, ну послушайте не сэмплы с сайта, которые действительно ужасно звучат(они просто закодированы/раскодированы на стандартных настройках кодера), а проведите эксперимент самостоятельно. VBR дает обалденное качество на 4Кб/с, по сравнению с другими!
Ну может быть посоветуйте что-нибудь, чтобы было не хуже GSM по субъективным оценкам пользователей, но на скорости не более 4.5.
Задача вообще решаема?
GSM очень расточителен(целых 13Кб/с!)


Целочисленный MELP 2.4 кб/cек считается не хуже gSM, но хуже всех стандартных вокодеров серии G
co скоростью > 5.3

Портируйте этот целочисленный код прямо на С
http://electronix.ru/forum/index.php?showt...335&hl=melp
легко получите 50 мипс (я проверял)
http://electronix.ru/forum/index.php?showt...177&hl=melp

Если важно потребление - делайте на BF. Снижая частоту штатно до 100мгц (напряжение питания 0.8в) вы легко получите 80 мвт
потребления - 0.8в х 100 ма - лучше всякого тмс

Остальные 50 мгц останутся на прибабахи типа эхоподавителя.

Эхоподавитель NLMS можете взять у меня на С (на той же библиотеке ETSI, что и все стандартные вокодеры)
http://electronix.ru/forum/index.php?showt...=21804&st=0

Или переделать эхоподавитель из SPEEX с помощью той статьи про Frequency-Domain на fixed.
http://people.xiph.org/~jm/papers/valin_taslp2006.pdf
Они по ней делают. Но это уже серьёзная работа, а не "портирование"
Stanislav
Цитата(fontp @ Apr 4 2008, 11:52) *
С 6.3 я погорячился, исправил на 5.3 ещё до Вашего поста.
G723.1 (5.3) - это ACELP, c FS-1016 одного поля ягода. "A" в ACELP влияет на скорость поиска,
но не на размер таблицы, а значит качество звучания
Не соглашусь, пожалуй.
"А" - это алгебраический способ возбуждения адаптивной кодовой книги, в отличие от стохастического, как в "родном" CELP-е. Видимо, более эффективный - качество звучания ACELP-5,3 заметно выше, чем CELP-4,8. Особенно на высоких мужских и женских голосах.

Цитата(fontp @ Apr 4 2008, 11:52) *
Слушать SPEEX нужно в соответствующем диапазоне > 4.8. На нижнем диапазоне 2.4 его лучше вообще не слушать.
Я слушал сэмплы на 4 и 6 кб/с. Честно говоря, "нифпечатлило".

Цитата(fontp @ Apr 4 2008, 11:52) *
...А так всё примерно одинаково (FS1016, SPEEX, G723/1 - 5.3) - линейные предсказания, спектральные пары, кодовые книги и т.д. Примерно одна фигня
Может быть, а только по мне G723.1 звучит всё-таки лучше. Правда, я давно этими делами не занимался, и у меня нет сейчас "работающих" реализаций для РС. Если у Вас есть, можно попробовать сравнить на разных речевых фрагментах, и выложить здесь результаты, на суд публики.


Цитата(fontp @ Apr 4 2008, 11:52) *
...Да ладно. Посмотрите как написано в FastFloat16 в соответствующем EE185 для BF
Мантиссы умножил, порядки сложил - вот и умножение
Нормализовал операнды к большему порядку, сложил мантиссы - вот и сложение
Или деление. Фигня. Нормализация и целочисленное деление.
Нормализация у BF - это две операции, норм и шифт.
Ну, вот и попробуйте сделать операцию типа свёртки над двумя или более массивами в формате, скажем, 1.15, и то же самое с любым "плывучим" форматом. А потом сравним.
Операции типа свёртки, кстати, отнимают около 90% вычислительной нагрузки при реализации вокодера CELP, так что остальное можно не учитывать.

Цитата(fontp @ Apr 4 2008, 11:52) *
...На ADSP2105, понятно, ничего не получится, нет там аппаратной нормализации :-)
Ошибаетесь - есть. biggrin.gif

Цитата(fontp @ Apr 4 2008, 11:52) *
...Всё инлайн. Без проверок переполнения и потери точности. В 10 раз даже много.
По-моему, в 10 раз всё-таки не получится... Могу предоставить пример исходника, на котором всё это можно проверить, но попозже.
fontp
Цитата(Stanislav @ Apr 4 2008, 14:50) *
Если у Вас есть, можно попробовать сравнить на разных речевых фрагментах, и выложить здесь результаты, на суд публики.

У меня есть буквально ВСЁ, но не хочу я этим заниматься, времени жалко. Оно всё ещё и плывёт от условий. Про экспертов и их субъективные оценки, я, как эксперт, уже всё сказал: "Всякий эксперт при субъективной оценке должен учитывать, что его не только могут не позвать в другой раз, но могут и не заплатить в этот" (с)
Наиважнейшее правило для всех экспертов. Копирайт мой собственный

От МOS 3 до 3.5 - качество приемлемое
От 3.5 до 4.0 - хорошее
Ниже 3.0 - синтетическое

Цитата: g729a сохраняет не ниже 3.5 при потере 3.5% пакетов, а при 5% качество падает до 3.0
g723.1 сохраняет стандартное качество 3.5 при потере менее 1% пакетов, а при 3% падает до 2.8
Конец цитаты.

В общем, не очень-то это занятие продуктивное - сравнивать... Экспертам за это хоть деньги дают

Цитата(Stanislav @ Apr 4 2008, 14:50) *
Ну, вот и попробуйте сделать операцию типа свёртки над двумя или более массивами в формате, скажем, 1.15, и то же самое с любым "плывучим" форматом. А потом сравним.


По уму нужно конечно делать блочную нормализацию и лупить целочисленно

Цитата(Stanislav @ Apr 4 2008, 14:50) *
Ошибаетесь - есть. biggrin.gif

По-моему, в 10 раз всё-таки не получится... Могу предоставить пример исходника, на котором всё это можно проверить, но попозже.


Уже есть? Ну может и есть. Уже не помню

Вот mult для BF из EE185 FastFloat.asm

.global _mult_ff16;
_mult_ff16:

r3.l = r0.l + r1.l (ns);
a0 = r0.h * r1.h;

r2.l = signbits a0; // get the number of sign bits
a0 = ashift a0 by r2.l; // normalize the mantissa
r0 = a0;
r0.l = r3.l - r2.l (ns); // adjust the exponent

rts;

_mult_ff16.end:

А вот add
_add_ff16:
.global _add_ff16;

r2.l = r0.l - r1.l (ns); // is Ex > Ey?
cc = an; // negative result?
r2.l = r2.l << 11 (s); // guarantee shift range [-16,15]
r2.l = r2.l >>> 11;
if !cc jump _add_ff16_1; // no, shift y
r0.h = ashift r0.h by r2.l; // yes, shift x
jump _add_ff16_2;

_add_ff16_1:
r2 = -r2 (v);
r1.h = ashift r1.h by r2.l; // shift y
a0 = 0;
a0.l = r0.l; // you can't do r1.h = r2.h
r1.l = a0 (iu); // so use a0.x as an intermediate storage place
_add_ff16_2:
r2.l = r0.h + r1.h (ns); // add fractional parts
cc = v; // was there an overflow?
if cc jump _add_ff16_3;

// normalize
r0.l = signbits r2.l; // get the number of sign bits
r0.h = ashift r2.l by r0.l; // normalize the mantissa
r0.l = r1.l - r0.l (ns); // adjust the exponent

rts;


Ну, там addd нужно немного доработать, чтобы избавить от глупостей проверки переполнения - это лишнее. Никаких Jump не должно быть, понятно. Никаких проверок. И всё в inline оформить
Где здесь 20 тактов? :-)

Цитата(fontp @ Apr 4 2008, 13:10) *
Целочисленный MELP 2.4 кб/cек считается не хуже gSM, но хуже всех стандартных вокодеров серии G
co скоростью > 5.3

про качество MELP почему-то не вставилось в тот раз
http://maya.arcon.com/ddvpc/compmelp.htm
Это родные цифры качества
Его качество 3-3.5 т.е. в точности соответствует GSM (13 кбит) и примерно CELP 1016 (4.8 кбит)
Если нужно меньше 4 кбит, то это скорее всего melp
sigmaN
Сэмплы MELPe-PLUS
Даааа, послушал я MELPe-Plus 4000 и обалдел - этот Speex действительно отдыхает, я так за него уцепился...видимо зря.
На низких битрейтах рулит MELP.
А GSM так вообще непонятный какой-то - при такой скорости можно было качество получить и по-лучше ))

Вот-бы спулить у них этот MELPe-Plus - вот была-бы настоящая халява!
Оригинал мужской голос
Оригинал женский голос
Сжатый мужской голос
Сжатый женский голос
Degun
Кто пробовал для DSP фирмы Texas Instruments серии 62x или 64x пользоваться библиотекой Fast Run Time Support Library fastrts64x.lib, которая вроде бы предоставляет быструю реализацию основных операций с типами double и float. Насколько она действительно быстрее тех же операций, но встроенных в компилятор? Будет ли выигрыш? Если нет, то зачем она нужна вообще?
fontp
Цитата(Degun @ Apr 21 2008, 21:51) *
Кто пробовал для DSP фирмы Texas Instruments серии 62x или 64x пользоваться библиотекой Fast Run Time Support Library fastrts64x.lib, которая вроде бы предоставляет быструю реализацию основных операций с типами double и float. Насколько она действительно быстрее тех же операций, но встроенных в компилятор? Будет ли выигрыш? Если нет, то зачем она нужна вообще?


Нужна затем, чтобы уйти от стандарта IEEE и игнорировать всякие overflow/underflow. Как всегда проверки на ошибки забирают большую часть усилий и вся мощь уходит зазря. В Borland C тоже всегда был "fast float" и смысл тот же - не делать проверок и ускориться раза в 2.
Насколько быстро это всё будет для TI? Да не очень . Раз в 50-100 медленнее такта процессора (т.е. вычислений fixed). Длинна слова-то - стандартная и мантисса/порядок не выровнены на границу 16 бит
rifch
Цитата(fontp @ Apr 22 2008, 11:21) *
Нужна затем, чтобы уйти от стандарта IEEE и игнорировать всякие overflow/underflow. Как всегда проверки на ошибки забирают большую часть усилий и вся мощь уходит зазря. В Borland C тоже всегда был "fast float" и смысл тот же - не делать проверок и ускориться раза в 2.
Насколько быстро это всё будет для TI? Да не очень . Раз в 50-100 медленнее такта процессора (т.е. вычислений fixed). Длинна слова-то - стандартная и мантисса/порядок не выровнены на границу 16 бит


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

Код
/*!\file fast_rts64x.h
* \brief Быстрая реализация основных операций с числами
* \brief с плавающей запятой для DSP фирмы Texas Instruments
* \brief серии 64x, основанная на библиотеке fast_rts64x.lib
* \version 1.0
* \date 2008
*/
#ifndef __FAST_RTS_64X_H
#define __FAST_RTS_64X_H

#ifdef __cplusplus
extern "C" {
#include <fastrts62x64x.h>
}
#else
#include <fastrts62x64x.h>
#endif

class double_fst
{
public:
    double value;

    inline double_fst( double v=0 ) { value=v; }
    inline double_fst( float v ) { value=spdp(v); }
    inline double_fst( char v ) { value=intdp(v); }
    inline double_fst( short v ) { value=intdp(v); }
    inline double_fst( int v ) { value=intdp(v); }
    inline double_fst( long v ) { value=longdp(v); }
    inline double_fst( unsigned char v ) { value=uintdp(v); }
    inline double_fst( unsigned short v ) { value=uintdp(v); }
    inline double_fst( unsigned int v ) { value=uintdp(v); }
    inline double_fst( unsigned long v ) { value=ulongdp(v); }

    inline operator double() const { return value; }
    inline operator float() const { return dpsp(value); }
    inline operator char() const { return (char)dpint(value); }
    inline operator short() const { return (short)dpint(value); }
    inline operator int() const { return dpint(value); }
    inline operator long() const { return dplong(value); }
    inline operator unsigned char() const { return (unsigned char)dpuint(value); }
    inline operator unsigned short() const { return (unsigned short)dpuint(value); }
    inline operator unsigned int() const { return dpuint(value); }
    inline operator unsigned long() const { return dpulong(value); }

    inline void operator = ( double_fst r ) { value=r.value; }
    inline void operator = ( double v ) { value=v; }
    inline void operator = ( float v ) { value=spdp(v); }
    inline void operator = ( char v ) { value=intdp(v); }
    inline void operator = ( short v ) { value=intdp(v); }
    inline void operator = ( int v ) { value=intdp(v); }
    inline void operator = ( long v ) { value=longdp(v); }
    inline void operator = ( unsigned char v ) { value=uintdp(v); }
    inline void operator = ( unsigned short v ) { value=uintdp(v); }
    inline void operator = ( unsigned int v ) { value=uintdp(v); }
    inline void operator = ( unsigned long v ) { value=ulongdp(v); }

    inline void operator += ( double_fst r ) { value=adddp(value, r.value); }
    inline void operator -= ( double_fst r ) { value=subdp(value, r.value); }
    inline void operator *= ( double_fst r ) { value=mpydp(value, r.value); }
    inline void operator /= ( double_fst r ) { value=divdp(value, r.value); }

    inline void operator += ( double v ) { value=adddp(value, v); }
    inline void operator -= ( double v ) { value=subdp(value, v); }
    inline void operator *= ( double v ) { value=mpydp(value, v); }
    inline void operator /= ( double v ) { value=divdp(value, v); }

    inline void operator += ( float v ) { value=adddp(value, spdp(v)); }
    inline void operator -= ( float v ) { value=subdp(value, spdp(v)); }
    inline void operator *= ( float v ) { value=mpydp(value, spdp(v)); }
    inline void operator /= ( float v ) { value=divdp(value, spdp(v)); }

    inline void operator += ( char v ) { value=adddp(value, intdp(v)); }
    inline void operator -= ( char v ) { value=subdp(value, intdp(v)); }
    inline void operator *= ( char v ) { value=mpydp(value, intdp(v)); }
    inline void operator /= ( char v ) { value=divdp(value, intdp(v)); }

    inline void operator += ( short v ) { value=adddp(value, intdp(v)); }
    inline void operator -= ( short v ) { value=subdp(value, intdp(v)); }
    inline void operator *= ( short v ) { value=mpydp(value, intdp(v)); }
    inline void operator /= ( short v ) { value=divdp(value, intdp(v)); }

    inline void operator += ( int v ) { value=adddp(value, intdp(v)); }
    inline void operator -= ( int v ) { value=subdp(value, intdp(v)); }
    inline void operator *= ( int v ) { value=mpydp(value, intdp(v)); }
    inline void operator /= ( int v ) { value=divdp(value, intdp(v)); }

    inline void operator += ( long v ) { value=adddp(value, longdp(v)); }
    inline void operator -= ( long v ) { value=subdp(value, longdp(v)); }
    inline void operator *= ( long v ) { value=mpydp(value, longdp(v)); }
    inline void operator /= ( long v ) { value=divdp(value, longdp(v)); }

    inline void operator += ( unsigned char v ) { value=adddp(value, uintdp(v)); }
    inline void operator -= ( unsigned char v ) { value=subdp(value, uintdp(v)); }
    inline void operator *= ( unsigned char v ) { value=mpydp(value, uintdp(v)); }
    inline void operator /= ( unsigned char v ) { value=divdp(value, uintdp(v)); }

    inline void operator += ( unsigned short v ) { value=adddp(value, uintdp(v)); }
    inline void operator -= ( unsigned short v ) { value=subdp(value, uintdp(v)); }
    inline void operator *= ( unsigned short v ) { value=mpydp(value, uintdp(v)); }
    inline void operator /= ( unsigned short v ) { value=divdp(value, uintdp(v)); }

    inline void operator += ( unsigned int v ) { value=adddp(value, uintdp(v)); }
    inline void operator -= ( unsigned int v ) { value=subdp(value, uintdp(v)); }
    inline void operator *= ( unsigned int v ) { value=mpydp(value, uintdp(v)); }
    inline void operator /= ( unsigned int v ) { value=divdp(value, uintdp(v)); }

    inline void operator += ( unsigned long v ) { value=adddp(value, ulongdp(v)); }
    inline void operator -= ( unsigned long v ) { value=subdp(value, ulongdp(v)); }
    inline void operator *= ( unsigned long v ) { value=mpydp(value, ulongdp(v)); }
    inline void operator /= ( unsigned long v ) { value=divdp(value, ulongdp(v)); }

    inline bool operator <  ( double_fst &r ) const { return value <  r.value; }
    inline bool operator >  ( double_fst &r ) const { return value >  r.value; }
    inline bool operator <= ( double_fst &r ) const { return value <= r.value; }
    inline bool operator >= ( double_fst &r ) const { return value >= r.value; }
    inline bool operator == ( double_fst &r ) const { return value == r.value; }
    inline bool operator != ( double_fst &r ) const { return value != r.value; }

    inline bool operator <  ( double v ) const { return value <  v; }
    inline bool operator >  ( double v ) const { return value >  v; }
    inline bool operator <= ( double v ) const { return value <= v; }
    inline bool operator >= ( double v ) const { return value >= v; }
    inline bool operator == ( double v ) const { return value == v; }
    inline bool operator != ( double v ) const { return value != v; }

    inline bool operator <  ( float v ) const { return value <  spdp(v); }
    inline bool operator >  ( float v ) const { return value >  spdp(v); }
    inline bool operator <= ( float v ) const { return value <= spdp(v); }
    inline bool operator >= ( float v ) const { return value >= spdp(v); }
    inline bool operator == ( float v ) const { return value == spdp(v); }
    inline bool operator != ( float v ) const { return value != spdp(v); }

    inline bool operator <  ( char v ) const { return value <  intdp(v); }
    inline bool operator >  ( char v ) const { return value >  intdp(v); }
    inline bool operator <= ( char v ) const { return value <= intdp(v); }
    inline bool operator >= ( char v ) const { return value >= intdp(v); }
    inline bool operator == ( char v ) const { return value == intdp(v); }
    inline bool operator != ( char v ) const { return value != intdp(v); }

    inline bool operator <  ( short v ) const { return value <  intdp(v); }
    inline bool operator >  ( short v ) const { return value >  intdp(v); }
    inline bool operator <= ( short v ) const { return value <= intdp(v); }
    inline bool operator >= ( short v ) const { return value >= intdp(v); }
    inline bool operator == ( short v ) const { return value == intdp(v); }
    inline bool operator != ( short v ) const { return value != intdp(v); }

    inline bool operator <  ( int v ) const { return value <  intdp(v); }
    inline bool operator >  ( int v ) const { return value >  intdp(v); }
    inline bool operator <= ( int v ) const { return value <= intdp(v); }
    inline bool operator >= ( int v ) const { return value >= intdp(v); }
    inline bool operator == ( int v ) const { return value == intdp(v); }
    inline bool operator != ( int v ) const { return value != intdp(v); }

    inline bool operator <  ( long v ) const { return value <  longdp(v); }
    inline bool operator >  ( long v ) const { return value >  longdp(v); }
    inline bool operator <= ( long v ) const { return value <= longdp(v); }
    inline bool operator >= ( long v ) const { return value >= longdp(v); }
    inline bool operator == ( long v ) const { return value == longdp(v); }
    inline bool operator != ( long v ) const { return value != longdp(v); }

    inline bool operator <  ( unsigned char v ) const { return value <  uintdp(v); }
    inline bool operator >  ( unsigned char v ) const { return value >  uintdp(v); }
    inline bool operator <= ( unsigned char v ) const { return value <= uintdp(v); }
    inline bool operator >= ( unsigned char v ) const { return value >= uintdp(v); }
    inline bool operator == ( unsigned char v ) const { return value == uintdp(v); }
    inline bool operator != ( unsigned char v ) const { return value != uintdp(v); }

    inline bool operator <  ( unsigned short v ) const { return value <  uintdp(v); }
    inline bool operator >  ( unsigned short v ) const { return value >  uintdp(v); }
    inline bool operator <= ( unsigned short v ) const { return value <= uintdp(v); }
    inline bool operator >= ( unsigned short v ) const { return value >= uintdp(v); }
    inline bool operator == ( unsigned short v ) const { return value == uintdp(v); }
    inline bool operator != ( unsigned short v ) const { return value != uintdp(v); }

    inline bool operator <  ( unsigned int v ) const { return value <  uintdp(v); }
    inline bool operator >  ( unsigned int v ) const { return value >  uintdp(v); }
    inline bool operator <= ( unsigned int v ) const { return value <= uintdp(v); }
    inline bool operator >= ( unsigned int v ) const { return value >= uintdp(v); }
    inline bool operator == ( unsigned int v ) const { return value == uintdp(v); }
    inline bool operator != ( unsigned int v ) const { return value != uintdp(v); }

    inline bool operator <  ( unsigned long v ) const { return value <  ulongdp(v); }
    inline bool operator >  ( unsigned long v ) const { return value >  ulongdp(v); }
    inline bool operator <= ( unsigned long v ) const { return value <= ulongdp(v); }
    inline bool operator >= ( unsigned long v ) const { return value >= ulongdp(v); }
    inline bool operator == ( unsigned long v ) const { return value == ulongdp(v); }
    inline bool operator != ( unsigned long v ) const { return value != ulongdp(v); }
};

//Для типа double_fst
inline double_fst operator + (double_fst l, double_fst r) { return double_fst(adddp(l.value,r.value)); }
inline double_fst operator - (double_fst l, double_fst r) { return double_fst(subdp(l.value,r.value)); }
inline double_fst operator * (double_fst l, double_fst r) { return double_fst(mpydp(l.value,r.value)); }
inline double_fst operator / (double_fst l, double_fst r) { return double_fst(divdp(l.value,r.value)); }

//Для типа double
inline double_fst operator + ( double l, double_fst r ) { return double_fst(adddp(l, r.value)); }
inline double_fst operator - ( double l, double_fst r ) { return double_fst(subdp(l, r.value)); }
inline double_fst operator * ( double l, double_fst r ) { return double_fst(mpydp(l, r.value)); }
inline double_fst operator / ( double l, double_fst r ) { return double_fst(divdp(l, r.value)); }
inline double_fst operator + ( double_fst l, double r ) { return double_fst(adddp(l.value, r)); }
inline double_fst operator - ( double_fst l, double r ) { return double_fst(subdp(l.value, r)); }
inline double_fst operator * ( double_fst l, double r ) { return double_fst(mpydp(l.value, r)); }
inline double_fst operator / ( double_fst l, double r ) { return double_fst(divdp(l.value, r)); }

//Для типа float
inline double_fst operator + ( float l, double_fst r ) { return double_fst(adddp(spdp(l), r.value)); }
inline double_fst operator - ( float l, double_fst r ) { return double_fst(subdp(spdp(l), r.value)); }
inline double_fst operator * ( float l, double_fst r ) { return double_fst(mpydp(spdp(l), r.value)); }
inline double_fst operator / ( float l, double_fst r ) { return double_fst(divdp(spdp(l), r.value)); }
inline double_fst operator + ( double_fst l, float r ) { return double_fst(adddp(l.value, spdp(r))); }
inline double_fst operator - ( double_fst l, float r ) { return double_fst(subdp(l.value, spdp(r))); }
inline double_fst operator * ( double_fst l, float r ) { return double_fst(mpydp(l.value, spdp(r))); }
inline double_fst operator / ( double_fst l, float r ) { return double_fst(divdp(l.value, spdp(r))); }

//Для типа char
inline double_fst operator + ( char l, double_fst r ) { return double_fst(adddp(intdp(l), r.value)); }
inline double_fst operator - ( char l, double_fst r ) { return double_fst(subdp(intdp(l), r.value)); }
inline double_fst operator * ( char l, double_fst r ) { return double_fst(mpydp(intdp(l), r.value)); }
inline double_fst operator / ( char l, double_fst r ) { return double_fst(divdp(intdp(l), r.value)); }
inline double_fst operator + ( double_fst l, char r ) { return double_fst(adddp(l.value, intdp(r))); }
inline double_fst operator - ( double_fst l, char r ) { return double_fst(subdp(l.value, intdp(r))); }
inline double_fst operator * ( double_fst l, char r ) { return double_fst(mpydp(l.value, intdp(r))); }
inline double_fst operator / ( double_fst l, char r ) { return double_fst(divdp(l.value, intdp(r))); }

//Для типа short
inline double_fst operator + ( short l, double_fst r ) { return double_fst(adddp(intdp(l), r.value)); }
inline double_fst operator - ( short l, double_fst r ) { return double_fst(subdp(intdp(l), r.value)); }
inline double_fst operator * ( short l, double_fst r ) { return double_fst(mpydp(intdp(l), r.value)); }
inline double_fst operator / ( short l, double_fst r ) { return double_fst(divdp(intdp(l), r.value)); }
inline double_fst operator + ( double_fst l, short r ) { return double_fst(adddp(l.value, intdp(r))); }
inline double_fst operator - ( double_fst l, short r ) { return double_fst(subdp(l.value, intdp(r))); }
inline double_fst operator * ( double_fst l, short r ) { return double_fst(mpydp(l.value, intdp(r))); }
inline double_fst operator / ( double_fst l, short r ) { return double_fst(divdp(l.value, intdp(r))); }

//Для типа int
inline double_fst operator + ( int l, double_fst r ) { return double_fst(adddp(intdp(l), r.value)); }
inline double_fst operator - ( int l, double_fst r ) { return double_fst(subdp(intdp(l), r.value)); }
inline double_fst operator * ( int l, double_fst r ) { return double_fst(mpydp(intdp(l), r.value)); }
inline double_fst operator / ( int l, double_fst r ) { return double_fst(divdp(intdp(l), r.value)); }
inline double_fst operator + ( double_fst l, int r ) { return double_fst(adddp(l.value, intdp(r))); }
inline double_fst operator - ( double_fst l, int r ) { return double_fst(subdp(l.value, intdp(r))); }
inline double_fst operator * ( double_fst l, int r ) { return double_fst(mpydp(l.value, intdp(r))); }
inline double_fst operator / ( double_fst l, int r ) { return double_fst(divdp(l.value, intdp(r))); }

//Для типа long
inline double_fst operator + ( long l, double_fst r ) { return double_fst(adddp(longdp(l), r.value)); }
inline double_fst operator - ( long l, double_fst r ) { return double_fst(subdp(longdp(l), r.value)); }
inline double_fst operator * ( long l, double_fst r ) { return double_fst(mpydp(longdp(l), r.value)); }
inline double_fst operator / ( long l, double_fst r ) { return double_fst(divdp(longdp(l), r.value)); }
inline double_fst operator + ( double_fst l, long r ) { return double_fst(adddp(l.value, longdp(r))); }
inline double_fst operator - ( double_fst l, long r ) { return double_fst(subdp(l.value, longdp(r))); }
inline double_fst operator * ( double_fst l, long r ) { return double_fst(mpydp(l.value, longdp(r))); }
inline double_fst operator / ( double_fst l, long r ) { return double_fst(divdp(l.value, longdp(r))); }

//Для типа unsigned char
inline double_fst operator + ( unsigned char l, double_fst r ) { return double_fst(adddp(uintdp(l), r.value)); }
inline double_fst operator - ( unsigned char l, double_fst r ) { return double_fst(subdp(uintdp(l), r.value)); }
inline double_fst operator * ( unsigned char l, double_fst r ) { return double_fst(mpydp(uintdp(l), r.value)); }
inline double_fst operator / ( unsigned char l, double_fst r ) { return double_fst(divdp(uintdp(l), r.value)); }
inline double_fst operator + ( double_fst l, unsigned char r ) { return double_fst(adddp(l.value, uintdp(r))); }
inline double_fst operator - ( double_fst l, unsigned char r ) { return double_fst(subdp(l.value, uintdp(r))); }
inline double_fst operator * ( double_fst l, unsigned char r ) { return double_fst(mpydp(l.value, uintdp(r))); }
inline double_fst operator / ( double_fst l, unsigned char r ) { return double_fst(divdp(l.value, uintdp(r))); }

//Для типа unsigned short
inline double_fst operator + ( unsigned short l, double_fst r ) { return double_fst(adddp(uintdp(l), r.value)); }
inline double_fst operator - ( unsigned short l, double_fst r ) { return double_fst(subdp(uintdp(l), r.value)); }
inline double_fst operator * ( unsigned short l, double_fst r ) { return double_fst(mpydp(uintdp(l), r.value)); }
inline double_fst operator / ( unsigned short l, double_fst r ) { return double_fst(divdp(uintdp(l), r.value)); }
inline double_fst operator + ( double_fst l, unsigned short r ) { return double_fst(adddp(l.value, uintdp(r))); }
inline double_fst operator - ( double_fst l, unsigned short r ) { return double_fst(subdp(l.value, uintdp(r))); }
inline double_fst operator * ( double_fst l, unsigned short r ) { return double_fst(mpydp(l.value, uintdp(r))); }
inline double_fst operator / ( double_fst l, unsigned short r ) { return double_fst(divdp(l.value, uintdp(r))); }

//Для типа unsigned int
inline double_fst operator + ( unsigned int l, double_fst r ) { return double_fst(adddp(uintdp(l), r.value)); }
inline double_fst operator - ( unsigned int l, double_fst r ) { return double_fst(subdp(uintdp(l), r.value)); }
inline double_fst operator * ( unsigned int l, double_fst r ) { return double_fst(mpydp(uintdp(l), r.value)); }
inline double_fst operator / ( unsigned int l, double_fst r ) { return double_fst(divdp(uintdp(l), r.value)); }
inline double_fst operator + ( double_fst l, unsigned int r ) { return double_fst(adddp(l.value, uintdp(r))); }
inline double_fst operator - ( double_fst l, unsigned int r ) { return double_fst(subdp(l.value, uintdp(r))); }
inline double_fst operator * ( double_fst l, unsigned int r ) { return double_fst(mpydp(l.value, uintdp(r))); }
inline double_fst operator / ( double_fst l, unsigned int r ) { return double_fst(divdp(l.value, uintdp(r))); }

//Для типа unsigned long
inline double_fst operator + ( unsigned long l, double_fst r ) { return double_fst(adddp(ulongdp(l), r.value)); }
inline double_fst operator - ( unsigned long l, double_fst r ) { return double_fst(subdp(ulongdp(l), r.value)); }
inline double_fst operator * ( unsigned long l, double_fst r ) { return double_fst(mpydp(ulongdp(l), r.value)); }
inline double_fst operator / ( unsigned long l, double_fst r ) { return double_fst(divdp(ulongdp(l), r.value)); }
inline double_fst operator + ( double_fst l, unsigned long r ) { return double_fst(adddp(l.value, ulongdp(r))); }
inline double_fst operator - ( double_fst l, unsigned long r ) { return double_fst(subdp(l.value, ulongdp(r))); }
inline double_fst operator * ( double_fst l, unsigned long r ) { return double_fst(mpydp(l.value, ulongdp(r))); }
inline double_fst operator / ( double_fst l, unsigned long r ) { return double_fst(divdp(l.value, ulongdp(r))); }

#endif //__FAST_RTS_64X_H
fontp
Цитата(rifch @ Apr 24 2008, 17:33) *
Сделал для функций этой библиотеки обёртку. Но оказалось, что с ней интересующая меня функция билинейного масштабирования работает даже медленее, чем при использовании встроенных в компилятор типа double. Из-за чего это? Может из-за накладных расходов на организацию классов?


Обёртка, то ладно...Надеюсь, все функции библиотеки объявлены как inline. Иначе - беда. Издержки на вызов функции
Degun
Цитата(fontp @ Apr 24 2008, 17:39) *
Обёртка, то ладно...Надеюсь, все функции библиотеки объявлены как inline. Иначе - беда. Издержки на вызов функции

А разве можно функции, собранные в файл-библиотеку fastrts62x64x.lib, объявить как inline. Вроде бы, т. к. они уже скомпилированны в библиотеку, то они не могут быть inline.
fontp
Цитата(Degun @ Apr 25 2008, 10:08) *
А разве можно функции, собранные в файл-библиотеку fastrts62x64x.lib, объявить как inline. Вроде бы, т. к. они уже скомпилированны в библиотеку, то они не могут быть inline.


Так чего Вы тогда от него хотите? Короткие функции, вызываемые через Call по определению будут работать медленно. Для стандартных float это не так, они оформлены intrinsic и вставляются компилятором inline
А вот Вы возьмите не библиотеку lib, а её исходный код. Повытаскивайте те функции, что Вам нужны в h-файл и припишите к каждой функции модификатор inline - и всё сразу станет во много раз быстрее.
Degun
Цитата(fontp @ Apr 25 2008, 11:16) *
Так чего Вы тогда от него хотите? Короткие функции, вызываемые через Call по определению будут работать медленно. Для стандартных float это не так, они оформлены intrinsic и вставляются компилятором inline
А вот Вы возьмите не библиотеку lib, а её исходный код. Повытаскивайте те функции, что Вам нужны в h-файл и припишите к каждой функции модификатор inline - и всё сразу станет во много раз быстрее.

Как-то это некрасиво - лучше пойти другим путём. Я сделал класс на основе представления плавающего числа типа double в виде целочисленного типа long long (на основе класса fastfloat по ссылке http://www.koders.com/cpp/fid5E90955711BFB...1C652C383C.aspx). Такой подход предоставляет полный эквивалент числа с плавающей запятой без использования последнего. Моя тестовая функция билинейного масштабирования при этом сразу стала выполняться в полтора раза быстрее. И это при том, что я её ещё не оптимизировал насчёт применения DMA (тогда бы улучшение производительности было бы гораздо заметнее). Так что предлагаю к использованию (охотно принимаются замечания по улучшению производительности этого класса или замеченные ошибки).

Код
/*!\file fastfloat.h
* \brief This class stores floating point numbers as integers,
* \brief with BITS shift, i.e. value XYZ is stored as XYZ * RATIO
* \version 1.0
* \date 25 april 2008
*/
#ifndef __FAST_FLOAT_H
#define __FAST_FLOAT_H

class fastdouble
{
private:
    enum { BITS = 16, RATIO = 65536 };
    long long value;
    inline fastdouble( long v, bool ) : value( v ) {} // for operator-()
public:
    inline fastdouble() { value=0; }
    inline fastdouble( double v ) { value=static_cast<long long>(v * RATIO + 0.5); }
    inline fastdouble( float v ) { value=static_cast<long long>(v * RATIO + 0.5); }
    inline fastdouble( char v ) { value=static_cast<long long>(v) << BITS; }
    inline fastdouble( short v ) { value=static_cast<long long>(v) << BITS; }
    inline fastdouble( int v ) { value=static_cast<long long>(v) << BITS; }
    inline fastdouble( long v ) { value=static_cast<long long>(v) << BITS; }
    inline fastdouble( unsigned char v ) { value=static_cast<long long>(v) << BITS; }
    inline fastdouble( unsigned short v ) { value=static_cast<long long>(v) << BITS; }
    inline fastdouble( unsigned int v ) { value=static_cast<long long>(v) << BITS; }
    inline fastdouble( unsigned long v ) { value=static_cast<long long>(v) << BITS; }

    inline void operator =( fastdouble r ) { value=r.value; }
    inline void operator =( double v ) { value=static_cast<long long>(v * RATIO + 0.5); }
    inline void operator =( float v ) { value=static_cast<long long>(v * RATIO + 0.5); }
    inline void operator =( char v ) { value=static_cast<long long>(v) << BITS; }
    inline void operator =( short v ) { value=static_cast<long long>(v) << BITS; }
    inline void operator =( int v ) { value=static_cast<long long>(v) << BITS; }
    inline void operator =( long v ) { value=static_cast<long long>(v) << BITS; }
    inline void operator =( unsigned char v ) { value=static_cast<long long>(v) << BITS; }
    inline void operator =( unsigned short v ) { value=static_cast<long long>(v) << BITS; }
    inline void operator =( unsigned int v ) { value=static_cast<long long>(v) << BITS; }
    inline void operator =( unsigned long v ) { value=static_cast<long long>(v) << BITS; }

    inline double toDouble() const { return static_cast<double>( value ) / RATIO; }
    inline long toLong() const { return static_cast<long>(value >> BITS); }

    inline operator double() const { return toDouble(); }
    inline operator float() const { return (float)toDouble(); }
    inline operator char() const { return (char)toLong(); }
    inline operator short() const { return (short)toLong(); }
    inline operator int() const { return (int)toLong(); }
    inline operator long() const { return toLong(); }
    inline operator unsigned char() const { return (unsigned char)toLong(); }
    inline operator unsigned short() const { return (unsigned short)toLong(); }
    inline operator unsigned int() const { return (unsigned int)toLong(); }
    inline operator unsigned long() const { return (unsigned long)toLong(); }

    inline fastdouble operator - () const { return fastdouble( -value, false ); }

    inline fastdouble& operator += ( fastdouble r ) { value += r.value; return *this; }
    inline fastdouble& operator -= ( fastdouble r ) { value -= r.value; return *this; }
    inline fastdouble& operator *= ( fastdouble r ) { value  = ( value * r.value ) >> BITS; return *this; }
    inline fastdouble& operator /= ( fastdouble r ) { value  = ( value << BITS ) / r.value; return *this; }

    inline fastdouble& operator += ( double v ) { value += static_cast<long long>( v * RATIO + 0.5 ); return *this; }
    inline fastdouble& operator -= ( double v ) { value -= static_cast<long long>( v * RATIO + 0.5 ); return *this; }
    inline fastdouble& operator *= ( double v ) { value  = static_cast<long long >( value * v + 0.5 ); return *this; }
    inline fastdouble& operator /= ( double v ) { value  = static_cast<long long>( value / v + 0.5 ); return *this; }

    inline fastdouble& operator += ( float v ) { value += static_cast<long long>( v * RATIO + 0.5 ); return *this; }
    inline fastdouble& operator -= ( float v ) { value -= static_cast<long long>( v * RATIO + 0.5 ); return *this; }
    inline fastdouble& operator *= ( float v ) { value  = static_cast<long long>( value * v + 0.5 ); return *this; }
    inline fastdouble& operator /= ( float v ) { value  = static_cast<long long>( value / v + 0.5 ); return *this; }

    inline fastdouble& operator += ( char v ) { value += static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator -= ( char v ) { value -= static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator *= ( char v ) { value *= v; return *this; }
    inline fastdouble& operator /= ( char v ) { value /= v; return *this; }

    inline fastdouble& operator += ( short v ) { value += static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator -= ( short v ) { value -= static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator *= ( short v ) { value *= v; return *this; }
    inline fastdouble& operator /= ( short v ) { value /= v; return *this; }

    inline fastdouble& operator += ( int v ) { value += static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator -= ( int v ) { value -= static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator *= ( int v ) { value *= v; return *this; }
    inline fastdouble& operator /= ( int v ) { value /= v; return *this; }

    inline fastdouble& operator += ( long v ) { value += static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator -= ( long v ) { value -= static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator *= ( long v ) { value *= v; return *this; }
    inline fastdouble& operator /= ( long v ) { value /= v; return *this; }

    inline fastdouble& operator += ( unsigned char v ) { value += static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator -= ( unsigned char v ) { value -= static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator *= ( unsigned char v ) { value *= v; return *this; }
    inline fastdouble& operator /= ( unsigned char v ) { value /= v; return *this; }

    inline fastdouble& operator += ( unsigned short v ) { value += static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator -= ( unsigned short v ) { value -= static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator *= ( unsigned short v ) { value *= v; return *this; }
    inline fastdouble& operator /= ( unsigned short v ) { value /= v; return *this; }

    inline fastdouble& operator += ( unsigned int v ) { value += static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator -= ( unsigned int v ) { value -= static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator *= ( unsigned int v ) { value *= v; return *this; }
    inline fastdouble& operator /= ( unsigned int v ) { value /= v; return *this; }

    inline fastdouble& operator += ( unsigned long v ) { value += static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator -= ( unsigned long v ) { value -= static_cast<long long>( v ) << BITS; return *this; }
    inline fastdouble& operator *= ( unsigned long v ) { value *= v; return *this; }
    inline fastdouble& operator /= ( unsigned long v ) { value /= v; return *this; }

    //Для типа fastdouble
    inline bool operator <  ( fastdouble r ) const { return value < r.value; }
    inline bool operator <= ( fastdouble r ) const { return value <= r.value; }
    inline bool operator >  ( fastdouble r ) const { return value > r.value; }
    inline bool operator >= ( fastdouble r ) const { return value >= r.value; }
    inline bool operator == ( fastdouble r ) const { return value == r.value; }
    inline bool operator != ( fastdouble r ) const { return value != r.value; }
};

//Для типа fastdouble
inline fastdouble operator+ ( fastdouble l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator- ( fastdouble l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator* ( fastdouble l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator/ ( fastdouble l, fastdouble r ) { return fastdouble( l ) /= r; }

//Для типа double
inline fastdouble operator + ( double l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( double l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( double l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( double l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, double r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, double r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, double r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, double r ) { return fastdouble( l ) /= r; }

//Для типа float
inline fastdouble operator + ( float l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( float l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( float l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( float l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, float r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, float r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, float r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, float r ) { return fastdouble( l ) /= r; }

//Для типа char
inline fastdouble operator + ( char l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( char l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( char l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( char l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, char r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, char r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, char r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, char r ) { return fastdouble( l ) /= r; }

//Для типа short
inline fastdouble operator + ( short l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( short l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( short l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( short l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, short r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, short r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, short r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, short r ) { return fastdouble( l ) /= r; }

//Для типа int
inline fastdouble operator + ( int l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( int l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( int l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( int l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, int r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, int r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, int r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, int r ) { return fastdouble( l ) /= r; }

//Для типа long
inline fastdouble operator + ( long l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( long l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( long l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( long l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, long r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, long r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, long r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, long r ) { return fastdouble( l ) /= r; }

//Для типа unsigned char
inline fastdouble operator + ( unsigned char l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( unsigned char l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( unsigned char l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( unsigned char l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, unsigned char r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, unsigned char r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, unsigned char r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, unsigned char r ) { return fastdouble( l ) /= r; }

//Для типа unsigned short
inline fastdouble operator + ( unsigned short l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( unsigned short l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( unsigned short l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( unsigned short l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, unsigned short r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, unsigned short r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, unsigned short r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, unsigned short r ) { return fastdouble( l ) /= r; }

//Для типа unsigned int
inline fastdouble operator + ( unsigned int l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( unsigned int l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( unsigned int l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( unsigned int l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, unsigned int r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, unsigned int r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, unsigned int r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, unsigned int r ) { return fastdouble( l ) /= r; }

//Для типа unsigned long
inline fastdouble operator + ( unsigned long l, fastdouble r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( unsigned long l, fastdouble r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( unsigned long l, fastdouble r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( unsigned long l, fastdouble r ) { return fastdouble( l ) /= r; }
inline fastdouble operator + ( fastdouble l, unsigned long r ) { return fastdouble( l ) += r; }
inline fastdouble operator - ( fastdouble l, unsigned long r ) { return fastdouble( l ) -= r; }
inline fastdouble operator * ( fastdouble l, unsigned long r ) { return fastdouble( l ) *= r; }
inline fastdouble operator / ( fastdouble l, unsigned long r ) { return fastdouble( l ) /= r; }


//Для типа double
inline bool operator <  ( fastdouble l, double r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, double r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, double r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, double r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, double r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, double r ) { return l != fastdouble( r ); }

inline bool operator <  ( double l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( double l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( double l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( double l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( double l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( double l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа float
inline bool operator <  ( fastdouble l, float r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, float r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, float r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, float r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, float r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, float r ) { return l != fastdouble( r ); }

inline bool operator <  ( float l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( float l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( float l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( float l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( float l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( float l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа char
inline bool operator <  ( fastdouble l, char r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, char r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, char r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, char r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, char r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, char r ) { return l != fastdouble( r ); }

inline bool operator <  ( char l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( char l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( char l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( char l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( char l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( char l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа short
inline bool operator <  ( fastdouble l, short r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, short r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, short r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, short r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, short r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, short r ) { return l != fastdouble( r ); }

inline bool operator <  ( short l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( short l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( short l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( short l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( short l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( short l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа int
inline bool operator <  ( fastdouble l, int r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, int r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, int r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, int r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, int r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, int r ) { return l != fastdouble( r ); }

inline bool operator <  ( int l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( int l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( int l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( int l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( int l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( int l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа long
inline bool operator <  ( fastdouble l, long r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, long r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, long r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, long r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, long r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, long r ) { return l != fastdouble( r ); }

inline bool operator <  ( long l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( long l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( long l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( long l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( long l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( long l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа unsigned char
inline bool operator <  ( fastdouble l, unsigned char r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, unsigned char r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, unsigned char r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, unsigned char r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, unsigned char r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, unsigned char r ) { return l != fastdouble( r ); }

inline bool operator <  ( unsigned char l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( unsigned char l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( unsigned char l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( unsigned char l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( unsigned char l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( unsigned char l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа unsigned short
inline bool operator <  ( fastdouble l, unsigned short r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, unsigned short r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, unsigned short r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, unsigned short r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, unsigned short r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, unsigned short r ) { return l != fastdouble( r ); }

inline bool operator <  ( unsigned short l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( unsigned short l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( unsigned short l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( unsigned short l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( unsigned short l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( unsigned short l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа unsigned int
inline bool operator <  ( fastdouble l, unsigned int r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, unsigned int r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, unsigned int r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, unsigned int r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, unsigned int r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, unsigned int r ) { return l != fastdouble( r ); }

inline bool operator <  ( unsigned int l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( unsigned int l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( unsigned int l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( unsigned int l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( unsigned int l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( unsigned int l, fastdouble r ) { return fastdouble( l ) != r; }

//Для типа unsigned long
inline bool operator <  ( fastdouble l, unsigned long r ) { return l <  fastdouble( r ); }
inline bool operator <= ( fastdouble l, unsigned long r ) { return l <= fastdouble( r ); }
inline bool operator >  ( fastdouble l, unsigned long r ) { return l >  fastdouble( r ); }
inline bool operator >= ( fastdouble l, unsigned long r ) { return l >= fastdouble( r ); }
inline bool operator == ( fastdouble l, unsigned long r ) { return l == fastdouble( r ); }
inline bool operator != ( fastdouble l, unsigned long r ) { return l != fastdouble( r ); }

inline bool operator <  ( unsigned long l, fastdouble r ) { return fastdouble( l ) <  r; }
inline bool operator <= ( unsigned long l, fastdouble r ) { return fastdouble( l ) <= r; }
inline bool operator >  ( unsigned long l, fastdouble r ) { return fastdouble( l ) >  r; }
inline bool operator >= ( unsigned long l, fastdouble r ) { return fastdouble( l ) >= r; }
inline bool operator == ( unsigned long l, fastdouble r ) { return fastdouble( l ) == r; }
inline bool operator != ( unsigned long l, fastdouble r ) { return fastdouble( l ) != r; }

#if 1  // change to 0 to turn fastdouble usage off
#else
#define fastdouble double
#define fasttodouble( v ) double( v )
#define fasttolong( v ) long( v )
#endif

#endif //__FAST_FLOAT_H
Andrew32768
... а если переписать этот класс с использованием типа данных fract16 (для BLACKFIN), то будет работать быстрее?

Цитата(Andrew32768 @ Jun 17 2008, 18:52) *
... а если переписать этот класс с использованием типа данных fract16 (для BLACKFIN), то будет работать быстрее?

или же fract16 виртуальный тип данных, не поддерживаемый напрямую процессором?
fontp
Цитата(Andrew32768 @ Jun 17 2008, 17:37) *
... а если переписать этот класс с использованием типа данных fract16 (для BLACKFIN), то будет работать быстрее?
или же fract16 виртуальный тип данных, не поддерживаемый напрямую процессором?


Как это? fract16 - это short c прямой поддержкой процессором и библиотеками
Какой же он виртуальный? Очевидно будет быстрее всего
fract32 уже как бы синтетический, как бы виртуальный smile.gif
Andrew32768
Цитата(fontp @ Jun 17 2008, 20:00) *
Как это? fract16 - это short c прямой поддержкой процессором и библиотеками
Какой же он виртуальный? Очевидно будет быстрее всего
fract32 уже как бы синтетический, как бы виртуальный smile.gif


я тоже читаю в описании, что его поддерживает процессор
но почему же тогда в INCLUDE, куча definов, которые описывают элементарные операции с этим типом (деление, например)?
fontp
Цитата(Andrew32768 @ Jun 17 2008, 18:18) *
я тоже читаю в описании, что его поддерживает процессор
но почему же тогда в INCLUDE, куча definов, которые описывают элементарные операции с этим типом (деление, например)?


Чтобы работать из С. Язык С не предусматривает такого типа, более того язык С не предусматривает даже естественных операций, когда fixed16*fixed16 = fixed32 и наоборот fixed32/fixed16 = fixed16
Куча инлайновых функций, а не define
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.