/** @(#) mathpos/statpos.cpp */ /** * Define las funciones de la cabecera. */ #include "statpos.h" /** * Cuenta el numero de datos de cada clase en un cierto intervalo * para un arreglo bidimensional. * No cuenta datos fuera del rango [leftRange, rightRange]. * Intervalo de la i-esima clase: [left, right). * @param f Lista de datos 2D. Antes: item. * @param nr Numero de renglones. * @param nc Numero de columnas. * @param leftRange Inicio del intervalo. * @param rightRange Fin del intervalo. * @param pClassMark return. * Uso: float *pClassMark = new float[bins]; * Almacena las marcas de clase. * @param pFreq return. * Uso: long *pFreq = new long[bins]; * Almacena las frecuencias absolutas. * @param bins Numero de clases en el histograma. * @throws invalid_argument IllegalArgumentException * No se puede contar frecuencias. */ void countFrequency2D(float **f, int nr, int nc, float leftRange, float rightRange, float *pClassMark, long *pFreq, int bins) throw (invalid_argument) { // Inicializa //[bins + 1] float *pClassFrontier = new float[bins + 1]; int i, j, b; float elem; // Valida (bins < 1) || (leftClass >= rightClass) calculateClassMarks(bins, leftRange, rightRange, pClassMark); calculateClassFrontiers(bins, leftRange, rightRange, pClassFrontier); vectorToZero(pFreq, bins); // Clasifica cada dato // Se incluye el borde. for (i = 0; i < nr; ++i) { for (j = 0; j < nc; ++j) { elem = f[i][j]; // optimizado // si el dato, esta fuera a la izq, se salta if (elem < pClassFrontier[0]) { continue; } // si el dato es menor que la superior, termina for (b = 0; b < bins; ++b) { //right = pClassFrontier[b + 1]; if (elem < pClassFrontier[b + 1]) { ++(pFreq[b]); break; } } // Si hubo break no debe entrar // Si no quedo en el ultimo, // Checa el extremo if ((b == bins) && (elem <= rightRange)) { ++(pFreq[bins - 1]); } } // for j } // for i // Libera memoria delete []pClassFrontier; } /** * Cuenta el numero de datos de cada clase en un cierto intervalo * para un arreglo bidimensional normalizados a 1.0. * No cuenta datos fuera del rango [leftRange, rightRange]. * Intervalo de la i-esima clase: [left, right). * @param f Lista de datos 2D. Antes: item. * @param nr Numero de renglones. * @param nc Numero de columnas. * @param leftRange Inicio del intervalo. * @param rightRange Fin del intervalo. * @param pClassMark return. * Uso: float *pClassMark = new float[bins]; * Almacena las marcas de clase. * @param pRelFreq return. * Uso: long *pRelFreq = new long[bins]; * Almacena las frecuencias relativas. * @param bins Numero de clases en el histograma. * @throws invalid_argument IllegalArgumentException * No se puede contar frecuencias. */ void relativeFrequency2D(float **f, int nr, int nc, float leftRange, float rightRange, float *pClassMark, float *pRelFreq, int bins) throw (invalid_argument) { // Encuentra el histograma long *pFreq = new long[bins]; countFrequency2D(f, nr, nc, leftRange, rightRange, pClassMark, pFreq, bins); if (pRelFreq == NULL) { throw invalid_argument("No hay datos"); } // Suma las frecuencias float sum = 0; int i; for (i = 0; i < bins; ++i) { sum += static_cast<float>(pFreq[i]); } // Relativo for (i = 0; i < bins; ++i) { pRelFreq[i] = static_cast<float>(pFreq[i]) / sum; } delete []pFreq; } /** * Busca las marcas de clase. * @param bins Numero de clases en el histograma. * @param leftRange Inicio del intervalo. * @param rightRange Fin del intervalo. * @param pClassMark return. Uso: float *pClassMark = new float[bins]; * Cada renglon tiene la marca de clase. * @throws invalid_argument IllegalArgumentException * No se puede contar frecuencias. */ void calculateClassMarks(int bins, float leftRange, float rightRange, float *pClassMark) throw (invalid_argument) { if ( (bins < 1) || (leftRange >= rightRange) ) { throw invalid_argument( "No se pueden crear marcas de clase."); } float interval = rightRange - leftRange; // =8 float base = interval / bins; // base de la barra //Inicia de izq a der pClassMark[0] = leftRange + (base / 2.0); int i; for (i = 1; i < bins; ++i) { pClassMark[i] = pClassMark[i - 1] + base; } } /** * Busca las fronteras entre las marcas de clase. * @param bins Numero de clases en el histograma. * @param leftRange Inicio del intervalo. * @param rightRange Fin del intervalo. * @param pClassFrontier return. * Uso: float *pClassFrontier = new float[bins + 1]; * Cada renglon tiene la frontera de clase. * @throws invalid_argument IllegalArgumentException * No se puede contar frecuencias. */ void calculateClassFrontiers(int bins, float leftRange, float rightRange, float *pClassFrontier) throw (invalid_argument) { // ejem: 4, -4, 4 if ( (bins < 1) || (leftRange >= rightRange) ) { throw invalid_argument( "No se pueden crear las fronteras de clase."); } float interval = rightRange - leftRange; // =8 float base = interval / bins; // base de la barra //Inicia de izq a der pClassFrontier[0] = leftRange; int i; for (i = 1; i < bins; ++i) { pClassFrontier[i] = pClassFrontier[i - 1] + base; } // Ajusta la ultima pClassFrontier[bins] = rightRange; } //template <class TObj> // constructor, ~, friend----------------------------------------------------- /* Constructor predeterminado. */ /** Construye. */ /* Destructor predeterminado. */ /** Libera recursos. */ // operator------------------------------------------------------------------- // public--------------------------------------------------------------------- // private-------------------------------------------------------------------- /** * * @param * @param * @return * @see paq1.paq2.MyClass#MyMethod(int,Object) * @throws Exception */ /** * Se incluye el borde. */ void calculateMeanMinMax2D(float **f, int nr, int nc, double &mean, float &min, float &max) { double sum = 0.0; float elem; min = max = f[0][0]; int i, j; // Se incluye el borde. for (i = 0; i < nr; ++i) { for (j = 0; j < nc; ++j) { elem = f[i][j]; sum += elem; if (elem < min) { min = elem; } else if (f[i][j] > max) { max = elem; } } } mean = sum / (nr * nc); } /** * Se incluye el borde. */ void findMinMax2D(float **f, int nr, int nc, float &min, float &max) { float elem; min = max = f[0][0]; int i, j; // Se incluye el borde. for (i = 0; i < nr; ++i) { for (j = 0; j < nc; ++j) { elem = f[i][j]; if (elem < min) { min = elem; } else if (f[i][j] > max) { max = elem; } } } } /** * @param pRelFreq Arreglo con las frecuencias relativas. * @param pCumFreq Arreglo con las frecuencias acumuladas. */ void cumulativeFrequency(float *pRelFreq, int bins, float *pCumFreq) { int i; pCumFreq[0] = pRelFreq[0]; for (i = 1; i < bins; ++i) { pCumFreq[i] = pCumFreq[i - 1] + pRelFreq[i]; } } // Fin------------------------------------------------------------------------