/* -*- coding: utf-8 -*- */
/**
\defgroup mate Módulo MATEMATICAS
\ingroup anespec gshhs legendre
\brief En este módulo se reúnen las funciones necesarias para la realización de
       cálculos matemáticos generales.
@{
\file mate.h
\brief Declaración de funciones para la realización de cálculos matemáticos
       generales.

En el momento de la compilación de las funciones que dan el factorial de un
número y el producto de una serie de números ha de seleccionarse el tipo de
cálculo a utilizar (para números mayores que #GEOC_MATE_CONST_DBL_NMAXFAC y
#GEOC_MATE_CONST_LDBL_NMAXFAC). Para realizar el cálculo es necesario definir la
variable \em CALCULO_PRODUCTO_MULT si se quiere utilizar el producto o
\em CALCULO_PRODUCTO_LOG si se quieren utilizar logaritmos. En \p gcc, las
variables para el preprocesador se pasan como \em -DXXX, donde \em XXX es la
variable a introducir.
\author José Luis García Pallero, jgpallero@gmail.com
\date 17 de mayo de 2010
\copyright
Copyright (c) 2009-2014, José Luis García Pallero. All rights reserved.
\par
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
\par
- Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.
- Neither the name of the copyright holders nor the names of its contributors
  may be used to endorse or promote products derived from this software without
  specific prior written permission.
\par
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/******************************************************************************/
/******************************************************************************/
#ifndef _MATE_H_
#define _MATE_H_
/******************************************************************************/
/******************************************************************************/
#include<stdlib.h>
#include<math.h>
#include"libgeoc/constantes.h"
#include"libgeoc/posmatvec.h"
/******************************************************************************/
/******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_PROD_MULT
\brief Identificador de cálculo de productos de series de números correlativos
       por multiplicación directa.
\date 30 de diciembre de 2010: Creación de la constante.
*/
#define GEOC_PROD_MULT 0
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_PROD_LOG
\brief Identificador de cálculo de productos de series de números correlativos
       por logaritmos.
\date 30 de diciembre de 2010: Creación de la constante.
*/
#define GEOC_PROD_LOG 1
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_MATE_CONST_DBL_NMAXFAC
\brief Número más alto para el que se almacena su factorial de manera explícita
       para tipo de dato \p double.
\date 03 de octubre de 2010: Creación de la constante.
*/
#define GEOC_MATE_CONST_DBL_NMAXFAC (170)
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_MATE_CONST_LDBL_NMAXFAC
\brief Número más alto para el que se almacena su factorial de manera explícita
       para tipo de dato \p long \p double.
\date 03 de octubre de 2010: Creación de la constante.
*/
#define GEOC_MATE_CONST_LDBL_NMAXFAC (200)
/******************************************************************************/
/******************************************************************************/
/** \struct __mateFactExpl
\brief Estructura contenedora de valores explícitos de algunos factoriales.
\brief Esta estructura se basa en la que se puede encontrar en el fichero
       \p gamma.c, de la biblioteca GSL.
\date 03 de octubre de 2010: Creación de la estructura.
*/
typedef struct
{
    /** \brief Número. */
    size_t numero;
    /** \brief Factorial del número almacenado en __mateFacExpl::numero. */
    long double valor;
}__mateFactExpl;
/******************************************************************************/
/******************************************************************************/
/**
\brief Indica el tipo de cálculo del producto de una serie de números
       correlativos.
\return Dos posibles valores:
        - #GEOC_PROD_MULT: Cálculo por multiplicación directa.
        - #GEOC_PROD_LOG: Cálculo mediante logaritmos.
\date 30 de diciembre de 2010: Creación de la función.
*/
int GeocTipoCalcProd(void);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la media de una serie de valores de tipo \p double.
\param[in] datos Dirección de comienzo del vector que almacena los datos.
\param[in] nDatos Número de datos que contiene el vector.
\param[in] inc Posiciones de separación entre los elementos del vector de datos.
           Si es un número negativo, el vector se recorre desde el final hasta
           el principio.
\return Valor medio de la serie de datos.
\note Esta función asume que \em nDatos>0.
\date 19 de noviembre de 2009: Creación de la función.
*/
double Media(const double* datos,
             const size_t nDatos,
             const int inc);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la varianza de una serie de valores de tipo \p double.
\brief Esta función calcula la varianza mediante la fórmula
       \f$
       \sigma^2_x=\frac{\sum_{i=1}^{N}(x_i-\bar{x})^2}{N-1},
       \f$
       donde \f$N\f$ es el número de elementos de trabajo y \f$\bar{x}\f$ es la
       media.
\param[in] datos Dirección de comienzo del vector que almacena los datos.
\param[in] nDatos Número de datos que contiene el vector.
\param[in] inc Posiciones de separación entre los elementos del vector de datos.
           Si es un número negativo, el vector se recorre desde el final hasta
           el principio.
\param[in] media Valor medio de la serie de datos.
\note Esta función asume que \em nDatos>1.
\return Varianza de la serie de datos.
\date 09 de marzo de 2011: Creación de la función.
*/
double Varianza(const double* datos,
                const size_t nDatos,
                const int inc,
                const double media);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la media ponderada de una serie de valores de tipo \p double.
\param[in] datos Dirección de comienzo del vector que almacena los datos.
\param[in] nDatos Número de datos que contienen los vectores \em datos y
           \em pesos.
\param[in] incDatos Posiciones de separación entre los elementos del vector
           \em datos. Si es un número negativo, el vector se recorre desde el
           final hasta el principio.
\param[in] pesos Dirección de comienzo del vector que almacena los pesos.
\param[in] incPesos Posiciones de separación entre los elementos del vector
           \em pesos. Si es un número negativo, el vector se recorre desde el
           final hasta el principio.
\return Valor medio de la serie de datos.
\note Esta función asume que \em nDatos>0.
\date 23 de abril de 2010: Creación de la función.
\todo Esta función no está probada.
*/
double MediaPonderada(const double* datos,
                      const size_t nDatos,
                      const int incDatos,
                      const double* pesos,
                      const int incPesos);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la mediana de una serie de valores de tipo \p double.
\param[in] datos Dirección de comienzo del vector que almacena los datos, que ha
           de estar ordenado (en orden ascendente o descendente, da igual).
\param[in] nDatos Número de datos que contiene el vector.
\param[in] inc Posiciones de separación entre los elementos del vector de datos.
           Si es un número negativo, el vector se recorre desde el final hasta
           el principio.
\date 19 de noviembre de 2009: Creación de la función.
*/
double Mediana(const double* datos,
               const size_t nDatos,
               const int inc);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el producto de una serie de números mediante multiplicaciones.
\param[in] inicio Número inicial de la serie.
\param[in] fin Número final de la serie.
\return Producto acumulado de los números de la serie, calculado mediante
        multiplicaciones.
\date 03 de octubre de 2010: Creación de la función.
*/
double ProductoMult(size_t inicio,
                    size_t fin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el producto de una serie de números mediante multiplicaciones.
\param[in] inicio Número inicial de la serie.
\param[in] fin Número final de la serie.
\return Producto acumulado de los números de la serie, calculado mediante
        multiplicaciones.
\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
      \p long \p double, para prevenir desbordamientos (el tipo de dato
      \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
      -2.22507e-308 y 2.22507e-308 a 1.79769e308).
\date 03 de octubre de 2010: Creación de la función.
*/
long double ProductoMultLD(size_t inicio,
                           size_t fin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el producto de una serie de números mediante logaritmos.
\param[in] inicio Número inicial de la serie.
\param[in] fin Número final de la serie.
\return Producto acumulado de los números de la serie, calculado mediante
        logaritmos.
\date 03 de octubre de 2010: Creación de la función.
*/
double ProductoLog(size_t inicio,
                   size_t fin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el producto de una serie de números mediante logaritmos.
\param[in] inicio Número inicial de la serie.
\param[in] fin Número final de la serie.
\return Producto acumulado de los números de la serie, calculado mediante
        logaritmos.
\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
      \p long \p double, para prevenir desbordamientos (el tipo de dato
      \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
      -2.22507e-308 y 2.22507e-308 a 1.79769e308).
\date 03 de octubre de 2010: Creación de la función.
*/
long double ProductoLogLD(size_t inicio,
                          size_t fin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el producto de una serie de números.
\param[in] inicio Número inicial de la serie.
\param[in] fin Número final de la serie.
\return Producto acumulado de los números de la serie.
\date 03 de octubre de 2010: Creación de la función.
*/
double Producto(size_t inicio,
                size_t fin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el producto de una serie de números.
\param[in] inicio Número inicial de la serie.
\param[in] fin Número final de la serie.
\return Producto acumulado de los números de la serie.
\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
      \p long \p double, para prevenir desbordamientos (el tipo de dato
      \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
      -2.22507e-308 y 2.22507e-308 a 1.79769e308).
\date 03 de octubre de 2010: Creación de la función.
*/
long double ProductoLD(size_t inicio,
                       size_t fin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el factorial de un número mediante productos.
\param[in] numero Número.
\return Factorial del número pasado.
\date 03 de octubre de 2010: Creación de la función.
*/
double FactorialMult(size_t numero);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el factorial de un número mediante productos.
\param[in] numero Número.
\return Factorial del número pasado.
\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
      \p long \p double, para prevenir desbordamientos (el tipo de dato
      \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
      -2.22507e-308 y 2.22507e-308 a 1.79769e308).
\date 03 de octubre de 2010: Creación de la función.
*/
long double FactorialMultLD(size_t numero);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el factorial de un número como el antilogaritmo de la suma de
       logaritmos.
\param[in] numero Número.
\return Factorial del número pasado.
\date 03 de octubre de 2010: Creación de la función.
*/
double FactorialLog(size_t numero);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el factorial de un número como el antilogaritmo de la suma de
       logaritmos.
\param[in] numero Número.
\return Factorial del número pasado.
\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
      \p long \p double, para prevenir desbordamientos (el tipo de dato
      \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
      -2.22507e-308 y 2.22507e-308 a 1.79769e308).
\date 03 de octubre de 2010: Creación de la función.
*/
long double FactorialLogLD(size_t numero);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el factorial de un número.
\param[in] numero Número.
\return Factorial del número pasado.
\note Si el número es menor o igual que #GEOC_MATE_CONST_DBL_NMAXFAC, el
      factorial se toma de un array donde están almacenados de manera explícita
      los resultados. Si es mayor que #GEOC_MATE_CONST_DBL_NMAXFAC, el factorial
      se calcula.
\date 02 de marzo de 2009: Creación de la función.
\date 03 de octubre de 2010: Reprogramación de la función como llamada a las
      funciones \ref FactorialMult o \ref FactorialLog y cambio del tipo de dato
      devuelto de \p size_t a \p double.
*/
double Factorial(size_t numero);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el factorial de un número.
\param[in] numero Número.
\return Factorial del número pasado.
\note Si el número es menor o igual que #GEOC_MATE_CONST_LDBL_NMAXFAC, el
      factorial se toma de un array donde están almacenados de manera explícita
      los resultados. Si es mayor que #GEOC_MATE_CONST_LDBL_NMAXFAC, el
      factorial se calcula.
\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
      \p long \p double, para prevenir desbordamientos (el tipo de dato
      \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
      -2.22507e-308 y 2.22507e-308 a 1.79769e308).
\date 03 de octubre de 2010: Creación de la función.
*/
long double FactorialLD(size_t numero);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula el producto vectorial de dos vectores.
\param[in] x1 Coordenada X del primer vector.
\param[in] y1 Coordenada Y del primer vector.
\param[in] z1 Coordenada Z del primer vector.
\param[in] x2 Coordenada X del segundo vector.
\param[in] y2 Coordenada Y del segundo vector.
\param[in] z2 Coordenada Z del segundo vector.
\param[out] x Coordenada X del vector producto vectorial de 1 y 2.
\param[out] y Coordenada Y del vector producto vectorial de 1 y 2.
\param[out] z Coordenada Z del vector producto vectorial de 1 y 2.
\date 08 de agosto de 2013: Creación de la función.
\todo Esta función no está probada.
*/
void ProductoVectorial(const double x1,
                       const double y1,
                       const double z1,
                       const double x2,
                       const double y2,
                       const double z2,
                       double* x,
                       double* y,
                       double* z);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula los senos y cosenos de una serie de ángulos equiespaciados.
\brief Esta función utiliza en el cálculo las expresiones (ecuacies número 5.4.6
       y 5.4.7, pág. 219) que se puede encontrar en:

       William H. Press, Saul A. Teukolsky, William T. Vetterling y Brian P.
       Flannery, 2007, Numerical recipes. The Art of Scientific Computing, 3a
       edición. Cambridge University Press, ISBN: 978-0-521-88068-8.
\param[in] anguloIni Ángulo inicial de la serie, en radianes.
\param[in] incAngulo Incremento entre los valores algulares de la serie, en
           radianes.
\param[in] numValores Número de valores angulares de la serie, incluido
           \em anguloIni.
\param[out] seno Vector para almacenar el seno de los valores angulares de la
            serie.
\param[in] incSeno Posiciones de separación entre los elementos del vector de
           salida \em seno. Este argumento siempre ha de ser un número positivo.
\param[out] coseno Vector para almacenar el coseno de los valores angulares de
            la serie.
\param[in] incCoseno Posiciones de separación entre los elementos del vector de
           salida \em coseno. Este argumento siempre ha de ser un número
           positivo.
\note Esta función no comprueba internamente si los vectores pasados contienen
      suficiente memoria.
\note Según pruebas realizadas, para una serie de 1000000 de elementos con
      incremento angular de 50 grados, las diferencias con respecto a los senos
      y cosenos calculados con las funciones de math.h están en el entorno de
      1e-10. Para incrementos de 1 grado, en el entorno de 1e-12.
\date 27 de diciembre de 2014: Creación de la función.
\todo Esta función no está probada.
*/
void SinCosRecurrencia(const double anguloIni,
                       const double incAngulo,
                       const size_t numValores,
                       double* seno,
                       const size_t incSeno,
                       double* coseno,
                       const size_t incCoseno);
/******************************************************************************/
/******************************************************************************/
/**
\brief Construye un \em spline cúbico natural para una serie de puntos e
       interpola el valor de la función para una posición dada.
\param[in] x Puntero a la dirección de memoria donde comienza el vector que
           almacena las coordenadas X de los puntos dato.
\param[in] y Puntero a la dirección de memoria donde comienza el vector que
           almacena los valores de la función a interpolar, correspondientes a
           cada posición del vector pasado en el argumento \em x.
\param[in] nDatos Tamaño de los vectores \em x e \em y.
\param[in,out] xInterp Puntero a la dirección de memoria donde comienza el
               vector que almacena las coordenadas X de los puntos a interpolar.
               Al término de la ejecución de la función, este argumento almacena
               las coordenadas Y interpoladas.
\param[in] nInterp Tamaño del vector \em xInterp.
\note El código de esta función es una modificación de la versión que se puede
      encontrar en:
      http://koders.com/cpp/fid16BE3A5D46A7AC7BF84EECB1ADBF99B913A8F610.aspx
\note El código original está acogido a la GNU Lesser General Public License
      Version 2.1
\note Esta función no controla internamente si los vectores \em x e \em y son
      del tamaño especificado en \em nDatos.
\note Esta función no controla internamente si el vector \em xInterp es del
      tamaño especificado en \em nInterp.
\note Esta función no controla internamente si las coordenadas X de los puntos a
      interpolar están dentro o fuera de los límites de los puntos dato.
\date 02 de marzo de 2009: Creación de la función.
\todo Esta función todavía no está programada.
*/
void SplineCubicoNatural(double* x,
                         double* y,
                         size_t nDatos,
                         double* xInterp,
                         size_t nInterp);
/******************************************************************************/
/******************************************************************************/
#ifdef __cplusplus
}
#endif
/******************************************************************************/
/******************************************************************************/
#endif
/******************************************************************************/
/******************************************************************************/
/** @} */
/******************************************************************************/
/******************************************************************************/
/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
/* kate: backspace-indents on; show-tabs on; */
/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
