Перейти к содержанию
    

Как реализованы функции cos(x) exp(x) в math.h ?

Собственно интересует метод реализации функций cos(x) и exp(x) . Как они вычисляются ? Таблично , посредством ряда фурье или ... ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Библиотека math.h, входящая в состав кейла, по- видимому также использует ряд Тейлора. Причем количество членов воидимо какое-то ужасное, судя по времени выполнения. На AVR из его библиотеки float sin(float x) выполнялся впятеро быстрее, там было 5 членов ряда. :)

 

Буду переписывать библиотеку- по времени выполнения математика меня не устраивает - медленнее чем на 8-ми битнике (AVR) работает при вчетверо большей тактовой.

А уж знаменито разрекламированная функция (hypot) вычисляющая длину двумерного вектора ( например, модуль комплексного числа ), это вообще песня. 0.76 мс!!! на 72-х мегагерцах...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Библиотека math.h, входящая в состав кейла, по- видимому также использует ряд Тейлора. Причем количество членов воидимо какое-то ужасное, судя по времени выполнения. На AVR из его библиотеки float sin(float x) выполнялся впятеро быстрее, там было 5 членов ряда. :)

 

Буду переписывать библиотеку- по времени выполнения математика меня не устраивает - медленнее чем на 8-ми битнике (AVR) работает при вчетверо большей тактовой.

А уж знаменито разрекламированная функция (hypot) вычисляющая длину двумерного вектора ( например, модуль комплексного числа ), это вообще песня. 0.76 мс!!! на 72-х мегагерцах...

Тоже столкнулся с проблемой очень медленной работы функций.

tab_sin_U[i]=round((sin(temp)*amount)+(1/6)*(sin(3*temp)*amount));

Расчет массива из 1024-х значений по этой формуле, в STR912 занимал примерно пол секунды. И это при частоте ядра 96МГц.

Изменено пользователем artur_off

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тоже столкнулся с проблемой очень медленной работы функций.

tab_sin_U[i]=round((sin(temp)*amount)+(1/6)*(sin(3*temp)*amount));

Расчет массива из 1024-х значений по этой формуле, в STR912 занимал примерно пол секунды. И это при частоте ядра 96МГц.

Формула как-то странно выглядит. Например, (1/6) - это 0. Возможно, что с типами других операндов напутано. Если можно не использовать double, то нужно внимательно проследить, чтобы везде был float. К тому же amount можно вынести за скобки и сэкономить одно умножение. Что делает round() и как - непонятно. Вывод: рано спешить с выводами про "быстро-медленно", сначала надо код подправить.

И вообще, что такое "очень медленная работа функций, и это с частотой ядра 96 МГц"? Эта фраза не имеет смысла, пока не сказано, сколько микросекунд - медленно, а сколько - быстро.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если есть желание реализовать свой алгоритм, тогда исключительно CORDIC. Такой ответ уже был. Алгоритм очень хорошо срабатывает на ПЛИС. Весь просчет за один такт. Нужно только не забывать, что для точности, например, 32 бит нужно закладывать в расчет не меньше 33 бит. Еще лучше держат бит 5 в запасе. Очень удобный алгоритм, если нужно сразу получить и синис, и косинус числа. Прирост в скорости вычисления колоссальный. Даже на микроконтроллере без сопроцессора. Да и вообще, для любителей численных методов интересная тема.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если есть желание реализовать свой алгоритм, тогда исключительно CORDIC. Такой ответ уже был. Алгоритм очень хорошо срабатывает на ПЛИС. Весь просчет за один такт. Нужно только не забывать, что для точности, например, 32 бит нужно закладывать в расчет не меньше 33 бит. Еще лучше держат бит 5 в запасе. Очень удобный алгоритм, если нужно сразу получить и синис, и косинус числа. Прирост в скорости вычисления колоссальный. Даже на микроконтроллере без сопроцессора. Да и вообще, для любителей численных методов интересная тема.

 

Готовых функций CORDIC не нашел, только алгоритм. Пока остановился на том, что и просто тупое копирование AVR-овской библиотеки от CVAvr (она, слава богу, открытая и на С писанная) дает примерно десятикратный прирост времени выполнения.

 

Возможно, в родной кейловской библиотеке больше точность, буду проверять. У меня дискретность значений примерно 50 микрорадиан.

 

Использовал функции в float синуса, косинуса и арктангенса ( на самом деле там один синус, остальные- через тригонометрические преобразования)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно, в родной кейловской библиотеке больше точность, буду проверять. У меня дискретность значений примерно 50 микрорадиан.

Если такой маленький прирост, то наверняка можно оптимизировать при помощи локальной линеаризации.

 

Использовал функции в float синуса, косинуса и арктангенса ( на самом деле там один синус, остальные- через тригонометрические преобразования)

Если честно, не понимаю, как арктангенс можно получить из синуса тригонометрическими преобразованиями. Скорее всего никак нельзя. Ну да ладно, это к делу не относится...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Формула как-то странно выглядит. Например, (1/6) - это 0. Возможно, что с типами других операндов напутано. Если можно не использовать double, то нужно внимательно проследить, чтобы везде был float. К тому же amount можно вынести за скобки и сэкономить одно умножение. Что делает round() и как - непонятно. Вывод: рано спешить с выводами про "быстро-медленно", сначала надо код подправить.

И вообще, что такое "очень медленная работа функций, и это с частотой ядра 96 МГц"? Эта фраза не имеет смысла, пока не сказано, сколько микросекунд - медленно, а сколько - быстро.

 

Это кусок кода с матлаба, так как сишный удалил. а на С естественно было приведение к float. хотя здесь протупил, вместо 1/6 можно было написать 0.167.

round() - математическое округление.

по поводу amount согласен, но это не так уж и сильно влияет на производительность.

По поводу времени выполнения было сказано, что занимает примерно пол секунды (0.5 с).

Изменено пользователем artur_off

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это кусок кода с матлаба, так как сишный удалил. а на С естественно было приведение к float. хотя здесь протупил, вместо 1/6 можно было написать 0.167.

round() - математическое округление.

Если везде float, то нужно использовать sinf() вместо sin(), roundf() вместо round(). 0.167 лучше писать как 0.167f, а если округление до трёх цифр не подходит, то 1.0f/6. Не сочтите за занудство, это на всякий случай. Скорее всего, у Вас так и написано.

Меня удивил round(), потому что в стандартной библиотеке Си его сразу не нашёл. Видимо, было добавлено в C99...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если везде float, то нужно использовать sinf() вместо sin(), roundf() вместо round(). 0.167 лучше писать как 0.167f, а если округление до трёх цифр не подходит, то 1.0f/6. Не сочтите за занудство, это на всякий случай. Скорее всего, у Вас так и написано.

Меня удивил round(), потому что в стандартной библиотеке Си его сразу не нашёл. Видимо, было добавлено в C99...

 

Благодарю за советы))).

 

 

А round() действительно добавлен в С99 и поэтому перед #include <math.h> надо объявить #define __USE_C99_MATH.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...