Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/Combinator.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2010 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include "Combinator.h"
00020 #include "../common_source.h"
00021 #include <algorithm>
00022 
00023 using std::ostringstream;
00024 using std::min;
00025 using std::max;
00026 
00027 using namespace Marsyas;
00028 
00029 const mrs_string Combinator::combinatorStrings[kNumCombinators] =
00030 {
00031   "+",
00032   "*",
00033   "max",
00034   "min"
00035 };
00036 
00037 Combinator::Combinators_t Combinator::GetCombinatorIdx (const mrs_string ctrlString)
00038 {
00039   Combinators_t ret = kAdd; // default
00040 
00041   for (mrs_natural i = 0; i < kNumCombinators; i++)
00042   {
00043     if (ctrlString == combinatorStrings[i])
00044       return (Combinators_t)i;
00045   }
00046 
00047   return ret;
00048 }
00049 
00050 Combinator::Combinator(mrs_string name) : MarSystem("Combinator", name)
00051 {
00053   // Default controls that all MarSystems should have (like "inSamples"
00054   // and "onObservations"), are already added by MarSystem::addControl(),
00055   // which is already called by the constructor MarSystem::MarSystem(name).
00056   // If no specific controls are needed by a MarSystem there is no need to
00057   // implement and call this addControl() method (see for e.g. Rms.cpp)
00058   addControls();
00059 }
00060 
00061 Combinator::Combinator(const Combinator& a) : MarSystem(a)
00062 {
00063   // IMPORTANT!
00066   // Otherwise this would result in trying to deallocate them twice!
00067   ctrl_combinator_ = getctrl("mrs_string/combinator");
00068   ctrl_weights_ = getctrl("mrs_realvec/weights");
00069   ctrl_numInputs_ = getctrl("mrs_natural/numInputs");
00070 }
00071 
00072 
00073 Combinator::~Combinator()
00074 {
00075 }
00076 
00077 MarSystem*
00078 Combinator::clone() const
00079 {
00080   // Every MarSystem should do this.
00081   return new Combinator(*this);
00082 }
00083 
00084 void
00085 Combinator::addControls()
00086 {
00087   mrs_realvec tmp(1);
00088   tmp(0)    = 1;
00089 
00090   addctrl("mrs_string/combinator", "+", ctrl_combinator_);
00091   addctrl("mrs_realvec/weights", tmp, ctrl_weights_);
00092   addctrl("mrs_natural/numInputs", 1, ctrl_numInputs_);
00093 
00094   setctrlState("mrs_natural/numInputs", true);
00095 }
00096 
00097 void
00098 Combinator::myUpdate(MarControlPtr sender)
00099 {
00100   MRSDIAG("Combinator.cpp - Combinator:myUpdate");
00101 
00103   MarSystem::myUpdate(sender);
00104 
00105   //if (ctrl_inObservations_->to<mrs_natural>() % ctrl_numInputs_->to<mrs_natural>())
00106   //    MRSWARN("Combinator: dimension mismatch");
00107   if (ctrl_numInputs_->to<mrs_natural>())
00108     updControl ("mrs_natural/onObservations", ctrl_inObservations_->to<mrs_natural>() / ctrl_numInputs_->to<mrs_natural>());
00109   else
00110     updControl ("mrs_natural/onObservations", 0);
00111 
00112 }
00113 
00114 void
00115 Combinator::myProcess(realvec& in, realvec& out)
00116 {
00117   mrs_natural k,i,j;
00118   mrs_real weight       = 1;
00119   mrs_bool useWeights = false;
00120 
00121   const Combinators_t       combi       = GetCombinatorIdx (ctrl_combinator_->to<mrs_string>());
00122   const mrs_natural     numInputs   = ctrl_numInputs_->to<mrs_natural>();
00123 
00124   // initialize output buffer
00125   if(combi == kAdd)
00126     out.setval(0); //identity operator
00127   if(combi == kMult)
00128     out.setval(1); //identity operator
00129   if(combi == kMax)
00130     out.setval(-1.0*MAXREAL);
00131   if(combi == kMin)
00132     out.setval(MAXREAL);
00133 
00134   // sanity check
00135   if ((inObservations_%numInputs) != 0)
00136   {
00137     MRSWARN("Combinator: dimension mismatch");
00138     MRSASSERT(false);
00139     out.setval(0);
00140     return;
00141   }
00142 
00143   if (ctrl_weights_->to<mrs_realvec>().getSize () == numInputs)
00144     useWeights  = true;
00145 
00147   for (k = 0; k < numInputs; k++)
00148   {
00149     weight  = (useWeights) ? (ctrl_weights_->to<mrs_realvec>())(k) : weight;
00150 
00151     for (i = 0; i < onObservations_; i++)
00152     {
00153       // do the col-loop inside the switch to avoid calling the switch for every entry
00154       // we might also do this with function pointers...
00155       switch (combi)
00156       {
00157       case kAdd:
00158       default:
00159       {
00160         for (j = 0; j < onSamples_; j++)
00161           out(i,j)  += weight * in(i+k*onObservations_,j);
00162         break;
00163       }
00164       case kMult:
00165       {
00166         if (weight == 1.0)   // avoid pow if possible
00167         {
00168           for (j = 0; j < onSamples_; j++)
00169             out(i,j)    *=  in(i+k*onObservations_,j);
00170         }
00171         else
00172         {
00173           for (j = 0; j < onSamples_; j++)
00174             out(i,j)    *=  pow (in(i+k*onObservations_,j), weight);
00175         }
00176         break;
00177       }
00178       case kMax:
00179       {
00180         for (j = 0; j < onSamples_; j++)
00181           out(i,j)  =  max (out(i,j),in(i+k*onObservations_,j));
00182         break;
00183       }
00184       case kMin:
00185       {
00186         for (j = 0; j < onSamples_; j++)
00187           out(i,j)  =  min (out(i,j),in(i+k*onObservations_,j));
00188         break;
00189       }
00190       }
00191     }
00192   }
00193 }