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