public void DetTest() { var matrix = new Matrix(new[] { new Vector(new[] { new Number(1), new Number(-2), new Number(3) }), new Vector(new[] { new Number(4), new Number(0), new Number(6) }), new Vector(new[] { new Number(-7), new Number(8), new Number(9) }) }); var det = matrix.Determinant(); Assert.AreEqual(204, det); }
public void Simple() { var matrix = new Matrix(3, 3); // [ 3, 1, 8 ] // [ 2, -5, 4 ] // [-1, 6, -2 ] // Determinant = 14 matrix[0, 0] = 3; matrix[0, 1] = 1; matrix[0, 2] = 8; matrix[1, 0] = 2; matrix[1, 1] = -5; matrix[1, 2] = 4; matrix[2, 0] = -1; matrix[2, 1] = 6; matrix[2, 2] = -2; Assert.AreEqual(14, matrix.Determinant(), 0.000000001); }
/// <summary> /// Evaluates the probability density function for the Wishart distribution. /// </summary> /// <param name="x">The matrix at which to evaluate the density at.</param> /// <exception cref="ArgumentOutOfRangeException">If the argument does not have the same dimensions as the scale matrix.</exception> /// <returns>the density at <paramref name="x"/>.</returns> public double Density(Matrix<double> x) { var p = _s.RowCount; if (x.RowCount != p || x.ColumnCount != p) { throw Matrix.DimensionsDontMatch<ArgumentOutOfRangeException>(x, _s, "x"); } var dX = x.Determinant(); var siX = _chol.Solve(x); // Compute the multivariate Gamma function. var gp = Math.Pow(Constants.Pi, p * (p - 1.0) / 4.0); for (var j = 1; j <= p; j++) { gp *= SpecialFunctions.Gamma((_nu + 1.0 - j) / 2.0); } return Math.Pow(dX, (_nu - p - 1.0) / 2.0) * Math.Exp(-0.5 * siX.Trace()) / Math.Pow(2.0, _nu * p / 2.0) / Math.Pow(_chol.Determinant, _nu / 2.0) / gp; }
public void Matrix_DeterminantCalculatedCorrectly() { var matrix = new Matrix( 3, 2, 0, 1, 4, 0, 1, 2, 3, 0, 2, 1, 9, 2, 3, 1); var determinant = matrix.Determinant(); TheResultingValue(determinant) .WithinDelta(0.1f).ShouldBe(24.0f); }
public void Determinant() { Matrix matrix = new Matrix(new double[][] { new double[] { 1.0, 2.0 }, new double[] { 3.0, 4.0 } }); double result = matrix.Determinant(); Assert.AreEqual((1.0 * 4.0) - (2.0 * 3.0), result); }
public void DeterminantRaiseException() { Matrix matrix = new Matrix(new double[][] { new double[] { 1.0, 2.0 }, new double[] { 3.0, 4.0 }, new double[] { 5.0, 6.0 } }); try { matrix.Determinant(); Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(InvalidOperationException)); Assert.AreEqual("Matrix is not square", ex.Message); } }
/// <summary> /// Given the transform to be applied to an unknown rectangle, this method finds (in axis-aligned local space) /// the largest rectangle that, after transform, fits within <paramref name="localBounds"/>. /// Largest rectangle means rectangle of the greatest area in local space (although maximal area in local space /// implies maximal area in transform space). /// </summary> /// <param name="transform">Transformation matrix.</param> /// <param name="localBounds">The bounds in local space where the returned size fits when transformed /// via the given <paramref name="transform"/>.</param> /// <returns>The dimensions, in local space, of the maximal area rectangle found.</returns> private static SizeF FindMaxTransformedSize(Matrix transform, SizeF localBounds) { // X (width) and Y (height) constraints for axis-aligned bounding box in dest. space float xConstr = localBounds.Width; float yConstr = localBounds.Height; // Avoid doing math on an empty rect if (IsNear(xConstr, 0) || IsNear(yConstr, 0)) return new SizeF(0, 0); bool xConstrInfinite = float.IsNaN(xConstr); bool yConstrInfinite = float.IsNaN(yConstr); if (xConstrInfinite && yConstrInfinite) return new SizeF(float.NaN, float.NaN); if (xConstrInfinite) // Assume square for one-dimensional constraint xConstr = yConstr; else if (yConstrInfinite) yConstr = xConstr; // We only deal with nonsingular matrices here. The nonsingular matrix is the one // that has inverse (determinant != 0). if (transform.Determinant() == 0) return new SizeF(0, 0); float a = transform.M11; float b = transform.M12; float c = transform.M21; float d = transform.M22; // Result width and height (in child/local space) float w; float h; // Because we are dealing with nonsingular transform matrices, we have (b==0 || c==0) XOR (a==0 || d==0) if (IsNear(b, 0) || IsNear(c, 0)) { // (b == 0 || c == 0) ==> a != 0 && d != 0 float yCoverD = yConstrInfinite ? float.PositiveInfinity : Math.Abs(yConstr / d); float xCoverA = xConstrInfinite ? float.PositiveInfinity : Math.Abs(xConstr / a); if (IsNear(b, 0)) { if (IsNear(c, 0)) { // b == 0, c == 0, a != 0, d != 0 // No constraint relation; use maximal width and height h = yCoverD; w = xCoverA; } else { // b == 0, a != 0, c != 0, d != 0 // Maximizing under line (hIntercept=xConstr/c, wIntercept=xConstr/a) // BUT we still have constraint: h <= yConstr/d h = Math.Min(0.5f * Math.Abs(xConstr / c), yCoverD); w = xCoverA - ((c * h) / a); } } else { // c == 0, a != 0, b != 0, d != 0 // Maximizing under line (hIntercept=yConstr/d, wIntercept=yConstr/b) // BUT we still have constraint: w <= xConstr/a w = Math.Min(0.5f * Math.Abs(yConstr / b), xCoverA); h = yCoverD - ((b * w) / d); } } else if (IsNear(a, 0) || IsNear(d, 0)) { // (a == 0 || d == 0) ==> b != 0 && c != 0 float yCoverB = Math.Abs(yConstr / b); float xCoverC = Math.Abs(xConstr / c); if (IsNear(a, 0)) { if (IsNear(d, 0)) { // a == 0, d == 0, b != 0, c != 0 // No constraint relation; use maximal width and height h = xCoverC; w = yCoverB; } else { // a == 0, b != 0, c != 0, d != 0 // Maximizing under line (hIntercept=yConstr/d, wIntercept=yConstr/b) // BUT we still have constraint: h <= xConstr/c h = Math.Min(0.5f * Math.Abs(yConstr / d), xCoverC); w = yCoverB - ((d * h) / b); } } else { // d == 0, a != 0, b != 0, c != 0 // Maximizing under line (hIntercept=xConstr/c, wIntercept=xConstr/a) // BUT we still have constraint: w <= yConstr/b w = Math.Min(0.5f * Math.Abs(xConstr / a), yCoverB); h = xCoverC - ((a * w) / c); } } else { float xCoverA = Math.Abs(xConstr / a); // w-intercept of x-constraint line float xCoverC = Math.Abs(xConstr / c); // h-intercept of x-constraint line float yCoverB = Math.Abs(yConstr / b); // w-intercept of y-constraint line float yCoverD = Math.Abs(yConstr / d); // h-intercept of y-constraint line // The tighest constraint governs, so we pick the lowest constraint line // The optimal point (w, h) for which Area = w*h is maximized occurs halfway to each intercept. w = Math.Min(yCoverB, xCoverA) * 0.5f; h = Math.Min(xCoverC, yCoverD) * 0.5f; if ((GreaterThanOrClose(xCoverA, yCoverB) && LessThanOrClose(xCoverC, yCoverD)) || (LessThanOrClose(xCoverA, yCoverB) && GreaterThanOrClose(xCoverC, yCoverD))) { // Constraint lines cross; since the most restrictive constraint wins, // we have to maximize under two line segments, which together are discontinuous. // Instead, we maximize w*h under the line segment from the two smallest endpoints. // Since we are not (except for in corner cases) on the original constraint lines, // we are not using up all the available area in transform space. So scale our shape up // until it does in at least one dimension. SizeF childSizeTr = new SizeF(w, h); transform.TransformIncludingRectangleSize(ref childSizeTr); float expandFactor = Math.Min(xConstr / childSizeTr.Width, yConstr / childSizeTr.Height); if (!float.IsNaN(expandFactor) && !float.IsInfinity(expandFactor)) { w *= expandFactor; h *= expandFactor; } } } return new SizeF(w, h); }
/// <summary> /// Given a pair of dimensions, this method calculates the size of the largest rectangle that will fit within /// those dimensions after having the specified transformation applied to it. /// </summary> /// <param name="xmax">The available width.</param> /// <param name="ymax">The available height.</param> /// <param name="transform">The transformation matrix to apply.</param> /// <returns>The size of the largest rectangle that will still fit within the available space after the specified transform is applied.</returns> private static Size2D CalculateMaximumAvailableSizeBeforeLayoutTransform(Double xmax, Double ymax, Matrix transform) { /* When using layout transforms, it's possible for an element to produce a desired size which, after the transform * is applied, will cause the element to lie outside of its maximum available layout area. To address this problem, * we need to shrink the available size that is passed into MeasureCore() such that, even if the element is as big * as it possibly can be, its post-transform bounds will still lie within the available layout area. * * To that end, we need to do a bit of calculus. Given the true maximum area (A_true) and a transformation * matrix (M_transform), we need to calculate the largest possible rectangle that will fit within A_true * after it has been subjected to M_transform. This will be the area that we pass into MeasureCore(). * * For simplicity's sake, consider the case of a rotation transform. Rotating a rectangle will cause its x-dimension * to point partially along both the x- and y-axes of the untransformed space. If we gradually make the rectangle wider, * it will eventually reach a point where its size along the untransformed x-axis will exceed our maximum width, and another * point where its size along the untransformed y-axis will exceed our maximum width. The smallest of these two widths * is the largest possible width of the transformed rectangle. We can do likewise to constrain the rectangle's height; * the biggest possible rectangle will have a width and height somewhere below the values established by these constraints. * * We can use trigonometry to establish that there is a simple linear relationship between the width of the transformed * rectangle and its dimensions along the untransformed x- and y-axes, such that w / sin(theta) = h / cos(theta). We can * use this to graph a pair of lines representing our transformed rectangle's width and height. We can then take the * first derivative in order to find the biggest rectangle that will fit under the lines. * * Let a = w / sin(theta) and b = h / cos(theta). * * The line formed by intercepts a and b forms a right triangle with the axes, so the total area beneath it is .5ab. * Given that we are trying to find the area of a rectangle beneath this line with dimensions x and y, we can equivalently * say that the triangle's total area is .5ay + .5bx. Solving for y, we find that y = (ab - bx) / a. We can then plug * this into the equation for the area of a rectangle, A = xy, to get A = x((ab - bx) / a). Taking the first derivative * and solving for x, we find that x = a / 2. Doing the same for y reveals, likewise, that y = b / 2. Therefore, the * biggest rectangle has dimensions halfway between the intercepts that form the line. */ if (Double.IsInfinity(xmax) && Double.IsInfinity(ymax)) return new Size2D(Double.PositiveInfinity, Double.PositiveInfinity); xmax = Double.IsInfinity(xmax) ? ymax : xmax; ymax = Double.IsInfinity(ymax) ? xmax : ymax; if (MathUtil.IsApproximatelyZero(xmax) || MathUtil.IsApproximatelyZero(ymax) || MathUtil.IsApproximatelyZero(transform.Determinant())) return Size2D.Zero; var m11 = transform.M11; var m21 = transform.M21; var m12 = transform.M12; var m22 = transform.M22; var w = 0.0; var h = 0.0; var xConstraintInterceptW = MathUtil.IsApproximatelyZero(m11) ? Double.NaN : Math.Abs(xmax / m11); var xConstraintInterceptH = MathUtil.IsApproximatelyZero(m12) ? Double.NaN : Math.Abs(xmax / m12); var yConstraintInterceptW = MathUtil.IsApproximatelyZero(m21) ? Double.NaN : Math.Abs(ymax / m21); var yConstraintInterceptH = MathUtil.IsApproximatelyZero(m22) ? Double.NaN : Math.Abs(ymax / m22); var xConstraintIsHorz = Double.IsNaN(xConstraintInterceptW); var xConstraintIsVert = Double.IsNaN(xConstraintInterceptH); var xConstraintIsHorzOrVert = xConstraintIsHorz || xConstraintIsVert; var yConstraintIsHorz = Double.IsNaN(yConstraintInterceptW); var yConstraintIsVert = Double.IsNaN(yConstraintInterceptH); var yConstraintIsHorzOrVert = yConstraintIsHorz || yConstraintIsVert; /* Below, we handle special cases where one or both of the constraint lines is vertical or horizontal due to zeroes in * the transformation matrix. This causes some of our intercepts to go undefined, which means their constraint lines * don't constrain one (or either) of our dimensions. */ if (xConstraintIsHorzOrVert && yConstraintIsHorzOrVert) { w = xConstraintIsVert ? xConstraintInterceptW : yConstraintInterceptW; h = xConstraintIsVert ? yConstraintInterceptH : xConstraintInterceptH; return new Size2D(w, h); } if (xConstraintIsVert || yConstraintIsVert) { var slope = xConstraintIsVert ? m21 / m22 : m11 / m12; w = xConstraintIsVert ? Math.Min(yConstraintInterceptW * 0.5, xConstraintInterceptW) : Math.Min(xConstraintInterceptW * 0.5, yConstraintInterceptW); h = (xConstraintIsVert ? yConstraintInterceptH : xConstraintInterceptH) - (slope * w); return new Size2D(w, h); } if (xConstraintIsHorz || yConstraintIsHorz) { var slope = xConstraintIsHorz ? m12 / m11 : m22 / m21; h = xConstraintIsHorz ? Math.Min(yConstraintInterceptH * 0.5, xConstraintInterceptH) : Math.Min(xConstraintInterceptH * 0.5, yConstraintInterceptH); w = (xConstraintIsHorz ? yConstraintInterceptW : xConstraintInterceptW) - (slope * h); return new Size2D(w, h); } /* If both constraint lines have a well-defined, non-zero slope, then the dimensions of the maximized rectangle lie halfway between the smaller line's * intercepts, as we established above using the first derivative. * * This is only true if the lines do not cross - otherwise, there is no clear "smaller line." So what we have to do is draw a third line * using the smallest intercept on both axes, then maximize beneath that instead. The result will actually be too small, since it doesn't correspond * to either of our original constraint lines; to address this problem, we scale the resulting size upwards until it saturates our constraints. */ w = Math.Min(xConstraintInterceptW, yConstraintInterceptW) * 0.5; h = Math.Min(xConstraintInterceptH, yConstraintInterceptH) * 0.5; var constraintXSlope = xConstraintInterceptH / xConstraintInterceptW; var constraintYSlope = yConstraintInterceptH / xConstraintInterceptW; var constraintLinesCross = !MathUtil.AreApproximatelyEqual(constraintXSlope, constraintYSlope); if (constraintLinesCross) { RectangleD area = new RectangleD(0, 0, w, h); RectangleD.TransformAxisAligned(ref area, ref transform, out area); var scale = Math.Min(xmax / area.Width, ymax / area.Height); w *= scale; h *= scale; } return new Size2D(w, h); }
public void Simple2() { var matrix = new Matrix(4, 4); // [ 1, 2, 3, 4 ] // [ 5, 6, 7, 8 ] // [ 2, 6, 4, 8 ] // [ 3, 1, 1, 2 ] // Determinant = 72 matrix[0, 0] = 1; matrix[0, 1] = 2; matrix[0, 2] = 3; matrix[0, 3] = 4; matrix[1, 0] = 5; matrix[1, 1] = 6; matrix[1, 2] = 7; matrix[1, 3] = 8; matrix[2, 0] = 2; matrix[2, 1] = 6; matrix[2, 2] = 4; matrix[2, 3] = 8; matrix[3, 0] = 3; matrix[3, 1] = 1; matrix[3, 2] = 1; matrix[3, 3] = 2; Assert.AreEqual(matrix.Determinant(), 72, 0.000000001); }
public void ExceptionNotSquare() { var matrix = new Matrix(2, 3); matrix.Determinant(); }
public void DeterminantTest1() { double[,] data = null; // TODO: инициализация подходящего значения Matrix target = new Matrix(data); // TODO: инициализация подходящего значения double expected = 0F; // TODO: инициализация подходящего значения double actual; actual = target.Determinant(); Assert.AreEqual(expected, actual); Assert.Inconclusive("Проверьте правильность этого метода теста."); }
private static Vector3 ScreenRelToWorld(Matrix mView, Vector2 screenCoordsRel) { mView.Transpose(); var vForward = mView.Row4; var vRight = mView.Row2; var vUpward = mView.Row3; var d = 1 - vForward.W; var h = screenCoordsRel.X - vRight.W; var s = -screenCoordsRel.Y - vUpward.W; var m = new Matrix(vForward.X, vForward.Y, vForward.Z, 0, vRight.X, vRight.Y, vRight.Z, 0, vUpward.X, vUpward.Y, vUpward.Z, 0, 0, 0, 0, 1); var det = m.Determinant(); var mx = new Matrix(d, vForward.Y, vForward.Z, 0, h, vRight.Y, vRight.Z, 0, s, vUpward.Y, vUpward.Z, 0, 0, 0, 0, 1); var detx = mx.Determinant(); var my = new Matrix(vForward.X, d, vForward.Z, 0, vRight.X, h, vRight.Z, 0, vUpward.X, s, vUpward.Z, 0, 0, 0, 0, 1); var dety = my.Determinant(); var mz = new Matrix(vForward.X, vForward.Y, d, 0, vRight.X, vRight.Y, h, 0, vUpward.X, vUpward.Y, s, 0, 0, 0, 0, 1); var detz = mz.Determinant(); var epsilon = 0.0000001; return Math.Abs(det) < epsilon ? new Vector3() : new Vector3(detx / det, dety / det, detz / det); }
public int Test(Matrix matrix1, Matrix matrix2, double[] means1, double[] means2, double[] vector) { var m1 = new Matrix(matrix1); var m2 = new Matrix(matrix2); var matrix_means1 = new Vector(means1); var matrix_means2 = new Vector(means2); var matrix_vector = new Vector(vector); // Calculate A B C var A = m2.Inverse() - m1.Inverse(); var B = 2 * (Matrix.Multiply(matrix_means1.ToMatrix().Transpose(), m1.Inverse()) - Matrix.Multiply(matrix_means2.ToMatrix().Transpose(), m2.Inverse())); var C = (Matrix.Multiply(Matrix.Multiply(matrix_means2.ToMatrix().Transpose(), m2.Inverse()), matrix_means2.ToMatrix())).Determinant() - (Matrix.Multiply(Matrix.Multiply(matrix_means1.ToMatrix().Transpose(), m1.Inverse()), matrix_means1.ToMatrix()).Determinant() - 2 * (Math.Log10(m1.Determinant() / m2.Determinant()))); var result = Matrix.Multiply(Matrix.Multiply(matrix_vector.ToMatrix().Transpose(), A), matrix_vector.ToMatrix()).Determinant() + B[0, 0] * matrix_vector[0] + B[0, 2] * matrix_vector[2] + B[0, 2] * matrix_vector[2] + C; if (result > 0) { return 1; } return 2; }
public void DrawDiscreminant(Panel p, Matrix matrix1, Matrix matrix2, double[] means1, double[] means2, int x, int y) { var m1 = new Matrix(matrix1); var m2 = new Matrix(matrix2); var matrix_means1 = new Vector(means1); var matrix_means2 = new Vector(means2); // Calculate A B C var A = m2.Inverse() - m1.Inverse(); var B = 2 * (Matrix.Multiply(matrix_means1.ToMatrix().Transpose(), m1.Inverse()) - Matrix.Multiply(matrix_means2.ToMatrix().Transpose(), m2.Inverse())); var C = (Matrix.Multiply(Matrix.Multiply(matrix_means2.ToMatrix().Transpose(), m2.Inverse()), matrix_means2.ToMatrix())).Determinant() - (Matrix.Multiply(Matrix.Multiply(matrix_means1.ToMatrix().Transpose(), m1.Inverse()), matrix_means1.ToMatrix()).Determinant() - 2 * (Math.Log10(m1.Determinant() / m2.Determinant()))); var a11 = A[x, x]; var a12 = A[x, y]; var a21 = A[y, x]; var a22 = A[y, y]; var b1 = B[0, x]; var b2 = B[0, y]; for (double i = -20; i < 20; i = i + 0.1) { var quad = a22; var line = a12 * i + a21 * i + b2; var cons = C + b1 * i + a11 * i * i; if ((line * line - 4 * quad * cons) >= 0) { try { if (quad != 0) { var j = (-line + Math.Sqrt(line * line - 4 * quad * cons)) / (2 * quad); Draw(p, Color.Black, i, j); j = (-line - Math.Sqrt(line * line - 4 * quad * cons)) / (2 * quad); Draw(p, Color.Black, i, j); } else if (line != 0) { var j = -cons / line; Draw(p, Color.Black, i, j); } } catch(Exception) { } } } }