private bool AnalyzeReflection(Operand vector, ref VersorDecomposition versorDecomposition, Context context)
        {
            BladeDecomposition decomp = this.AnalyzeBlade(vector, context);

            if (decomp.analysisList[0] == "The blade is a real plane.")
            {
                versorDecomposition.analysisList.Add("Reflection:");
                //...
                return(true);
            }
            else if (decomp.analysisList[0] == "The blade is a real sphere.")
            {
                versorDecomposition.analysisList.Add("Inversion:");
                //...
                return(true);
            }
            else if (decomp.analysisList[0] == "The blade is an imaginary sphere.")
            {
                versorDecomposition.analysisList.Add("Imaginary inversion?");
                //...
                return(true);
            }

            return(false);
        }
        private bool AnalyzeRotation(Operand vectorA, Operand vectorB, ref VersorDecomposition versorDecomposition, Context context)
        {
            BladeDecomposition decompA = this.AnalyzeBlade(vectorA, context);
            BladeDecomposition decompB = this.AnalyzeBlade(vectorB, context);

            if (decompA.analysisList[0] == "The blade is a plane." && decompB.analysisList[0] == "The blade is a plane.")
            {
                Operand wedgeProduct = ExhaustEvaluation(new Trim(new List <Operand>()
                {
                    new OuterProduct(new List <Operand>()
                    {
                        decompA.normal, decompB.normal
                    })
                }), context);
                if (wedgeProduct.IsAdditiveIdentity)
                {
                    versorDecomposition.analysisList.Add("Translation:");
                    //...calculate translation vector...
                }
                else
                {
                    versorDecomposition.analysisList.Add("Rotation:");
                    //...calculate center of rotation, axis of rotation, and rotation angle...
                }

                return(true);
            }
            else if (decompA.analysisList[0] == "The blade is a real sphere." && decompB.analysisList[0] == "The blade is a real sphere.")
            {
                Operand difference = ExhaustEvaluation(new Trim(new List <Operand>()
                {
                    new Sum(new List <Operand>()
                    {
                        decompA.center, new GeometricProduct(new List <Operand>()
                        {
                            new NumericScalar(-1.0), decompB.center
                        })
                    })
                }), context);
                if (difference.IsAdditiveIdentity)
                {
                    versorDecomposition.analysisList.Add("Dilation:");
                    //...calculate center of dilation and dilation scale...
                }
                else
                {
                    versorDecomposition.analysisList.Add("Transversion:");
                    //...
                }

                return(true);
            }

            return(false);
        }
        public override Operand EvaluationStep(Context context)
        {
            if (operandList.Count != 1)
            {
                throw new MathException(string.Format($"Expected exactly 1 argument, got {operandList.Count}."));
            }

            Operand operand = base.EvaluationStep(context);

            if (operand != null)
            {
                return(operand);
            }

            operand = operandList[0];

            BladeDecomposition bladeDecomposition = AnalyzeBlade(operand, context);

            context.Log("Blade analysis:");
            context.Log(bladeDecomposition.analysisList);

            VersorDecomposition versorDecomposition = AnalyzeVersor(operand, context);

            context.Log("Versor analysis:");
            context.Log(versorDecomposition.analysisList);

            if (bladeDecomposition.weight != null)
            {
                context.operandStorage.SetStorage("weight", bladeDecomposition.weight);
            }

            if (bladeDecomposition.center != null)
            {
                context.operandStorage.SetStorage("center", bladeDecomposition.center);
            }

            if (bladeDecomposition.radius != null)
            {
                context.operandStorage.SetStorage("radius", bladeDecomposition.radius);
            }

            if (bladeDecomposition.normal != null)
            {
                context.operandStorage.SetStorage("normal", bladeDecomposition.normal);
            }

            return(operand);
        }