This library provides the ability to compute the median, circular median, mean and standard deviation of a dataset stored in a circular buffer

Dependents:   Ni-MH_V3

Committer:
greletj
Date:
Tue May 28 17:50:55 2013 +0000
Revision:
6:df815bdada09
Parent:
3:27019c77bf90
add default in switch(mode) to suppress compiler warning: ; enumeration value 'SETF' not handled in switch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
greletj 1:a4c87bc5b008 1 /* Copyright (c) <2012> <copyright J. Grelet>, MIT License
greletj 1:a4c87bc5b008 2 *
greletj 2:809d085bf2cb 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
greletj 2:809d085bf2cb 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
greletj 2:809d085bf2cb 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
greletj 2:809d085bf2cb 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
greletj 1:a4c87bc5b008 7 * furnished to do so, subject to the following conditions:
greletj 1:a4c87bc5b008 8 *
greletj 2:809d085bf2cb 9 * The above copyright notice and this permission notice shall be included in all copies or
greletj 1:a4c87bc5b008 10 * substantial portions of the Software.
greletj 1:a4c87bc5b008 11 *
greletj 2:809d085bf2cb 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
greletj 2:809d085bf2cb 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
greletj 2:809d085bf2cb 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
greletj 2:809d085bf2cb 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
greletj 1:a4c87bc5b008 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
greletj 1:a4c87bc5b008 17 */
greletj 2:809d085bf2cb 18
greletj 2:809d085bf2cb 19 /*****************************************************************************
greletj 2:809d085bf2cb 20 * Statis.c *
greletj 2:809d085bf2cb 21 * *
greletj 2:809d085bf2cb 22 * Module de calcul statistique utilisees par le logiciel THERMO *
greletj 2:809d085bf2cb 23 * Ce module dans la version 1.0 calcule : la mediane *
greletj 2:809d085bf2cb 24 * la moyenne *
greletj 2:809d085bf2cb 25 * l'ecart type *
greletj 2:809d085bf2cb 26 * Les fonctions prennent toutes comme argumemts un tableau FAR list[] *
greletj 2:809d085bf2cb 27 * et les n_elem sur lequel est realise le calcul. *
greletj 2:809d085bf2cb 28 * *
greletj 2:809d085bf2cb 29 * Jacques Grelet Mars 1992 *
greletj 2:809d085bf2cb 30 * Bruno Buisson Aout 92 *
greletj 2:809d085bf2cb 31 * Septembre 1992 *
greletj 2:809d085bf2cb 32 * Septembre 1994 *
greletj 2:809d085bf2cb 33 * Adapted for mbed ARM cortex Novembre 2012 *
greletj 2:809d085bf2cb 34 *****************************************************************************/
greletj 0:b3a2e39a13ad 35 #define DEBUG
greletj 0:b3a2e39a13ad 36 #include "mbed.h"
greletj 0:b3a2e39a13ad 37 extern Serial pc;
greletj 0:b3a2e39a13ad 38
greletj 2:809d085bf2cb 39 #undef DEBUG
greletj 0:b3a2e39a13ad 40
greletj 0:b3a2e39a13ad 41 #include <debug.h>
greletj 0:b3a2e39a13ad 42 #include <math.h>
greletj 0:b3a2e39a13ad 43 #include <stdlib.h> // cf. qsort(),fabs()
greletj 0:b3a2e39a13ad 44
greletj 0:b3a2e39a13ad 45 // ring
greletj 0:b3a2e39a13ad 46 #include "ring.h" // cf. statis.h
greletj 0:b3a2e39a13ad 47
greletj 0:b3a2e39a13ad 48 // statis
greletj 0:b3a2e39a13ad 49
greletj 0:b3a2e39a13ad 50 #include "bitmsk.h" // cf. statis.h
greletj 0:b3a2e39a13ad 51 #define _STATIS
greletj 0:b3a2e39a13ad 52 #include "statis.h"
greletj 0:b3a2e39a13ad 53 #undef _STATIS
greletj 0:b3a2e39a13ad 54
greletj 0:b3a2e39a13ad 55 /*****************************************************************************
greletj 0:b3a2e39a13ad 56 * classe Mediane_item *
greletj 0:b3a2e39a13ad 57 *****************************************************************************/
greletj 0:b3a2e39a13ad 58
greletj 0:b3a2e39a13ad 59 /*****************************************************************************
greletj 0:b3a2e39a13ad 60 *****************************************************************************/
greletj 0:b3a2e39a13ad 61 void Mediane_item::raz( void )
greletj 0:b3a2e39a13ad 62 {
greletj 2:809d085bf2cb 63 valeur = FLOAT_ERREUR;
greletj 2:809d085bf2cb 64 indice = 0;
greletj 0:b3a2e39a13ad 65 }
greletj 0:b3a2e39a13ad 66
greletj 0:b3a2e39a13ad 67 /*****************************************************************************
greletj 0:b3a2e39a13ad 68 *****************************************************************************/
greletj 0:b3a2e39a13ad 69 Mediane_item::Mediane_item( void )
greletj 0:b3a2e39a13ad 70 {
greletj 2:809d085bf2cb 71 raz();
greletj 0:b3a2e39a13ad 72 }
greletj 0:b3a2e39a13ad 73
greletj 0:b3a2e39a13ad 74 /*****************************************************************************
greletj 0:b3a2e39a13ad 75 * fonction utilitaire de qsort(),donc pas membre de classe *
greletj 0:b3a2e39a13ad 76 * si a < b retourne -1 *
greletj 0:b3a2e39a13ad 77 * si a = b 0 *
greletj 0:b3a2e39a13ad 78 * si a > b 1 *
greletj 0:b3a2e39a13ad 79 *****************************************************************************/
greletj 0:b3a2e39a13ad 80 static int compare( const void *a,const void *b )
greletj 0:b3a2e39a13ad 81 {
greletj 2:809d085bf2cb 82 register float c = ((Mediane_item *)a)->valeur - ((Mediane_item *)b)->valeur;
greletj 0:b3a2e39a13ad 83
greletj 2:809d085bf2cb 84 return( ( c == 0.0 ) ? 0 : ( ( c > 0.0 ) ? 1 : -1 ) );
greletj 0:b3a2e39a13ad 85 }
greletj 0:b3a2e39a13ad 86
greletj 0:b3a2e39a13ad 87 /*****************************************************************************
greletj 0:b3a2e39a13ad 88 * classe Mediane *
greletj 0:b3a2e39a13ad 89 *****************************************************************************/
greletj 0:b3a2e39a13ad 90
greletj 0:b3a2e39a13ad 91 /*****************************************************************************
greletj 0:b3a2e39a13ad 92 * n_elem est forcement impair (protege par Statis_data::mediane()) *
greletj 0:b3a2e39a13ad 93 *****************************************************************************/
greletj 0:b3a2e39a13ad 94 Mediane_item &Mediane::mediane( Mediane_item list[],unsigned n_elem )
greletj 0:b3a2e39a13ad 95 {
greletj 2:809d085bf2cb 96 switch( n_elem ) {
greletj 2:809d085bf2cb 97 case 1 :
greletj 2:809d085bf2cb 98 return( list[ 0 ] );
greletj 2:809d085bf2cb 99 default :
greletj 2:809d085bf2cb 100 qsort( (Mediane_item *)list,n_elem,sizeof( list[ 0 ] ),compare );
greletj 2:809d085bf2cb 101 return( list[ ( n_elem - 1 ) / 2 ] );
greletj 2:809d085bf2cb 102 }
greletj 0:b3a2e39a13ad 103 }
greletj 0:b3a2e39a13ad 104
greletj 0:b3a2e39a13ad 105 /*****************************************************************************
greletj 0:b3a2e39a13ad 106 * classe Mediane_circ *
greletj 0:b3a2e39a13ad 107 *****************************************************************************/
greletj 0:b3a2e39a13ad 108
greletj 0:b3a2e39a13ad 109 /*****************************************************************************
greletj 0:b3a2e39a13ad 110 * n_elem est forcement impair (protege par Statis_data::mediane()) *
greletj 0:b3a2e39a13ad 111 *****************************************************************************/
greletj 0:b3a2e39a13ad 112 Mediane_item &Mediane_circ::mediane( Mediane_item list[],unsigned n_elem )
greletj 0:b3a2e39a13ad 113 {
greletj 2:809d085bf2cb 114 int delta_nord,
greletj 2:809d085bf2cb 115 delta_sud,
greletj 2:809d085bf2cb 116 borne_25,
greletj 2:809d085bf2cb 117 borne_75;
greletj 2:809d085bf2cb 118 Mediane_item *result;
greletj 0:b3a2e39a13ad 119
greletj 2:809d085bf2cb 120 if( n_elem == 1 ) return( list[ 0 ] );
greletj 2:809d085bf2cb 121 qsort( (Mediane_item *)list,n_elem,sizeof( list[ 0 ] ),compare );
greletj 2:809d085bf2cb 122 borne_25 = n_elem / 4; // 25%
greletj 2:809d085bf2cb 123 borne_75 = 3 * n_elem / 4; // 75%
greletj 2:809d085bf2cb 124 delta_nord = int( list[ borne_75 ].valeur - list[ borne_25 ].valeur );
greletj 2:809d085bf2cb 125 delta_sud = abs( delta_nord - (int)(int)maxi );
greletj 2:809d085bf2cb 126 if( delta_sud < delta_nord ) { // si plus de 50% de valeurs dans
greletj 2:809d085bf2cb 127 for( unsigned i = 0; i < n_elem; i++ ) // le nord, on change de repere
greletj 2:809d085bf2cb 128 if( list[ i ].valeur > moitie && list[ i ].valeur < maxi ) // 180/360
greletj 2:809d085bf2cb 129 list[ i ].valeur -= maxi; // -180/180
greletj 2:809d085bf2cb 130 qsort( (Mediane_item *)list,n_elem,sizeof( list[ 0 ] ),compare );
greletj 2:809d085bf2cb 131 }
greletj 2:809d085bf2cb 132 result = &list[ ( n_elem - 1 ) / 2 ];
greletj 2:809d085bf2cb 133 if( result->valeur < 0 ) result->valeur += maxi;
greletj 2:809d085bf2cb 134 return( *result );
greletj 0:b3a2e39a13ad 135 }
greletj 0:b3a2e39a13ad 136
greletj 0:b3a2e39a13ad 137 /*****************************************************************************
greletj 0:b3a2e39a13ad 138 *****************************************************************************/
greletj 0:b3a2e39a13ad 139 Mediane_circ::Mediane_circ( float a_maxi )
greletj 0:b3a2e39a13ad 140 {
greletj 2:809d085bf2cb 141 moitie = ( maxi = fabs( a_maxi ) ) / 2;
greletj 0:b3a2e39a13ad 142 }
greletj 0:b3a2e39a13ad 143
greletj 0:b3a2e39a13ad 144 /*****************************************************************************
greletj 0:b3a2e39a13ad 145 * classe Statis_data *
greletj 0:b3a2e39a13ad 146 *****************************************************************************/
greletj 0:b3a2e39a13ad 147
greletj 0:b3a2e39a13ad 148 /*****************************************************************************
greletj 0:b3a2e39a13ad 149 *****************************************************************************/
greletj 0:b3a2e39a13ad 150 bool Statis_data::verifie( float &val )
greletj 0:b3a2e39a13ad 151 {
greletj 2:809d085bf2cb 152 if( ( borne_inf == borne_sup ) || ( val >= borne_inf && val <= borne_sup ) )
greletj 2:809d085bf2cb 153 return( true );
greletj 2:809d085bf2cb 154 val = FLOAT_ERREUR;
greletj 2:809d085bf2cb 155 return( false );
greletj 0:b3a2e39a13ad 156 }
greletj 0:b3a2e39a13ad 157
greletj 0:b3a2e39a13ad 158 /*****************************************************************************
greletj 0:b3a2e39a13ad 159 *****************************************************************************/
greletj 0:b3a2e39a13ad 160 Mediane_item *Statis_data::cons_liste( void )
greletj 0:b3a2e39a13ad 161 {
greletj 2:809d085bf2cb 162 for( unsigned i = 0; i < n_elem; i++ ) {
greletj 2:809d085bf2cb 163 mediane_liste[ i ].indice = i;
greletj 2:809d085bf2cb 164 mediane_liste[ i ].valeur = ring.list[ i ];
greletj 2:809d085bf2cb 165 }
greletj 2:809d085bf2cb 166 return( mediane_liste );
greletj 0:b3a2e39a13ad 167 }
greletj 0:b3a2e39a13ad 168
greletj 0:b3a2e39a13ad 169 /*****************************************************************************
greletj 0:b3a2e39a13ad 170 *****************************************************************************/
greletj 0:b3a2e39a13ad 171 bool Statis_data::mediane( void )
greletj 0:b3a2e39a13ad 172 {
greletj 2:809d085bf2cb 173 if( !mediane_methode || n_elem == 0 ) {
greletj 2:809d085bf2cb 174 med.raz();
greletj 2:809d085bf2cb 175 return( false );
greletj 2:809d085bf2cb 176 }
greletj 2:809d085bf2cb 177 med = mediane_methode->mediane( cons_liste(),
greletj 2:809d085bf2cb 178 ( n_elem % 2 == 0 ) ? n_elem - 1 : n_elem );
greletj 2:809d085bf2cb 179 return( verifie( med.valeur ) );
greletj 0:b3a2e39a13ad 180 }
greletj 0:b3a2e39a13ad 181
greletj 0:b3a2e39a13ad 182 /*****************************************************************************
greletj 0:b3a2e39a13ad 183 *****************************************************************************/
greletj 0:b3a2e39a13ad 184 bool Statis_data::moyenne( void )
greletj 0:b3a2e39a13ad 185 {
greletj 2:809d085bf2cb 186 if( n_elem == 0 ) {
greletj 2:809d085bf2cb 187 moy = FLOAT_ERREUR;
greletj 2:809d085bf2cb 188 return( false );
greletj 2:809d085bf2cb 189 }
greletj 2:809d085bf2cb 190 moy = 0;
greletj 2:809d085bf2cb 191 for( unsigned i = 0; i < n_elem; moy += ring.list[ i++ ] );
greletj 2:809d085bf2cb 192 moy /= (float) n_elem;
greletj 2:809d085bf2cb 193 return( verifie( moy ) );
greletj 0:b3a2e39a13ad 194 }
greletj 0:b3a2e39a13ad 195
greletj 0:b3a2e39a13ad 196 /*****************************************************************************
greletj 0:b3a2e39a13ad 197 *****************************************************************************/
greletj 0:b3a2e39a13ad 198 bool Statis_data::ecart_type( void )
greletj 0:b3a2e39a13ad 199 {
greletj 2:809d085bf2cb 200 float somme_xi_carre = 0.0,
greletj 2:809d085bf2cb 201 somme_xi = 0.0,
greletj 2:809d085bf2cb 202 x_bar = 0.0;
greletj 2:809d085bf2cb 203 float *ptxi;
greletj 2:809d085bf2cb 204 unsigned i;
greletj 0:b3a2e39a13ad 205
greletj 2:809d085bf2cb 206 switch( n_elem ) {
greletj 2:809d085bf2cb 207 case 0 :
greletj 2:809d085bf2cb 208 case 1 :
greletj 2:809d085bf2cb 209 case 2 :
greletj 2:809d085bf2cb 210 ecart = FLOAT_ERREUR;
greletj 2:809d085bf2cb 211 return( false );
greletj 2:809d085bf2cb 212 default :
greletj 2:809d085bf2cb 213 for( i = 0,ptxi = ring.list; i < n_elem;
greletj 2:809d085bf2cb 214 i++,ptxi++ ) {
greletj 2:809d085bf2cb 215 somme_xi += *ptxi;
greletj 2:809d085bf2cb 216 somme_xi_carre += *ptxi * *ptxi;
greletj 2:809d085bf2cb 217 }
greletj 2:809d085bf2cb 218 x_bar = somme_xi / (float) n_elem;
greletj 2:809d085bf2cb 219 ecart = sqrt( fabs( somme_xi_carre / (float) n_elem -
greletj 2:809d085bf2cb 220 x_bar * x_bar ) );
greletj 2:809d085bf2cb 221 return( true );
greletj 2:809d085bf2cb 222 }
greletj 0:b3a2e39a13ad 223 }
greletj 0:b3a2e39a13ad 224
greletj 0:b3a2e39a13ad 225 /*****************************************************************************
greletj 0:b3a2e39a13ad 226 *****************************************************************************/
greletj 2:809d085bf2cb 227 unsigned Statis_data::calcule( void )
greletj 0:b3a2e39a13ad 228 {
greletj 2:809d085bf2cb 229 unsigned size = n_elem;
greletj 2:809d085bf2cb 230
greletj 2:809d085bf2cb 231 DPRINTF( ("\r\nStatis::calcule:stat_on=%u,calculs=%x\r\n",stat_on,calculs) );
greletj 2:809d085bf2cb 232 if( stat_on ) {
greletj 2:809d085bf2cb 233 n_elem = size = ring.store();
greletj 2:809d085bf2cb 234 DPRINTF( ("n_elem=%u. size=%u",n_elem, size) );
greletj 2:809d085bf2cb 235 if( calculs & STAT_MED ) mediane();
greletj 2:809d085bf2cb 236 if( calculs & STAT_MOYENNE ) {
greletj 2:809d085bf2cb 237 moyenne();
greletj 2:809d085bf2cb 238 if( calculs & STAT_ECART_TYPE ) ecart_type();
greletj 2:809d085bf2cb 239 }
greletj 2:809d085bf2cb 240 } else {
greletj 2:809d085bf2cb 241 ecart = 0;
greletj 2:809d085bf2cb 242 moy =
greletj 3:27019c77bf90 243 med.valeur = ( n_elem > 0 ) ? instant : FLOAT_ERREUR;
greletj 2:809d085bf2cb 244 med.indice = 0;
greletj 2:809d085bf2cb 245 }
greletj 2:809d085bf2cb 246 DPRINTF( ("med=%5.4g,moy=%5.4g,instant=%5.4g\r\n",
greletj 2:809d085bf2cb 247 med.valeur,moy,instant) );
greletj 2:809d085bf2cb 248 n_elem = 0;
greletj 2:809d085bf2cb 249 return size;
greletj 0:b3a2e39a13ad 250 }
greletj 0:b3a2e39a13ad 251
greletj 0:b3a2e39a13ad 252 /*****************************************************************************
greletj 0:b3a2e39a13ad 253 *****************************************************************************/
greletj 0:b3a2e39a13ad 254 float Statis_data::put( float val )
greletj 0:b3a2e39a13ad 255 {
greletj 2:809d085bf2cb 256 instant = val;
greletj 2:809d085bf2cb 257 if( stat_on ) ring.put( instant );
greletj 2:809d085bf2cb 258 else n_elem = 1;
greletj 2:809d085bf2cb 259 return( instant );
greletj 0:b3a2e39a13ad 260 }
greletj 0:b3a2e39a13ad 261
greletj 0:b3a2e39a13ad 262 /*****************************************************************************
greletj 0:b3a2e39a13ad 263 *****************************************************************************/
greletj 0:b3a2e39a13ad 264 Statis_data::Statis_data( BITMSK calc,unsigned taille,
greletj 0:b3a2e39a13ad 265 float b_inf /*= 0*/,float b_sup /*= 0*/ )
greletj 2:809d085bf2cb 266 : ring( taille ),
greletj 2:809d085bf2cb 267 med()
greletj 2:809d085bf2cb 268 {
greletj 3:27019c77bf90 269 moy = FLOAT_ERREUR;
greletj 3:27019c77bf90 270 ecart = FLOAT_ERREUR;
greletj 3:27019c77bf90 271 instant = FLOAT_ERREUR;
greletj 2:809d085bf2cb 272 borne_inf = b_inf;
greletj 2:809d085bf2cb 273 borne_sup = b_sup;
greletj 2:809d085bf2cb 274 n_elem = 0;
greletj 2:809d085bf2cb 275
greletj 2:809d085bf2cb 276 stat_on = taille > 1 ? true : false;
greletj 2:809d085bf2cb 277 if( stat_on ) {
greletj 0:b3a2e39a13ad 278 // init_ring_d( &ring,taille );
greletj 2:809d085bf2cb 279 mediane_methode = ( ( calculs = calc ) & STAT_MED_NORM )
greletj 2:809d085bf2cb 280 ? new Mediane
greletj 2:809d085bf2cb 281 : ( calc & STAT_MED_CIRC ) ? new Mediane_circ( b_sup )
greletj 2:809d085bf2cb 282 : NULL;
greletj 2:809d085bf2cb 283 if( mediane_methode )
greletj 2:809d085bf2cb 284 mediane_liste = new Mediane_item[ taille ];
greletj 2:809d085bf2cb 285 else
greletj 2:809d085bf2cb 286 mediane_liste = NULL;
greletj 2:809d085bf2cb 287 } else {
greletj 2:809d085bf2cb 288 mediane_methode = NULL;
greletj 2:809d085bf2cb 289 mediane_liste = NULL;
greletj 2:809d085bf2cb 290 }
greletj 0:b3a2e39a13ad 291 }
greletj 0:b3a2e39a13ad 292
greletj 0:b3a2e39a13ad 293 /*****************************************************************************
greletj 0:b3a2e39a13ad 294 *****************************************************************************/
greletj 0:b3a2e39a13ad 295 Statis_data::~Statis_data()
greletj 0:b3a2e39a13ad 296 {
greletj 2:809d085bf2cb 297 if( stat_on ) {
greletj 2:809d085bf2cb 298 if( mediane_methode ) delete mediane_methode;
greletj 2:809d085bf2cb 299 if( mediane_liste ) delete [] mediane_liste;
greletj 2:809d085bf2cb 300 }
greletj 0:b3a2e39a13ad 301 }