/*****************************************convol_fun*********************************************************/ BaseGDL* convol_fun( EnvT* e) { SizeT nParam=e->NParam( 2); /************************************Checking_parameters************************************************/ BaseGDL* p0 = e->GetNumericParDefined( 0); if( p0->Rank() == 0) e->Throw( "Expression must be an array in this context: "+ e->GetParString(0)); BaseGDL* p1 = e->GetNumericParDefined( 1); if( p1->Rank() == 0) e->Throw( "Expression must be an array in this context: "+ e->GetParString(1)); if( p0->N_Elements() < p1->N_Elements()) e->Throw( "Incompatible dimensions for Array and Kernel."); // rank 1 for kernel works always if( p1->Rank() != 1) { SizeT rank = p0->Rank(); if( rank != p1->Rank()) e->Throw( "Incompatible dimensions for Array and Kernel."); for( SizeT r=0; r<rank; ++r) if( p0->Dim( r) < p1->Dim( r)) e->Throw( "Incompatible dimensions for Array and Kernel."); } /***************************************Preparing_matrices*************************************************/ // convert kernel to array type Guard<BaseGDL> p1Guard; if( p0->Type() == GDL_BYTE) { if( p1->Type() != GDL_INT) { p1 = p1->Convert2( GDL_INT, BaseGDL::COPY); p1Guard.Reset( p1); } } else if( p0->Type() != p1->Type()) { p1 = p1->Convert2( p0->Type(), BaseGDL::COPY); p1Guard.Reset( p1); } BaseGDL* scale; Guard<BaseGDL> scaleGuard; if( nParam > 2) { scale = e->GetParDefined( 2); if( scale->Rank() > 0) e->Throw( "Expression must be a scalar in this context: "+ e->GetParString(2)); // p1 here handles GDL_BYTE case also if( p1->Type() != scale->Type()) { scale = scale->Convert2( p1->Type(),BaseGDL::COPY); scaleGuard.Reset( scale); } } else { scale = p1->New( dimension(), BaseGDL::ZERO); } /********************************************Arguments_treatement***********************************/ bool center = true; static int centerIx = e->KeywordIx( "CENTER"); if( e->KeywordPresent( centerIx)) { DLong c; e->AssureLongScalarKW( centerIx, c); center = (c != 0); } // overrides EDGE_TRUNCATE static int edge_wrapIx = e->KeywordIx( "EDGE_WRAP"); bool edge_wrap = e->KeywordSet( edge_wrapIx); static int edge_truncateIx = e->KeywordIx( "EDGE_TRUNCATE"); bool edge_truncate = e->KeywordSet( edge_truncateIx); static int edge_zeroIx = e->KeywordIx( "EDGE_ZERO"); bool edge_zero = e->KeywordSet( edge_zeroIx); int edgeMode = 0; if( edge_wrap) edgeMode = 1; else if( edge_truncate) edgeMode = 2; else if( edge_zero) edgeMode = 3; // p0, p1 and scale have same type // p1 has rank of 1 or same rank as p0 with each dimension smaller than p0 // scale is a scalar /***********************************Parameter_BIAS**************************************/ static int biasIx = e->KeywordIx("BIAS"); bool statusBias = e->KeywordPresent( biasIx ); // DLong bias=0; BaseGDL* bias; if(statusBias) { bias=e->GetKW( biasIx); if( p0->Type() != bias->Type()) { bias = bias->Convert2( p0->Type(), BaseGDL::COPY); } } else bias=p1->New( 1,BaseGDL::ZERO); /***********************************Parameter_Normalize**********************************/ static int normalIx = e->KeywordIx( "NORMALIZE"); bool normalize = e->KeywordPresent( normalIx); /***********************************Parameter NAN****************************************/ static int nanIx = e->KeywordIx( "NAN"); bool doNan = e->KeywordPresent( nanIx); /***********************************Parameter MISSING************************************/ static int missingIx = e->KeywordIx("MISSING"); bool doMissing = e->KeywordPresent( missingIx ); BaseGDL* missing; if (p0->Type() != GDL_BYTE) { if (doMissing) { missing = e->GetKW(missingIx); if (p0->Type() != missing->Type()) { missing = missing->Convert2(p0->Type(), BaseGDL::COPY); } } else missing = p1->New(1, BaseGDL::ZERO); } else { if (doMissing) { missing = e->GetKW(missingIx); } else missing = p1->New(1, BaseGDL::ZERO); missing = missing->Convert2(GDL_LONG, BaseGDL::COPY); } /***********************************Parameter INVALID************************************/ static int invalidIx = e->KeywordIx("INVALID"); bool doInvalid = e->KeywordPresent( invalidIx ); BaseGDL* invalid; if (p0->Type() != GDL_BYTE) { if (doInvalid) { invalid = e->GetKW(invalidIx); if (p0->Type() != invalid->Type()) { invalid = invalid->Convert2(p0->Type(), BaseGDL::COPY); } } else invalid = p1->New(1, BaseGDL::ZERO); } else { if (doInvalid) { invalid = e->GetKW(invalidIx); } else invalid = p1->New(1, BaseGDL::ZERO); invalid = invalid->Convert2(GDL_LONG, BaseGDL::COPY); } if (!doNan && !doInvalid) doMissing=false; if (!doMissing && (p0->Type()==GDL_FLOAT ||p0->Type()==GDL_COMPLEX)) missing = SysVar::Values()->GetTag(SysVar::Values()->Desc()->TagIndex("F_NAN"), 0); if (!doMissing && (p0->Type()==GDL_DOUBLE ||p0->Type()==GDL_COMPLEXDBL)) missing = SysVar::Values()->GetTag(SysVar::Values()->Desc()->TagIndex("D_NAN"), 0); return p0->Convol( p1, scale, bias, center, normalize, edgeMode, doNan, missing, doMissing, invalid,doInvalid); } //end of convol_fun
// execute one line of code (commands and statements) DInterpreter::CommandCode DInterpreter::ExecuteLine( istream* in, SizeT lineOffset) { string line = (in != NULL) ? ::GetLine(in) : GetLine(); // cout << "ExecuteLine: " << line << endl; string firstChar = line.substr(0,1); // command if( firstChar == ".") { return ExecuteCommand( line.substr(1)); } // online help (if possible, start a browser) if( firstChar == "?") { // later, we will have to check whether we have X11/Display or not // on some computing nodes on supercomputers, this is de-activated. if (line.substr(1).length() > 0) { line=line.substr(1); StrTrim(line); line="online_help, '"+line+"'"; //' } else { line="online_help"; } } // shell command if( firstChar == "#") { if (line.substr(1).length() > 0) { line=line.substr(1); StrTrim(line); line=StrUpCase(line); //cout << "yes ! >>"<<StrUpCase(line)<<"<<" << endl; SizeT nProFun; int nbFound=0; // looking in internal procedures nProFun=libProList.size(); for( SizeT i = 0; i<nProFun; ++i) { if (line.compare(libProList[ i]->Name()) == 0) { cout << "Internal PROCEDURE : " << libProList[ i]->ToString() << endl; nbFound++; break; } } // looking in internal functions nProFun = libFunList.size(); for( SizeT i = 0; i<nProFun; ++i) { if (line.compare(libFunList[ i]->Name()) == 0) { cout << "Internal FUNCTION : " << libFunList[ i]->ToString() << endl; nbFound++; break; } } // looking in compiled functions nProFun = funList.size(); for( SizeT i = 0; i<nProFun; ++i) { if (line.compare(funList[ i]->Name()) == 0) { cout << "Compiled FUNCTION : " << funList[ i]->ToString() << endl; nbFound++; break; } } // looking in compiled procedures nProFun = proList.size(); for( SizeT i = 0; i<nProFun; ++i) { if (line.compare(proList[ i]->Name()) == 0) { cout << "Compiled PROCEDURE : " << proList[ i]->ToString() << endl; nbFound++; break; } } if (nbFound == 0) { cout << "No Procedure/Function, internal or compiled, with name : "<< line << endl; } } else { cout << "Please provide a pro/fun name !" << endl; } return CC_OK; } // shell command if( firstChar == "$") { ExecuteShellCommand( line.substr(1)); return CC_OK; } // include (only when at $MAIN$) // during compilation this is handled by the interpreter if( firstChar == "@" && callStack.size() <= 1) { string fileRaw = line.substr(1); StrTrim( fileRaw); string file = fileRaw; AppendExtension( file); bool found = CompleteFileName( file); if( !found) { file = fileRaw; CompleteFileName( file); } ExecuteFile( file); return CC_OK; } // statement -> execute it executeLine.clear(); // clear EOF (for executeLine) executeLine.str( line + "\n"); // append new line RefDNode theAST; try { Guard<GDLLexer> lexer; // LineContinuation LC // conactenate the strings and insert \n // the resulting string can be fed to the lexer // print if expr parse ok int lCNum = 0; for(;;) { lexer.Reset( new GDLLexer(executeLine, "", callStack.back()->CompileOpt())); try { // works, but ugly -> depends from parser detecting an error // (which it always will due to missing END_U token in case of LC) //lexer->Parser().SetCompileOpt(callStack.back()->CompileOpt()); lexer.Get()->Parser().interactive(); break; // no error -> everything ok } catch( GDLException& e) { int lCNew = lexer.Get()->LineContinuation(); if( lCNew == lCNum) // throw; // no LC -> real error { #ifdef AUTO_PRINT_EXPR #ifndef GDL_DEBUG try { // executeLine.clear(); // clear EOF (for executeLine) // lexer.reset( new GDLLexer(executeLine, "", callStack.back()->CompileOpt())); // lexer->Parser().expr(); executeLine.clear(); // clear EOF (for executeLine) executeLine.str( "print," + executeLine.str()); // append new line lexer.reset( new GDLLexer(executeLine, "", callStack.back()->CompileOpt())); lexer->Parser().interactive(); break; // no error -> everything ok } catch( GDLException& e2) #endif #endif { throw e; } } lCNum = lCNew; // save number to see if next line also has LC } // line continuation -> get next line if( in != NULL && !in->good()) throw GDLException( "End of file encountered during line continuation."); string cLine = (in != NULL) ? ::GetLine(in) : GetLine(); executeLine.clear(); // clear EOF (for executeLine) executeLine.str( executeLine.str() + cLine + "\n"); // append new line } // lexer->Parser().interactive(); theAST = lexer.Get()->Parser().getAST(); } catch( GDLException& e) { ReportCompileError( e); return CC_OK; } catch( ANTLRException& e) { cerr << "Lexer/Parser exception: " << e.getMessage() << endl; return CC_OK; } if( theAST == NULL) return CC_OK; // consider line offset if( lineOffset > 0) AddLineOffset( lineOffset, theAST); #ifdef GDL_DEBUG antlr::print_tree pt; cout << "Parser output:" << endl; pt.pr_tree(static_cast<antlr::RefAST>(theAST)); cout << "ExecuteLine: Parser end." << endl; #endif ProgNodeP progAST = NULL; RefDNode trAST; assert( dynamic_cast<EnvUDT*>(callStack.back()) != NULL); EnvUDT* env = static_cast<EnvUDT*>(callStack.back()); int nForLoopsIn = env->NForLoops(); try { GDLTreeParser treeParser( callStack.back()); treeParser.interactive(theAST); trAST=treeParser.getAST(); if( trAST == NULL) { // normal condition for cmd line procedure calls return CC_OK; } #ifdef GDL_DEBUG cout << "Tree parser output (RefDNode):" << endl; pt.pr_tree(static_cast<antlr::RefAST>(trAST)); cout << "ExecuteLine: Tree parser end." << endl; #endif // ************************************** // this is the call of the ProgNode factory // ************************************** progAST = ProgNode::NewProgNode( trAST); assert( dynamic_cast<EnvUDT*>(callStack.back()) != NULL); EnvUDT* env = static_cast<EnvUDT*>(callStack.back()); int nForLoops = ProgNode::NumberForLoops( progAST, nForLoopsIn); env->ResizeForLoops( nForLoops); } catch( GDLException& e) { env->ResizeForLoops( nForLoopsIn); ReportCompileError( e); return CC_OK; } catch( ANTLRException& e) { env->ResizeForLoops( nForLoopsIn); cerr << "Compiler exception: " << e.getMessage() << endl; return CC_OK; } Guard< ProgNode> progAST_guard( progAST); try { #ifdef GDL_DEBUG cout << "Converted tree (ProgNode):" << endl; pt.pr_tree( progAST); cout << "end." << endl; #endif RetCode retCode = interactive( progAST); env->ResizeForLoops( nForLoopsIn); // write to journal file string actualLine = GetClearActualLine(); if( actualLine != "") lib::write_journal( actualLine); if( retCode == RC_RETURN) return CC_RETURN; return CC_OK; } catch( GDLException& e) { env->ResizeForLoops( nForLoopsIn); cerr << "Unhandled GDL exception: " << e.toString() << endl; return CC_OK; } catch( ANTLRException& e) { env->ResizeForLoops( nForLoopsIn); cerr << "Interpreter exception: " << e.getMessage() << endl; return CC_OK; } return CC_OK; }
BaseGDL* _GDL_OBJECT_OverloadBracketsRightSide( EnvUDT* e) { // // debug/check // std::cout << "_GDL_OBJECT_OverloadBracketsRightSide called" << std::endl; SizeT nParam = e->NParam(); // number of parameters actually given // int envSize = e->EnvSize(); // number of parameters + keywords 'e' (pro) has defined if( nParam < 3) // consider implicit SELF ThrowFromInternalUDSub( e, "At least 2 parameters are needed: ISRANGE, SUB1 [, ...]."); // default behavior: Exact like scalar indexing BaseGDL* isRange = e->GetKW(1); if( isRange == NULL) ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) is undefined."); if( isRange->Rank() == 0) ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) must be an array in this context: " + e->Caller()->GetString(e->GetKW(1))); SizeT nIsRange = isRange->N_Elements(); if( nIsRange > (nParam - 2)) //- SELF and ISRANGE ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) must have "+i2s(nParam-2)+" elements."); Guard<DLongGDL> isRangeLongGuard; DLongGDL* isRangeLong; if( isRange->Type() == GDL_LONG) isRangeLong = static_cast<DLongGDL*>( isRange); else { try{ isRangeLong = static_cast<DLongGDL*>( isRange->Convert2( GDL_LONG, BaseGDL::COPY)); } catch( GDLException& ex) { ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); } isRangeLongGuard.Reset( isRangeLong); } ArrayIndexVectorT ixList; // IxExprListT exprList; try { for( int p=0; p<nIsRange; ++p) { BaseGDL* parX = e->GetKW( p + 2); // implicit SELF, ISRANGE, par1..par8 if( parX == NULL) ThrowFromInternalUDSub( e, "Parameter is undefined: " + e->Caller()->GetString(e->GetKW( p + 2))); DLong isRangeX = (*isRangeLong)[p]; if( isRangeX != 0 && isRangeX != 1) { ThrowFromInternalUDSub( e, "Value of parameter 1 (ISRANGE["+i2s(p)+"]) is out of allowed range."); } if( isRangeX == 1) { if( parX->N_Elements() != 3) { ThrowFromInternalUDSub( e, "Range vector must have 3 elements: " + e->Caller()->GetString(e->GetKW( p + 2))); } DLongGDL* parXLong; Guard<DLongGDL> parXLongGuard; if( parX->Type() != GDL_LONG) { try{ parXLong = static_cast<DLongGDL*>( parX->Convert2( GDL_LONG, BaseGDL::COPY)); parXLongGuard.Reset( parXLong); } catch( GDLException& ex) { ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); } } else { parXLong = static_cast<DLongGDL*>( parX); } // negative end ix is fine -> CArrayIndexRangeS can handle [b:*:s] ([b,-1,s]) ixList.push_back(new CArrayIndexRangeS( (*parXLong)[0], (*parXLong)[1], (*parXLong)[2])); } else // non-range { // ATTENTION: These two grab c1 (all others don't) // a bit unclean, but for maximum efficiency if( parX->Rank() == 0) ixList.push_back( new CArrayIndexScalar( parX->Dup())); else ixList.push_back( new CArrayIndexIndexed( parX->Dup())); } } // for } catch( GDLException& ex) { ixList.Destruct(); // ixList is not valid afterwards, but as we throw this is ok throw ex; } ArrayIndexListT* aL; MakeArrayIndex( &ixList, &aL, NULL); // important to get the non-NoAssoc ArrayIndexListT // because only they clean up ixList on destruction Guard< ArrayIndexListT> aLGuard( aL); IxExprListT ixL; return aL->Index( e->GetKW( 0), ixL); // index SELF }
bool handle_args(EnvT* e) { //T3D? static int t3dIx = e->KeywordIx( "T3D"); doT3d=(e->KeywordSet(t3dIx)|| T3Denabled()); //note: Z (VALUE) will be used uniquely if Z is not effectively defined. static int zvIx = e->KeywordIx( "ZVALUE"); zValue=0.0; e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); zValue=min(zValue,0.999999); //to avoid problems with plplot zValue=max(zValue,0.0); // system variable !P.NSUM first DLong nsum=(*static_cast<DLongGDL*>(SysVar::P()-> GetTag(SysVar::P()->Desc()->TagIndex("NSUM"), 0)))[0]; static int NSUMIx = e->KeywordIx( "NSUM"); e->AssureLongScalarKWIfPresent( NSUMIx, nsum); static int polarIx = e->KeywordIx( "POLAR"); bool polar = (e->KeywordSet(polarIx)); // DDoubleGDL *yValBis, *xValBis; // Guard<BaseGDL> xvalBis_guard, yvalBis_guard; //test and transform eventually if POLAR and/or NSUM! if( nParam() == 1) { yTemp = e->GetParAs< DDoubleGDL>( 0); if (yTemp->Rank() == 0) e->Throw("Expression must be an array in this context: "+e->GetParString(0)); yEl=yTemp->N_Elements(); xEl=yEl; xTemp = new DDoubleGDL( dimension( xEl), BaseGDL::INDGEN); xtemp_guard.Reset( xTemp); // delete upon exit } else { xTemp = e->GetParAs< DDoubleGDL>( 0); if (xTemp->Rank() == 0) e->Throw("Expression must be an array in this context: "+e->GetParString(0)); xEl=xTemp->N_Elements(); yTemp = e->GetParAs< DDoubleGDL>( 1); if (yTemp->Rank() == 0) e->Throw("Expression must be an array in this context: "+e->GetParString(1)); yEl=yTemp->N_Elements(); //silently drop unmatched values if (yEl != xEl) { SizeT size; size = min(xEl, yEl); xEl = size; yEl = size; } } //check nsum validity nsum=max(1,nsum); nsum=min(nsum,(DLong)xEl); if (nsum == 1) { if (polar) { xVal = new DDoubleGDL(dimension(xEl), BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit yVal = new DDoubleGDL(dimension(yEl), BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit for (int i = 0; i < xEl; i++) (*xVal)[i] = (*xTemp)[i] * cos((*yTemp)[i]); for (int i = 0; i < yEl; i++) (*yVal)[i] = (*xTemp)[i] * sin((*yTemp)[i]); } else { //careful about previously set autopointers! if (nParam() == 1) xval_guard.Init( xtemp_guard.release()); xVal = xTemp; yVal = yTemp; } } else { int i, j, k; DLong size = (DLong)xEl / nsum; xVal = new DDoubleGDL(size, BaseGDL::ZERO); //SHOULD BE ZERO, IS NOT! xval_guard.Reset(xVal); // delete upon exit yVal = new DDoubleGDL(size, BaseGDL::ZERO); //IDEM yval_guard.Reset(yVal); // delete upon exit for (i = 0, k = 0; i < size; i++) { (*xVal)[i] = 0.0; (*yVal)[i] = 0.0; for (j = 0; j < nsum; j++, k++) { (*xVal)[i] += (*xTemp)[k]; (*yVal)[i] += (*yTemp)[k]; } } for (i = 0; i < size; i++) (*xVal)[i] /= nsum; for (i = 0; i < size; i++) (*yVal)[i] /= nsum; if (polar) { DDouble x, y; for (i = 0; i < size; i++) { x = (*xVal)[i] * cos((*yVal)[i]); y = (*xVal)[i] * sin((*yVal)[i]); (*xVal)[i] = x; (*yVal)[i] = y; } } } return false; }