diff --git a/utils/sislin.c b/utils/sislin.c new file mode 100644 index 0000000000000000000000000000000000000000..875f6dad3a868cbd52265ba7154ec19328283023 --- /dev/null +++ b/utils/sislin.c @@ -0,0 +1,181 @@ +#include <stdio.h> +#include <math.h> +#include <stdlib.h> + +#include "utils.h" +#include "sislin.h" + +// Alocaçao de memória. Matriz como vetor de ponteiros para vetores +// alocados independentemente +SistLinear_t* alocaSisLin (unsigned int n, tipoAloc_t tipo) +{ + SistLinear_t *SL = (SistLinear_t *) malloc(sizeof(SistLinear_t)); + + if ( SL ) { + + SL->n = n; + SL->tipoAloc_A = tipo; + SL->A = (real_t **) malloc(n * sizeof(real_t *)); + SL->b = (real_t *) malloc(n * sizeof(real_t)); + + if (!(SL->A) || !(SL->b)) { + liberaSisLin(SL); + return NULL; + } + + if (tipo == pontVet) { + SL->A[0] = (real_t *) malloc(n * n * sizeof(real_t)); + if (!(SL->A[0])) { + liberaSisLin(SL); + return NULL; + } + + for (int i=1; i < n; ++i) { + SL->A[i] = SL->A[i-1]+n; + } + } + else if (tipo == pontPont) { + for (int i=0; i < n; ++i) + SL->A[i] = (real_t *) malloc(n * sizeof(real_t)); + } + } + + return (SL); +} + +// Liberacao de memória +void liberaSisLin (SistLinear_t *SL) +{ + if (SL) { + if (SL->A) { + if (SL->tipoAloc_A == pontVet) { + if (SL->A[0]) free (SL->A[0]); + } + else if (SL->tipoAloc_A == pontPont) { + for (int i=0; i < SL->n; ++i) + free (SL->A[i]); + } + + free(SL->A); + } + if (SL->b) free(SL->b); + free(SL); + } +} + + +/*! + \brief Cria coeficientes e termos independentes do SL + * + \param SL Ponteiro para o sistema linear + \param tipo Tipo de sistema linear a ser criado. Pode ser: + comSolucao, eqNula, eqProporcional, eqCombLinear, hilbert + \param coef_max Maior valor para coeficientes e termos independentes +*/ +void iniSisLin (SistLinear_t *SL, tipoSistLinear_t tipo, real_t coef_max) +{ + unsigned int n = SL->n; + // para gerar valores no intervalo [0,coef_max] + real_t invRandMax = ((real_t)coef_max / (real_t)RAND_MAX); + + // inicializa vetor b + for (unsigned int i=0; i<n; ++i) { + SL->b[i] = (real_t)rand() * invRandMax; + } + + if (tipo == hilbert) { + for (unsigned int i=0; i<n; ++i) { + for (unsigned int j=0; j<n; ++j) { + SL->A[i][j] = 1.0 / (real_t)(i+j+1); + } + } + } + else { // inicializa sistema normal e depois altera + // inicializa a matriz A + for (unsigned int i=0; i<n; ++i) { + for (unsigned int j=0; j<n; ++j) { + SL->A[i][j] = (real_t)rand() * invRandMax; + } + } + if (tipo == eqNula) { + // sorteia eq a ser "nula" + unsigned int nula = rand() % n; + for (unsigned int j=0; j<n; ++j) { + SL->A[nula][j] = 0.0; + } + SL->b[nula] = 0.0; + } + else if (tipo == eqProporcional) { + // sorteia eq a ser "proporcional" e valor + unsigned int propDst = rand() % n; + unsigned int propSrc = (propDst + 1) % n; + real_t mult = (real_t)rand() * invRandMax; + for (unsigned int j=0; j<n; ++j) { + SL->A[propDst][j] = SL->A[propSrc][j] * mult; + } + SL->b[propDst] = SL->b[propSrc] * mult; + } + else if (tipo == eqCombLinear) { + // sorteia eq a ser "combLinear" + unsigned int combDst = rand() % n; + unsigned int combSrc1 = (combDst + 1) % n; + unsigned int combSrc2 = (combDst + 2) % n; + for (unsigned int j=0; j<n; ++j) { + SL->A[combDst][j] = SL->A[combSrc1][j] + SL->A[combSrc2][j]; + } + SL->b[combDst] = SL->b[combSrc1] + SL->b[combSrc2]; + } + else if (tipo == diagDominante) { + // aumenta o expoente dos termos da diagonal principal + for (unsigned int i=0; i<n; ++i) { + SL->A[i][i] *= (real_t)n; + } + } + } +} + + +SistLinear_t *lerSisLin (tipoAloc_t tipo) +{ + unsigned int n; + SistLinear_t *SL; + + scanf("%d",&n); + + SL = alocaSisLin (n, tipo); + + for(int i=0; i < n; ++i) + for(int j=0; j < n; ++j) + scanf ("%lg", &SL->A[i][j]); + + for(int i=0; i < n; ++i) + scanf ("%lg", &SL->b[i]); + + return SL; +} + + +void prnSisLin (SistLinear_t *SL) +{ + int n=SL->n; + + for(int i=0; i < n; ++i) { + printf("\n "); + for(int j=0; j < n; ++j) + printf ("%10g", SL->A[i][j]); + printf (" | %g", SL->b[i]); + } + printf("\n\n"); +} + +void prnVetor (real_t *v, unsigned int n) +{ + int i; + + printf ("\n"); + for(i=0; i < n; ++i) + printf ("%10g ", v[i]); + printf ("\n\n"); + +} + diff --git a/utils/sislin.h b/utils/sislin.h new file mode 100644 index 0000000000000000000000000000000000000000..c02806a07591bb1a7c802ddf7f2a447e3dce8f8a --- /dev/null +++ b/utils/sislin.h @@ -0,0 +1,48 @@ +#ifndef __SISLIN_H__ +#define __SISLIN_H__ + +#define COEF_MAX 32.0 // Valor máximo usado para gerar valores aleatórios de + // coeficientes nos sistemas lineares. + +#define ABS(num) ((num) < 0.0 ? -(num) : (num)) // Valor absoluto de um número + +// tipo usado para representar valores em ponto flutuante +typedef double real_t; + +// Tipo de alocação para matrizes +typedef enum { + pontPont=0, // Matriz como vetor de N ponteiros para vetores de tamanho N + pontVet // Matriz como vetor de N ponteiros para um único vetor de tamanho N*N +} tipoAloc_t; + +// Estrutura para definiçao de um sistema linear qualquer +typedef struct { + real_t **A; // coeficientes + real_t *b; // termos independentes + unsigned int n; // tamanho do SL + tipoAloc_t tipoAloc_A; // tipo de alocação usada na matriz de coeficientes +} SistLinear_t; + +// Tipos de matrizes de coeficientes usados pela função 'inicializaSistLinear()' +typedef enum { + generico = 0, + eqNula, + eqProporcional, + eqCombLinear, + hilbert, + diagDominante +} tipoSistLinear_t; + + +// Alocaçao e desalocação de matrizes +SistLinear_t* alocaSisLin (unsigned int n, tipoAloc_t tipo); +void liberaSisLin (SistLinear_t *SL); +void iniSisLin (SistLinear_t *SL, tipoSistLinear_t tipo, real_t coef_max); + +// Leitura e impressão de sistemas lineares +SistLinear_t *lerSisLin (); +void prnSisLin (SistLinear_t *SL); +void prnVetor (real_t *vet, unsigned int n); + +#endif // __SISLIN_H__ +