bool GradeSelector::Select( void ) { if( !operand ) return false; Expander expander; expander.expansionTarget = Expander::SUM_OF_BLADES; expander.ManipulateTree( &operand ); Addition* addition = dynamic_cast< Addition* >( operand ); if( !addition ) return false; Addition::OperandList::Node* node = addition->operandList.Head(); while( node ) { Addition::OperandList::Node* nextNode = node->Next(); Operand* nestedOperand = node->data; int count = -1; OuterProduct* outerProduct = dynamic_cast< OuterProduct* >( nestedOperand ); Vector* vector = dynamic_cast< Vector* >( nestedOperand ); if( outerProduct && outerProduct->IsHomogeneousOfVectors() ) count = outerProduct->operandList.Count(); else if( vector ) count = 1; else if( nestedOperand->IsScalar() ) count = 0; if( ( count == grade && type == TYPE_EXCLUSIVE ) || ( count != grade && type == TYPE_INCLUSIVE ) ) addition->operandList.Remove( node ); node = nextNode; } return true; }
bool Sum::CombineLikeOperands( void ) { for( OperandList::Node* nodeA = operandList->Head(); nodeA; nodeA = nodeA->Next() ) { Operand* operandA = nodeA->data; for( OperandList::Node* nodeB = nodeA->Next(); nodeB; nodeB = nodeB->Next() ) { Operand* operandB = nodeB->data; if( operandA->IsScalar() && operandB->IsScalar() ) { Operand* scalar = AddScalars( operandA, operandB ); if( scalar ) { operandList->InsertAfter()->data = scalar; operandList->Remove( nodeA ); operandList->Remove( nodeB ); return true; } } else if( dynamic_cast< Vector* >( operandA ) && dynamic_cast< Vector* >( operandB ) ) { Vector* vectorA = ( Vector* )operandA; Vector* vectorB = ( Vector* )operandB; if( 0 == strcmp( vectorA->GetName(), vectorB->GetName() ) ) { Operand* scalarA = vectorA->GetScalar(); Operand* scalarB = vectorB->GetScalar(); vectorA->SetScalar( 0, false ); vectorB->SetScalar( 0, false ); if( !scalarA ) { NumericScalar* numericScalar = new NumericScalar(); numericScalar->SetReal( 1.0 ); scalarA = numericScalar; } if( !scalarB ) { NumericScalar* numericScalar = new NumericScalar(); numericScalar->SetReal( 1.0 ); scalarB = numericScalar; } Sum* scalar = new Sum(); scalar->operandList->InsertAfter()->data = scalarA; scalar->operandList->InsertAfter()->data = scalarB; vectorB->SetScalar( scalar ); operandList->Remove( nodeA ); return true; } } else if( ( operandA->IsBlade() && operandB->IsBlade() ) || ( operandA->IsVersor() && operandB->IsVersor() ) ) { Operation* operationA = ( Operation* )operandA; Operation* operationB = ( Operation* )operandB; if( OperationsAlike( operationA, operationB ) ) { // Degenerates are removed well before we can get here, so this shouldn't happen. Vector* vector = operationB->FindLeadingVector(); if( !vector ) { Error* error = new Error(); error->Format( "Sum expected to find a leading vector, but didn't." ); throw error; } // An empty geometric product in either case will do fine. GeometricProduct* scalarA = operationA->StripScalars(); GeometricProduct* scalarB = operationB->StripScalars(); Sum* scalar = new Sum(); scalar->operandList->InsertAfter()->data = scalarA; scalar->operandList->InsertAfter()->data = scalarB; vector->MarryWithScalar( scalar ); operandList->Remove( nodeA ); return true; } } } } return false; }