ScaledSymbol* Product::FindLeadingScaledSymbol( void ) { for( OperandList::Node* node = operandList.Head(); node; node = node->Next() ) { ScaledSymbol* scaledSymbol = dynamic_cast< ScaledSymbol* >( node->data ); if( scaledSymbol ) return scaledSymbol; Product* product = dynamic_cast< Product* >( node->data ); if( product ) { scaledSymbol = product->FindLeadingScaledSymbol(); if( scaledSymbol ) return scaledSymbol; } } return nullptr; }
/*virtual*/ bool Product::Combine( const Operand* leftOperand, const Operand* rightOperand, Operand** resultOperand ) const { const NumericReal* leftNumericReal = dynamic_cast< const NumericReal* >( leftOperand ); const NumericReal* rightNumericReal = dynamic_cast< const NumericReal* >( rightOperand ); if( leftNumericReal ) { if( leftNumericReal->real == 0.0 ) { *resultOperand = leftNumericReal->Clone(); return true; } else if( leftNumericReal->real == 1.0 ) { *resultOperand = rightOperand->Clone(); return true; } } if( rightNumericReal ) { if( rightNumericReal->real == 0.0 ) { *resultOperand = rightNumericReal->Clone(); return true; } else if( rightNumericReal->real == 1.0 ) { *resultOperand = leftOperand->Clone(); return true; } } if( leftNumericReal && rightNumericReal ) { NumericReal* numericReal = new NumericReal(); numericReal->real = leftNumericReal->real * rightNumericReal->real; return true; } const SymbolicReal* leftSymbolicReal = dynamic_cast< const SymbolicReal* >( leftOperand ); const SymbolicReal* rightSymbolicReal = dynamic_cast< const SymbolicReal* >( rightOperand ); if( leftNumericReal && rightSymbolicReal ) { SymbolicReal* symbolicReal = ( SymbolicReal* )rightSymbolicReal->Clone(); if( !symbolicReal->scalar ) symbolicReal->scalar = leftNumericReal->Clone(); else { GeometricProduct* geometricProduct = new GeometricProduct(); geometricProduct->operandList.InsertAfter()->data = leftNumericReal->Clone(); geometricProduct->operandList.InsertAfter()->data = symbolicReal->scalar; symbolicReal->scalar = geometricProduct; } } if( leftSymbolicReal && rightNumericReal ) { SymbolicReal* symbolicReal = ( SymbolicReal* )leftSymbolicReal->Clone(); if( !symbolicReal->scalar ) symbolicReal->scalar = rightNumericReal->Clone(); else { GeometricProduct* geometricProduct = new GeometricProduct(); geometricProduct->operandList.InsertAfter()->data = symbolicReal->scalar; geometricProduct->operandList.InsertAfter()->data = rightNumericReal->Clone(); symbolicReal->scalar = geometricProduct; } } if( leftSymbolicReal && rightSymbolicReal && 0 == strcmp( leftSymbolicReal->name, rightSymbolicReal->name ) ) { Operand* leftScalar = leftSymbolicReal->scalar; Operand* rightScalar = rightSymbolicReal->scalar; Operand* scalar = nullptr; if( leftScalar && rightScalar ) { GeometricProduct* geometricProduct = new GeometricProduct(); geometricProduct->operandList.InsertAfter()->data = leftScalar->Clone(); geometricProduct->operandList.InsertAfter()->data = rightScalar->Clone(); scalar = geometricProduct; } else if( leftScalar ) scalar = leftScalar->Clone(); else if( rightScalar ) scalar = rightScalar->Clone(); int exponent = leftSymbolicReal->exponent + rightSymbolicReal->exponent; if( exponent == 0 ) { if( !scalar ) { NumericReal* numericReal = new NumericReal(); numericReal->real = 1.0; *resultOperand = numericReal; return true; } else { *resultOperand = scalar; return true; } } else { SymbolicReal* symbolicReal = new SymbolicReal(); symbolicReal->name = _strdup( leftSymbolicReal->name ); symbolicReal->exponent = exponent; symbolicReal->scalar = scalar; *resultOperand = symbolicReal; return true; } } const Vector* leftVector = dynamic_cast< const Vector* >( leftOperand ); const Vector* rightVector = dynamic_cast< const Vector* >( rightOperand ); if( leftOperand->IsScalar() && rightVector ) { Vector* vector = ( Vector* )rightVector->Clone(); if( !vector->scalar ) vector->scalar = leftOperand->Clone(); else { GeometricProduct* geometricProduct = new GeometricProduct(); geometricProduct->operandList.InsertAfter()->data = leftOperand->Clone(); geometricProduct->operandList.InsertAfter()->data = vector->scalar; vector->scalar = geometricProduct; } *resultOperand = vector; return true; } if( leftVector && rightOperand->IsScalar() ) { Vector* vector = ( Vector* )leftVector->Clone(); if( !vector->scalar ) vector->scalar = rightOperand->Clone(); else { GeometricProduct* geometricProduct = new GeometricProduct(); geometricProduct->operandList.InsertAfter()->data = vector->scalar; geometricProduct->operandList.InsertAfter()->data = rightOperand->Clone(); vector->scalar = geometricProduct; } *resultOperand = vector; return true; } const Product* leftProduct = dynamic_cast< const Product* >( leftOperand ); const Product* rightProduct = dynamic_cast< const Product* >( rightOperand ); if( leftOperand->IsScalar() && rightProduct && rightProduct->FindLeadingScaledSymbol() ) { Product* product = ( Product* )rightProduct->Clone(); ScaledSymbol* scaledSymbol = product->FindLeadingScaledSymbol(); if( !scaledSymbol->scalar ) scaledSymbol->scalar = leftOperand->Clone(); else { GeometricProduct* geometricProduct = new GeometricProduct(); geometricProduct->operandList.InsertAfter()->data = scaledSymbol->scalar; geometricProduct->operandList.InsertAfter()->data = leftOperand->Clone(); scaledSymbol->scalar = geometricProduct; } *resultOperand = product; return true; } if( leftProduct && leftProduct->FindLeadingScaledSymbol() && rightOperand->IsScalar() ) { Product* product = ( Product* )leftProduct->Clone(); ScaledSymbol* scaledSymbol = product->FindLeadingScaledSymbol(); if( !scaledSymbol->scalar ) scaledSymbol->scalar = rightOperand->Clone(); else { GeometricProduct* geometricProduct = new GeometricProduct(); geometricProduct->operandList.InsertAfter()->data = scaledSymbol->scalar; geometricProduct->operandList.InsertAfter()->data = rightOperand->Clone(); scaledSymbol->scalar = geometricProduct; } *resultOperand = product; return true; } return false; }