/** @(#) matrixdouble/vectordouble.cpp */ #include "vectordouble.h" // constructor, ~, friend----------------------------------------------------- /** Construye un vector. * Necesario un constructor sin parametros para crear arreglo de VectorDouble. * @param theSize Taman~o del vector. Min: 1. * @param theLogic 0: Logica 0. 1: Otro numero. * @param cleanMe true: Limpia el vector con 0.0. false: no inicializa. */ VectorDouble :: VectorDouble(int theSize, int theLogic, bool cleanMe) { //cout << "\n{ VectorDouble()"; v = NULL; // flags de creacion resize(theSize, theLogic, cleanMe); } /** Constructor de copia. Copia dimension, logica y valores. */ VectorDouble :: VectorDouble(VectorDouble &source) { int theSize = source.size; int theLogic = source.logic; //cout << "\n{ VectorDouble()"; v = NULL; // flags de creacion resize(theSize, theLogic, false); // false se van a copiar copyFrom(source); } /** Libera memoria. Para funciones fuera de clases, usar deleteArray(). * Para llamar al destructor theObject = NULL; */ VectorDouble :: ~VectorDouble() { if (v != NULL) { // Por algun error se tiene que atrapar try { //delete[] v; } catch(exception e) { cout << "~VectorDouble: " << e.what(); } catch(...) { cout << "~VectorDouble: catch(...)"; } // No usar v = NULL; // Asegurarse } } /** Para ser usado por RectangularMatrix. * Libera y asigna memoria. Se pierden los datos. * Si es del mismo taman~o, no hace nada. * Logica cero.*/ void VectorDouble :: resize(int theSize, int theLogic, bool cleanMe) { /* algoritmo resize(theSize); // 1. logic = (theLogic ? 1 : 0); // 2. Necesita memoria if (cleanMe) { // 3. Necesita logica clean(); } */ int validSize = ((theSize > 0) ? theSize : 1); // Primero se determina si se creo luego la validacion // Si no esta creada, valida y reservar if (v == NULL) { v = new double[validSize]; // Si ya estaba creada y es del mismo taman~o, no hace nada // Compara size anterior con el nuevo } else if (size != validSize) { // julio no lo hace delete[] v; // 1o. v = new double[validSize]; } size = validSize; logic = (theLogic ? 1 : 0); // 2. Necesita memoria if (cleanMe) { // 3. Necesita logica clean(); } } /** Asume dimensiones y logica iguales. */ // operator= void VectorDouble :: copyFrom(VectorDouble &source) { int i; for (i = 0; i < size; ++i) { v[i] = source.v[i]; } } // operator------------------------------------------------------------------- /** * Muestra el vector en la consola. No muestra las dimensiones. * @param outStr Destino del flujo. * @param vector Vector a mostrar. * @return Vector */ ostream & operator<<(ostream &outStr, const VectorDouble &theVector) { int i; // Ajuste a la logica int first = theVector.getLogic(); int last = theVector.getSize() + first - 1; double value; for (i = first; i <= last; ++i) { value = theVector[i]; // error si << theVector[i] outStr << value << "\t"; } return outStr; } /** * Entrada de la matriz en la consola. * Permite lectura de archivo de la dimension y de los datos. * No se lee la logica de la matriz. * Uso: * 3 1.1 2.2 3.3 * Logica variable. * @param outStr Destino del flujo. * @param matrix Matriz a mostrar. * @return Matriz */ istream & operator>>(istream &inpStr, VectorDouble &theVector) { //matrix.read(); // sig inpStr >> int i, n; inpStr >> n; // Ajuste a la logica int first = theVector.getLogic(); int last = n + first - 1; // Reserva memoria theVector.resize(n, first, true); // logic for (i = first; i <= last; ++i) { inpStr >> theVector[i]; // error si inpStr >> matrix(i, j) } return inpStr; } /** * Permite asignacion (operator=). * Logica 0, (0, 0) apunta al matematico A 1,1 esq sup izq * @param row Logica cero: [0, row -1]. Logica uno: [1, row] * @param column Logica cero: [0, col -1]. Logica uno: [1, col] */ double & VectorDouble :: operator()(int index) throw (invalid_argument) { if ( (index < logic) || (index >= (size + logic)) ) { throw invalid_argument("operator(): indices fuera de rango."); } return v[index - logic]; } /** @version const Sino error por rvalue. */ const double & VectorDouble :: operator()(int index) const throw (invalid_argument) { if ( (index < logic) || (index >= (size + logic)) ) { throw invalid_argument("operator(): indices fuera de rango."); } return v[index - logic]; } /** No checa dimensiones, ni logica. */ VectorDouble VectorDouble :: operator+(VectorDouble &right) { VectorDouble res(size, logic); int i; for (i = 0; i < size; ++i) { res.v[i] = v[i] + right.v[i]; } return res; } /** No checa dimensiones, ni logica. */ VectorDouble VectorDouble :: operator-(VectorDouble &right) { VectorDouble res(size, logic); int i; for (i = 0; i < size; ++i) { res.v[i] = v[i] - right.v[i]; } return res; } /** * Multiplica un vector por un escalar. * Logica cero. * @param product Donde se almacenara el resultado */ void VectorDouble :: multiply(double escalar, VectorDouble &product) throw (invalid_argument) { if (size != product.size) { throw invalid_argument("multiply: Dimensiones diferentes."); } int i; for (i = 0; i < size; ++i) { product.v[i] = v[i] * escalar; } } /** Multiplica un vector por un escalar. * Logica cero. * @return Nuevo Vector multiplicado. */ // error de memoria // dep VectorDouble VectorDouble :: operator*(double right) { int i; VectorDouble res(size, logic); // mismo tam y log for (i = 0; i < size; ++i) { res.v[i] = right * v[i]; } return res; // No se puede regresar solo product } /** * Multiplica un vector por un escalar. * Logica cero. * @return Nuevo Vector multiplicado. */ /* error de memoria VectorDouble VectorDouble :: operator*(double right) { //double VectorDouble :: multiply(double escalar) { int i; VectorDouble product(size, logic); // mismo tam y log for (i = 0; i < size; ++i) { product[i + logic] = right * v[i]; } return VectorDouble(product); // No se puede regresar solo product } */ /** @version Usar constantes. */ /*VectorDouble VectorDouble :: operator*(const double right) { return (*this) * const_cast<double>(right); } */ /** * Multiplica un vector por otro vector. Producto interno. * Checa dimensiones. * Logica cero. * @param y Segundo operador. */ double VectorDouble :: operator*(VectorDouble &right) throw(invalid_argument) { //double VectorDouble :: multiply(double escalar) { if (size != right.getSize()) { throw invalid_argument( "operator*: Las dimensiones son diferentes."); } int i; double sum = 0.0; // proceso con la actual, pero manejar distintas logicas // caso logic=1, rightLogic=0 for (i = 0; i < size; ++i) { sum += v[i] * right.v[i]; } return sum; } /** Redimensiona el vector, copia los datos de right y las caracteristicas. */ const VectorDouble &VectorDouble :: operator=(const VectorDouble &right) { if (size != right.getSize()) { resize(right.getSize(), right.getLogic(), false); //throw invalid_argument( // "operator=: Las dimensiones son diferentes."); } if (&right != this) { // Revisa autoasignacion copyFrom( const_cast<VectorDouble &>(right) ); } return *this; // Permite x = y = z; } // public--------------------------------------------------------------------- /** * Llena el vector con el valor indicado. * Logica cero. * @param value Cada elemento valdra este numero. */ void VectorDouble :: fill(double value) { int i; for (i = 0; i < size; ++i) { v[i] = value; } } /** * Solo lee los elementos sin la dimension desde consola. * Logica cero. */ void VectorDouble :: readElements() { int i; for (i = 0; i < size; ++i) { cin >> v[i]; } } /** @return true: Hay al menos un cero (menor que MACHEPS). * false: todos los elementos distintos de cero.*/ bool VectorDouble :: hasAlmostZeros() { int i; for (i = 0; i < size; ++i) { if ( fabs(v[i]) < MACHEPS) { return true; } } return false; } /** Usado por RectangularMatrix::deleteRectangular. * Cuando no funciona el destructor (~). */ void VectorDouble :: deleteArray() { if (v != NULL) { delete[] v; } v = NULL; } /** @param digits Precision. Numero de digitos. Logica cero. */ void VectorDouble :: print(int digits) { int i; cout << setiosflags(ios::fixed) << setprecision(digits); for (i = 0; i < size; ++i) { cout << v[i] << "\t"; } cout << "\t"; } /** @param digits Precision. Numero de digitos. Logica cero. */ string VectorDouble :: toString(int digits, char separator) { ostringstream outStr; int i; outStr << setiosflags(ios::fixed) << setprecision(digits); for (i = 0; i < size; ++i) { outStr << v[i] << separator; } return outStr.str(); } /** Calcula la inversa. 1/v[i]. */ VectorDouble VectorDouble :: inverse() { VectorDouble res(size, logic); int i; for (i = 0; i < size; ++i) { res.v[i] = 1.0 / v[i]; } return res; } /** Calcula el producto interno. Vector renglon * Vector columna = escalar. * No checa dimensiones. */ // // ver operator * /*double VectorDouble :: innerProduct(VectorDouble &right) { double sum = 0.0; int i; for (i = 0; i < size; ++i) { sum += v[i] * right[i]; } return sum; } */ /** Toma el vector actual como si fuera una matriz diagonal. * [ v[0] 0 ][r[0]] * [ v[2] ][r[1]] * [ ... ][...] * [ 0 v[n] ][r[n]] * Se multiplica la matriz diagonal por un vector columna, resultando un vector columna. */ VectorDouble VectorDouble :: diagonalProduct(VectorDouble &right) { VectorDouble res(size, logic); int i; for (i = 0; i < size; ++i) { res.v[i] = v[i] * right.v[i]; } return res; } /** Calcula la norma superior o infinita. * || v ||oo l(infinity) sup norm */ double VectorDouble :: infinityNorm() { double mx = v[0]; int i; // i = 1 se asigna el primero como maximo for (i = 1; i < size; ++i) { if (v[i] > mx) { mx = v[i]; } } return mx; } /** Calcula la norma del minimo residuo absoluto * || v ||1 l1 LAR norm (Least Absolute Residual) */ // No usar generalNorm por velocidad double VectorDouble :: norm1() { double sum = 0.0; int i; for (i = 0; i < size; ++i) { sum += fabs(v[i]); } return sum; } /** Calcula la norma del minimo residuo absoluto * || v ||2 l2 Euclidean or least-squares norm */ // No usar generalNorm por velocidad double VectorDouble :: norm2() { double sum = 0.0; int i; for (i = 0; i < size; ++i) { sum += v[i] * v[i]; } return sqrt(sum); } /** Calcula la norma del minimo residuo absoluto * || v ||p lp General norm * @param p p=[1, infinity) No lo checa. */ double VectorDouble :: generalNorm(double p) { double sum = 0.0; int i; for (i = 0; i < size; ++i) { sum += pow( fabs(v[i]), p); } return pow(sum, 1.0/p); } /** Lee de un archivo dos columnas. Ignora las cadenas. Ejemplo: <pre> Dim 3 Tiempo Poblacion 0.00 2.50000000000 0.25 4.46185192849 0.50 7.09001693225 </pre> */ //static void VectorDouble :: read2ColumnsFromFile(string pathFile, VectorDouble &v1, VectorDouble &v2) throw (runtime_error) { ifstream inFile(pathFile.data(), ios::in); if ( !inFile ) { // !sobrecargado throw runtime_error( "graphDoglegFile: Error de apertura de archivo."); } string dummy; int i, n; // Dim inFile >> dummy >> n; v1.resize(n, 1, false); v2.resize(n, 1, false); // Titulo1 Titulo2 inFile >> dummy >> dummy; for (i = 0; i < n; ++i) { inFile >> v1.v[i] >> v2.v[i]; } } // Sin ajustar /** * compute norm1 for V[n] (vector) * Logica uno. */ /*double norm1( double *V, int n) { double sum = 0.0; for (int i=1; i<=n; ++i) sum += fabs(V[i]); return sum; } */ // Sin ajustar /** * Solve Rx = e for x . * Logica uno. */ /*void solveRxe( double **R, double *x, int n) { double *p = new double[n + 1]; double *pm = new double[n + 1]; double xp; double xm; double temp; double tempm; x[1] = 1.0/R[1][1]; for (int i=2; i<=n; ++i) p[i] = x[1] * R[1][i]; for (int j=2; j<=n; ++j) { xp = (1.0-p[j])/R[j][j]; xm = (-1.0-p[j])/R[j][j]; temp = fabs(xp); tempm = fabs(xm); for (int i=j+1; i<=n; ++i) { pm[i] = p[i] + xm*R[j][i]; tempm += fabs(pm[i])/fabs(R[i][i]); p[i] += xp *R[j][i]; temp += fabs(p[i])/fabs(R[i][i]); } if (temp >= tempm) x[j] = xp; else { x[j] = xm; for (int i=j+1; i<=n; ++i) p[i] = pm[i]; } } delete []p; delete []pm; } */ // Sin ajustar /** * Solve Ry = x for y * Logica uno. */ /* void solveRyx(double **R, double *y, double *x, int n) { double sum; for (int i=n; i>=1; --i) { sum = 0.0; for (int j=i+1; j<=n; ++j) sum += R[i][j] * y[j]; y[i] = (x[i] - sum)/R[i][i]; } } */ // Sin ajustar /** * computes estimation for condition number k1(R) * Logica uno. */ /* double condest( double **R, int n ) { double *x = new double[n + 1]; double *y = new double[n + 1]; double est; est = norm1(R, n, n); solveRxe(R, x, n); solveRyx(R, y, x, n); est *= norm1(y, n)/norm1(x, n); delete []x; delete []y; return est; } */ // private-------------------------------------------------------------------- // Fin------------------------------------------------------------------------