public QsValue StdDeviation(int fromIndex, int toIndex)
        {
            var n = toIndex - fromIndex + 1;

            if (this.Parameters.Length > 0)
            {
                throw new QsException("Standard Deviation with symbolic quantities (I think you went so far ^_^ )", new NotImplementedException());
            }
            else
            {
                FixIndices(ref fromIndex, ref toIndex);
                var     mean  = Average(fromIndex, toIndex);
                var     Two   = "2".ToScalarValue();
                QsValue Total = (GetElementValue(fromIndex) - mean).PowerOperation(Two);
                for (int i = fromIndex + 1; i <= toIndex; i++)
                {
                    var p   = GetElementValue(i) - mean;
                    var pp2 = p.PowerOperation(Two);
                    Total = Total + pp2;
                }
                var count = new QsScalar {
                    NumericalQuantity = Qs.ToQuantity((double)n)
                };

                return(Total / count);
            }
        }
        /// <summary>
        /// Matrix ^ scalar
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public QsMatrix PowerScalar(QsScalar value)
        {
            QsMatrix Total = (QsMatrix)this.Identity; //first get the identity matrix of this matrix.

            int count = Qs.IntegerFromQsValue(value);

            if (count > 0)
            {
                for (int i = 1; i <= count; i++)
                {
                    Total = Total.MultiplyMatrix(this);
                }
            }
            else if (count == 0)
            {
                return(Total);   //which id identity already
            }
            else
            {
                count = Math.Abs(count);
                for (int i = 1; i <= count; i++)
                {
                    Total = Total.MultiplyMatrix(this.Inverse);    //multiply the inverses many times
                }
            }

            return(Total);
        }
Пример #3
0
        /// <summary>
        /// constructor accepts quantities and qs functions also
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="radius"></param>
        public Circle(QsScalar x, QsScalar y, QsScalar radius)
        {
            if (x.ScalarType == ScalarTypes.FunctionQuantity)
            {
                xfunc = x.FunctionQuantity.Value;
            }
            else
            {
                _x = x.NumericalQuantity;
            }

            if (y.ScalarType == ScalarTypes.FunctionQuantity)
            {
                yfunc = y.FunctionQuantity.Value;
            }
            else
            {
                _y = y.NumericalQuantity;
            }

            if (radius.ScalarType == ScalarTypes.FunctionQuantity)
            {
                radfunc = radius.FunctionQuantity.Value;
            }
            else
            {
                _radius = radius.NumericalQuantity;
            }
        }
Пример #4
0
        /// <summary>
        /// Wrap AnyQuantity of Symbolic Variable object into qs scalar object.
        /// </summary>
        /// <param name="qty"></param>
        /// <returns></returns>
        public static QsScalar ToScalar(this AnyQuantity <SymbolicVariable> qty)
        {
            QsScalar symscalar = new QsScalar(ScalarTypes.SymbolicQuantity)
            {
                SymbolicQuantity = qty
            };

            return(symscalar);
        }
Пример #5
0
        /// <summary>
        /// Returns a scalar object from function quantity.
        /// </summary>
        /// <param name="functionQuantity"></param>
        /// <returns></returns>
        public static QsScalar ToScalar(this AnyQuantity <QsFunction> functionQuantity)
        {
            QsScalar fnScalar = new QsScalar(ScalarTypes.FunctionQuantity)
            {
                FunctionQuantity = functionQuantity
            };

            return(fnScalar);
        }
        /// <summary>
        /// Differentiate operation for function.
        /// </summary>
        /// <param name="value">object of <see cref="QsScalar"/> that hold <see cref="AnyQuantity&lt;SymbolicVariable&gt;"/></param>
        /// <returns></returns>
        public override QsValue DifferentiateOperation(QsValue value)
        {
            QsScalar sval = (QsScalar)value;

            if (sval.ScalarType == ScalarTypes.SymbolicQuantity)
            {
                var dsv = sval.SymbolicQuantity.Value;

                string fname         = "_";
                string WholeFunction = string.Empty;
                if (this.FunctionBodyToken[0].TokenClassType == typeof(CurlyBracketGroupToken))
                {
                    // vector differentiation
                    // take every term in the vector and differentiate it
                    var           vcs = QsVar.VectorComponents(this.FunctionBodyToken[0]);
                    StringBuilder sc  = new StringBuilder();
                    sc.Append(fname + "(" + RemoveRedundantParameters(this.ParametersNames) + ") = ");
                    sc.Append("{ ");
                    foreach (var c in vcs)
                    {
                        SymbolicVariable nsv = SymbolicVariable.Parse(c);
                        int times            = (int)dsv.SymbolPower;
                        while (times > 0)
                        {
                            nsv = nsv.Differentiate(dsv.Symbol);
                            times--;
                        }
                        sc.Append(nsv.ToString());
                        sc.Append(" ");
                    }
                    sc.Append("}");

                    WholeFunction = sc.ToString();
                }
                else
                {
                    SymbolicVariable nsv = ToSymbolicVariable();
                    int times            = (int)dsv.SymbolPower;
                    while (times > 0)
                    {
                        nsv = nsv.Differentiate(dsv.Symbol);
                        times--;
                    }

                    WholeFunction = fname + "(" + RemoveRedundantParameters(this.ParametersNames) + ") = " + nsv.ToString();
                }


                return(QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, WholeFunction));
            }
            else
            {
                return(base.DifferentiateOperation(value));
            }
        }
Пример #7
0
        public static QsValue Name(QsParameter value)
        {
            QsScalar s = value.QsNativeValue as QsScalar;

            if (s != null)
            {
                return(new QsText(s.Unit.QuantityType.Name.TrimEnd('`', '1').ToString()));
            }

            return(new QsText("Works on scalar quantities"));
        }
Пример #8
0
        /// <summary>
        /// The function try to convert the passed array into an array of scalars.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static QsScalar[] ToScalars <T>(this T[] data)
        {
            QsScalar[] ss = new QsScalar[data.Length];

            for (int i = 0; i < data.Length; i++)
            {
                double d = Convert.ToDouble(data[i]);

                ss[i] = d.ToQuantity().ToScalar();
            }
            return(ss);
        }
Пример #9
0
        public QsValue Average(int fromIndex, int toIndex, QsValue arg0, QsValue arg1, QsValue arg2, QsValue arg3)
        {
            FixIndices(ref fromIndex, ref toIndex);

            var tot   = SumElements(fromIndex, toIndex, arg0, arg1, arg2, arg3);
            var n     = toIndex - fromIndex + 1;
            var count = new QsScalar {
                NumericalQuantity = Qs.ToQuantity((double)n)
            };

            return(tot / count);
        }
        /// <summary>
        /// for the tensor product '(*)'  operator
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override QsValue TensorProductOperation(QsValue vl)
        {
            QsValue value;

            if (vl is QsReference)
            {
                value = ((QsReference)vl).ContentValue;
            }
            else
            {
                value = vl;
            }


            if (value is QsMatrix)
            {
                // Kronecker product
                var tm = (QsMatrix)value;

                QsMatrix result = new QsMatrix();

                List <QsMatrix> lm = new List <QsMatrix>();

                for (int i = 0; i < this.RowsCount; i++)
                {
                    QsMatrix rowM = null;
                    for (int j = 0; j < this.ColumnsCount; j++)
                    {
                        QsScalar element = this[i, j];
                        var      imat    = (QsMatrix)(tm * element);
                        if (rowM == null)
                        {
                            rowM = imat;
                        }
                        else
                        {
                            rowM = rowM.AppendRightMatrix(imat);
                        }
                    }
                    lm.Add(rowM);
                }

                // append vertically all matrices

                foreach (var rm in lm)
                {
                    result = result.AppendLowerMatrix(rm);
                }

                return(result);
            }
            throw new NotImplementedException();
        }
Пример #11
0
        public Shape Circle(QsScalar x, QsScalar y, QsScalar radius)
        {
            Shape s;

            lock (Shapes)
            {
                s = new Circle(x, y, radius);
                Shapes.Add(s);
            }

            return(s);
        }
Пример #12
0
        /// <summary>
        /// Returns the dimension of value quantity.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static QsValue Dimension(QsParameter value)
        {
            QsScalar s = value.QsNativeValue as QsScalar;

            if (s != null)
            {
                return(new QsText(s.Unit.UnitDimension.ToString()));
            }


            return(new QsText("Works on scalar quantities"));
        }
Пример #13
0
        /// <summary>
        /// Returns the name of the quantity associated with this value
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static QsValue FromValue(QsParameter value)
        {
            QsScalar s = value.QsNativeValue as QsScalar;

            if (s != null)
            {
                string qt = s.Unit.QuantityType.Name;
                return(new QsText(qt.Substring(0, qt.Length - 2)));
            }


            return(new QsText("Works on scalar quantities"));
        }
Пример #14
0
        public void FactorialTest()
        {
            QsValue number = new QsScalar()
            {
                NumericalQuantity = Unit.ParseQuantity("5<kg>")
            };

            QsScalar actual;

            actual = (QsScalar)QsGamma.Factorial(number);

            Assert.AreEqual <AnyQuantity <double> >(Unit.ParseQuantity("120<kg^5>"), actual.NumericalQuantity);
        }
Пример #15
0
        public static QsValue InvertedQuantityName(QsParameter value)
        {
            QsScalar s = value.QsNativeValue as QsScalar;

            if (s != null)
            {
                var InvertedDimension = s.Unit.UnitDimension.Invert();

                var qp = QsParameter.MakeParameter(null, InvertedDimension.ToString());
                return(Quantity.FromDimension(qp));
            }


            return(new QsText("Works on scalar quantities"));
        }
        /// <summary>
        /// Matrix + scalar
        /// </summary>
        /// <param name="scalar"></param>
        /// <returns></returns>
        private QsMatrix AddScalar(QsScalar scalar)
        {
            QsMatrix Total = new QsMatrix();

            for (int IY = 0; IY < this.RowsCount; IY++)
            {
                List <QsScalar> row = new List <QsScalar>(ColumnsCount);

                for (int IX = 0; IX < this.ColumnsCount; IX++)
                {
                    row.Add(this[IY, IX] + scalar);
                }

                Total.AddRow(row.ToArray());
            }
            return(Total);
        }
Пример #17
0
        /// <summary>
        /// returns all quantities in the matrix in <see cref="AnyQuantity<double>"/> array.
        /// starting from left to right then by going down.
        /// </summary>
        /// <returns></returns>
        public QsScalar[] ToArray()
        {
            QsScalar[] values = new QsScalar[ColumnsCount * RowsCount];

            int valIndex = 0;

            for (int IX = 0; IX < this.ColumnsCount; IX++)
            {
                for (int IY = 0; IY < this.RowsCount; IY++)
                {
                    values[valIndex] = this[IY, IX];
                    valIndex++;
                }
            }

            return(values);
        }
        /// <summary>
        /// Matrix elements ^. scalar
        /// </summary>
        /// <param name="scalarQuantity"></param>
        /// <returns></returns>
        public QsMatrix ElementsPowerScalar(QsScalar scalar)
        {
            QsMatrix Total = new QsMatrix();

            for (int IY = 0; IY < this.RowsCount; IY++)
            {
                List <QsScalar> row = new List <QsScalar>(ColumnsCount);

                for (int IX = 0; IX < this.ColumnsCount; IX++)
                {
                    row.Add(this[IY, IX].PowerScalar(scalar));
                }

                Total.AddRow(row.ToArray());
            }
            return(Total);
        }
Пример #19
0
        /// <summary>
        /// Ordinary multiplicatinon of the matrix.
        /// Naive implementation :D  and I am proud :P
        ///
        /// </summary>
        /// <param name="matrix"></param>
        /// <returns></returns>
        public QsMatrix MultiplyMatrix(QsMatrix matrix)
        {
            if (this.ColumnsCount == matrix.RowsCount)
            {
                QsMatrix Total = new QsMatrix();

                //loop through my rows
                for (int iy = 0; iy < RowsCount; iy++)
                {
                    var        vec  = this.Rows[iy];
                    QsScalar[] tvec = new QsScalar[matrix.ColumnsCount]; //the target row in the Total Matrix.

                    //loop through all co vectors in the target matrix.
                    for (int tix = 0; tix < matrix.ColumnsCount; tix++)
                    {
                        var covec = matrix.GetColumnVectorMatrix(tix).ToArray();

                        //multiply vec*covec and store it at the Total matrix at iy,ix

                        QsScalar[] snum = new QsScalar[vec.Count];
                        for (int i = 0; i < vec.Count; i++)
                        {
                            snum[i] = vec[i].MultiplyScalar(covec[i]);
                        }

                        QsScalar tnum = snum[0];

                        for (int i = 1; i < snum.Length; i++)
                        {
                            tnum = tnum + snum[i];
                        }

                        tvec[tix] = tnum;
                    }

                    Total.AddRow(tvec);
                }

                return(Total);
            }
            else
            {
                throw new QsMatrixException("Width of the first matrix [" + this.ColumnsCount + "] not equal to the height of the second matrix [" + matrix.RowsCount + "]");
            }
        }
Пример #20
0
        /// <summary>
        /// Returns a value from the dimension of this quantity.
        /// </summary>
        /// <param name="dimension"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static QsValue FromDimension(QsParameter dimension, QsParameter value)
        {
            string ss = dimension.ParameterRawText;

            if (dimension.QsNativeValue is QsText)
            {
                ss = ((QsText)dimension.QsNativeValue).Text;
            }
            var q = QuantityDimension.Parse(ss);

            var unit = QuantitySystem.Units.Unit.DiscoverUnit(q);
            var qval = unit.GetThisUnitQuantity <double>(double.Parse(value.ParameterRawText, CultureInfo.InvariantCulture));

            var qs = new QsScalar(ScalarTypes.NumericalQuantity)
            {
                NumericalQuantity = qval
            };

            return(qs);
        }
Пример #21
0
        /// <summary>
        /// Take the average of the sequence.
        /// Corresponds To: S[i!!k]
        /// </summary>
        /// <param name="fromIndex"></param>
        /// <param name="toIndex"></param>
        /// <returns></returns>
        public QsValue Average(int fromIndex, int toIndex)
        {
            var n = toIndex - fromIndex + 1;

            if (this.Parameters.Length > 0)
            {
                // this is a call to form symbolic element
                // like g[n](x) ..> x^n
                // and calling g[0++2]
                //  the output should be x^0 + x^1 + x^2
                //  and be parsed into function  (QsFunction)


                string porma = string.Empty;  // the parameters separated by comma ','
                foreach (var prm in this.Parameters)
                {
                    porma += prm.Name + ", ";
                }
                porma = porma.TrimEnd(',', ' ');

                string FunctionBody = "(" + JoinElementsWithOperation(fromIndex, toIndex, "+") + ")/" + n.ToString(CultureInfo.InvariantCulture);

                string FunctionDeclaration = "_(" + porma + ") = " + FunctionBody;

                QsFunction qs = QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, FunctionDeclaration);

                return(qs);
            }
            else
            {
                FixIndices(ref fromIndex, ref toIndex);

                var tot = SumElements(fromIndex, toIndex);

                var count = new QsScalar {
                    NumericalQuantity = Qs.ToQuantity((double)n)
                };

                return(tot / count);
            }
        }
        public QsValue StdDeviation(int fromIndex, int toIndex, QsValue arg0, QsValue arg1, QsValue arg2)
        {
            var n = toIndex - fromIndex + 1;

            FixIndices(ref fromIndex, ref toIndex);
            var     mean  = Average(fromIndex, toIndex, arg0, arg1, arg2);
            var     Two   = "2".ToScalarValue();
            QsValue Total = (GetElementValue(fromIndex, arg0, arg1, arg2) - mean).PowerOperation(Two);

            for (int i = fromIndex + 1; i <= toIndex; i++)
            {
                var p   = GetElementValue(i, arg0, arg1, arg2) - mean;
                var pp2 = p.PowerOperation(Two);
                Total = Total + pp2;
            }
            var count = new QsScalar {
                NumericalQuantity = Qs.ToQuantity((double)n)
            };

            return(Total / count);
        }
Пример #23
0
        /// <summary>
        ///  gets a specific covector as a vector object
        /// </summary>
        /// <param name="columnIndex"></param>
        /// <returns></returns>
        public QsVector GetColumnVector(int columnIndex)
        {
            if (columnIndex > ColumnsCount)
            {
                throw new QsMatrixException("Index '" + columnIndex + "' Exceeds the columns limits '" + ColumnsCount + "'");
            }


            QsScalar[] col = new QsScalar[this.RowsCount];
            int        nc  = 0;

            for (int IY = 0; IY < this.RowsCount; IY++)
            {
                col[nc] = this[IY, columnIndex];
                nc++;
            }
            QsVector vec = new QsVector(col);


            return(vec);
        }
Пример #24
0
        public static QsValue FromName(QsParameter name, QsParameter value)
        {
            string ss = name.ParameterRawText;

            if (name.QsNativeValue is QsText)
            {
                ss = ((QsText)name.QsNativeValue).Text;
            }

            var qval = AnyQuantity <double> .Parse(ss);

            qval.Unit  = Unit.DiscoverUnit(qval);
            qval.Value = double.Parse(value.ParameterRawText, CultureInfo.InvariantCulture);

            var qs = new QsScalar(ScalarTypes.NumericalQuantity)
            {
                NumericalQuantity = qval
            };

            return(qs);
        }
Пример #25
0
 static Z80()
 {
     R = QsScalar.Zero;
 }
Пример #26
0
        /// <summary>
        /// Get factorial for the <see>QsValue</see> whether it is Scalar, Vector, Matrix, and later Tensor.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static QsValue Factorial(QsValue value)
        {
            if (value is QsBoolean)
            {
                var b = (QsBoolean)value;
                return(new QsBoolean {
                    Value = !b.Value
                });
            }

            if (value is QsScalar)
            {
                QsScalar sv = (QsScalar)value;
                if (sv.ScalarType == ScalarTypes.NumericalQuantity)
                {
                    AnyQuantity <double> number = sv.NumericalQuantity;
                    return(new QsScalar {
                        NumericalQuantity = QuantityFactorial(number)
                    });
                }
                else
                {
                    throw new QsException("Unsupported scalar object");
                }
            }
            else if (value is QsVector)
            {
                var vec = value as QsVector;

                QsVector rvec = new QsVector(vec.Count);

                foreach (var v in vec)
                {
                    rvec.AddComponent((QsScalar)Factorial(v));
                }

                return(rvec);
            }
            else if (value is QsMatrix)
            {
                var      mat   = value as QsMatrix;
                QsMatrix Total = new QsMatrix();

                for (int IY = 0; IY < mat.RowsCount; IY++)
                {
                    List <QsScalar> row = new List <QsScalar>(mat.ColumnsCount);

                    for (int IX = 0; IX < mat.ColumnsCount; IX++)
                    {
                        row.Add((QsScalar)Factorial(mat[IY, IX]));
                    }

                    Total.AddRow(row.ToArray());
                }
                return(Total);
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #27
0
 public static QsValue Parse(string value)
 {
     return(QsScalar.ParseScalar(value));
 }
        /// <summary>
        /// Take the value and operation in text and return the current function operationed by value.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="operation"></param>
        /// <returns></returns>
        private QsFunction FOperation(QsValue value, string operation)
        {
            if (value is QsFunction)
            {
                QsFunction fn2 = (QsFunction)value;

                string fParameters = RemoveRedundantParameters(this.ParametersNames.Union(fn2.ParametersNames).ToArray());

                string thisFunctionBody = this.FunctionBody;
                foreach (string p in this.ParametersNames)
                {
                    thisFunctionBody = thisFunctionBody.Replace(p, "$" + p);
                }

                string targetFunctionBody = fn2.FunctionBody;
                foreach (string p in fn2.ParametersNames)
                {
                    targetFunctionBody = targetFunctionBody.Replace(p, "$" + p);
                }

                // form the expressions that will be parsed.
                string fpt = "(" + thisFunctionBody + ")" + operation + "(" + targetFunctionBody + ")";

                fpt = fpt.Replace("!", "__FAC__"); // replacing the ! sign with __FAC__ to include the '!' sign into the calculations {because '!' is operator in parsing so it doesn't enter the algebraic calculations}
                //evaulate fpt

                try
                {
                    QsScalar sc            = (QsScalar)QsEvaluator.CurrentEvaluator.SilentEvaluate(fpt);
                    string   FuncBody      = sc.SymbolicQuantity.Value.ToString().Replace("__FAC__", "!");
                    string   WholeFunction = "_(" + fParameters + ") = " + FuncBody;
                    return(QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, WholeFunction));
                }
                catch (QsIncompleteExpression)
                {
                    // something happened make the operation in old fashion
                    string WholeFunction;
                    Token  FunctionToken = JoinFunctionsArrayTokensWithOperation(operation, out WholeFunction, this, fn2);
                    return(QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, WholeFunction, FunctionToken));
                }
            }
            else if (value is QsScalar)
            {
                QsScalar svl = (QsScalar)value;

                var fname = "_";

                var fbody = this.FunctionBody;
                if (svl.ScalarType == ScalarTypes.SymbolicQuantity)
                {
                    fbody = "(" + fbody + ")" + operation + "(" + svl.SymbolicQuantity.Value.ToString() + ")";
                }
                else if (svl.ScalarType == ScalarTypes.NumericalQuantity)
                {
                    fbody = "(" + fbody + ")" + operation + svl.NumericalQuantity.Value.ToString();
                }
                else if (svl.ScalarType == ScalarTypes.RationalNumberQuantity)
                {
                    fbody = "(" + fbody + ")" + operation + svl.RationalQuantity.Value.Value.ToString();
                }
                else if (svl.ScalarType == ScalarTypes.FunctionQuantity)
                {
                    fbody = "(" + fbody + ")" + operation + "(" + svl.FunctionQuantity.Value.FunctionBody + ")";
                }
                else
                {
                    throw new QsException("Operation '" + operation + "' for the target scalar type (" + svl.ScalarType + ") is not supported");
                }


                QsScalar fb = SymbolicVariable.Parse(fbody).ToQuantity().ToScalar();

                string FuncBody = string.Empty;
                if (fb.ScalarType == ScalarTypes.SymbolicQuantity)
                {
                    FuncBody = fb.SymbolicQuantity.Value.ToString().Replace("__FAC__", "!");
                }
                else
                {
                    FuncBody = fb.ToExpressionParsableString();
                }

                string[] functionParametersArray = this.ParametersNames; // this is the available parameters for the original function.

                if (svl.ScalarType == ScalarTypes.SymbolicQuantity)
                {
                    List <string> newParametersList = new List <string>(functionParametersArray);

                    newParametersList.AddRange(svl.SymbolicQuantity.Value.InvolvedSymbols);

                    functionParametersArray = newParametersList.ToArray();
                }

                if (svl.ScalarType == ScalarTypes.FunctionQuantity)
                {
                    List <string> newParametersList = new List <string>(functionParametersArray);

                    newParametersList.AddRange(svl.FunctionQuantity.Value.ParametersNames);

                    functionParametersArray = newParametersList.ToArray();
                }

                var f = fname + "(" + RemoveRedundantParameters(functionParametersArray) + ") = " + FuncBody;
                return(QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, f));
            }

            else
            {
                throw new NotImplementedException();
            }
        }
Пример #29
0
        // Contribution by Edward Popko, a well commented version: determinant.c for Microsoft C++ Visual Studio 6.
        // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/determinant/determinant.c
        //==============================================================================
        // Recursive definition of determinate using expansion by minors.
        //
        // Notes: 1) arguments:
        //             a (double **) pointer to a pointer of an arbitrary square matrix
        //             n (int) dimension of the square matrix
        //
        //        2) Determinant is a recursive function, calling itself repeatedly
        //           each time with a sub-matrix of the original till a terminal
        //           2X2 matrix is achieved and a simple determinat can be computed.
        //           As the recursion works backwards, cumulative determinants are
        //           found till untimately, the final determinate is returned to the
        //           initial function caller.
        //
        //        3) m is a matrix (4X4 in example)  and m13 is a minor of it.
        //           A minor of m is a 3X3 in which a row and column of values
        //           had been excluded.   Another minor of the submartix is also
        //           possible etc.
        //             m  a b c d   m13 . . . .
        //                e f g h       e f . h     row 1 column 3 is elminated
        //                i j k l       i j . l     creating a 3 X 3 sub martix
        //                m n o p       m n . p
        //
        //        4) the following function finds the determinant of a matrix
        //           by recursively minor-ing a row and column, each time reducing
        //           the sub-matrix by one row/column.  When a 2X2 matrix is
        //           obtained, the determinat is a simple calculation and the
        //           process of unstacking previous recursive calls begins.
        //
        //                m n
        //                o p  determinant = m*p - n*o
        //
        //        5) this function uses dynamic memory allocation on each call to
        //           build a m X m matrix  this requires **  and * pointer variables
        //           First memory allocation is ** and gets space for a list of other
        //           pointers filled in by the second call to malloc.
        //
        //        6) C++ implements two dimensional arrays as an array of arrays
        //           thus two dynamic malloc's are needed and have corresponsing
        //           free() calles.
        //
        //        7) the final determinant value is the sum of sub determinants
        //
        //==============================================================================

        /*
         * double Determinant(double** a, int n)
         * {
         *  int i, j, j1, j2;                    // general loop and matrix subscripts
         *  double det = 0;                   // init determinant
         *  double** m = NULL;                // pointer to pointers to implement 2d
         *  // square array
         *
         *  if (n < 1) { }                // error condition, should never get here
         *
         *  else if (n == 1)
         *  {                 // should not get here
         *      det = a[0][0];
         *  }
         *
         *  else if (n == 2)
         *  {                // basic 2X2 sub-matrix determinate
         *      // definition. When n==2, this ends the
         *      det = a[0][0] * a[1][1] - a[1][0] * a[0][1];// the recursion series
         *  }
         *
         *
         *                                     // recursion continues, solve next sub-matrix
         *  else
         *  {                             // solve the next minor by building a
         *      // sub matrix
         *      det = 0;                      // initialize determinant of sub-matrix
         *
         *      // for each column in sub-matrix
         *      for (j1 = 0; j1 < n; j1++)
         *      {
         *          // get space for the pointer list
         *          m = (double**)malloc((n - 1) * sizeof(double*));
         *
         *          for (i = 0; i < n - 1; i++)
         *              m[i] = (double*)malloc((n - 1) * sizeof(double));
         *          //     i[0][1][2][3]  first malloc
         *          //  m -> +  +  +  +   space for 4 pointers
         *          //       |  |  |  |          j  second malloc
         *          //       |  |  |  +-> _ _ _ [0] pointers to
         *          //       |  |  +----> _ _ _ [1] and memory for
         *          //       |  +-------> _ a _ [2] 4 doubles
         *          //       +----------> _ _ _ [3]
         *          //
         *          //                   a[1][2]
         *          // build sub-matrix with minor elements excluded
         *          for (i = 1; i < n; i++)
         *          {
         *              j2 = 0;               // start at first sum-matrix column position
         *              // loop to copy source matrix less one column
         *              for (j = 0; j < n; j++)
         *              {
         *                  if (j == j1) continue; // don't copy the minor column element
         *
         *                  m[i - 1][j2] = a[i][j];  // copy source element into new sub-matrix
         *                  // i-1 because new sub-matrix is one row
         *                  // (and column) smaller with excluded minors
         *                  j2++;                  // move to next sub-matrix column position
         *              }
         *          }
         *
         *          det += pow(-1.0, 1.0 + j1 + 1.0) * a[0][j1] * Determinant(m, n - 1);
         *          // sum x raised to y power
         *          // recursively get determinant of next
         *          // sub-matrix which is now one
         *          // row & column smaller
         *
         *          for (i = 0; i < n - 1; i++) free(m[i]);// free the storage allocated to
         *          // to this minor's set of pointers
         *          free(m);                       // free the storage for the original
         *          // pointer to pointer
         *      }
         *  }
         *  return (det);
         * }
         */

        // the code above is converted by  me Ahmed Sadek to support determinant in Qs  :)
        //  I copied the code with the information about who made it to preserve the rights of the person
        //    who made this effort.
        //   Thank you

        public static QsScalar Determinant(QsMatrix a)
        {
            // code taken from: http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/determinant/

            int      n   = a.RowsCount;
            QsScalar det = default(QsScalar);

            if (n < 1)
            {
                throw new QsException("Zero component matrix, are you crazy :)");                       // error condition, should never get here
            }
            else if (n == 1)
            {
                // should not get here
                det = a[0][0];
            }

            else if (n == 2)
            {
                // basic 2X2 sub-matrix determinate
                // definition. When n==2, this ends the
                det = a[0][0] * a[1][1] - a[1][0] * a[0][1];// the recursion series
            }

            // recursion continues, solve next sub-matrix
            else
            {                             // solve the next minor by building a
                // sub matrix

                int i, j, j1, j2;

                QsMatrix m = QsMatrix.MakeEmptySquareMatrix(n - 1);

                // for each column in sub-matrix
                for (j1 = 0; j1 < n; j1++)
                {
                    // build sub-matrix with minor elements excluded
                    for (i = 1; i < n; i++)
                    {
                        j2 = 0;               // start at first sum-matrix column position

                        // loop to copy source matrix less one column
                        for (j = 0; j < n; j++)
                        {
                            if (j == j1)
                            {
                                continue;           // don't copy the minor column element
                            }
                            m[i - 1][j2] = a[i][j]; // copy source element into new sub-matrix
                            // i-1 because new sub-matrix is one row
                            // (and column) smaller with excluded minors
                            j2++;                  // move to next sub-matrix column position
                        }
                    }

                    var fn = System.Math.Pow(-1.0, 1.0 + j1 + 1.0);
                    var f  = fn.ToQuantity().ToScalar();
                    var mr = Determinant(m);

                    if (det == null)
                    {
                        det = f * (a[0][j1] * mr);
                    }
                    else
                    {
                        det += f * (a[0][j1] * mr);
                    }

                    // sum x raised to y power
                    // recursively get determinant of next
                    // sub-matrix which is now one
                    // row & column smaller
                }
            }

            return(det);
        }