예제 #1
0
        public Matrix(List <List <Operand> > listOfOperandLists)
        {
            this.rows = listOfOperandLists.Count;
            this.cols = 0;
            for (int i = 0; i < rows; i++)
            {
                if (listOfOperandLists[i].Count > cols)
                {
                    cols = listOfOperandLists[i].Count;
                }
            }

            operandArray = new Operand[rows, cols];
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    try
                    {
                        operandArray[i, j] = listOfOperandLists[i][j];
                    }
                    catch (Exception)    // TODO: Catch specific out-of-bounds exception here.
                    {
                        operandArray[i, j] = new NumericScalar(0.0);
                    }
                }
            }
        }
예제 #2
0
 public void ResetAsIdentity()
 {
     for (int i = 0; i < rows; i++)
     {
         for (int j = 0; j < cols; j++)
         {
             operandArray[i, j] = new NumericScalar(i == j ? 1.0 : 0.0);
         }
     }
 }
예제 #3
0
        public Matrix(Matrix <double> matrix) : base()
        {
            this.rows = matrix.RowCount;
            this.cols = matrix.ColumnCount;

            operandArray = new Operand[rows, cols];
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    operandArray[i, j] = new NumericScalar(matrix.At(i, j));
                }
            }
        }
예제 #4
0
        // Notice that we try to cull by grade first before evaluating our main argument.
        // This is what may be an optimization by early detection of grade.  We must evaluate
        // our main argument as long as its grade remains indeterminant.  How good the optimization
        // is depends on how well we can determine the grade of an arbitrary operand tree.
        // Of course, some trees well never have a grade, such as a sum of blades of non-homogeneous grade.
        public override Operand EvaluationStep(Context context)
        {
            if (operandList.Count < 2)
            {
                throw new MathException(string.Format("Grade-part operation expects two or more arguments, got {0}.", operandList.Count));
            }

            int grade = operandList[0].Grade;

            if (grade == -1)
            {
                Operand operand = base.EvaluationStep(context);
                if (operand != null)
                {
                    return(operand);
                }
            }
            else
            {
                var gradeSet = new HashSet <int>();
                for (int i = 1; i < operandList.Count; i++)
                {
                    NumericScalar scalar = operandList[i] as NumericScalar;
                    if (scalar == null)
                    {
                        Operand operand = operandList[i].EvaluationStep(context);
                        if (operand != null)
                        {
                            operandList[i] = operand;
                            return(this);
                        }

                        throw new MathException("Encountered non-numeric-scalar when looking for grade arguments.");
                    }

                    gradeSet.Add((int)scalar.value);
                }

                if (gradeSet.Contains(grade))
                {
                    return(operandList[0]);
                }

                return(new NumericScalar(0.0));
            }

            return(null);
        }
예제 #5
0
        public override Operand EvaluationStep(Context context)
        {
            if (operandList.Count == 0)
            {
                return(new NumericScalar(1.0));
            }

            Operand operand;

            for (int i = 0; i < operandList.Count; i++)
            {
                operand = operandList[i];
                if (operand.IsAdditiveIdentity)
                {
                    return(new NumericScalar(0.0));
                }

                if (operand.IsMultiplicativeIdentity)
                {
                    operandList.RemoveAt(i);
                    return(this);
                }
            }

            operand = base.EvaluationStep(context);
            if (operand != null)
            {
                return(operand);
            }

            for (int i = 0; i < operandList.Count; i++)
            {
                Operand operandA = operandList[i];

                for (int j = i + 1; j < operandList.Count; j++)
                {
                    Operand operandB = operandList[j];
                    Operand product  = null;

                    if (operandA is NumericScalar scalarA && operandB is NumericScalar scalarB)
                    {
                        product = new NumericScalar(scalarA.value * scalarB.value);
                    }
예제 #6
0
        public List <RowOperation> GaussJordanEliminate(Context context)
        {
            List <RowOperation> rowOperationList = new List <RowOperation>();

            int pivotRow = 0;
            int pivotCol = 0;

            while (pivotRow < this.rows && pivotCol < this.cols)
            {
                //
                // Step 1: If we have a zero in our pivot location, we need to find a non-zero entry in our pivot column.
                //

                if (operandArray[pivotRow, pivotCol].IsAdditiveIdentity)
                {
                    int i;
                    for (i = pivotRow + 1; i < this.rows; i++)
                    {
                        if (!operandArray[i, pivotCol].IsAdditiveIdentity)
                        {
                            break;
                        }
                    }

                    if (i == this.rows)
                    {
                        // Go to the next column.
                        pivotCol++;
                        continue;
                    }
                    else
                    {
                        // Get a non-zero entry into our pivot location.
                        var rowOp = new SwapRows(i, pivotRow);
                        rowOperationList.Add(rowOp);
                        rowOp.Apply(this, context);
                    }
                }

                //
                // Step 2: If we don't have a one in our pivot location, we need to scale our pivot row.
                //

                if (!operandArray[pivotRow, pivotCol].IsMultiplicativeIdentity)
                {
                    var rowOp = new ScaleRow(pivotRow, new Inverse(new List <Operand>()
                    {
                        operandArray[pivotRow, pivotCol].Copy()
                    }));
                    rowOperationList.Add(rowOp);
                    rowOp.Apply(this, context);

                    // TODO: This is a hack until the algebra system can recognize the ratio of two identical polynomials as being one.
                    if (!operandArray[pivotRow, pivotCol].IsMultiplicativeIdentity)
                    {
                        operandArray[pivotRow, pivotCol] = new NumericScalar(1.0);
                    }
                }

                //
                // Step 3: All other entries in our pivot column must be reduced to zero.
                //

                for (int i = 0; i < this.rows; i++)
                {
                    if (i != pivotRow && !operandArray[i, pivotCol].IsAdditiveIdentity)
                    {
                        var rowOp = new AddRowMultiple(i, pivotRow, new GeometricProduct(new List <Operand>()
                        {
                            new NumericScalar(-1.0), operandArray[i, pivotCol].Copy()
                        }));
                        rowOperationList.Add(rowOp);
                        rowOp.Apply(this, context);

                        // TODO: Again, this is a hack, because the algebra system does not yet handle ratios of polynomials very well at all.
                        if (!operandArray[i, pivotCol].IsAdditiveIdentity)
                        {
                            operandArray[i, pivotCol] = new NumericScalar(0.0);
                        }
                    }
                }

                //
                // Step 4: The pivot row always increments, but the next pivot column needs to be determined.
                //

                if (++pivotRow < this.rows)
                {
                    while (++pivotCol < this.cols)
                    {
                        if (!Enumerable.Range(pivotRow, this.rows - pivotRow).Select(i => operandArray[i, pivotCol]).All(operand => operand.IsAdditiveIdentity))
                        {
                            break;
                        }
                    }
                }
            }

            return(rowOperationList);
        }