Grelet Jacques
/
Ni-MH_V3
example code using statis library for temperature measurement with LM35 and LM335
Diff: statis.cpp
- Revision:
- 3:0e06300940cd
- Child:
- 4:ffc39af07ade
diff -r 9517837c642d -r 0e06300940cd statis.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/statis.cpp Thu Nov 22 14:47:20 2012 +0000 @@ -0,0 +1,272 @@ +/***************************************************************************** + * Statis.c * + * * + * Module de calcul statistique utilisees par le logiciel THERMO * + * Ce module dans la version 1.0 calcule : la mediane * + * la moyenne * + * l'ecart type * + * Les fonctions prennent toutes comme argumemts un tableau FAR list[] * + * et les n_elem sur lequel est realise le calcul. * + * * + * Jacques Grelet Mars 1992 * + * Bruno Buisson Aout 92 * + * Septembre 1992 * + * Septembre 1994 * + *****************************************************************************/ +#define DEBUG +#undef DEBUG + +#include <debug.h> +#include <sys.h> +#include <math.h> +#include <stdlib.h> // cf. qsort(),fabs() + +// ring +#include <ring.h> // cf. statis.h + +// statis +#include <bitmsk.h> // cf. statis.h +#define _STATIS +#include <statis.h> +#undef _STATIS + +/***************************************************************************** + * classe Mediane_item * + *****************************************************************************/ + +/***************************************************************************** + *****************************************************************************/ +procedure Mediane_item::raz( void ) +{ + valeur = FLOAT_ERREUR; + indice = 0; +} + +/***************************************************************************** + *****************************************************************************/ +Mediane_item::Mediane_item( void ) +{ + raz(); +} + +/***************************************************************************** + * fonction utilitaire de qsort(),donc pas membre de classe * + * si a < b retourne -1 * + * si a = b 0 * + * si a > b 1 * + *****************************************************************************/ +static int compare( const void *a,const void *b ) +{ + register double c = ((Mediane_item *)a)->valeur - ((Mediane_item *)b)->valeur; + + return( ( c == 0.0 ) ? 0 : ( ( c > 0.0 ) ? 1 : -1 ) ); +} + +/***************************************************************************** + * classe Mediane * + *****************************************************************************/ + +/***************************************************************************** + * n_elem est forcement impair (protege par Statis_data::mediane()) * + *****************************************************************************/ +Mediane_item &Mediane::mediane( Mediane_item list[],int n_elem ) +{ + switch( n_elem ) { + case 1 : return( list[ 0 ] ); + default : qsort( (Mediane_item *)list,n_elem,sizeof( list[ 0 ] ),compare ); + return( list[ ( n_elem - 1 ) / 2 ] ); + } +} + +/***************************************************************************** + * classe Mediane_circ * + *****************************************************************************/ + +/***************************************************************************** + * n_elem est forcement impair (protege par Statis_data::mediane()) * + *****************************************************************************/ +Mediane_item &Mediane_circ::mediane( Mediane_item list[],int n_elem ) +{ + int delta_nord, + delta_sud, + borne_25, + borne_75; + Mediane_item *result; + + if( n_elem == 1 ) return( list[ 0 ] ); + qsort( (Mediane_item *)list,n_elem,sizeof( list[ 0 ] ),compare ); + borne_25 = n_elem / 4; // 25% + borne_75 = 3 * n_elem / 4; // 75% + delta_nord = int( list[ borne_75 ].valeur - list[ borne_25 ].valeur ); + delta_sud = abs( delta_nord - (int)(int)maxi ); + if( delta_sud < delta_nord ) { // si plus de 50% de valeurs dans + for( unsigned i = 0; i < n_elem; i++ ) // le nord, on change de repere + if( list[ i ].valeur > moitie && list[ i ].valeur < maxi ) // 180/360 + list[ i ].valeur -= maxi; // -180/180 + qsort( (Mediane_item *)list,n_elem,sizeof( list[ 0 ] ),compare ); + } + result = &list[ ( n_elem - 1 ) / 2 ]; + if( result->valeur < 0 ) result->valeur += maxi; + return( *result ); +} + +/***************************************************************************** + *****************************************************************************/ +Mediane_circ::Mediane_circ( double a_maxi ) +{ + moitie = ( maxi = fabs( a_maxi ) ) / 2; +} + +/***************************************************************************** + * classe Statis_data * + *****************************************************************************/ + +/***************************************************************************** + *****************************************************************************/ +booleen Statis_data::verifie( double &val ) +{ + if( ( borne_inf == borne_sup ) || ( val >= borne_inf && val <= borne_sup ) ) + return( TRUE ); + val = FLOAT_ERREUR; + return( FALSE ); +} + +/***************************************************************************** + *****************************************************************************/ +Mediane_item *Statis_data::cons_liste( void ) +{ + for( unsigned i = 0; i < n_elem; i++ ) { + mediane_liste[ i ].indice = i; + mediane_liste[ i ].valeur = ring.list[ i ]; + } + return( mediane_liste ); +} + +/***************************************************************************** + *****************************************************************************/ +booleen Statis_data::mediane( void ) +{ + if( !mediane_methode || n_elem == 0 ) { + med.raz(); + return( FALSE ); + } + med = mediane_methode->mediane( cons_liste(), + ( n_elem % 2 == 0 ) ? n_elem - 1 : n_elem ); + return( verifie( med.valeur ) ); +} + +/***************************************************************************** + *****************************************************************************/ +booleen Statis_data::moyenne( void ) +{ + if( n_elem == 0 ) { + moy = FLOAT_ERREUR; + return( FALSE ); + } + moy = 0; + for( unsigned i = 0; i < n_elem; moy += ring.list[ i++ ] ); + moy /= (double) n_elem; + return( verifie( moy ) ); +} + +/***************************************************************************** + *****************************************************************************/ +booleen Statis_data::ecart_type( void ) +{ + double somme_xi_carre = 0.0, + somme_xi = 0.0, + x_bar = 0.0; + double *ptxi; + unsigned i; + + switch( n_elem ) { + case 0 : + case 1 : + case 2 : ecart = FLOAT_ERREUR; + return( FALSE ); + default : for( i = 0,ptxi = ring.list; i < n_elem; + i++,ptxi++ ) { + somme_xi += *ptxi; + somme_xi_carre += *ptxi * *ptxi; + } + x_bar = somme_xi / (double) n_elem; + ecart = sqrt( fabs( somme_xi_carre / (double) n_elem - + x_bar * x_bar ) ); + return( TRUE ); + } +} + +/***************************************************************************** + *****************************************************************************/ +procedure Statis_data::calcule( void ) +{ + DPRINTF( ("Statis::calcule:stat_on=%u,calculs=%x\n",stat_on,calculs) ); + if( stat_on ) { + n_elem = ring.store(); + DPRINTF( ("n_elem=%u.",n_elem) ); + if( calculs & STAT_MED ) mediane(); + if( calculs & STAT_MOYENNE ) { + moyenne(); + if( calculs & STAT_ECART_TYPE ) ecart_type(); + } + } + else { + ecart = 0; + moy = + med.valeur = ( n_elem > 0 ) ? instant : FLOAT_ERREUR; + med.indice = 0; + } + DPRINTF( ("med=%5.4g,moy=%5.4g,instant=%5.4g\n", + med.valeur,moy,instant) ); + n_elem = 0; +} + +/***************************************************************************** + *****************************************************************************/ +double Statis_data::put( double val ) +{ + instant = val; + if( stat_on ) ring.put( instant ); + else n_elem = 1; + return( instant ); +} + +/***************************************************************************** + *****************************************************************************/ +Statis_data::Statis_data( BITMSK calc,unsigned taille, + double b_inf /*= 0*/,double b_sup /*= 0*/ ) + : ring( taille ), + med() +{ + moy = + ecart = + instant = FLOAT_ERREUR; + borne_inf = b_inf; + borne_sup = b_sup; + n_elem = 0; + if( stat_on = ( taille > 1 ) ) { +// init_ring_d( &ring,taille ); + if( mediane_methode = ( ( calculs = calc ) & STAT_MED_NORM ) + ? new Mediane + : ( calc & STAT_MED_CIRC ) ? new Mediane_circ( b_sup ) + : NULL ) + mediane_liste = new Mediane_item[ taille ]; + else + mediane_liste = NULL; + } + else { + mediane_methode = NULL; + mediane_liste = NULL; + } +} + +/***************************************************************************** + *****************************************************************************/ +Statis_data::~Statis_data() +{ + if( stat_on ) { +// term_ring_d( &ring ); + if( mediane_methode ) delete mediane_methode; + if( mediane_liste ) delete [] mediane_liste; + } +}