/******************************************************* * * DESCRIPTION: Uniform and Non-uniform quantizers classes * * AUTHOR: Mariana C. D'Abreu * * EMAIL: mdabreu@dc.uba.ar * ********************************************************/ #include "quantizer.h" #include "strutil.h" #include "misc.h" #include "except.h" /******************************************************************* * Function Name: ********************************************************************/ Quantizer *Quantizer::create( const string &method ) { string qmethod = lowerCase( method ); if ( qmethod == UNIFORM_METHOD ) { return new UniformQuantizer(); } else if ( qmethod == INTERVALS_METHOD ) { return new IntervalsQuantizer(); } throw MException( "Invalid method: " + method ); } /******************************************************************* * Function Name: ********************************************************************/ bool Quantizer::validMethod( const string &method ) { string qmethod = lowerCase( method ); return ( ( method == UNIFORM_METHOD ) || ( qmethod == INTERVALS_METHOD ) ); } /******************************************************************* * Function Name: ********************************************************************/ string Quantizer::validMethodsAsString() { string methods; methods = UNIFORM_METHOD + string( ", " ) + INTERVALS_METHOD; return methods; } /******************************************************************* * Function Name: ********************************************************************/ string UniformQuantizer::getParam( const int n ) const { switch (n) { case 1: return "quantum"; case 2: return "upperSatValue"; case 3: return "lowerSatValue"; default: throw MException( "Invalid parameter: " + n ); } } /******************************************************************* * Function Name: ********************************************************************/ Quantizer &UniformQuantizer::setQuantum( const RealValue &value ) { if ( value <= 0 ) { throw MException( string( "Invalid quantum: " ) + Value2StrReal( value ) ); } quantum = value; return *this; } /******************************************************************* * Function Name: ********************************************************************/ Quantizer &UniformQuantizer::setParam( const int n, const string &value ) { if ( !isFloat( value ) ) { throw MException( "Parameter \'" + value + "\' not numeric!" ); } RealValue fvalue = atof( value.data() ); switch (n) { case 1: quantum = fvalue; if ( quantum <= 0 ) { throw MException( string( "Invalid quantum: " ) + value ); } break; case 2: upperSatValue = fvalue; break; case 3: lowerSatValue = fvalue; break; default: throw MException( "Invalid parameter: " + n ); } return *this; } /******************************************************************* * Function Name: ********************************************************************/ RealValue UniformQuantizer::quantize( const RealValue &dvalue ) { if ( quantum == 0 ) { throw MException( string( "Invalid quantum: " ) + quantum ); } if ( upperSatValue < lowerSatValue ) { throw MException( string( "Invalid saturation values: [" ) + lowerSatValue + "," + upperSatValue + "]" ); } RealValue value = dvalue / quantum; //RealValue lvalue = (long long)( ceil( value / precision() ) * precision() ); RealValue lvalue = floor( ( floor( value / precision() ) * precision() ) ); lvalue = lvalue * quantum; if ( lvalue < lowerSatValue ) { return lowerSatValue; } else if ( lvalue > upperSatValue ) { return upperSatValue; } return lvalue; } /****************************************************************** * Function Name: ********************************************************************/ void UniformQuantizer::printInfo ( ostream &out ) const { out << endl; out << "Quantum : " << quantum << endl; out << "UpperSatValue : " << upperSatValue << endl; out << "LowerSatValue : " << lowerSatValue << endl; } /*******************************************************************/ /*******************************************************************/ const int IntervalsQuantizer::MAX_INTERVALS = 256; const char IntervalsQuantizer::INTERVAL_SEPARATOR = ','; /******************************************************************* * Function Name: ********************************************************************/ string IntervalsQuantizer::getParam( const int n ) const { if ( n != 0 ) { throw MException( "Invalid parameter: " + n ); } return "intervals"; } /******************************************************************* * Function Name: ********************************************************************/ Quantizer &IntervalsQuantizer::setParam( const int n, const string &value ) { if ( n != 0 ) { throw MException( "Invalid parameter: " + n ); } initIntervals( value ); return *this; } /******************************************************************* * Function Name: ********************************************************************/ RealValue IntervalsQuantizer::quantize( const RealValue &value ) { assert( intervals ); if ( value < intervals[0] ) { return intervals[0]; } else if ( value > intervals[number-1] ) { return intervals[number-1]; } return findInterval( value ); } /****************************************************************** * Function Name: ********************************************************************/ void IntervalsQuantizer::printInfo ( ostream &out ) const { assert( intervals ); char *sep = ","; out << endl << "Intervals:" << endl; out << "["; for ( int i=0; i < number; i++ ) { if ( i == number - 1 ) { sep = ""; } char ss[256]; sprintf( ss, "%f%s", intervals[i], sep ); out << ss; } out << "]" << endl; } /******************************************************************* * Function Name: ********************************************************************/ bool IntervalsQuantizer::initIntervals( const string &value ) { intervals = new RealValue[MAX_INTERVALS]; assert( intervals ); // obtengo el array de intervalos number = getFloatN( value, intervals, MAX_INTERVALS, INTERVAL_SEPARATOR ); if ( number == 0 ) { throw MException( "Invalid intervals: " + value ); } // verifico la condicion di-1 < di (orden) for ( int i=1; i < number; i++ ) { if ( intervals[i-1] >= intervals[i] ) { throw MException( "Invalid intervals. Condition di-1 < di not verified!" ); } } return true; } /******************************************************************* * Function Name: findInterval ********************************************************************/ const RealValue &IntervalsQuantizer::findInterval( const RealValue &value ) { assert( intervals ); long a, b, index; a = 0; b = number-1; index = (a+b)/2; while ( ( b - a > 1 ) && ( intervals[index] != value ) ) { if ( intervals[index] < value ) { a = index; } else { b = index; } index = (a+b)/2; } if ( b - a <= 1 ) { return ( intervals[b] < value ? intervals[b] : intervals[a] ); } return intervals[index]; }