реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Как реализованы функции cos(x) exp(x) в math.h ?
Костян
сообщение Jan 28 2010, 07:29
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 740
Регистрация: 24-07-06
Из: Minsk
Пользователь №: 19 059



Собственно интересует метод реализации функций cos(x) и exp(x) . Как они вычисляются ? Таблично , посредством ряда фурье или ... ?
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 28 2010, 07:55
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Можно подглядеть у newlib.
Вот синус-косинус:
sf_sine.c
Вот экспонента:
sf_exp.c
Go to the top of the page
 
+Quote Post
kosyak©
сообщение Jan 28 2010, 08:03
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 179
Регистрация: 1-10-07
Из: НЧ
Пользователь №: 30 966



Скорее всего ряд Тейлора.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 28 2010, 10:11
Сообщение #4


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(kosyak© @ Jan 28 2010, 11:03) *
Скорее всего ряд Тейлора.

sf_sine.c
Код
   /* Calculate the Taylor series. */

smile.gif
Go to the top of the page
 
+Quote Post
Serj78
сообщение Jan 28 2010, 18:48
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 966
Регистрация: 27-05-06
Из: СПб
Пользователь №: 17 499



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

Буду переписывать библиотеку- по времени выполнения математика меня не устраивает - медленнее чем на 8-ми битнике (AVR) работает при вчетверо большей тактовой.
А уж знаменито разрекламированная функция (hypot) вычисляющая длину двумерного вектора ( например, модуль комплексного числа ), это вообще песня. 0.76 мс!!! на 72-х мегагерцах...
Go to the top of the page
 
+Quote Post
blackfin
сообщение Jan 28 2010, 18:54
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



CORDIC

Сообщение отредактировал blackfin - Jan 28 2010, 18:58
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 28 2010, 22:45
Сообщение #7


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(blackfin @ Jan 28 2010, 21:54) *

Newlib весь безнадежно тормозной. И далеко не "new" smile.gif
Go to the top of the page
 
+Quote Post
artur_off
сообщение Jan 29 2010, 19:48
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 118
Регистрация: 24-05-08
Из: Odessa
Пользователь №: 37 784



Цитата(Serj78 @ Jan 28 2010, 20:48) *
Библиотека math.h, входящая в состав кейла, по- видимому также использует ряд Тейлора. Причем количество членов воидимо какое-то ужасное, судя по времени выполнения. На AVR из его библиотеки float sin(float x) выполнялся впятеро быстрее, там было 5 членов ряда. smile.gif

Буду переписывать библиотеку- по времени выполнения математика меня не устраивает - медленнее чем на 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 - Jan 29 2010, 20:05


--------------------
 Big time. 
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 30 2010, 20:02
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(artur_off @ Jan 29 2010, 22:48) *
Тоже столкнулся с проблемой очень медленной работы функций.
Код
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 МГц"? Эта фраза не имеет смысла, пока не сказано, сколько микросекунд - медленно, а сколько - быстро.
Go to the top of the page
 
+Quote Post
Drozd2
сообщение Jan 30 2010, 23:23
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 97
Регистрация: 19-11-09
Пользователь №: 53 743



Если есть желание реализовать свой алгоритм, тогда исключительно CORDIC. Такой ответ уже был. Алгоритм очень хорошо срабатывает на ПЛИС. Весь просчет за один такт. Нужно только не забывать, что для точности, например, 32 бит нужно закладывать в расчет не меньше 33 бит. Еще лучше держат бит 5 в запасе. Очень удобный алгоритм, если нужно сразу получить и синис, и косинус числа. Прирост в скорости вычисления колоссальный. Даже на микроконтроллере без сопроцессора. Да и вообще, для любителей численных методов интересная тема.
Go to the top of the page
 
+Quote Post
Serj78
сообщение Jan 31 2010, 10:35
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 966
Регистрация: 27-05-06
Из: СПб
Пользователь №: 17 499



Цитата(Drozd2 @ Jan 31 2010, 02:23) *
Если есть желание реализовать свой алгоритм, тогда исключительно CORDIC. Такой ответ уже был. Алгоритм очень хорошо срабатывает на ПЛИС. Весь просчет за один такт. Нужно только не забывать, что для точности, например, 32 бит нужно закладывать в расчет не меньше 33 бит. Еще лучше держат бит 5 в запасе. Очень удобный алгоритм, если нужно сразу получить и синис, и косинус числа. Прирост в скорости вычисления колоссальный. Даже на микроконтроллере без сопроцессора. Да и вообще, для любителей численных методов интересная тема.


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

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

Использовал функции в float синуса, косинуса и арктангенса ( на самом деле там один синус, остальные- через тригонометрические преобразования)
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 31 2010, 11:40
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Serj78 @ Jan 31 2010, 13:35) *
Возможно, в родной кейловской библиотеке больше точность, буду проверять. У меня дискретность значений примерно 50 микрорадиан.

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

Цитата(Serj78 @ Jan 31 2010, 13:35) *
Использовал функции в float синуса, косинуса и арктангенса ( на самом деле там один синус, остальные- через тригонометрические преобразования)

Если честно, не понимаю, как арктангенс можно получить из синуса тригонометрическими преобразованиями. Скорее всего никак нельзя. Ну да ладно, это к делу не относится...
Go to the top of the page
 
+Quote Post
artur_off
сообщение Jan 31 2010, 12:29
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 118
Регистрация: 24-05-08
Из: Odessa
Пользователь №: 37 784



Цитата(scifi @ Jan 30 2010, 22:02) *
Формула как-то странно выглядит. Например, (1/6) - это 0. Возможно, что с типами других операндов напутано. Если можно не использовать double, то нужно внимательно проследить, чтобы везде был float. К тому же amount можно вынести за скобки и сэкономить одно умножение. Что делает round() и как - непонятно. Вывод: рано спешить с выводами про "быстро-медленно", сначала надо код подправить.
И вообще, что такое "очень медленная работа функций, и это с частотой ядра 96 МГц"? Эта фраза не имеет смысла, пока не сказано, сколько микросекунд - медленно, а сколько - быстро.


Это кусок кода с матлаба, так как сишный удалил. а на С естественно было приведение к float. хотя здесь протупил, вместо 1/6 можно было написать 0.167.
round() - математическое округление.
по поводу amount согласен, но это не так уж и сильно влияет на производительность.
По поводу времени выполнения было сказано, что занимает примерно пол секунды (0.5 с).

Сообщение отредактировал artur_off - Jan 31 2010, 12:45


--------------------
 Big time. 
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 31 2010, 13:45
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(artur_off @ Jan 31 2010, 15:29) *
Это кусок кода с матлаба, так как сишный удалил. а на С естественно было приведение к float. хотя здесь протупил, вместо 1/6 можно было написать 0.167.
round() - математическое округление.

Если везде float, то нужно использовать sinf() вместо sin(), roundf() вместо round(). 0.167 лучше писать как 0.167f, а если округление до трёх цифр не подходит, то 1.0f/6. Не сочтите за занудство, это на всякий случай. Скорее всего, у Вас так и написано.
Меня удивил round(), потому что в стандартной библиотеке Си его сразу не нашёл. Видимо, было добавлено в C99...
Go to the top of the page
 
+Quote Post
artur_off
сообщение Jan 31 2010, 17:26
Сообщение #15


Частый гость
**

Группа: Свой
Сообщений: 118
Регистрация: 24-05-08
Из: Odessa
Пользователь №: 37 784



Цитата(scifi @ Jan 31 2010, 15:45) *
Если везде float, то нужно использовать sinf() вместо sin(), roundf() вместо round(). 0.167 лучше писать как 0.167f, а если округление до трёх цифр не подходит, то 1.0f/6. Не сочтите за занудство, это на всякий случай. Скорее всего, у Вас так и написано.
Меня удивил round(), потому что в стандартной библиотеке Си его сразу не нашёл. Видимо, было добавлено в C99...


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


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


--------------------
 Big time. 
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 8th July 2025 - 21:04
Рейтинг@Mail.ru


Страница сгенерированна за 0.01611 секунд с 7
ELECTRONIX ©2004-2016