/*************************************************************************** mpsymbols.cpp ------------------- begin : Sun Nov 25 2001 copyright : (C) 2001 by Kamil email : kamil@localhost.localdomain ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include"mpsymbols.h" #include"mpdelunay.h" #include #include //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //bool MPCommonSymFactory::m_initialized = false; //QAsciiDict MPCommonSymFactory::m_list; //-------------------------------------------------------------------------// MPCommonSymFactory::MPCommonSymFactory() : MPSymbolFactory() { m_initialized = false; if ( !m_initialized ) { m_list.setAutoDelete( TRUE ); m_list.insert( "e", new item(CONST, MPSymConstant::E, QT_TR_NOOP(" e - base of the natural logarithm.") ) ); m_list.insert( "pi", new item(CONST, MPSymConstant::PI, QT_TR_NOOP(" pi - 3.141592..." ) ) ); m_list.insert( "floor", new item(FUNC1, MPSymFunction1::FLOOR, QT_TR_NOOP("floor(x) - rounds x downwards to the nearest integer.") ) ); m_list.insert( "ceil", new item(FUNC1, MPSymFunction1::CEIL, QT_TR_NOOP("ceil(x) - rounds x upwards to the nearest integer.") ) ); m_list.insert( "sign", new item(FUNC1, MPSymFunction1::SIGN, QT_TR_NOOP("sign(x) - returns -1 for x<0 and 1 for x>= 0.") ) ); m_list.insert( "abs", new item(FUNC1, MPSymFunction1::ABS, QT_TR_NOOP("abs(x) - returns the absolute value of x") ) ); m_list.insert( "sin", new item(FUNC1, MPSymFunction1::SIN, QT_TR_NOOP("sin(x) - returns the sine of x ( radians )") ) ); m_list.insert( "sinh", new item(FUNC1, MPSymFunction1::SINH, QT_TR_NOOP("sinh(x) - returns the hyperblic sine of x ( radians )") ) ); m_list.insert( "cos", new item(FUNC1, MPSymFunction1::COS, QT_TR_NOOP("cos(x) - returns the cosine of x ( radians )") ) ); m_list.insert( "cosh", new item(FUNC1, MPSymFunction1::COSH, QT_TR_NOOP("cosh(x) - returns the hyperbolic cosine of x ( radians )") ) ); m_list.insert( "tan", new item(FUNC1, MPSymFunction1::TAN, QT_TR_NOOP("tan(x) - returns the tangent of x ( radians ).") ) ); m_list.insert( "tanh", new item(FUNC1, MPSymFunction1::TANH, QT_TR_NOOP("tanh(x) - returns the hyperbolic tangent of x ( radians )") ) ); m_list.insert( "acos", new item(FUNC1, MPSymFunction1::ACOS, QT_TR_NOOP("acos(x) - returns the arc cosine of x for x=<-1,1>") ) ); m_list.insert( "acosh", new item(FUNC1, MPSymFunction1::ACOSH, QT_TR_NOOP("acosh(x) - returns the inverse hyperbolic cosine of x for x>=1") ) ); m_list.insert( "asin", new item(FUNC1, MPSymFunction1::ASIN, QT_TR_NOOP("asin(x) - returns the arc sine of x, x=<-1,1>") ) ); m_list.insert( "asinh", new item(FUNC1, MPSymFunction1::ASINH, QT_TR_NOOP("asinh(x) - returns the inverse hyperbolic sine of x") ) ); m_list.insert( "atan", new item(FUNC1, MPSymFunction1::ATAN, QT_TR_NOOP("atan(x) - returns the arc tangent of x. Result belongs to (-pi/2,pi/2>.") ) ); m_list.insert( "atanh", new item(FUNC1, MPSymFunction1::ATANH, QT_TR_NOOP("atanh(x) - returns the inverse hyperbolic tangent of x.") ) ); m_list.insert( "ln", new item(FUNC1, MPSymFunction1::LN, QT_TR_NOOP("ln(x) - returns the natural logarithm of x.") ) ); m_list.insert( "log10", new item(FUNC1, MPSymFunction1::LOG10, QT_TR_NOOP("log10(x) - returns the base-10 logarithm of x. ") ) ); m_list.insert( "log2", new item(FUNC1, MPSymFunction1::LOG2, QT_TR_NOOP("log2(x) - returns the base-2 logarithm of x.") ) ); m_list.insert( "sqrt", new item(FUNC1, MPSymFunction1::SQRT, QT_TR_NOOP("sqrt(x) - returns the square root of x for x >= 0..") ) ); m_list.insert( "mod", new item(FUNC2, MPSymFunction2::MOD, QT_TR_NOOP("mod(x,y) - returns remainder of dividing x by y.") ) ); m_list.insert( "min", new item(FUNC2, MPSymFunction2::MIN, QT_TR_NOOP("min(x,y) - returns the lower value of pair (x,y). ") ) ); m_list.insert( "max", new item(FUNC2, MPSymFunction2::MAX, QT_TR_NOOP("min(x,y) - returns the greater value of pair (x,y). ") ) ); m_list.insert( "log", new item(FUNC2, MPSymFunction2::LOG, QT_TR_NOOP("log(x,y) - returns the y-base logarithm of x. ") ) ); m_list.insert( "pow", new item(FUNC2, MPSymFunction2::POW, QT_TR_NOOP("pow(x,y) - raises x to the power y. ") ) ); m_list.insert( "atan2", new item(FUNC2, MPSymFunction2::ATAN2, QT_TR_NOOP("atan2(x,y) - returns the arc tangent of y/x. Result belongs to (-PI,PI>.") ) ); m_list.insert( "delunay", new item(DELUNAY, 0, QT_TR_NOOP("delunay(x,y) - performs a delunay triangulation of points in x, y column vectors.") ) ); m_initialized = true; } } //-------------------------------------------------------------------------// MPCommonSymFactory::~MPCommonSymFactory() { } //-------------------------------------------------------------------------// const char *MPCommonSymFactory::name() const { return QT_TR_NOOP("Built-in"); } //-------------------------------------------------------------------------// MPSymbol *MPCommonSymFactory::create( const char *identifier, MPSymbolList *args, int colFrom, int colTo ) { item *new_item = m_list[identifier]; if ( new_item ) switch( new_item->m_type ) { case CONST: return new MPSymConstant( (MPSymConstant::Constant )new_item->m_function, args, colFrom, colTo, identifier ); case FUNC1: return new MPSymFunction1( (MPSymFunction1::Function )new_item->m_function, args, colFrom, colTo, identifier ); case FUNC2: return new MPSymFunction2( (MPSymFunction2::Function )new_item->m_function, args, colFrom, colTo, identifier ); case DELUNAY: return new MPDelunay( args, colFrom, colTo, identifier ); } return NULL; } //-------------------------------------------------------------------------// int MPCommonSymFactory::symbolCount() const { return m_list.count(); } //-------------------------------------------------------------------------// const char *MPCommonSymFactory::symbolIdentifier( int symbolNumber ) { QAsciiDictIterator it(m_list); it += symbolNumber; return it.currentKey(); } //-------------------------------------------------------------------------// const char *MPCommonSymFactory::symbolDescription( int symbolNumber ) { QAsciiDictIterator it(m_list); it += symbolNumber; return it.current()->m_description; } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymValue::MPSymValue( double value, int columnFrom, int columnTo, const char *id ) : MPSymbol( NULL, columnFrom, columnTo, id ) { m_value = value; } //-------------------------------------------------------------------------// MPSymValue::~MPSymValue() { } //-------------------------------------------------------------------------// void MPSymValue::checkArgs( MPError& ) { m_rows = 1; m_cols = 1; } //-------------------------------------------------------------------------// double MPSymValue::value( int, int ) { return m_value; } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymColon::MPSymColon( int columnFrom, int columnTo, const char *id ) : MPSymbol( NULL, columnFrom, columnTo, id ) { m_rows = 0; m_cols = 0; } //-------------------------------------------------------------------------// double MPSymColon::value( int, int ) { return sqrt(-1); } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymColonExpr::MPSymColonExpr( MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { } //-------------------------------------------------------------------------// MPSymColonExpr::~MPSymColonExpr() { } //-------------------------------------------------------------------------// void MPSymColonExpr::checkArgs( MPError& error ) { for ( int i=0; icount(); i++ ) m_args->at(i)->checkArgs(error); MPSymbol::checkArgs( error ); if ( m_args->count() != 2 && m_args->count() != 3 ) { error.setWrongNumberOfArguments( m_args->count(), 3, this ); return; } for ( int i=0; icount(); i++ ) if ( !m_args->at(i)->isScalar() ) { error.setNonconformantArgument( i, m_args->at(i), this ); return; } if ( m_args->count() == 3 ) { m_start = m_args->at(0)->value( 0, 0 ); m_step = m_args->at(1)->value( 0, 0 ); m_stop = m_args->at(2)->value( 0, 0 ); } else if ( m_args->count() == 2 ) { m_start = m_args->at(0)->value( 0, 0 ); m_stop = m_args->at(1)->value( 0, 0 ); m_step = 1.0; } if ( m_step == 0.0 ) { error.setNonconformantArgument( 1, m_args->at(1), this ); return; } m_rows = 1; m_cols = QMAX( (int )floor( (m_stop-m_start)/m_step )+1, 0 ); } //-------------------------------------------------------------------------// double MPSymColonExpr::value( int, int col ) { return m_start + col * m_step; } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// const double MPSymConstant::pi = 3.1415926535897932385; const double MPSymConstant::e = 2.7182818284590452354; //-------------------------------------------------------------------------// MPSymConstant::MPSymConstant( Constant c, int columnFrom, int columnTo, const char *id ) : MPSymbol( NULL, columnFrom, columnTo, id ) { m_c = c; } //-------------------------------------------------------------------------// MPSymConstant::MPSymConstant( Constant c, MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { m_c = c; } //-------------------------------------------------------------------------// MPSymConstant::~MPSymConstant() { } //-------------------------------------------------------------------------// void MPSymConstant::checkArgs( MPError& ) { m_rows = 1; m_cols = 1; } //-------------------------------------------------------------------------// double MPSymConstant::value( int, int ) { switch( m_c ) { case E: return e; case PI: return pi; default: return sqrt(-1); } } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymFunction1::MPSymFunction1( Function f, MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { m_f = f; } //-------------------------------------------------------------------------// MPSymFunction1::~MPSymFunction1() { } //-------------------------------------------------------------------------// void MPSymFunction1::checkArgs( MPError& error ) { if ( m_args->count() != 1 ) error.setWrongNumberOfArguments( m_args->count(), 1, this ); MPSymbol::checkArgs( error ); } //-------------------------------------------------------------------------// double MPSymFunction1::value( int row, int col ) { double value = m_args->at(0)->value( row, col ); switch( m_f ) { case FLOOR: return floor( value ); case CEIL: return ceil( value ); case SIGN: return value >= 0 ? 1.0 : -1.0; // should return 0 for value == 0 ??? case ABS: return fabs(value); case COS: return cos(value); case COSH: return cosh(value); case SIN: return sin(value); case SINH: return sinh(value); case TAN: return tan(value); case TANH: return tanh(value); case ACOS: return acos(value); case ACOSH: return acosh(value); case ASIN: return asin(value); case ASINH: return asinh(value); case ATAN: return atan(value); case ATANH: return atanh(value); case LN: return log(value); case LOG2: return log10(value)/log10(2.0); case LOG10: return log10(value); case SQRT: return sqrt(value); case NEG: return -value; default: return sqrt(-1); }; } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymFunction2::MPSymFunction2( Function f, MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { m_f = f; } //-------------------------------------------------------------------------// MPSymFunction2::~MPSymFunction2() { } //-------------------------------------------------------------------------// void MPSymFunction2::checkArgs( MPError& error ) { if ( m_args->count() != 2 ) error.setWrongNumberOfArguments( m_args->count(), 2, this ); MPSymbol::checkArgs( error ); } //-------------------------------------------------------------------------// double MPSymFunction2::value( int row, int col ) { double val1 = m_args->at(0)->value(row,col); double val2 = m_args->at(1)->value(row,col); switch( m_f ) { case ADD: return val1+val2; case SUB: return val1-val2; case MUL: return val1*val2; case DIV: return val2 ? val1/val2 : sqrt(-1); case MOD: return fmod( val1, val2 ); case MIN: return min( val1, val2 ); case MAX: return max( val1, val2 ); case LOG: return log10(val1)/log10(val2); case POW: return pow( val1, val2 ); case ATAN2: return atan2( val1, val2 ); default: return sqrt(-1); } } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymMatrixIndexer::MPSymMatrixIndexer( MPSymbol *sym, MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { m_symbol = sym; } //-------------------------------------------------------------------------// MPSymMatrixIndexer::~MPSymMatrixIndexer() { delete m_symbol; } //-------------------------------------------------------------------------// void MPSymMatrixIndexer::checkArgs( MPError& error ) // a bit complicated { if ( m_args->count() != 2 ) { error.setWrongNumberOfArguments( m_args->count(), 2, this ); return; } m_symbol->checkArgs( error ); for( int i=0; icount(); i++ ) m_args->at(i)->checkArgs(error); if ( error.hasError() ) return; m_rows = index_size(m_args->at(0)) == 0 ? m_symbol->rows() : index_size(m_args->at(0)); m_cols = index_size(m_args->at(1)) == 0 ? m_symbol->cols() : index_size(m_args->at(1)); for ( int row=0; rowat(0),row) < 0 || index_value(m_args->at(0),row) >= m_symbol->rows() ) error.setError( QString(QT_TR_NOOP("Invalid row index value %1")).arg(index_value(m_args->at(0),row)), this ); for ( int col=0; colat(1),col) < 0 || index_value(m_args->at(1),col) >= m_symbol->cols() ) error.setError( QString(QT_TR_NOOP("Invalid column index value %1")).arg(index_value(m_args->at(1),col)), this ); } //-------------------------------------------------------------------------// double MPSymMatrixIndexer::value( int row, int col ) { return m_symbol->value( index_value(m_args->at(0),row), index_value(m_args->at(1),col) ); } //-------------------------------------------------------------------------// int MPSymMatrixIndexer::index_size( MPSymbol *index ) { return index->rows() * index->cols(); } //-------------------------------------------------------------------------// int MPSymMatrixIndexer::index_value( MPSymbol *index, int pos ) { return index->rows() == 0 ? pos : (int )floor( index->value(pos/index->cols(),pos%index->cols()) ); } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymVectorIndexer::MPSymVectorIndexer( MPSymbol *sym, MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { m_symbol = sym; } //-------------------------------------------------------------------------// MPSymVectorIndexer::~MPSymVectorIndexer() { delete m_symbol; } //-------------------------------------------------------------------------// void MPSymVectorIndexer::checkArgs( MPError& error ) // a bit complicated { if ( m_args->count() != 1 ) error.setWrongNumberOfArguments( m_args->count(), 1, this ); m_symbol->checkArgs( error ); m_args->at(0)->checkArgs(error); if ( m_symbol->rows() != 1 && m_symbol->cols() != 1 ) error.setError( QT_TR_NOOP("Single index only valid for vectors;"), this ); if ( error.hasError() ) return; // result will be a row vector if ( m_symbol->rows() == 1 ) { m_cols = index_size() == 0 ? m_symbol->cols() : index_size(); m_rows = 1; } else { // result will be a column vector m_rows = index_size() == 0 ? m_symbol->rows() : index_size(); m_cols = 1; } for( int index=0;index= m_symbol->rows()*m_symbol->cols() ) error.setError( QString(QT_TR_NOOP("Invalid index value %1")).arg(index_value(index)), this ); } //-------------------------------------------------------------------------// double MPSymVectorIndexer::value( int row, int col ) { int index = index_value(row*m_cols+col); return m_symbol->value( index/m_symbol->cols(), index%m_symbol->cols() ); } //-------------------------------------------------------------------------// int MPSymVectorIndexer::index_size() { return m_args->at(0)->rows() * m_args->at(0)->cols(); } //-------------------------------------------------------------------------// int MPSymVectorIndexer::index_value( int pos ) { MPSymbol *index = m_args->at(0); return index->rows() == 0 ? pos : (int )floor( index->value(pos/index->cols(),pos%index->cols()) ); } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymTranspose::MPSymTranspose( MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { } //-------------------------------------------------------------------------// MPSymTranspose::~MPSymTranspose() { } //-------------------------------------------------------------------------// void MPSymTranspose::checkArgs( MPError& error ) { if ( m_args->count() != 1 ) error.setWrongNumberOfArguments( m_args->count(), 1, this ); m_args->at(0)->checkArgs( error ); m_rows = m_args->at(0)->cols(); m_cols = m_args->at(0)->rows(); } //-------------------------------------------------------------------------// double MPSymTranspose::value( int row, int col ) { return m_args->at(0)->value( col, row ); } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymVector::MPSymVector( MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { m_vector = NULL; } //-------------------------------------------------------------------------// MPSymVector::~MPSymVector() { delete m_vector; } //-------------------------------------------------------------------------// void MPSymVector::checkArgs( MPError& error ) { delete m_vector; m_vector = NULL; MPSymbol::checkArgs( error ); m_rows = 1; m_cols = 0; if ( !error.hasError() ) for( int i=0; icount(); i++ ) { if ( m_args->at(i)->rows() != 1 ) { error.setNonconformantArgument( i, m_args->at(i), this ); break; } m_cols += m_args->at(i)->cols(); } int curr_col = 0; m_vector = new double[m_cols]; for( int i=0; icount(); i++ ) for( int col=0; colat(i)->cols(); col++ ) m_vector[curr_col++] = m_args->at(i)->value(0,col); } //-------------------------------------------------------------------------// double MPSymVector::value( int, int col ) { return m_vector[col]; } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// //-------------------------------------------------------------------------// MPSymMatrix::MPSymMatrix( MPSymbolList *args, int columnFrom, int columnTo, const char *id ) : MPSymbol( args, columnFrom, columnTo, id ) { } //-------------------------------------------------------------------------// MPSymMatrix::~MPSymMatrix() { } //-------------------------------------------------------------------------// void MPSymMatrix::checkArgs( MPError& error ) { MPSymbol::checkArgs( error ); if ( !error.hasError() ) { m_cols = m_args->at(0)->cols(); m_rows = m_args->count(); for( int i=0; icount(); i++ ) { if ( m_args->at(i)->rows() != 1 || m_args->at(i)->cols() != m_cols ) { error.setNonconformantArgument( i, m_args->at(i), this ); break; } } } } //-------------------------------------------------------------------------// double MPSymMatrix::value( int row, int col ) { return m_args->at(row)->value(0,col); } //-------------------------------------------------------------------------//