From: Leandro Lucarella Date: Sun, 24 Aug 2003 06:59:52 +0000 (+0000) Subject: Se separa el TP en varios archivos. X-Git-Tag: svn_import~13 X-Git-Url: https://git.llucax.com/z.facultad/75.42/euler.git/commitdiff_plain/977e05b75c7af07b8b733b0ce17c0f9e5cefa13b?hp=b578c6e6beb9d5b1f2957f0b0367b91413b49d82 Se separa el TP en varios archivos. --- diff --git a/Doxyfile b/Doxyfile index 08d6c7e..bf54cac 100644 --- a/Doxyfile +++ b/Doxyfile @@ -58,8 +58,8 @@ WARN_LOGFILE = # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = -FILE_PATTERNS = *.c \ - *.h +FILE_PATTERNS = *.h \ + *.c RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO diff --git a/Makefile b/Makefile index 6a18539..33d8e28 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ CFLAGS=-ansi -pedantic -Wall -g3 # Programa a compilar. -TARGETS=enunciado +TARGETS=tp1 # Regla por defecto. all: $(TARGETS) diff --git a/documentacion.h b/documentacion.h new file mode 100644 index 0000000..a5c1b2b --- /dev/null +++ b/documentacion.h @@ -0,0 +1,101 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: dom ago 24 03:12:43 ART 2003 + * + * $Id$ + */ + +/** \mainpage Taller de Programación I (75.42) + +\section objetivo Objetivo. + Desarrollar un \ref main "programa" que resuelva, utilizando un + \ref metodo "método iterativo", una \ref funcion "función diferencial" + en un intervalo de tiempo dado. + \note Utilizar sólo funciones ANSI C. + +\section desarrollo Desarrollo. + \subsection parte1 Parte 1. + Dada una \ref funcion "función diferencial" \f$df_{(t)}\f$, + desarrolle un \ref main "programa" que calcule la integral de la + misma utilizando el método iterativo (\ref metodo "Euler explícito"), + tal como se explica a continuación. Almacene estos resultados en un + \ref Resultados "vector". + + \subsubsection funcion Función diferencial. + \f[ + df_{(t)} = \frac{500 - f_{(t)}}{30} + \f] + + \subsubsection variables Variables. + - \f$t_i\f$: \ref T0 "Tiempo inicial de la iteración" = 0. + + Solicitar al usuario el ingreso de las restantes variables por + línea de comandos: + - \f$f_{(t)}\f$: Estado inicial del sistema. + - \f$t_f\f$: Tiempo final de la iteración (segundos). + - \f$step\f$: Paso (en segundos). + + \subsubsection metodo Método de iteración (Euler explícito). + \f[ + f_{(t + step)} = f_{(t)} + df_{(t)} \cdot step + \f] + + \subsection parte2 Parte 2. + Grafique los primeros 70 pasos (si los hay) de la + \ref funcion "función" en formato texto, entre los valores máximos y + mínimos que tome en este intervalo, utilizando 20 líneas horizontales. + + Por ejemplo: + \verbatim + + t0 = 0 + tf = 10 + step = 0.5 + 400 *** + 390 * ** **** + 380 * * ****** + 370 ** + + \endverbatim + +\section resolucion Resolución. + El \ref main "programa principal" se divide en FIXME N tareas principales, + cada una realizada por una función particular. + + \subsection obtencion Obtención y validación de parámetros del usuario. + Antes de comenzar a hacer cálculos es necesario obtener los valores de + las \ref variables "variables" de la entrada del usuario (en este caso + a través de parámetros de línea de comandos). Esto es realizado + por la función cargar_datos(). + + \subsection integracion Integración de la ecuación diferencial. + Reemplazando la \ref funcion "ecuación diferencial" \f$ df_{(t)} \f$ + en la solución por el \ref metodo "método de Euler", obtenemos + la siguiente función: + \f[ + f_{(t + step)} = f_{(t)} + \frac{500 - f_{(t)}}{30} \cdot step + \f] + Resultando, en realidad, una función númerica de dos variables + (\f$ step \f$ y \f$ f_t \f$): + \f[ + f_{t + step} = f_{(step, f_t)} = f_t + \frac{500 - f_t}{30} \cdot step + \f] + Este paso es realizado por el macro FUNCION() para que sea más + veloz. + + Todo lo que resta es iterar, paso a paso, calculando los valores de la + función y almacenándolos en el \ref Resultados "vector de resultados", + tarea realizada por la función calcular(). + +*/ + diff --git a/enunciado.c b/enunciado.c deleted file mode 100644 index 3d877a1..0000000 --- a/enunciado.c +++ /dev/null @@ -1,379 +0,0 @@ -/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: - * - * Taller de Programación (75.42). - * - * Ejercicio Número 1: - * Graficador de la solución de una ecuación diferencial por el método - * de Euler (explícito). - * - * Copyleft 2003 - Leandro Lucarella - * Puede copiar, modificar y distribuir este programa bajo los términos de - * la licencia GPL (http://www.gnu.org/). - * - * Creado: sáb ago 23 16:59:01 ART 2003 - * - * $Id$ - */ - -/** \mainpage Taller de Programación I (75.42) - -\section objetivo Objetivo. - Desarrollar un \ref main "programa" que resuelva, utilizando un - \ref metodo "método iterativo", una \ref funcion "función diferencial" - en un intervalo de tiempo dado. - \note Utilizar sólo funciones ANSI C. - -\section desarrollo Desarrollo. - \subsection parte1 Parte 1. - Dada una \ref funcion "función diferencial" \f$df_{(t)}\f$, - desarrolle un \ref main "programa" que calcule la integral de la - misma utilizando el método iterativo (\ref metodo "Euler explícito"), - tal como se explica a continuación. Almacene estos resultados en un - \ref Resultados "vector". - - \subsubsection funcion Función diferencial. - \f[ - df_{(t)} = \frac{500 - f_{(t)}}{30} - \f] - - \subsubsection variables Variables. - - \f$t_i\f$: \ref T0 "Tiempo inicial de la iteración" = 0. - - Solicitar al usuario el ingreso de las restantes variables por - línea de comandos: - - \f$f_{(t)}\f$: Estado inicial del sistema. - - \f$t_f\f$: Tiempo final de la iteración (segundos). - - \f$step\f$: Paso (en segundos). - - \subsubsection metodo Método de iteración (Euler explícito). - \f[ - f_{(t + step)} = f_{(t)} + df_{(t)} \cdot step - \f] - - \subsection parte2 Parte 2. - Grafique los primeros 70 pasos (si los hay) de la \ref funcion - "función" en formato texto, entre los valores máximos y mínimos que tome en - este intervalo, utilizando 20 líneas horizontales. - - Por ejemplo: - \verbatim - - t0 = 0 - tf = 10 - step = 0.5 - 400 *** - 390 * ** **** - 380 * * ****** - 370 ** - - \endverbatim - -\section resolucion Resolución. - El \ref main "programa principal" se divide en FIXME N tareas principales, - cada una realizada por una función particular. - - \subsection obtencion Obtención y validación de parámetros del usuario. - Antes de comenzar a hacer cálculos es necesario obtener los valores de - las \ref variables "variables" de la entrada del usuario (en este caso - a través de parámetros de línea de comandos). Esto es realizado - por la función cargar_datos(). - - \subsection integracion Integración de la ecuación diferencial. - Reemplazando la \ref "ecuación diferencial" \f$ df_{(t)} \f$ - en la solución por el \ref metodo "método de Euler", obtenemos - la siguiente función: - \f[ - f_{(t + step)} = f_{(t)} + \frac{500 - f_{(t)}}{30} \cdot step - \f] - Resultando, en realidad, una función númerica de dos variables - (\f$ step \f$ y \f$ f_t \f$): - \f[ - f_{t + step} = f_{(step, f_t)} = f_t + \frac{500 - f_t}{30} \cdot step - \f] - Este paso es realizado por el macro FUNCION() para que sea más - veloz. - - Todo lo que resta es iterar, paso a paso, calculando los valores de la - función y almacenándolos en el \ref Resultados "vector de resultados", - tarea realizada por la función calcular(). - -*/ - - - -/************************ BIBLIOTECAS USADAS *******************************/ - -/* Para utilizar printf() */ -#include - -/* Para utilizar strtod(), EXIT_SUCCES y EXIT_FAILURE */ -#include - - - -/***************************** CONSTANTES **********************************/ - -/** Indica un valor verdadero */ -#define TRUE 1 - -/** Indica un valor falso */ -#define FALSE 0 - -/** Máxima cantidad de pasos a calcular. */ -#define MAX_PASOS 70 - -/** Altura (en líneas) utilizadas para dibujar el gráfico. */ -#define ALTO 20 - -/** Tiempo inicial. */ -#define T0 0.0 - -/** Tiempo final por omisión. */ -#define DEFAULT_TF 70.0 - -/** Valor inicial de la función por omisión. */ -#define DEFAULT_F0 0.0 - -/** Valor del pas de iteración por omisión. */ -#define DEFAULT_PASO 1.0 - - - -/******************************* MACROS ************************************/ - -/** - * \ref integracion "Calcula" el siguiente paso de la función numérica. - * Obtiene el siguiente valor de \f$ f \f$, integrando numéricamente la \ref - * funcion "ecuación diferencial" por el \ref metodo "método de euler". - * \f[ - * f_{t + step} = f_{(step, f_t)} = f_t + \frac{500 - f_t}{30} \cdot step - * \f] - * - * \note Se pone en un macro para poder reemplazar fácilmente la función sin la - * pérdida de velocidad que agrega la indirección de un llamado a una - * función. - */ -#define FUNCION(paso, ft) ((ft) + (500.0 - (ft)) / 30.0 * paso) - - - -/************************ TIPOS DE DATOS UTILIZADOS ************************/ - -/** - * Tipo de dato utilizado para medir el tiempo y el valor de la función. - * Se define como un tipo de dato propio para cambiar fácilmente la precisión. - */ -typedef float Real; - -/** - * Vector que representa los resultados. - * El índice del vector representa el número de iteración (que multiplicado por - * el paso da el tiempo, o eje X). El contenido es el valor de la - * \ref funcion "función" en ese instante. - */ -typedef Real Resultados[MAX_PASOS]; - - - -/********************************* FUNCIONES *******************************/ - -/** - * Imprime una explicación de como usar el programa. - * - * \param fh Archivo en donde imprimir el mensaje (ej: stdout o stderr). - */ -void imprimir_uso(FILE* fh) { - fprintf(fh, "\n"); - fprintf(fh, "Modo de uso:\n"); - fprintf(fh, " tp1 [paso [tf [f0]]]\n"); - fprintf(fh, "\n"); - fprintf(fh, "Donde:\n"); - fprintf(fh, " paso: Paso a utilizar (%.2f por omisión).\n", DEFAULT_PASO); - fprintf(fh, " tf: Tiempo final (%.2f por omisión).\n", DEFAULT_TF); - fprintf(fh, " f0: Valor inicial de la función (%.2f por omisión).\n", - DEFAULT_F0); -} - -/** - * Carga (validando) un dato real en una variable. - * Si al validar hay algún error, muestra un mensaje por la salida de error y - * devuelve false. - * - * \param arg Argumento a cargar (y validar). - * \param var Variable en donde cargar el real. - * \param nom Nombre de la variable que se quiere cargar (para el mensaje de - * error, en caso de haberlo). - * - * \return TRUE si se cargó bien, FALSE si no. - */ -int argtod(const char* arg, Real* var, const char* nom) { - /* Puntero al último caracter bien interpretado por strtod. */ - char* err = NULL; - /* Realiza la conversión de un string a un Real */ - *var = strtod(arg, &err); - /* Si el caracter donde apunta endptr es 0 es porque se interpretó toda la - * cadena bien */ - if ((char)*err == '\0') { - return TRUE; - /* Si no, es que hubo error. */ - } else { - fprintf(stderr, "Error: El parámetro '%s' debe ser un número ", nom); - fprintf(stderr, "real. Usted ingresó '%s' pero '%s' no ", arg, err); - fprintf(stderr, "pudo ser interpretado.\n"); - return FALSE; - } -} - -/** - * Carga los datos necesarios por el programai. - * Obtiene los datos desde los parámetros de la línea de comandos, validándolos - * y mostrando un mensaje de error en caso de haberlo. - * - * \param argc Cantidad de parámetros de línea de comandos ingresados. - * \param argv Parámetros de línea de comandos. - * \param paso Paso utilizado para las iteraciones. - * \param tf Tiempo final. - * \param f0 Valor inicial de la función. - * - * \return TRUE si se cargaron bien, FALSE si no. - * \todo Verificar que el paso no sea cero y que tf > ti. - */ -int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0) { - switch (argc) { - /* Si no tiene parámetros usa los valores por omisión. */ - case 1: - break; - /* Si tiene de 1 a 3 parámetros, los lee y valida, saliendo con un - * mensaje de error en caso de haberlo. */ - case 4: - /* Hay 3 parámetros, lee el 3er parámetro. */ - if (!argtod(argv[3], f0, "f0")) { - return FALSE; - } - /* Continúa con el resto de los parámetros. */ - case 3: - /* Hay al menos 2 parámetros, lee el 2do parámetro. */ - if (!argtod(argv[2], tf, "tf")) { - return FALSE; - } - /* Continúa con el resto de los parámetros. */ - case 2: - /* Hay al menos 1 parámetro, lee el 1er parámetro. */ - if (!argtod(argv[1], paso, "paso")) { - return FALSE; - } - break; /* Finaliza el switch (no lee más parámetros). */ - /* Hay demasiados parámetros, sale con mensaje de error. */ - default: - fprintf(stderr, "Error: Demasiados parámetros.\n"); - return FALSE; - } - /* TODO Verificar que el paso no sea cero y que tf > ti. */ - /* XXX - sacar */ - printf("paso = %f, tf = %f, f0 = %f\n", *paso, *tf, *f0); - return TRUE; -} - -/** - * \ref integracion "Calcula" todos los valores de la función. - * - * \param res Vector donde se guardan los resultados. - * \param paso Paso de iteración. - * \param ti Tiempo de inicio de la iteración. - * \param tf Tiempo final de la iteración. - * \param f0 Valor inicial de la función. - * - * \return Cantidad de pasos realizados. - */ -size_t calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0) { - /* Índice para iterar. */ - size_t i; - /* Calculo la cantidad de pasos necesarios según el tiempo inicial, el - * tiempo final y el "tamaño" del paso. */ - size_t pasos = (size_t)((tf - ti) / paso); - /* Respeto la cantidad máxima de pasos admitida. */ - if (pasos > MAX_PASOS) { - pasos = MAX_PASOS; - } - /* Agrego el valor inicial de la función (para empezar a iterar). */ - (*res)[0] = f0; - /* Itero paso a paso calculando el valor de la función. */ - for (i = 1; i < pasos; i++) { - /* f(t+paso) = FUNCION(paso, f(t)) */ - (*res)[i] = FUNCION(paso, (*res)[i-1]); - /* FIXME sacar!!!! */ - printf("i = %i, t = %.2f, f(t) = %.2f\n", i, (Real)i * paso, (*res)[i]); - } - return pasos; -} - -/** - * Devuelve el valor máximo de los resultados. - * - * \param res Vector de resultados. - * \param pasos Cantidad de pasos a iterar. - * - * \return Máximo resultado. - */ -Real max(const Resultados* res, size_t pasos) { - size_t i; - Real max = (*res)[0]; - for (i = 1; i < pasos; i++) { - if ((*res)[i] > max) { - max = (*res)[i]; - } - } - return max; -} - -/** - * Devuelve el valor mínimo de los resultados. - * - * \param res Vector de resultados. - * \param pasos Cantidad de pasos a iterar. - * - * \return Mínimo resultado. - */ -Real min(const Resultados* res, size_t pasos) { - size_t i; - Real min = (*res)[0]; - for (i = 1; i < pasos; i++) { - if ((*res)[i] < min) { - min = (*res)[i]; - } - } - return min; -} - -/** - * Programa principal. - * Este es el programa que se encarga de resolver el trabajo práctico. - * - * \param argc Cantidad de parámetros de línea de comandos ingresados. - * \param argv Parámetros de línea de comandos. - * - * \return EXIT_FAILURE si hubo un error, si no EXIT_SUCCESS. - */ -int main(int argc, const char** argv) { - /* TODO: Declaración de variables. */ - Resultados resultados; - size_t pasos; - Real paso = DEFAULT_PASO; - Real tf = DEFAULT_TF; - Real f0 = DEFAULT_F0; - - /* Obtención de datos. */ - if (!cargar_datos(argc, argv, &paso, &tf, &f0)) { - imprimir_uso(stderr); - return EXIT_FAILURE; - } - - /* Cálculo de la solución, dejando en un array los valores de cada paso. */ - pasos = calcular(&resultados, paso, T0, tf, f0); - - /* TODO: Barrido de pantalla de arriba hacia abajo consultando el array - * y dibujando los resultados pertinentes. */ - /* TODO: Liberación de memoria y otras limpiezas, en caso de ser necesario. */ - return EXIT_SUCCESS; -} - diff --git a/tp1.c b/tp1.c new file mode 100644 index 0000000..f8b7c86 --- /dev/null +++ b/tp1.c @@ -0,0 +1,153 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +/* Cabecera del TP. */ +#include "tp1.h" + +void imprimir_uso(FILE* fh) { + fprintf(fh, "\n"); + fprintf(fh, "Modo de uso:\n"); + fprintf(fh, " tp1 [paso [tf [f0]]]\n"); + fprintf(fh, "\n"); + fprintf(fh, "Donde:\n"); + fprintf(fh, " paso: Paso a utilizar (%.2f por omisión).\n", DEFAULT_PASO); + fprintf(fh, " tf: Tiempo final (%.2f por omisión).\n", DEFAULT_TF); + fprintf(fh, " f0: Valor inicial de la función (%.2f por omisión).\n", + DEFAULT_F0); +} + +int argtod(const char* arg, Real* var, const char* nom) { + /* Puntero al último caracter bien interpretado por strtod. */ + char* err = NULL; + /* Realiza la conversión de un string a un Real */ + *var = strtod(arg, &err); + /* Si el caracter donde apunta endptr es 0 es porque se interpretó toda la + * cadena bien */ + if ((char)*err == '\0') { + return TRUE; + /* Si no, es que hubo error. */ + } else { + fprintf(stderr, "Error: El parámetro '%s' debe ser un número ", nom); + fprintf(stderr, "real. Usted ingresó '%s' pero '%s' no ", arg, err); + fprintf(stderr, "pudo ser interpretado.\n"); + return FALSE; + } +} + +int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0) { + switch (argc) { + /* Si no tiene parámetros usa los valores por omisión. */ + case 1: + break; + /* Si tiene de 1 a 3 parámetros, los lee y valida, saliendo con un + * mensaje de error en caso de haberlo. */ + case 4: + /* Hay 3 parámetros, lee el 3er parámetro. */ + if (!argtod(argv[3], f0, "f0")) { + return FALSE; + } + /* Continúa con el resto de los parámetros. */ + case 3: + /* Hay al menos 2 parámetros, lee el 2do parámetro. */ + if (!argtod(argv[2], tf, "tf")) { + return FALSE; + } + /* Continúa con el resto de los parámetros. */ + case 2: + /* Hay al menos 1 parámetro, lee el 1er parámetro. */ + if (!argtod(argv[1], paso, "paso")) { + return FALSE; + } + break; /* Finaliza el switch (no lee más parámetros). */ + /* Hay demasiados parámetros, sale con mensaje de error. */ + default: + fprintf(stderr, "Error: Demasiados parámetros.\n"); + return FALSE; + } + /* TODO Verificar que el paso no sea cero y que tf > ti. */ + /* XXX - sacar */ + printf("paso = %f, tf = %f, f0 = %f\n", *paso, *tf, *f0); + return TRUE; +} + +size_t calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0) { + /* Índice para iterar. */ + size_t i; + /* Calculo la cantidad de pasos necesarios según el tiempo inicial, el + * tiempo final y el "tamaño" del paso. */ + size_t pasos = (size_t)((tf - ti) / paso); + /* Respeto la cantidad máxima de pasos admitida. */ + if (pasos > MAX_PASOS) { + pasos = MAX_PASOS; + } + /* Agrego el valor inicial de la función (para empezar a iterar). */ + (*res)[0] = f0; + /* Itero paso a paso calculando el valor de la función. */ + for (i = 1; i < pasos; i++) { + /* f(t+paso) = FUNCION(paso, f(t)) */ + (*res)[i] = FUNCION(paso, (*res)[i-1]); + /* FIXME sacar!!!! */ + printf("i = %i, t = %.2f, f(t) = %.2f\n", i, (Real)i * paso, (*res)[i]); + } + return pasos; +} + +Real max(const Resultados* res, size_t pasos) { + size_t i; + Real max = (*res)[0]; + for (i = 1; i < pasos; i++) { + if ((*res)[i] > max) { + max = (*res)[i]; + } + } + return max; +} + +Real min(const Resultados* res, size_t pasos) { + size_t i; + Real min = (*res)[0]; + for (i = 1; i < pasos; i++) { + if ((*res)[i] < min) { + min = (*res)[i]; + } + } + return min; +} + +int main(int argc, const char** argv) { + /* TODO: Declaración de variables. */ + Resultados resultados; + size_t pasos; + Real paso = DEFAULT_PASO; + Real tf = DEFAULT_TF; + Real f0 = DEFAULT_F0; + + /* Obtención de datos. */ + if (!cargar_datos(argc, argv, &paso, &tf, &f0)) { + imprimir_uso(stderr); + return EXIT_FAILURE; + } + + /* Cálculo de la solución, dejando en un array los valores de cada paso. */ + pasos = calcular(&resultados, paso, T0, tf, f0); + + /* TODO: Barrido de pantalla de arriba hacia abajo consultando el array + * y dibujando los resultados pertinentes. */ + /* TODO: Liberación de memoria y otras limpiezas, en caso de ser necesario. */ + return EXIT_SUCCESS; +} + diff --git a/tp1.h b/tp1.h new file mode 100644 index 0000000..8ae9410 --- /dev/null +++ b/tp1.h @@ -0,0 +1,173 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +/************************ BIBLIOTECAS USADAS *******************************/ + +/* Para utilizar printf(), fprintf() y stderr */ +#include +/* Para utilizar strtod(), EXIT_SUCCES y EXIT_FAILURE */ +#include + + + +/***************************** CONSTANTES **********************************/ + +/** Indica un valor verdadero */ +#define TRUE 1 + +/** Indica un valor falso */ +#define FALSE 0 + +/** Máxima cantidad de pasos a calcular. */ +#define MAX_PASOS 70 + +/** Altura (en líneas) utilizadas para dibujar el gráfico. */ +#define ALTO 20 + +/** Tiempo inicial. */ +#define T0 0.0 + +/** Tiempo final por omisión. */ +#define DEFAULT_TF 70.0 + +/** Valor inicial de la función por omisión. */ +#define DEFAULT_F0 0.0 + +/** Valor del pas de iteración por omisión. */ +#define DEFAULT_PASO 1.0 + + + +/******************************* MACROS ************************************/ + +/** + * \ref integracion "Calcula" el siguiente paso de la función numérica. + * Obtiene el siguiente valor de \f$ f \f$, integrando numéricamente la \ref + * funcion "ecuación diferencial" por el \ref metodo "método de euler". + * \f[ + * f_{t + step} = f_{(step, f_t)} = f_t + \frac{500 - f_t}{30} \cdot step + * \f] + * + * \note Se pone en un macro para poder reemplazar fácilmente la función sin la + * pérdida de velocidad que agrega la indirección de un llamado a una + * función. + */ +#define FUNCION(paso, ft) ((ft) + (500.0 - (ft)) / 30.0 * paso) + + + +/************************ TIPOS DE DATOS UTILIZADOS ************************/ + +/** + * Tipo de dato utilizado para medir el tiempo y el valor de la función. + * Se define como un tipo de dato propio para cambiar fácilmente la precisión. + */ +typedef float Real; + +/** + * Vector que representa los resultados. + * El índice del vector representa el número de iteración (que multiplicado por + * el paso da el tiempo, o eje X). El contenido es el valor de la + * \ref funcion "función" en ese instante. + */ +typedef Real Resultados[MAX_PASOS]; + + + +/********************************* FUNCIONES *******************************/ + +/** + * Imprime una explicación de como usar el programa. + * + * \param fh Archivo en donde imprimir el mensaje (ej: stdout o stderr). + */ +void imprimir_uso(FILE* fh); + +/** + * Carga (validando) un dato real en una variable. + * Si al validar hay algún error, muestra un mensaje por la salida de error y + * devuelve false. + * + * \param arg Argumento a cargar (y validar). + * \param var Variable en donde cargar el real. + * \param nom Nombre de la variable que se quiere cargar (para el mensaje de + * error, en caso de haberlo). + * + * \return TRUE si se cargó bien, FALSE si no. + */ +int argtod(const char* arg, Real* var, const char* nom); + +/** + * Carga los datos necesarios por el programai. + * Obtiene los datos desde los parámetros de la línea de comandos, validándolos + * y mostrando un mensaje de error en caso de haberlo. + * + * \param argc Cantidad de parámetros de línea de comandos ingresados. + * \param argv Parámetros de línea de comandos. + * \param paso Paso utilizado para las iteraciones. + * \param tf Tiempo final. + * \param f0 Valor inicial de la función. + * + * \return TRUE si se cargaron bien, FALSE si no. + * \todo Verificar que el paso no sea cero y que tf > ti. + */ +int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0); + +/** + * \ref integracion "Calcula" todos los valores de la función. + * + * \param res Vector donde se guardan los resultados. + * \param paso Paso de iteración. + * \param ti Tiempo de inicio de la iteración. + * \param tf Tiempo final de la iteración. + * \param f0 Valor inicial de la función. + * + * \return Cantidad de pasos realizados. + */ +size_t calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0); + +/** + * Devuelve el valor máximo de los resultados. + * + * \param res Vector de resultados. + * \param pasos Cantidad de pasos a iterar. + * + * \return Máximo resultado. + */ +Real max(const Resultados* res, size_t pasos); + +/** + * Devuelve el valor mínimo de los resultados. + * + * \param res Vector de resultados. + * \param pasos Cantidad de pasos a iterar. + * + * \return Mínimo resultado. + */ +Real min(const Resultados* res, size_t pasos); + +/** + * Programa principal. + * Este es el programa que se encarga de resolver el trabajo práctico. + * + * \param argc Cantidad de parámetros de línea de comandos ingresados. + * \param argv Parámetros de línea de comandos. + * + * \return EXIT_FAILURE si hubo un error, si no EXIT_SUCCESS. + */ +int main(int argc, const char** argv); +