/** @(#) 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------------------------------------------------------------------------