|
Hormiga 1.0
|
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 }