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); }
/// <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; } }
/// <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); }
/// <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<SymbolicVariable>"/></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)); } }
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")); }
/// <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); }
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(); }
public Shape Circle(QsScalar x, QsScalar y, QsScalar radius) { Shape s; lock (Shapes) { s = new Circle(x, y, radius); Shapes.Add(s); } return(s); }
/// <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")); }
/// <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")); }
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); }
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); }
/// <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); }
/// <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 + "]"); } }
/// <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); }
/// <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); }
/// <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); }
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); }
static Z80() { R = QsScalar.Zero; }
/// <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(); } }
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(); } }
// 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); }