Hormiga 1.0

/var/www/hormigaproject.com.ar/files/src/function/function.cpp

Go to the documentation of this file.
00001 
00002 /*
00003 # Hormiga - Software de cálculo programable.
00004 #
00005 # Copyright (C) 2008, 2009 Leonardo Román, Hugo J. Curti, Norma  Ercoli,
00006 # Universidad Nacional del Centro de la Provincia de Buenos Aires
00007 # (UNCPBA)
00008 #
00009 # Este programa es parte de Hormiga.
00010 #
00011 # Hormiga es software libre. Puede redistribuirlo y/o modificarlo
00012 # bajo los términos de la Licencia Pública General de GNU según es
00013 # publicada por la Free Software Foundation, versión 2. Vea el archivo
00014 # COPIA (español, no oficial) o COPYING (inglés, oficial) en directorio
00015 # raíz.
00016 #
00017 # Hormiga se distribuye con la esperanza de que sea útil, pero SIN
00018 # NINGUNA GARANTÍA, incluso sin la garantía MERCANTIL implícita o sin
00019 # garantizar la CONVENIENCIA PARA UN PROPÓSITO PARTICULAR. Véase la
00020 # Licencia Pública General de GNU para más detalles.
00021 #
00022 # Debería haber recibido una copia de la Licencia Pública General junto
00023 # con Hormiga. Si no ha sido así, escriba a la Free Software
00024 # Foundation, Inc., en 675 Mass Ave, Cambridge, MA 02139, EEUU.
00025 # Añada también información sobre cómo contactar con usted mediante
00026 # correo electrónico y postal.
00027 #
00028 # This file is part of Hormiga.
00029 #
00030 # Hormiga is free software; you can redistribute it and/or modify
00031 # it under the terms of the GNU General Public License version 2
00032 # as published by the Free Software Foundation; see the file COPYING
00033 # in the top directory for details.
00034 #
00035 # Hormiga is distributed in the hope that it will be useful,
00036 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00037 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00038 # GNU General Public License for more details.
00039 #
00040 # You should have received a copy of the GNU General Public License
00041 # along with Hormiga; if not, write to the Free Software
00042 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
00043 # USA
00044 */
00045 
00046 #include "function.h"
00047 
00049 UserFunction::UserFunction( T_STRING &symbol , T_FUNCTION_ARGUMENTS *argv ,
00050                     VarValue* toRet , Statement *codeBlock )
00051         : Typeable ( toRet->getType () )
00052 {
00053     this->formalParams = argv ;
00054     this->code = codeBlock ;
00055     this->toRet = toRet ;
00056     this->name = symbol ;
00057 }
00058 
00059 T_MAGNITUDE UserFunction::eval( T_FUNCTION_ARGUMENTS *argv )
00060 {
00061     /* First. We need to setup arguments relationship */
00062     int lastArg = formalParams->count() ;
00063     for ( int i = 0 ; i < lastArg ; i++ )
00064     {
00065         VarValueProxy *fp = (VarValueProxy*) formalParams->at( i ) ;
00066         fp->setProxiedOperand( argv->at( i ) ) ;
00067     }
00068     toRet->setValue( 0.0 ) ;
00069     /* Ok ... now we are ready to run ! */
00070     this->code->exec() ;
00071     return toRet->getValue() ;
00072 }
00073 
00074 
00076 T_STRING FunctionInstance::toString () const
00077 {
00078     QString args = "" ;
00079     for ( int i = 0; i < this->argv->count() ; i++ )
00080     {
00081         if ( i != 0 )
00082             args += ", " ;
00083         args += this->argv->at( i )->toString() ;
00084     }
00085     return ( QString ("%1 ( %2 )")
00086              .arg ( this->f->getName() )
00087              .arg ( args ) ) ;
00088 }
00089 
00090 T_STRING FunctionInstance::getSymbol () const
00091 {
00092     return ( f->getName() ) ;
00093 }
00094 
00095 bool FunctionInstance::isConstantExpresion () const
00096 {
00097     return ( false ) ;
00098 }
00099 
00100 FunctionInstanceIterator* FunctionInstance::getIterator () const
00101 {
00102     return new FunctionInstanceIterator ( this->f , this->argv );
00103 }
00104 
00105 T_MAGNITUDE FunctionInstance::getValue () const
00106 {
00107     /* We need to known if you want to 'evaluate' or 'integrate' this function*/
00108     bool integrate = FALSE ;
00109     T_FUNCTION_ARGUMENTS internalArgs ;
00110     T_INT_ARRAY seqArgs ;
00111     for ( int i = 0; i < this->argv->count() ; i++ )
00112     {
00113         VarValueProxy *o = (VarValueProxy*) argv->at( i ) ;
00114         if ( o->getProxiedOperand()->isSequence() )
00115         {
00116             integrate = true ;
00117         /* Crear un arreglo auxiliar e ir cargandole cada uno de los 'parametros'.
00118            En caso de encontrar un 'sequence' reemplazarlo en el arr.aux por un
00119            VarValueProxy. Estos parametros reemplazados junto con las secuencias
00120            asociadas deben ademas agregarse en otro arreglo auxiliar el cual
00121            sera usado en un algoritmo recursivo que realizara la integracion.
00122            */
00123             seqArgs.append( i ) ;
00124             VarValueProxy *vp = new VarValueProxy("Seq Value" , NULL , false ) ;
00125             //vp->setValue( ((Sequence*) o->getProxiedOperand())->getFirst () ) ;
00126             internalArgs.append( vp ) ;
00127         }
00128         else
00129         {
00130             /* First... PRE-calc and cache parameters */
00131             o->resetInternalValue() ;
00132             o->setValue( o->getValue() ) ;
00133             internalArgs.append( o ) ;
00134         }
00135     }
00136     if ( integrate )
00137     {
00138         T_MAGNITUDE toRet = this->integrate( this->argv , &internalArgs ,
00139                                              &seqArgs , 0 ) ;
00140         for ( int i = seqArgs.count() - 1 ; i >= 0 ; i-- )
00141         {   /* delete only ValueProxys created before */
00142             delete internalArgs.takeAt( seqArgs.at( i ) ) ;
00143         }
00144         return ( toRet ) ;
00145     }
00146     else
00147         return ( this->eval( this->argv ) ) ;
00148 }
00149 
00150 T_MAGNITUDE FunctionInstance::integrate ( T_FUNCTION_ARGUMENTS *reals ,
00151                                           T_FUNCTION_ARGUMENTS *internals ,
00152                                           T_INT_ARRAY *seqArgs ,
00153                                           int actualArg ) const
00154 {
00155     int pn = seqArgs->at( actualArg ) ; /* Param Number */
00156     Sequence *s = (Sequence*)( (VarValueProxy*) reals->at( pn ) )
00157                                         ->getProxiedOperand() ;
00158     VarValueProxy *v = (VarValueProxy*) internals->at( pn ) ;
00159     T_MAGNITUDE total = 0 ;
00160     // Here we will cache the last result
00161     T_MAGNITUDE prev = 0 ;
00162     for ( T_MAGNITUDE i = s->getFirst() ; i <= s->getLast() ; i += s->getStep() )
00163     {
00164         v->setValue( i ) ;
00165         T_MAGNITUDE a = 0 ;
00166         if ( actualArg != ( seqArgs->count() - 1 ) )
00167         {
00168             a = integrate( reals, internals , seqArgs ,
00169                                        actualArg + 1 ) ;
00170         }
00171         else
00172         {
00173             a = this->eval ( internals ) ;
00174         }
00175         if ( i != s->getFirst() )
00176         {   // Interpolated result:
00177             total += ( a + prev ) * s->getStep() / 2 ;
00178         }
00179         prev = a ;
00180     }
00181     return ( total ) ;
00182 }
00183 
00184 T_MAGNITUDE FunctionInstance::eval ( T_FUNCTION_ARGUMENTS *argv ) const
00185 {
00186     return ( this->f->eval( argv ) ) ;
00187 }
00188 
00189 FunctionInstance::FunctionInstance ( Function *f , T_FUNCTION_ARGUMENTS *argv )
00190 {
00191     this->f = f ;
00192     this->argv = argv ;
00193 }
00194 
00195 FunctionInstance::~FunctionInstance ()
00196 {
00197     for ( int i = 0; i < this->argv->count() ; i++ )
00198     {
00199         Operand *o = this->argv->at( i ) ;
00200         if ( ! o->isShareable() )
00201             delete o ;
00202     }
00203     delete this->argv ;
00204 }
00205 
00206 
00208 const T_MAGNITUDE* FunctionInstanceIterator::first()
00209 {
00210     if ( this->seq != NULL ) {
00211         this->data[localDimension] = this->seq->getFirst() ;
00212         this->currVal->setValue( this->data[localDimension] ) ;
00213         if ( this->nextDimension != NULL ) this->nextDimension->first() ;
00214     }
00215     if ( this->localDimension == 0 ) // I'm the master ?
00216         this->data[dimensions] = this->f->eval( this->args ) ;
00217     return this->data ;
00218 }
00219 
00220 bool FunctionInstanceIterator::hasNext()
00221 {
00222     if ( this->seq == NULL ) return false ;
00223     if ( this->seq->getLast() >= ( this->data[localDimension] + this->seq->getStep() ) )
00224         return true ;
00225     if ( this->nextDimension != NULL )
00226         return this->nextDimension->hasNext() ;
00227     return false ;
00228 }
00229 
00230 const T_MAGNITUDE* FunctionInstanceIterator::next()
00231 {
00232     if ( (this->nextDimension != NULL) && (this->nextDimension->hasNext()) ) {
00233         this->nextDimension->next() ;
00234     } else if ( this->hasNext() ) {
00235         // Reset next dimensions and advance this one.
00236         if ( this->nextDimension != NULL ) this->nextDimension->first() ;
00237         this->data[localDimension] += this->seq->getStep() ;
00238     } else return NULL ;
00239     // Allways refresh the value of VarValue, in case the function has been modified it.
00240     this->currVal->setValue( this->data[localDimension] ) ;
00241     if ( this->localDimension == 0 ) // I'm the master ?
00242         this->data[this->dimensions] = f->eval( this->args ) ;
00243     return this->data ;
00244 }
00245 
00246 const T_MAGNITUDE* FunctionInstanceIterator::getCurrent()
00247 {
00248     return this->data ;
00249 }
00250 
00251 #include <math.h>
00252 int FunctionInstanceIterator::iterationsCount () const
00253 {
00254     int count = 0 ;
00255     if ( this->seq != NULL ) {
00256         for ( T_MAGNITUDE v = seq->getFirst() ; v <= seq->getLast() ; v+= seq->getStep() )
00257             count++ ;
00258     }
00259     if ( this->nextDimension != NULL )
00260         count *= this->nextDimension->iterationsCount() ;
00261     return count ;
00262 }
00263 
00264 FunctionInstanceIterator::FunctionInstanceIterator( Function *f , T_FUNCTION_ARGUMENTS* realArgs )
00265 {
00266     this->args = new T_FUNCTION_ARGUMENTS( *realArgs ) ;
00267     this->seq = NULL ;
00268     int dim = 0 ;   // dimensions count
00269     for ( int i = 0; (i < this->args->count()) && !this->seq  ; i++ )
00270     {
00271         VarValueProxy *o = (VarValueProxy*) this->args->at( i ) ;
00272         if ( o->getProxiedOperand()->isSequence() ) {
00273             dim++ ;
00274         } else {
00275             // Pre-calcular y cachear los valores de los paramentros que no sean secuencias
00276             o->resetInternalValue() ;
00277             o->setValue( o->getValue() ) ;
00278         }
00279     }
00280     this->data = new T_MAGNITUDE[dim+1] ;
00281     this->setup( f, this->args, this->data, dim, 0 ) ;
00282 }
00283 
00284 FunctionInstanceIterator::FunctionInstanceIterator( Function *f ,
00285                               T_FUNCTION_ARGUMENTS* internalArguments ,
00286                               T_MAGNITUDE* data ,
00287                               int dimensions ,
00288                               int currentDimension
00289                               )
00290 {
00291     this->setup( f, internalArguments, data, dimensions, currentDimension ) ;
00292 }
00293 
00294 void FunctionInstanceIterator::setup( Function *f ,
00295                               T_FUNCTION_ARGUMENTS* internalArguments ,
00296                               T_MAGNITUDE* data ,
00297                               int dimensions ,
00298                               int currentDimension
00299                               )
00300 {
00301     this->nextDimension = NULL ;
00302     this->f = f ;
00303     this->args = internalArguments ;
00304     this->data = data ;
00305     this->dimensions = dimensions ;
00306     this->localDimension = currentDimension ;
00307 
00308     this->seq = NULL ;
00309     for ( int i = 0; (i < internalArguments->count()) && !this->seq  ; i++ )
00310     {   /* Find for the first 'Sequence', own it, and replace it in the vector
00311            by a VarValue */
00312         VarValueProxy *o = (VarValueProxy*) internalArguments->at( i ) ;
00313         if ( o->getProxiedOperand()->isSequence() ) {
00314             this->seq = (Sequence*) o->getProxiedOperand() ;
00315             data[currentDimension] = this->seq->getFirst() ;
00316             this->currVal = new VarValue() ; //("Seq Value" , NULL , false ) ;
00317             this->currVal->setValue( data[currentDimension] ) ;
00318             internalArguments->replace( i , this->currVal ) ;
00319             break ;
00320         }
00321     }
00322     currentDimension++ ;
00323     if ( currentDimension < dimensions ) {
00324         this->nextDimension = new FunctionInstanceIterator( f , internalArguments ,
00325                                                             data , dimensions ,
00326                                                             currentDimension ) ;
00327     }
00328 }
00329 
00330 FunctionInstanceIterator::~FunctionInstanceIterator()
00331 {
00332     if ( this->nextDimension ) delete this->nextDimension ;
00333     // Only in the main Iterator:
00334     if ( this->localDimension == 0 ) {
00335         delete this->args ;
00336         delete[] this->data ;
00337     }
00338     if ( this->seq != NULL ) {
00339         delete this->currVal ;
00340     }
00341 }