Определения sqrt, sin, cos, pow и т. Д. В cmath - PullRequest
33 голосов
/ 27 декабря 2010

Имеются ли какие-либо определения функций, таких как sqrt(), sin(), cos(), tan(), log(), exp() (эти из math.h / cmath)?Я просто хотел знать, как они работают.

Ответы [ 7 ]

63 голосов
/ 27 декабря 2010

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

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

  • Часто используются таблицы поиска
  • Тригонометрические функции часто реализуются с помощью алгоритма CORDIC (либо на процессоре, либо с библиотекой). Обратите внимание, что обычно синус и косинус вычисляются вместе, я всегда удивлялся, почему стандартная библиотека С не обеспечивает функцию sincos.
  • Квадратные корни используют Метод Ньютона с некоторыми хитрыми приемами реализации: где-то в Интернете вы можете найти выдержку из исходного кода Quake с невероятной реализацией 1 / sqrt (x).
  • Экспоненциальный и логарифмический выражения используют exp (2 ^ nx) = exp (x) ^ (2 ^ n) и log2 (2 ^ nx) = n + log2 (x), чтобы аргумент был близок к нулю (один для лога) ) и использовать приближение рациональной функции (обычно аппроксимации Паде ). Обратите внимание, что этот же трюк может дать вам матричные экспоненты и логарифмы. Согласно @Stephen Canon, современные реализации предпочитают расширение Тейлора, а не приближение рациональных функций, где деление намного медленнее, чем умножение.
  • Другие функции могут быть выведены из этих. Реализации могут предоставлять специализированные процедуры.
  • pow (x, y) = exp (y * log (x)), поэтому pow - это , а не для использования, когда y является целым числом
  • hypot (x, y) = abs (x) sqrt (1 + (y / x) ^ 2), если x> y (hypot (y, x) в противном случае), чтобы избежать переполнения. atan2 вычисляется с помощью вызова sincos и небольшой логики. Эти функции являются строительными блоками для сложной арифметики.
  • Что касается других трансцендентных функций (гамма, э.р.ф., бессел, ...), пожалуйста, обратитесь к превосходной книге Числовые рецепты, 3-е издание , чтобы узнать некоторые идеи. Good'old Abramowitz & Stegun также полезен. Новая версия на http://dlmf.nist.gov/.
  • Такие методы, как приближение Чебышева, непрерывное расширение дроби (фактически связанные с аппроксимациями Паде) или экономия степенных рядов, используются в более сложных функциях (например, если вы читаете исходный код для erf, bessel или gamma). Я сомневаюсь, что они реально используются в простых математических функциях, но кто знает. Консультируйтесь с Числовыми Рецептами для обзора.
21 голосов
/ 27 декабря 2010

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

edit: Поиск кода Google отключен, поэтому старая ссылка, которую я имел, никуда не ведет.

Исходники для математической библиотеки glibc находятся здесь:

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

7 голосов
/ 27 декабря 2010

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

5 голосов
/ 28 декабря 2010

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

4 голосов
/ 28 декабря 2010

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

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

0 голосов
/ 28 декабря 2010

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

0 голосов
/ 27 декабря 2010

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

...