00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #ifndef fb_freq_INCLUDED
00090 #define fb_freq_INCLUDED
00091
00092 #include "defs.h"
00093 #ifndef ERRORS_INCLUDED
00094 #include "errors.h"
00095 #endif
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 enum FB_FREQ_TYPE {
00109 FB_FREQ_TYPE_EXACT = 1,
00110 FB_FREQ_TYPE_GUESS = 0,
00111 FB_FREQ_TYPE_UNKNOWN = -1,
00112 FB_FREQ_TYPE_UNINIT = -2,
00113 FB_FREQ_TYPE_ERROR = -3
00114 };
00115
00116 #define FB_FREQ_TYPE_COMBINE( type1, type2 ) \
00117 ( (type1) > (type2) ? (type2) : (type1) )
00118 #define FB_FREQ_TYPE_BETTER( type1, type2 ) ( (type1) > (type2) )
00119
00120 #define FB_FREQ_TYPE_IS_EXACT( type ) ( (type) > 0 )
00121 #define FB_FREQ_TYPE_IS_GUESS( type ) ( (type) == 0 )
00122 #define FB_FREQ_TYPE_IS_KNOWN( type ) ( (type) >= 0 )
00123 #define FB_FREQ_TYPE_NOT_KNOWN( type ) ( (type) < 0 )
00124 #define FB_FREQ_TYPE_INITIALIZED( type ) ( (type) >= FB_FREQ_TYPE_UNKNOWN )
00125
00126 #define FB_FREQ_TYPE_IS_VALID( type ) \
00127 ( (type) >= FB_FREQ_TYPE_ERROR && (type) <= FB_FREQ_TYPE_EXACT )
00128
00129
00130
00131
00132
00133
00134
00135
00136 const float FB_FREQ_EPSILON = 0.0001;
00137
00138 class FB_FREQ {
00139 private:
00140
00141 FB_FREQ_TYPE _type;
00142 float _value;
00143
00144
00145
00146
00147
00148
00149
00150 FB_FREQ( FB_FREQ_TYPE type, float value )
00151 : _type( type ), _value( value ) { }
00152
00153 public:
00154
00155
00156
00157 FB_FREQ()
00158 : _type( FB_FREQ_TYPE_UNINIT ),
00159 _value( (float) FB_FREQ_TYPE_UNINIT ) {}
00160
00161 FB_FREQ( float value, bool exact )
00162 : _type( exact ? FB_FREQ_TYPE_EXACT : FB_FREQ_TYPE_GUESS ),
00163 _value( value )
00164 { Is_True( value >= 0.0, ( "FB_FREQ: negative value %f", value ) ); }
00165
00166 FB_FREQ( INT64 value )
00167 : _type( FB_FREQ_TYPE_EXACT ),
00168 _value( (float) value )
00169 { Is_True( value >= 0, ( "FB_FREQ: negative value %lld", value ) ); }
00170
00171 FB_FREQ( FB_FREQ_TYPE type )
00172 : _type( type ),
00173 _value( type >= 0 ? 0.0 : (float) type ) {
00174 Is_True( FB_FREQ_TYPE_IS_VALID( type ),
00175 ( "FB_FREQ: invalid type %d", type ) );
00176 }
00177
00178
00179
00180 float Value() const { return _value; }
00181
00182
00183
00184 bool Known() const { return FB_FREQ_TYPE_IS_KNOWN( _type ); }
00185 bool Guess() const { return FB_FREQ_TYPE_IS_GUESS( _type ); }
00186 bool Exact() const { return FB_FREQ_TYPE_IS_EXACT( _type ); }
00187 bool Uninitialized() const { return ( _type == FB_FREQ_TYPE_UNINIT ); }
00188 bool Initialized() const { return FB_FREQ_TYPE_INITIALIZED( _type ); }
00189 bool Error() const { return ( _type == FB_FREQ_TYPE_ERROR ); }
00190 bool Zero() const { return ( _value < FB_FREQ_EPSILON &&
00191 _value > - FB_FREQ_EPSILON ); }
00192
00193 bool Better( const FB_FREQ freq ) const {
00194 return FB_FREQ_TYPE_BETTER( _type, freq._type );
00195 }
00196
00197
00198
00199 FB_FREQ operator+= ( const FB_FREQ freq ) {
00200 _type = FB_FREQ_TYPE_COMBINE( _type, freq._type );
00201 if ( FB_FREQ_TYPE_NOT_KNOWN( _type ) )
00202 _value = (float) _type;
00203 else
00204 _value += freq._value;
00205 return *this;
00206 }
00207
00208 FB_FREQ operator-= ( const FB_FREQ freq ) {
00209 _type = FB_FREQ_TYPE_COMBINE( _type, freq._type );
00210 if ( FB_FREQ_TYPE_NOT_KNOWN( _type ) )
00211 _value = (float) _type;
00212 else {
00213 _value -= freq._value;
00214 if ( _value < 0 )
00215 if ( - _value < FB_FREQ_EPSILON
00216 || - _value < FB_FREQ_EPSILON * freq._value )
00217 _value = 0;
00218 else {
00219 DevWarn( "FB_FREQ: subtraction of larger from smaller value" );
00220 _type = FB_FREQ_TYPE_ERROR;
00221 _value = (float) _type;
00222 }
00223 }
00224 return *this;
00225 }
00226
00227 FB_FREQ operator*= ( const FB_FREQ freq ) {
00228 if ( Zero() && Exact() )
00229 ;
00230 else if ( freq.Zero() && freq.Exact() ) {
00231 _type = FB_FREQ_TYPE_EXACT;
00232 _value = 0.0;
00233 } else {
00234 _type = FB_FREQ_TYPE_COMBINE( _type, freq._type );
00235 if ( FB_FREQ_TYPE_NOT_KNOWN( _type ) )
00236 _value = (float) _type;
00237 else
00238 _value *= freq._value;
00239 }
00240 return *this;
00241 }
00242
00243
00244 FB_FREQ operator*= ( const float scale ) {
00245 Is_True ( scale >= 0.0, ( "FB_FREQ: negative scale %f", scale ) );
00246 return ( *this *= FB_FREQ( FB_FREQ_TYPE_GUESS, scale ) );
00247 }
00248
00249
00250
00251 FB_FREQ operator/= ( const FB_FREQ freq ) {
00252 if ( Zero() && Exact() )
00253 ;
00254 else if ( freq.Zero() ) {
00255 DevWarn("FB_FREQ: division by zero");
00256 _type = FB_FREQ_TYPE_ERROR;
00257 _value = (float) _type;
00258 } else {
00259 _type = FB_FREQ_TYPE_COMBINE( _type, freq._type );
00260 if ( FB_FREQ_TYPE_NOT_KNOWN( _type ) )
00261 _value = (float) _type;
00262 else {
00263 if ( _value != freq._value )
00264 _type = FB_FREQ_TYPE_COMBINE( _type, FB_FREQ_TYPE_GUESS );
00265 _value /= freq._value;
00266 }
00267 }
00268 return *this;
00269 }
00270
00271
00272 FB_FREQ operator/= ( const float scale ) {
00273 Is_True ( scale >= 0.0, ( "FB_FREQ: negative scale %f", scale ) );
00274 return ( *this /= FB_FREQ( FB_FREQ_TYPE_GUESS, scale ) );
00275 }
00276
00277
00278
00279 friend FB_FREQ operator+ ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00280 FB_FREQ_TYPE type = FB_FREQ_TYPE_COMBINE( freq1._type, freq2._type );
00281 if ( FB_FREQ_TYPE_NOT_KNOWN( type ) )
00282 return FB_FREQ( type );
00283 return FB_FREQ( type, freq1._value + freq2._value );
00284 }
00285
00286 friend FB_FREQ operator- ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00287 FB_FREQ_TYPE type = FB_FREQ_TYPE_COMBINE( freq1._type, freq2._type );
00288 if ( FB_FREQ_TYPE_NOT_KNOWN( type ) )
00289 return FB_FREQ( type );
00290 float value = freq1._value - freq2._value;
00291 if ( value >= 0 )
00292 return FB_FREQ( type, value );
00293 if ( - value < FB_FREQ_EPSILON
00294 || - value < freq2._value * FB_FREQ_EPSILON )
00295 return FB_FREQ( type, 0 );
00296 DevWarn( "FB_FREQ: subtraction of larger from smaller value" );
00297 return FB_FREQ( FB_FREQ_TYPE_ERROR );
00298 }
00299
00300 friend FB_FREQ operator* ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00301 if ( ( freq1.Zero() && freq1.Exact() ) ||
00302 ( freq2.Zero() && freq2.Exact() ) )
00303 return FB_FREQ( FB_FREQ_TYPE_EXACT, 0.0 );
00304 FB_FREQ_TYPE type = FB_FREQ_TYPE_COMBINE( freq1._type, freq2._type );
00305 if ( FB_FREQ_TYPE_NOT_KNOWN( type ) )
00306 return FB_FREQ( type );
00307 return FB_FREQ( type, freq1._value * freq2._value );
00308 }
00309
00310
00311 friend FB_FREQ operator* ( const FB_FREQ freq, const float scale ) {
00312 Is_True ( scale >= 0.0, ( "FB_FREQ: negative scale %f", scale ) );
00313 return ( freq * FB_FREQ( FB_FREQ_TYPE_GUESS, scale ) );
00314 }
00315
00316
00317
00318 friend FB_FREQ operator/ ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00319 if ( freq1.Zero() && freq1.Exact() )
00320 return FB_FREQ( FB_FREQ_TYPE_EXACT, 0.0 );
00321 if ( freq2.Zero() ) {
00322 DevWarn("FB_FREQ: division by zero");
00323 return FB_FREQ( FB_FREQ_TYPE_ERROR );
00324 }
00325 FB_FREQ_TYPE type = FB_FREQ_TYPE_COMBINE( freq1._type, freq2._type );
00326 if ( FB_FREQ_TYPE_NOT_KNOWN( type ) )
00327 return FB_FREQ( type );
00328 if ( freq1._value != freq2._value )
00329 type = FB_FREQ_TYPE_COMBINE( type, FB_FREQ_TYPE_GUESS );
00330 float value = freq1._value / freq2._value;
00331 return FB_FREQ( type, value );
00332 }
00333
00334
00335 friend FB_FREQ operator/ ( const FB_FREQ freq, float scale ) {
00336 Is_True ( scale >= 0.0, ( "FB_FREQ: negative scale %f", scale ) );
00337 return ( freq / FB_FREQ( FB_FREQ_TYPE_GUESS, scale ) );
00338 }
00339
00340 friend bool operator== ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00341 if ( freq1._value > freq2._value )
00342 return ( freq1._value < FB_FREQ_EPSILON
00343 || freq1._value * ( 1 - FB_FREQ_EPSILON ) < freq2._value );
00344 else if ( freq1._value < freq2._value )
00345 return ( freq2._value < FB_FREQ_EPSILON
00346 || freq2._value * ( 1 - FB_FREQ_EPSILON ) < freq1._value );
00347 else return true;
00348 }
00349
00350 friend bool operator!= ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00351 if ( freq1._value > freq2._value )
00352 return ( freq1._value >= FB_FREQ_EPSILON
00353 && freq1._value * ( 1 - FB_FREQ_EPSILON ) >= freq2._value );
00354 else if ( freq1._value < freq2._value )
00355 return ( freq2._value >= FB_FREQ_EPSILON
00356 && freq2._value * ( 1 - FB_FREQ_EPSILON ) >= freq1._value );
00357 else return false;
00358 }
00359
00360 friend bool operator> ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00361 return ( freq1._value > freq2._value );
00362 }
00363
00364 friend bool operator< ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00365 return ( freq1._value < freq2._value );
00366 }
00367
00368 friend bool operator<= ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00369 return ( (freq1._value < freq2._value) || (freq1 == freq2) );
00370 }
00371
00372
00373
00374 void Print( FILE *fp ) const {
00375 switch ( _type ) {
00376 case FB_FREQ_TYPE_EXACT:
00377 fprintf( fp, "%g!", _value );
00378 break;
00379 case FB_FREQ_TYPE_GUESS:
00380 fprintf( fp, "%g?", _value );
00381 break;
00382 case FB_FREQ_TYPE_UNKNOWN:
00383 fprintf( fp, "unknown" );
00384 break;
00385 case FB_FREQ_TYPE_UNINIT:
00386 fprintf( fp, "uninitialized" );
00387 break;
00388 case FB_FREQ_TYPE_ERROR:
00389 fprintf( fp, "error" );
00390 break;
00391 default:
00392 Is_True( FALSE, ("FB_FREQ: Unexpected type %d", _type ));
00393 break;
00394 }
00395 }
00396
00397 INT Sprintf( char *buffer ) const {
00398 INT length = 0;
00399 switch ( _type ) {
00400 case FB_FREQ_TYPE_EXACT:
00401 length = sprintf( buffer, "%g!", _value );
00402 break;
00403 case FB_FREQ_TYPE_GUESS:
00404 length = sprintf( buffer, "%g?", _value );
00405 break;
00406 case FB_FREQ_TYPE_UNKNOWN:
00407 length = sprintf( buffer, "unknown" );
00408 break;
00409 case FB_FREQ_TYPE_UNINIT:
00410 length = sprintf( buffer, "uninitialized" );
00411 break;
00412 case FB_FREQ_TYPE_ERROR:
00413 length = sprintf( buffer, "error" );
00414 break;
00415 default:
00416 Is_True( FALSE, ("FB_FREQ: Unexpected type %d", _type ));
00417 break;
00418 }
00419 return length;
00420 }
00421 };
00422
00423
00424
00425
00426
00427 const FB_FREQ FB_FREQ_ZERO( 0.0, true );
00428 const FB_FREQ FB_FREQ_UNKNOWN( FB_FREQ_TYPE_UNKNOWN );
00429 const FB_FREQ FB_FREQ_UNINIT( FB_FREQ_TYPE_UNINIT );
00430 const FB_FREQ FB_FREQ_ERROR( FB_FREQ_TYPE_ERROR );
00431
00432
00433
00434 #endif //#ifndef fb_freq_INCLUDED