1 #include "MathMLSolverStableHeaders.h" 2 #include "MathMLASTConstantExpression.h" 3 #include "MathMLError.h" 4 5 #include "MathMLString.h" 6 7 namespace MathML 8 { 9 10 namespace AST 11 { 12 13 /** String constant for a Scalar with an invalid value. */ 14 const static String SCALAR_INVALID_VALUE = "INVALID"; 15 /** String constant for a Scalar with the boolean value false. */ 16 const static String SCALAR_FALSE_VALUE = "false"; 17 /** String constant for a Scalar with the boolean value true. */ 18 const static String SCALAR_TRUE_VALUE = "true"; 19 20 21 //--------------------------------------------------------------------------------- accept(IVisitor * visitor) const22 void ConstantExpression::accept( IVisitor* visitor ) const 23 { 24 visitor->visit( this ); 25 } 26 27 //--------------------------------------------------------------------------------- ConstantExpression(const ConstantExpression & ref)28 ConstantExpression::ConstantExpression( const ConstantExpression& ref ) 29 : mType ( ref.mType ) 30 , mValue ( ref.mValue ) 31 , mStringValue ( ref.mStringValue ) 32 , mErrorHandler( 0 ) 33 {} 34 35 //--------------------------------------------------------------------------------- ConstantExpression()36 ConstantExpression::ConstantExpression() 37 : mType ( SCALAR_INVALID ) 38 , mErrorHandler( 0 ) 39 {} 40 41 //--------------------------------------------------------------------------------- ~ConstantExpression()42 ConstantExpression::~ConstantExpression() 43 {} 44 45 //--------------------------------------------------------------------------------- ConstantExpression(const MathML::String & str,Type type)46 ConstantExpression::ConstantExpression( const MathML::String& str, Type type ) 47 : mType ( type ) 48 , mErrorHandler( 0 ) 49 { 50 51 switch ( type ) 52 { 53 54 case SCALAR_INVALID: 55 break; 56 57 case SCALAR_DOUBLE: 58 mValue = StringUtil::parseDouble( str ); 59 //mValue = 1.0; 60 break; 61 62 case SCALAR_LONG: 63 mValue = StringUtil::parseLong( str ); 64 break; 65 66 case SCALAR_BOOL: 67 mValue = ( str.size() > 0 && ( str[ 0 ] == 'f' || str[ 0 ] == 'F' ) ) ? 0. : 1.; 68 break; 69 70 default: 71 //@todo: exception 72 break; 73 } 74 75 } 76 77 //--------------------------------------------------------------------------------- ConstantExpression(const MathML::String & str)78 ConstantExpression::ConstantExpression( const MathML::String& str ) 79 : mStringValue ( str ) 80 , mErrorHandler( 0 ) 81 {} 82 83 //------------------------------------------------------------------------- ConstantExpression(double val)84 ConstantExpression::ConstantExpression( double val ) 85 { 86 setValue( val ); 87 } 88 89 //------------------------------------------------------------------------- ConstantExpression(long val)90 ConstantExpression::ConstantExpression( long val ) 91 { 92 setValue( val ); 93 } 94 95 //------------------------------------------------------------------------- ConstantExpression(bool val)96 ConstantExpression::ConstantExpression( bool val ) 97 { 98 setValue( val ); 99 } 100 101 //------------------------------------------------------------------------- setValue(const String & str,Type type)102 void ConstantExpression::setValue( const String& str, Type type ) 103 { 104 switch ( type ) 105 { 106 107 case SCALAR_INVALID: 108 break; 109 110 case SCALAR_DOUBLE: 111 mValue = StringUtil::parseDouble( str ); 112 mType = SCALAR_DOUBLE; 113 //mValue = 1.0; 114 break; 115 116 case SCALAR_LONG: 117 mValue = StringUtil::parseLong( str ); 118 mType = SCALAR_LONG; 119 break; 120 121 case SCALAR_BOOL: 122 mValue = ( str.size() > 0 && ( str[ 0 ] == 'f' || str[ 0 ] == 'F' ) ) ? 0. : 1.; 123 mType = SCALAR_BOOL; 124 break; 125 126 default: 127 //@todo: exception 128 break; 129 } 130 } 131 132 //------------------------------------------------------------------------- setValue(double val)133 void ConstantExpression::setValue( double val ) 134 { 135 mType = SCALAR_DOUBLE; 136 mValue = val; 137 } 138 139 //------------------------------------------------------------------------- setValue(long val)140 void ConstantExpression::setValue( long val ) 141 { 142 mType = SCALAR_LONG; 143 mValue = static_cast<double>( val ); 144 } 145 146 //------------------------------------------------------------------------- setValue(bool val)147 void ConstantExpression::setValue( bool val ) 148 { 149 mType = SCALAR_BOOL; 150 mValue = val ? 1. : 0.; 151 } 152 153 //------------------------------------------------------------------------- getType() const154 ConstantExpression::Type ConstantExpression::getType() const 155 { 156 return mType; 157 } 158 159 //------------------------------------------------------------------------- getDoubleValue() const160 double ConstantExpression::getDoubleValue() const 161 { 162 return mValue; 163 } 164 165 //------------------------------------------------------------------------- getLongValue() const166 long ConstantExpression::getLongValue() const 167 { 168 return static_cast<long>( mValue ); 169 } 170 171 //------------------------------------------------------------------------- getUnsignedLongValue() const172 unsigned long ConstantExpression::getUnsignedLongValue() const 173 { 174 if ( mValue < 0 ) 175 { 176 if ( mErrorHandler ) 177 { 178 Error error( Error::ERR_INTERNAL_ERROR, "could not convert to unsigned cause value is negative!" ); 179 mErrorHandler->handleError( &error ); 180 return 0; 181 } 182 } 183 184 return static_cast<long>( mValue ); 185 } 186 187 //------------------------------------------------------------------------- getBoolValue() const188 bool ConstantExpression::getBoolValue() const 189 { 190 return ( mValue == 0. ) ? false : true; 191 } 192 193 //------------------------------------------------------------------------- arithmeticalBinaryOperation(ConstantExpression & result,const ConstantExpression & rhs,AST::ArithmeticExpression::Operator op) const194 void ConstantExpression::arithmeticalBinaryOperation( ConstantExpression& result, const ConstantExpression& rhs, AST::ArithmeticExpression::Operator op ) const 195 { 196 if ( this->getType() == SCALAR_INVALID || rhs.getType() == SCALAR_INVALID ) 197 { 198 if ( mErrorHandler ) 199 { 200 Error error( Error::ERR_INVALIDPARAMS, "uninitilized operand(s)" ); 201 mErrorHandler->handleError( &error ); 202 } 203 result.setValue( 0. ); 204 return; 205 } 206 207 else if ( (this->getType() == SCALAR_BOOL && rhs.getType() == SCALAR_LONG) || (this->getType() == SCALAR_LONG && rhs.getType() == SCALAR_BOOL) ) 208 { 209 long val1 = this->getLongValue(); 210 long val2 = rhs.getLongValue(); 211 arithmeticalBinaryOperation( result, val1, val2, op ); 212 } 213 214 else if ( this->getType() == SCALAR_LONG && rhs.getType() == SCALAR_LONG ) 215 { 216 long val1 = this->getLongValue(); 217 long val2 = rhs.getLongValue(); 218 arithmeticalBinaryOperation( result, val1, val2, op ); 219 } 220 221 else 222 { 223 double val1 = this->getDoubleValue(); 224 double val2 = rhs.getDoubleValue(); 225 arithmeticalBinaryOperation( result, val1, val2, op ); 226 } 227 } 228 229 //------------------------------------------------------------------------- unaryOperation(ConstantExpression & result,AST::UnaryExpression::Operator op) const230 void ConstantExpression::unaryOperation( ConstantExpression& result, AST::UnaryExpression::Operator op ) const 231 { 232 if ( this->getType() == SCALAR_INVALID ) 233 { 234 if ( mErrorHandler ) 235 { 236 Error err( Error::ERR_INVALIDPARAMS, "uninitilized operand" ); 237 mErrorHandler->handleError( &err ); 238 } 239 result.setValue( 0. ); 240 return; 241 } 242 243 else if ( this->getType() == SCALAR_BOOL && op != AST::UnaryExpression::NOT ) 244 { 245 if ( mErrorHandler ) 246 { 247 Error err( Error::ERR_INVALIDPARAMS, "boolean operand in arithmetical operation" ); 248 mErrorHandler->handleError( &err ); 249 } 250 result.setValue( 0. ); 251 return; 252 } 253 254 else if ( this->getType() == SCALAR_BOOL && op == AST::UnaryExpression::NOT ) 255 { 256 result.setValue( !this->getBoolValue() ); 257 } 258 259 else if ( this->getType() == SCALAR_LONG ) 260 { 261 result.setValue( unaryOperation( this->getLongValue(), op ) ); 262 } 263 264 else 265 { 266 result.setValue( unaryOperation( this->getDoubleValue(), op ) ); 267 } 268 } 269 270 //------------------------------------------------------------------------- relationalBinaryOperation(ConstantExpression & result,const ConstantExpression & rhs,AST::BinaryComparisonExpression::Operator op) const271 void ConstantExpression::relationalBinaryOperation( ConstantExpression& result, const ConstantExpression& rhs, AST::BinaryComparisonExpression::Operator op ) const 272 { 273 if ( this->getType() == SCALAR_INVALID || rhs.getType() == SCALAR_INVALID ) 274 { 275 if ( mErrorHandler ) 276 { 277 Error err( Error::ERR_INVALIDPARAMS, "uninitilized operand(s)" ); 278 mErrorHandler->handleError( &err ); 279 } 280 result.setValue( 0. ); 281 return; 282 } 283 284 else if ( this->getType() == SCALAR_BOOL || rhs.getType() == SCALAR_BOOL ) 285 { 286 //check if both bool 287 288 if ( this->getType() != rhs.getType() ) 289 { 290 if ( mErrorHandler ) 291 { 292 Error err( Error::ERR_INVALIDPARAMS, "not both operands of type boolean for binary comparison operation" ); 293 mErrorHandler->handleError( &err ); 294 } 295 result.setValue( 0. ); 296 return; 297 } 298 299 // valid == 300 if ( op == AST::BinaryComparisonExpression::EQ ) 301 { 302 result.setValue( this->getLongValue() == rhs.getLongValue() ); 303 return ; 304 } 305 306 // valid != 307 else if ( op == AST::BinaryComparisonExpression::NEQ ) 308 { 309 result.setValue( this->getLongValue() != rhs.getLongValue() ); 310 return ; 311 } 312 313 //invalid: <, <=, >, .. 314 if ( mErrorHandler ) 315 { 316 Error err( Error::ERR_INVALIDPARAMS, "boolean operand(s) not allowed for this kind of binary comparision operation" ); 317 mErrorHandler->handleError( &err ); 318 } 319 result.setValue( 0. ); 320 return; 321 } 322 323 //only double or long values 324 else 325 { 326 double val1 = this->getDoubleValue(); 327 double val2 = rhs.getDoubleValue(); 328 329 switch ( op ) 330 { 331 332 case AST::BinaryComparisonExpression::EQ: 333 result.setValue( val1 == val2 ); 334 return ; 335 336 case AST::BinaryComparisonExpression::NEQ: 337 result.setValue( val1 != val2 ); 338 return ; 339 340 case AST::BinaryComparisonExpression::LT: 341 result.setValue( val1 < val2 ); 342 return ; 343 344 case AST::BinaryComparisonExpression::LTE: 345 result.setValue( val1 <= val2 ); 346 return ; 347 348 case AST::BinaryComparisonExpression::GT: 349 result.setValue( val1 > val2 ); 350 return ; 351 352 case AST::BinaryComparisonExpression::GTE: 353 result.setValue( val1 >= val2 ); 354 return ; 355 356 default: 357 if ( mErrorHandler ) 358 { 359 Error err( Error::ERR_INVALIDPARAMS, "invalid operator: " + AST::BinaryComparisonExpression::operatorString( op ) ); 360 mErrorHandler->handleError( &err ); 361 } 362 result.setValue( 0. ); 363 return; 364 } 365 } 366 } 367 368 //------------------------------------------------------------------------- logicalBinaryOperation(ConstantExpression & result,const ConstantExpression & rhs,AST::LogicExpression::Operator op) const369 void ConstantExpression::logicalBinaryOperation( ConstantExpression& result, const ConstantExpression& rhs, AST::LogicExpression::Operator op ) const 370 { 371 // accept non bool values ! 372 //if ( this->getType() != SCALAR_BOOL || rhs.getType() != SCALAR_BOOL ) 373 //{ 374 // MML_EXCEPT( MathML::Exception::ERR_INVALIDPARAMS, "boolean operand in arithmetical operation", "ConstantExpression::logicalBinaryOperation" ); 375 //} 376 switch ( op ) 377 { 378 379 case AST::LogicExpression::AND: 380 result.setValue( this->getBoolValue() && rhs.getBoolValue() ); 381 return ; 382 383 case AST::LogicExpression::OR: 384 result.setValue( this->getBoolValue() || rhs.getBoolValue() ); 385 return ; 386 387 case AST::LogicExpression::XOR: 388 result.setValue( ( bool ) ( this->getBoolValue() ^ rhs.getBoolValue() ) ); 389 return ; 390 391 default: 392 if ( mErrorHandler ) 393 { 394 Error err( Error::ERR_INVALIDPARAMS, "invalid operator: " + AST::LogicExpression::operatorString( op ) ); 395 mErrorHandler->handleError( &err ); 396 } 397 result.setValue( 0. ); 398 return; 399 400 } 401 } 402 403 //--------------------------------------------------------------------------------- getStringValue() const404 const MathML::String& ConstantExpression::getStringValue() const 405 { 406 return mStringValue; 407 } 408 409 //--------------------------------------------------------------------------------- setStringValue(const MathML::String & value)410 void ConstantExpression::setStringValue( const MathML::String& value ) 411 { 412 mStringValue = value; 413 } 414 415 //--------------------------------------------------------------------------------- toString() const416 MathML::String ConstantExpression::toString() const 417 { 418 std::stringstream ss; 419 420 if ( mStringValue.size() > 0 && mType == SCALAR_INVALID ) 421 { 422 return mStringValue; 423 } 424 425 //check type 426 switch ( mType ) 427 { 428 429 case SCALAR_BOOL: 430 return ( mValue == 0. ) ? SCALAR_FALSE_VALUE : SCALAR_TRUE_VALUE; 431 432 case SCALAR_LONG: 433 //return StringUtil::valueOf( static_cast<long>( mValue ) ); 434 ss << static_cast<long>( mValue ); 435 return ss.str(); 436 437 case SCALAR_DOUBLE: 438 //return StringUtil::valueOf( mValue ); 439 ss << mValue; 440 return ss.str(); 441 442 default: 443 return SCALAR_INVALID_VALUE; 444 } 445 } 446 447 //----------------------------------------------------------------- clone(CloneFlags cloneFlags) const448 INode* ConstantExpression::clone(CloneFlags cloneFlags) const 449 { 450 ConstantExpression* copy = new ConstantExpression(); 451 copy->mType = mType; 452 copy->mValue = mValue; 453 copy->mStringValue = mStringValue; 454 return copy; 455 } 456 457 } //namespace AST 458 459 } //namespace MathML 460