00001 /**********************************************************/ 00002 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00003 /* 00004 Copyright: 1993 - Grupo de Voz (DAET) ETSII/IT-Bilbao 00005 00006 Nombre fuente................ STAT.C 00007 Nombre paquete............... SPL 00008 Lenguaje fuente.............. C (Borland C/C++ 3.1) 00009 Estado....................... Completado 00010 Dependencia Hard/OS.......... - 00011 Codigo condicional........... NDEBUG 00012 00013 Codificacion................. Borja Etxebarria 00014 00015 Version dd/mm/aa Autor Proposito de la edicion 00016 ------- -------- -------- ----------------------- 00017 1.1.2 04/03/97 Borja eliminar warnings inocentes 00018 1.1.1 30/07/95 Borja scope funciones explicito 00019 1.1.0 08/12/94 Borja revision de tipos. 00020 1.0.0 11/01/93 Borja Codificacion inicial. 00021 00022 ======================== Contenido ======================== 00023 Calculo de estadisticos de primer y segundo orden. 00024 00025 NOTA: Para la reserva de memoria dinamica se han definido 00026 dos macros en _STAT.H: stat_malloc() y stat_free(), que mapean 00027 a las funciones _malloc() y _free(), definidas en _ALLOC.H. 00028 00029 Definir NDEBUG para desconectar la validacion de parametros 00030 con assert(). No definir este simbolo mientras se depuren 00031 aplicaciones, ya que aunque las funciones son algo mas lentas, 00032 el chequeo de validacion de parametros resuelve muchos problemas. 00033 =========================================================== 00034 */ 00035 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00036 /**********************************************************/ 00037 00038 #include <stdlib.h> 00039 #include <math.h> 00040 #include <assert.h> 00041 00042 #include "_stat.h" 00043 00044 /**********************************************************/ 00045 /* Constructor de una estructura stat. 00046 {devuelve} un puntero a la estructura creada, o NULL si no se puede. 00047 {nhistdivs}=numero de celdas para el histograma */ 00048 00049 PUBLIC pSTAT XAPI stat_construct( SPL_INT nhistdivs ) 00050 { 00051 pSTAT st; 00052 assert(nhistdivs>=0); 00053 00054 st = (pSTAT)stat_malloc(sizeof(STAT)); 00055 if (st!=NULL) { 00056 st->_divs = nhistdivs; 00057 st->_hist = (SPL_pLONG)stat_malloc( 00058 sizeof(SPL_LONG)*nhistdivs); 00059 00060 if (st->_hist!=NULL) 00061 stat_first(st); 00062 else { 00063 stat_destruct(st); 00064 st=NULL; 00065 } 00066 } 00067 00068 return st; 00069 } 00070 00071 /**********************************************************/ 00072 /* destructor para estructura stat {st} */ 00073 00074 PUBLIC SPL_VOID XAPI stat_destruct( pSTAT st ) 00075 { 00076 assert(st!=NULL); 00077 00078 if (st->_hist!=NULL) 00079 stat_free(st->_hist); 00080 stat_free(st); 00081 } 00082 00083 /**********************************************************/ 00084 /* llamar para reinicializar el calculo de estadisticos de primer 00085 orden. Durante este analisis, los estadisticos de primer orden (media, 00086 valor cuadratico medio, valor minimo, maximo, numero de elementos) se 00087 actualizan constantemente mientras llegan nuevos datos, 00088 mientras que los de segundo orden valen 0 */ 00089 00090 PUBLIC SPL_VOID XAPI stat_first( pSTAT st ) 00091 { 00092 assert(st!=NULL); 00093 00094 st->_sec=1; 00095 stat_second(st); 00096 st->_sec=0; 00097 00098 st->_n=0; 00099 st->_mean=0.0; 00100 st->_msqv=0.0; 00101 st->_min=0.0; 00102 st->_max=0.0; 00103 st->_var=0.0; 00104 st->_range=0.0; 00105 } 00106 00107 /**********************************************************/ 00108 /* pasa al sistema una ocurrencia {x} de la variable en estudio, 00109 para analisis de primer o segundo orden. Esta es la funcion de 00110 entrada de datos al sistema de analisis */ 00111 00112 PUBLIC SPL_VOID XAPI stat_setvalue( pSTAT st, SPL_FLOAT x ) 00113 { 00114 SPL_INT i; 00115 assert(st!=NULL); 00116 00117 st->_n++; 00118 if (st->_sec) { 00119 i = stat_histlocate(st,x); 00120 st->_var+=(x-st->_mean)*(x-st->_mean); 00121 if (i>=0) 00122 st->_hist[i]++; 00123 else if (i==-1) 00124 st->_under++; 00125 else if (i==-2) 00126 st->_over++; 00127 } 00128 else { 00129 st->_mean+=x; 00130 st->_msqv+=x*x; 00131 if (x<st->_min) 00132 st->_min=x; 00133 if (x>st->_max) 00134 st->_max=x; 00135 } 00136 } 00137 00138 /**********************************************************/ 00139 /* {devuelve} la media hasta el momento (durante el analisis de primer 00140 orden) o la definitiva (durante el analisis de segundo orden) */ 00141 00142 PUBLIC SPL_FLOAT XAPI stat_mean( pSTAT st ) 00143 { 00144 if (st->_sec) 00145 return st->_mean; 00146 else if (st->_n) 00147 return st->_mean/st->_n; 00148 else 00149 return 0.0; 00150 } 00151 00152 /**********************************************************/ 00153 /* {devuelve} el valor cuadratico medio hasta el momento (durante 00154 el analisis de primer orden) o el definitivo (durante el analisis 00155 de segundo orden) */ 00156 00157 PUBLIC SPL_FLOAT XAPI stat_msqv( pSTAT st ) 00158 { 00159 assert(st!=NULL); 00160 00161 if (st->_sec) 00162 return st->_msqv; 00163 else if (st->_n) 00164 return st->_msqv/st->_n; 00165 else 00166 return 0.0; 00167 } 00168 00169 /**********************************************************/ 00170 /* {devuelve} el numero de ocurrencias de la variable analizada que se 00171 llevan pasados al sistema mediante la funcion stat_setvalue() */ 00172 00173 PUBLIC SPL_LONG XAPI stat_n( pSTAT st ) 00174 { 00175 assert(st!=NULL); 00176 00177 return st->_n; 00178 } 00179 00180 /**********************************************************/ 00181 /* {devuelve} el valor minimo sucedido hasta el momento (durante 00182 el analisis de primer orden) o el definitivo (durante el analisis 00183 de segundo orden) */ 00184 00185 PUBLIC SPL_FLOAT XAPI stat_min( pSTAT st ) 00186 { 00187 assert(st!=NULL); 00188 00189 return st->_min; 00190 } 00191 00192 /**********************************************************/ 00193 /* {devuelve} el valor maximo sucedido hasta el momento (durante 00194 el analisis de primer orden) o el definitivo (durante el analisis 00195 de segundo orden) */ 00196 00197 PUBLIC SPL_FLOAT XAPI stat_max( pSTAT st ) 00198 { 00199 assert(st!=NULL); 00200 00201 return st->_max; 00202 } 00203 00204 /**********************************************************/ 00205 /* Fuerza los valores minimo y maximo con {min} y {max}. Solo funciona 00206 si se realiza durante el analisis de primer orden, forzando estos 00207 como los nuevos extremos, aunque pueden variar si se continua 00208 enviando valores con stat_setvalue() en analisis de primer orden. */ 00209 00210 PUBLIC SPL_VOID XAPI stat_setminmax( pSTAT st, 00211 SPL_FLOAT min, SPL_FLOAT max ) 00212 { 00213 assert(st!=NULL); 00214 00215 if (!st->_sec) { 00216 st->_min=min; 00217 st->_max=max; 00218 } 00219 } 00220 00221 /**********************************************************/ 00222 /* Da por concluido el analisis de primer orden, calcula 00223 los estadisticos de primer orden definitivos (media, valor 00224 cuadratico medio, numero de elementos, valor minimo y maximo), 00225 e inicializa el analisis de segundo orden. Si ya se estaba realizando un 00226 analisis de segundo orden, simplemente reinicializa este analisis. 00227 Durante el analisis de segundo orden los estadisticos de primer 00228 orden no se modifican, aunque cambie la naturaleza de los datos. 00229 Los estadisticos de segundo orden (varianza, desv. tipica 00230 e histograma) se actualizan constantemente segun llegan nuevos 00231 datos */ 00232 00233 PUBLIC SPL_VOID XAPI stat_second( pSTAT st ) 00234 { 00235 SPL_INT i; 00236 assert(st!=NULL); 00237 00238 if (!st->_sec) { 00239 st->_mean=stat_mean(st); 00240 st->_msqv=stat_msqv(st); 00241 st->_range=(st->_max-st->_min); 00242 } 00243 st->_n=0; 00244 st->_var=0.0; 00245 st->_sec=1; 00246 for (i=0; i<st->_divs; i++) 00247 st->_hist[i]=0; 00248 st->_under=0; 00249 st->_over=0; 00250 } 00251 00252 /**********************************************************/ 00253 /* {devuelve} la varianza si se esta realizando un analisis de segundo 00254 orden, o 0 si aun se esta en uno de primer orden */ 00255 00256 PUBLIC SPL_FLOAT XAPI stat_variance( pSTAT st ) 00257 { 00258 assert(st!=NULL); 00259 00260 if ((st->_sec)&&(st->_n)) 00261 return st->_var/st->_n; 00262 else 00263 return 0.0; 00264 } 00265 00266 /**********************************************************/ 00267 /* {devuelve} la desviacion tipica si se esta realizando un analisis 00268 de segundo orden, o 0 si aun se esta en uno de primer orden */ 00269 00270 PUBLIC SPL_FLOAT XAPI stat_stddev( pSTAT st ) 00271 { 00272 assert(st!=NULL); 00273 00274 return sqrt(stat_variance(st)); 00275 } 00276 00277 /**********************************************************/ 00278 /* {devuelve} el numero de divisiones que tiene el histograma */ 00279 00280 PUBLIC SPL_INT XAPI stat_nhistdivs( pSTAT st ) 00281 { 00282 assert(st!=NULL); 00283 00284 return st->_divs; 00285 } 00286 00287 /**********************************************************/ 00288 /* {devuelve} el array de contadores del histograma */ 00289 00290 PUBLIC SPL_pLONG XAPI stat_hists( pSTAT st ) 00291 { 00292 assert(st!=NULL); 00293 00294 return st->_hist; 00295 } 00296 00297 /**********************************************************/ 00298 /* {devuelve} el numero de valores acumulado por debajo 00299 del rango del histograma */ 00300 00301 PUBLIC SPL_LONG XAPI stat_histunder( pSTAT st ) 00302 { 00303 assert(st!=NULL); 00304 00305 return st->_under; 00306 } 00307 00308 /**********************************************************/ 00309 /* {devuelve} el numero de valores acumulado por encima del rango 00310 del histograma */ 00311 00312 PUBLIC SPL_LONG XAPI stat_histover( pSTAT st ) 00313 { 00314 assert(st!=NULL); 00315 00316 return st->_over; 00317 } 00318 00319 /**********************************************************/ 00320 /* {devuelve} la anchura de una celda del histograma. */ 00321 00322 PUBLIC SPL_FLOAT XAPI stat_histdivwidth( pSTAT st ) 00323 { 00324 assert(st!=NULL); 00325 00326 if (st->_divs) 00327 return st->_range/st->_divs; 00328 else 00329 return 0.0; 00330 } 00331 00332 /**********************************************************/ 00333 /* {devuelve} la cuenta (numero de ocurrencias) acumulada en la 00334 celda {div} del histograma. 00335 Si {div}<0 {devuelve} las acumuladas por debajo del minimo, y si 00336 {div}>=numero de celdas (stat_nhistdivs()) {devuelve} las acumuladas 00337 por encima del maximo */ 00338 00339 PUBLIC SPL_LONG XAPI stat_histdivcount( pSTAT st, SPL_INT div ) 00340 { 00341 assert(st!=NULL); 00342 00343 if (div<0) 00344 return st->_under; 00345 else if (div>=st->_divs) 00346 return st->_over; 00347 else 00348 return st->_hist[div]; 00349 } 00350 00351 /**********************************************************/ 00352 /* {devuelve} la cuenta (numero de ocurrencias) acumuladas desde menos 00353 infinito hasta la celda {div} (incluida esta) del histograma. 00354 Si {div}<0 {devuelve} las acumuladas por debajo del minimo del histograma 00355 Si {div}>=numero de celdas (stat_nhistdivs()) entonces {devuelve} el total */ 00356 00357 PUBLIC SPL_LONG XAPI stat_histdivacccount( pSTAT st, SPL_INT div ) 00358 { 00359 SPL_INT i; 00360 SPL_LONG a; 00361 assert(st!=NULL); 00362 00363 a=0; 00364 for (i=-1; i<=div; i++) 00365 a += stat_histdivcount(st,i); 00366 00367 return a; 00368 } 00369 00370 /**********************************************************/ 00371 /* {devuelve} la probabilidad (0-1) de la celda {div} del 00372 histograma. Es la funcion de densidad de probabilidad de 00373 cada celda. Si se quiere calcular la funcion de densidad 00374 de probabilidad en un punto, dividir este valor por la 00375 anchura de la celda (stat_histdivwidth()). 00376 Si {div}<0 {devuelve} la probabilidad de los valores por debajo del 00377 minimo del histograma, y si {div}>=numero de celdas (stat_nhistdivs()) 00378 {devuelve} la probabilidad de los valores por encima del maximo del 00379 histograma */ 00380 00381 PUBLIC SPL_FLOAT XAPI stat_histdivprob( pSTAT st, SPL_INT div ) 00382 { 00383 assert(st!=NULL); 00384 00385 if (st->_n) 00386 return ((SPL_FLOAT)stat_histdivcount(st,div))/st->_n; 00387 else 00388 return 0.0; 00389 } 00390 00391 /**********************************************************/ 00392 /* {devuelve} la probabilidad (0-1) acumulada desde menos infinito 00393 hasta la celda {div} (inclusive). 00394 Si {div}<0 {devuelve} la probabilidad por debajo del minimo del histograma 00395 Si {div}>=numero de celdas (stat_nhistdivs()) entonces {devuelve} todo (1) */ 00396 00397 PUBLIC SPL_FLOAT XAPI stat_histdivaccprob( pSTAT st, SPL_INT div ) 00398 { 00399 assert(st!=NULL); 00400 00401 if (st->_n) 00402 return ((SPL_FLOAT)stat_histdivacccount(st,div))/st->_n; 00403 else 00404 return 0.0; 00405 } 00406 00407 /**********************************************************/ 00408 /* {devuelve} el extremo inferior de la celda {div}. Este valor 00409 esta contenido en esta celda */ 00410 00411 PUBLIC SPL_FLOAT XAPI stat_histdivmin( pSTAT st, SPL_INT div ) 00412 { 00413 assert(st!=NULL); 00414 00415 if (st->_divs) 00416 return st->_min+(div*st->_range)/st->_divs; 00417 else 00418 return 0.0; 00419 } 00420 00421 /**********************************************************/ 00422 /* {devuelve} el extremo superior de la celda {div}. Este valor 00423 _no_ esta contenido en esta celda. Esta celda acumula ocurrencias 00424 hasta justo antes de este valor. Este valor pertenece ya a la 00425 celda siguiente. La excepcion es la ultima celda, que si incluye 00426 al valor superior */ 00427 00428 PUBLIC SPL_FLOAT XAPI stat_histdivmax( pSTAT st, SPL_INT div ) 00429 { 00430 assert(st!=NULL); 00431 00432 return stat_histdivmin(st,div+1); 00433 } 00434 00435 /**********************************************************/ 00436 /* Dada una ocurrencia {x} de la variable en estudio, {devuelve} 00437 el indice de la celda del histograma en la que se debe integrar. 00438 {devuelve} -1 si esta por debajo del histograma, y -2 si esta por 00439 encima */ 00440 00441 PUBLIC SPL_INT XAPI stat_histlocate( pSTAT st, SPL_FLOAT x ) 00442 { 00443 assert(st!=NULL); 00444 00445 if (x<st->_min) 00446 return -1; 00447 else if (x>st->_max) 00448 return -2; 00449 else if (x==st->_max) 00450 return st->_divs-1; 00451 else if (st->_range) 00452 return (SPL_INT)(((x-st->_min)/(st->_range))*st->_divs); 00453 else 00454 return 0; 00455 } 00456 00457 /**********************************************************/ 00458 /* dada una probabilidad {blkprob} (0-1), la funcion calcula el rango 00459 {min},{max} en el que se asegura que la probabilidad acumulada 00460 es la indicada en {blkprob} */ 00461 00462 PUBLIC SPL_VOID XAPI stat_blocklimits( pSTAT st, SPL_FLOAT blkprob, 00463 SPL_FLOAT * min, SPL_FLOAT * max ) 00464 { 00465 SPL_LONG blk; 00466 SPL_INT i,j, maxj; 00467 SPL_LONG sum, maxsum; 00468 assert(st!=NULL); 00469 00470 blk=(SPL_LONG)(blkprob*st->_n+0.5); 00471 maxj=0; 00472 00473 for (i=0; i<st->_divs; i++) { 00474 maxsum=sum=stat_histdivacccount(st,i); 00475 for (j=1; j<st->_divs-i; j++) { 00476 sum += stat_histdivcount(st,j+i) - 00477 stat_histdivcount(st,j-1); 00478 if (sum>maxsum) { 00479 maxsum=sum; 00480 maxj=j; 00481 } 00482 } 00483 if (maxsum>=blk) 00484 break; 00485 } 00486 *min=stat_histdivmin(st,maxj); 00487 *max=stat_histdivmax(st,maxj+i); 00488 } 00489 00490 /**********************************************************/ 00491