public static Operand CalculateJoin(List <Operand> operandList, Context context) { OuterProduct[] bladeArray = new OuterProduct[operandList.Count]; int j = -1; for (int i = 0; i < bladeArray.Length; i++) { try { bladeArray[i] = FactorBlade.Factor(operandList[i], context); if (j < 0 || bladeArray[i].Grade > bladeArray[j].Grade) { j = i; } } catch (MathException exc) { throw new MathException($"Failed to factor argument {i} as blade.", exc); } } OuterProduct join = bladeArray[j]; for (int i = 0; i < bladeArray.Length; i++) { if (i != j) { foreach (Operand vector in bladeArray[i].operandList) { Operand operand = Operand.ExhaustEvaluation(new Trim(new List <Operand>() { new OuterProduct(new List <Operand>() { vector.Copy(), join.Copy() }) }), context); if (!operand.IsAdditiveIdentity) { join.operandList.Add(vector); } } } } return(join); }
// The algorithm implemented here comes straight out of Christian Perwass' book. // TODO: Also, as noted by Perwass, this algorithm doesn't work for null versors. public static GeometricProduct Factor(Operand operand, Context context) { Operand currentVersor = operand.Copy(); GeometricProduct versorFactorization = new GeometricProduct(); while (true) { HashSet <int> gradeSet = DiscoverGrades(currentVersor, context); int maxGrade = gradeSet.ToList().Aggregate(0, (currentMaxGrade, grade) => grade > currentMaxGrade ? grade : currentMaxGrade); if (maxGrade <= 0) { break; } Operand blade = Operand.ExhaustEvaluation(new GradePart(new List <Operand>() { currentVersor.Copy(), new NumericScalar(maxGrade) }), context); OuterProduct bladeFactorization = null; try { bladeFactorization = FactorBlade.Factor(blade, context); } catch (MathException exc) { throw new MathException("Highest-grade-part of multivector does not factor as a blade.", exc); } Operand nonNullVector = null, magnitude = null; foreach (Operand vector in bladeFactorization.operandList) { if (vector.Grade == 1) { magnitude = Operand.ExhaustEvaluation(new Trim(new List <Operand>() { new Magnitude(new List <Operand>() { vector.Copy() }) }), context); if (!magnitude.IsAdditiveIdentity) { nonNullVector = vector; break; } } } if (nonNullVector == null) { throw new MathException("Failed to find non-null vector in blade factorization."); } Operand unitVector = Operand.ExhaustEvaluation(new Normalize(new List <Operand>() { nonNullVector }), context); versorFactorization.operandList.Insert(0, unitVector); currentVersor = Operand.ExhaustEvaluation(new Trim(new List <Operand>() { new GeometricProduct(new List <Operand>() { currentVersor, unitVector.Copy() }) }), context); } versorFactorization.operandList.Add(currentVersor); return(versorFactorization); }