2010-12-27 5 views
32

Существует ли какое-либо определение функций, такие как sqrt(), sin(), cos(), tan(), log(), exp() (это из math.h/CMATH) доступны?Определение SQRT, синус, косинус, пау и т.д. в CMATH

Я просто хотел знать, как они работают.

+1

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

+0

Возможный дубликат [Как C вычисляет sin() и другие математические функции?] (Http://stackoverflow.com/questions/2284860/how-does-c-compute-sin-and-other-math-functions) –

ответ

58

Это интересный вопрос, но чтение источников эффективных библиотек не приведет вас далеко, если вы не знаете, какой метод используется.

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

  • Таблица поиска часто используется
  • тригонометрических функций часто реализуются с помощью алгоритма CORDIC (либо на центральном процессоре или с библиотекой). Обратите внимание, что обычно синус и косинус вычисляются вместе, я всегда задавался вопросом, почему стандартная библиотека C не предоставляет функцию sincos.
  • Квадратные корни используют Newton's method с некоторыми хитроумными трюками: вы можете найти где-нибудь в Интернете выдержку из исходного кода Quake с реализацией реализаций 1/sqrt (x).
  • Экспоненциальные и логарифмы используют exp (2^nx) = exp (x)^(2^n) и log2 (2^nx) = n + log2 (x), чтобы иметь аргумент, близкий к нулю (одному для log) и использовать приближение рациональной функции (обычно Padé approximants). Обратите внимание, что этот точный трюк может дать вам матричные экспоненты и логарифмы. Согласно @Stephen Canon, современные реализации благоприятствуют расширению Тейлора над приближением рациональной функции, где деление намного медленнее, чем умножение.
  • Другие функции могут быть выведены из этих. Реализации могут предоставлять специализированные процедуры.
  • пау (х, у) = ехр (у * журнал (х)), так что POW является не, которые будут использоваться, когда у вл етс целым
  • hypot (х, у) = абс (х) SQRT (1 + (y/x)^2) если x> y (hypot (y, x) в противном случае), чтобы избежать переполнения. atan2 вычисляется по вызову sincos и немного логики. Эти функции являются строительными блоками для сложной арифметики.
  • Для других трансцендентных функций (gamma, erf, bessel, ...), пожалуйста, обратитесь к отличной книге Numerical Recipes, 3rd edition за некоторые идеи. Полезен также good'old Abramowitz & Stegun.Существует новая версия: http://dlmf.nist.gov/.
  • Методы, такие как приближение Чебышева, расширение продолженной фракции (фактически связанные с аппроксимациями Паде) или экономия энергетических рядов, используются в более сложных функциях (если вы, например, читаете исходный код для erf, bessel или gamma). Я сомневаюсь, что они действительно используют простые простые математические функции, но кто знает. Проконсультируйтесь с многочисленными рецептами.
+9

+1 для фактического объяснения математики. Я чувствовал себя намного лучше, когда понял, что триггерные функции были просто усеченными расширениями серии Тейлора.В противном случае приближения выглядят как серьезная магия! –

+0

+1 для численных методов. – birryree

+3

@Ben: хорошие библиотеки обычно не используют усеченные ряды Тейлора - другие полиномиальные аппроксимации (Minimax, Chebyshev, Padé) имеют гораздо более желательные характеристики ошибки и позволяют получить ту же точность с меньшим количеством арифметических операций. –

-15

Это почти всегда реализуется как системные вызовы. Если вы хотите посмотреть источники, вам понадобится доступ к источникам ОС, а это значит, что вам нужно посмотреть на ОС с открытым исходным кодом, например на Linux или BSD.

+8

'sin' как syscall? Это будет пустой тратой пространства ядра, если только ОС не является чрезвычайно графической, и даже тогда она будет медленнее, чем реализация RTL из-за переключения контекста. Есть * инструкции *, которые могут вычислять sin, cos и т. Д., Но syscalls? Я сомневаюсь в этом. – cHao

+6

Почти никогда. Эти функции являются обычными вызовами C, предоставляемыми библиотекой компилятора или C. Для систем без FPU инструкции, используемые этими функциями, могут быть захвачены ОС и затем эмулированы, но это редкий случай. – wnoise

+3

Математические функции, реализованные в виде системных вызовов? В самом деле?? –

21

Каждая реализация может отличаться, но вы можете проверить одну реализацию из исходного кода glibc (библиотеки GNU C).

Редактировать: Поиск в Google Code был удален в автономном режиме, поэтому старое соединение, которое у меня было, отсутствует.

Источники для математической библиотеки GLibC расположены здесь:

http://sourceware.org/git/?p=glibc.git;a=tree;f=math;h=3d5233a292f12cd9e9b9c67c3a114c64564d72ab;hb=HEAD

+0

спасибо за интересную ссылку. :-) – Nawaz

+0

Ссылка была разбита на данный момент ... – unkulunkulu

+1

@unkulunkulu - Обновлено прямой ссылкой на git repo glibc. – birryree

7

Посмотрите, как glibc реализует различные математические функции, полные магии, приближения и сборки.

+0

+1 для ссылки на источник glibc, но ничего себе сайт сейчас неактивен. (отредактировано) – birryree

+1

Afaik - это медленные версии с более быстрой реализацией в арке. специфические подпапки. – ismail

+0

haha ​​Я имел в виду, что сайт очень медленный. – birryree

5

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

+0

+1 для рекомендации fdlibm –

4

Многозначительно посмотрев на математический код, я бы посоветовал не смотреть на glibc - код часто бывает довольно сложным, и многое зависит от магии glibc. math lib in FreeBSD гораздо легче читать, если иногда иногда медленнее (но не сильно).

Для сложных функций основной трудностью являются граничные случаи - правильная обработка nan/inf/0 уже сложна для реальных функций, но это кошмар для сложных функций. Стандарт C99 определяет много угловых случаев, некоторые функции имеют легко 10-20 угловых случаев. Вы можете посмотреть приложение G обновленной версии C99 standard document, чтобы получить представление об этом. Существует также сложный с длинным двойником, потому что его формат не стандартизирован - по моему опыту, вы должны ожидать довольно много ошибок с длинным двойным. Надеемся, что новая версия IEEE754 с расширенной точностью улучшит ситуацию.

+0

Хороший вопрос об угловых случаях. В некоторых случаях они могут легко стать узкими местами (реализация 'ldexp' на MSVC делает функцию практически бесполезной, например) –

0

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