2010-12-27 21 views
32

¿Hay alguna definición de funciones como sqrt(), sin(), cos(), tan(), log(), exp() (estos de math.h/cmath) disponibles?Definiciones de raíz cuadrada, seno, coseno, prisionero de guerra, etc., en cmath

Solo quería saber cómo funcionan.

+1

fdlibm proporciona implementaciones de todo eso, es de código abierto, independiente, bastante legible. No son las implementaciones más simples posibles, ya que están diseñadas para proporcionar un rendimiento decente. –

+0

posible duplicado de [¿Cómo C calcula sin() y otras funciones matemáticas?] (Http://stackoverflow.com/questions/2284860/how-does-c-compute-sin-and-other-math-functions) –

Respuesta

58

Esta es una pregunta interesante, pero leer fuentes de bibliotecas eficientes no te llevará muy lejos a menos que conozcas el método utilizado.

Aquí hay algunos consejos para ayudarlo a comprender los métodos clásicos. Mi información no es exacta. Los siguientes métodos son solo los clásicos, las implementaciones particulares pueden usar otros métodos.

  • Las tablas de consulta se utilizan con frecuencia
  • funciones trigonométricas a menudo se implementan a través de la algoritmo CORDIC (ya sea en la CPU o con una biblioteca). Tenga en cuenta que normalmente el seno y el coseno se calculan juntos, siempre me pregunté por qué la biblioteca C estándar no proporciona una función sincos.
  • Las raíces cuadradas usan Newton's method con algunos ingeniosos trucos de implementación: es posible que encuentres en algún lugar de la web un extracto del código fuente de Quake con una implementación de 1/sqrt (x).
  • Exponencial y uso de logaritmos exp (2^nx) = exp (x)^(2^n) y log2 (2^nx) = n + log2 (x) para tener un argumento cercano a cero (a uno para el registro) y utiliza la aproximación de función racional (generalmente Padé approximants). Tenga en cuenta que este mismo truco puede obtener exponenciales y logaritmos de la matriz. Según @Stephen Canon, las implementaciones modernas favorecen la expansión de Taylor sobre la aproximación de funciones racionales, donde la división es mucho más lenta que la multiplicación.
  • Las otras funciones se pueden deducir de estas. Las implementaciones pueden proporcionar rutinas especializadas.
  • pow (x, y) = exp (log y * (x)), por lo pow es no para ser utilizado cuando y es un número entero
  • hypot (x, y) = abs (x) sqrt (1 + (y/x)^2) si x> y (hypot (y, x) de lo contrario) para evitar el desbordamiento. atan2 se calcula con una llamada al sincos y un poco de lógica. Estas funciones son los bloques de construcción para la aritmética compleja.
  • Para otras funciones trascendentales (gamma, erf, bessel, ...), consulte el excelente libro Numerical Recipes, 3rd edition para obtener algunas ideas. El good'old Abramowitz & Stegun también es útil.Hay una nueva versión en http://dlmf.nist.gov/.
  • Técnicas como la aproximación de Chebyshev, la expansión continua de fracciones (realmente relacionada con los aproximantes de Padé) o la economización de series de potencias se utilizan en funciones más complejas (si lees el código fuente de erf, bessel o gamma, por ejemplo). Dudo que tengan un uso real en las funciones simples de matemáticas, pero quién sabe. Consulte las recetas numéricas para obtener una descripción general.
+9

+1 para explicar realmente las matemáticas. Me sentí mucho mejor cuando me di cuenta de que las funciones trigonométricas solo se habían truncado en las expansiones de la serie Taylor.¡De lo contrario, las aproximaciones parecen una magia seria! –

+0

+1 para métodos numéricos. – birryree

+3

@Ben: las buenas bibliotecas generalmente no usan series truncadas de taylor; otras aproximaciones polinomiales (Minimax, Chebyshev, Padé) tienen características de error mucho más deseables y permiten obtener la misma precisión con menos operaciones aritméticas. –

-15

Esas casi siempre se implementan como llamadas al sistema. Si quieres ver las fuentes, necesitarás acceder a las fuentes del SO, lo que significa que debes buscar un sistema operativo de código abierto como Linux o BSD.

+8

'pecado' como un syscall? Eso sería un desperdicio de espacio en el kernel, a menos que el sistema operativo en cuestión sea extremadamente gráfico, e incluso así, sería más lento que una implementación de RTL debido al cambio de contexto. Hay * instrucciones * que pueden calcular sin, cos, etc., pero llamadas de sys? Lo dudo. – cHao

+6

Casi nunca. Las funciones son llamadas C normales, proporcionadas por el compilador o biblioteca C. Para sistemas sin FPU, las instrucciones que utilizan estas funciones pueden ser atrapadas por el sistema operativo y luego emuladas, pero este es un caso raro. – wnoise

+3

Funciones matemáticas implementadas como llamadas al sistema? ¿¿De Verdad?? –

21

Cada implementación puede ser diferente, pero puede verificar una implementación del código fuente de glibc (la biblioteca C de GNU).

editar: Google Code Search se ha desconectado, por lo que el antiguo enlace que tenía no llega a ninguna parte.

Las fuentes para la biblioteca matemática de glibc se encuentran aquí:

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

+0

gracias por el interesante enlace. :-) – Nawaz

+0

El enlace está roto ahora ... – unkulunkulu

+1

@unkulunkulu - Actualizado con un enlace directo al repositorio git de glibc. – birryree

7

Tener un vistazo a cómo glibc implementa varias funciones matemáticas, llenos de magia, la aproximación y el montaje.

+0

+1 para el enlace de fuente de programación glibc, pero wow, el sitio es lento en este momento. (editado) – birryree

+1

Afaik estas son las versiones lentas con implementaciones más rápidas en el arco. subcarpetas específicas. – ismail

+0

jaja Me refiero a que el sitio en sí es lento. – birryree

5

Definitivamente, eche un vistazo a las fuentes fdlibm. Son agradables porque la biblioteca fdlibm es autónoma, cada función está bien documentada con explicaciones detalladas de las matemáticas involucradas, y el código es inmensamente claro de leer.

+0

+1 para recomendar fdlibm –

4

Después de haber mirado mucho el código matemático, aconsejaría no mirar glibc - el código es a menudo bastante difícil de seguir, y depende mucho de la magia glibc. El math lib in FreeBSD es mucho más fácil de leer, aunque de alguna manera a veces más lento (pero no por mucho).

Para las funciones complejas, la principal dificultad son los casos fronterizos: el manejo correcto de nan/inf/0 ya es difícil para las funciones reales, pero es una pesadilla para las funciones complejas. El estándar C99 define muchos casos de esquina, algunas funciones tienen fácilmente 10-20 casos de esquina. Puede ver el anexo G de la fecha de actualización C99 standard document para tener una idea. También es difícil con el doble largo, porque su formato no está estandarizado; en mi experiencia, debe esperar bastantes errores con el doble largo. Con suerte, la próxima versión revisada de IEEE754 con precisión ampliada mejorará la situación.

+0

Buen punto sobre las cajas de esquina. Pueden convertirse fácilmente en cuellos de botella en algunos casos (la implementación de 'ldexp' en MSVC hace que la función sea prácticamente inútil, por ejemplo) –

0

La mayoría del hardware moderno incluye unidades de coma flotante que implementan estas funciones de manera muy eficiente.

Cuestiones relacionadas