// Matrix mean of 2D Array along a dimension public static void Mean(ManagedArray dst, ManagedArray src, int dim) { if (dim == 1) { dst.Resize(src.x, 1, false); for (int x = 0; x < src.x; x++) { var sum = 0.0; for (int y = 0; y < src.y; y++) { sum += src[x, y]; } dst[x] = sum / src.y; } } else { dst.Resize(1, src.y, false); for (int y = 0; y < src.y; y++) { double sum = 0.0; for (int x = 0; x < src.x; x++) { sum += src[x, y]; } dst[y] = sum / src.x; } } }
// Flip Matrix along a dimension public static void Flip(ManagedArray dst, ManagedArray src, int FlipDim) { dst.Resize(src.x, src.y, src.z, false); for (int z = 0; z < src.z; z++) { for (int y = 0; y < src.y; y++) { for (int x = 0; x < src.x; x++) { switch (FlipDim) { case 0: dst[x, y, z] = src[src.x - x - 1, y, z]; break; case 1: dst[x, y, z] = src[x, src.y - y - 1, z]; break; case 2: dst[x, y, z] = src[x, y, src.z - z - 1]; break; default: dst[x, y, z] = src[src.x - x - 1, y, z]; break; } } } } }
// 2D Matrix multiplication public static void Multiply(ManagedArray result, ManagedArray A, ManagedArray B) { if (A.x == B.y) { /* * * // Naive version * result.Resize(B.x, A.y, false); * * for (var y = 0; y < A.y; y++) * { * for (var x = 0; x < B.x; x++) * { * result[x, y] = 0; * * for (var k = 0; k < A.x; k++) * { * result[x, y] = result[x, y] + A[k, y] * B[x, k]; * } * } * } */ // slightly faster (due to memory access pattern) but still naive // see: https://tavianator.com/a-quick-trick-for-faster-naive-matrix-multiplication/ var dest = 0; var lhs = 0; var rhs = 0; var mid = A.x; var cols = B.x; var rows = A.y; result.Resize(cols, rows, true); for (var y = 0; y < rows; y++) { rhs = 0; for (var x = 0; x < mid; x++) { for (var k = 0; k < cols; k++) { result[dest + k] += A[lhs + x] * B[rhs + k]; } rhs += cols; } dest += cols; lhs += mid; } } else { Console.WriteLine("Incompatible dimensions"); } }
// ------------------------------------------------------------------------------------ // Matrix Operations // ------------------------------------------------------------------------------------ // 2D Matrix transposition public static void Transpose(ManagedArray dst, ManagedArray src) { dst.Resize(src.y, src.x, false); for (int y = 0; y < src.y; y++) { for (int x = 0; x < src.x; x++) { dst[y, x] = src[x, y]; } } }
// Rotate a 2D matrix public static void Rotate180(ManagedArray dst, ManagedArray src) { dst.Resize(src.x, src.y); var tmp = new ManagedArray(src.x, src.y, false); ManagedOps.Copy2D(tmp, src, 0, 0); for (int FlipDim = 0; FlipDim < 2; FlipDim++) { Flip(dst, tmp, FlipDim); ManagedOps.Copy2D(tmp, dst, 0, 0); } ManagedOps.Free(tmp); }
// Flip 3D Matrix along a dimension public static void FlipAll(ManagedArray dst, ManagedArray src) { dst.Resize(src.x, src.y, src.z, false); var tmp = new ManagedArray(src.x, src.y, src.z, false); ManagedOps.Copy3D(tmp, src, 0, 0, 0); for (var FlipDim = 0; FlipDim < 3; FlipDim++) { Flip(dst, tmp, FlipDim); ManagedOps.Copy3D(tmp, dst, 0, 0, 0); } ManagedOps.Free(tmp); }
public static void Convolve(ManagedArray input, ManagedArray filter, ManagedArray result, int minx, int miny, int minz, int limx, int limy, int limz) { result.Resize(limx, limy, limz, false); if (input.x >= filter.x & input.y >= filter.y & input.z >= filter.z) { for (int ck = minz; ck < minz + limz; ck++) { for (int cj = miny; cj < miny + limy; cj++) { for (int ci = minx; ci < minx + limx; ci++) { result[ci - minx, cj - miny, ck - minz] = 0; for (int kz = 0; kz < input.z; kz++) { var boundz = ck - kz; if (boundz >= 0 & boundz < filter.z & kz < input.z & kz >= 0) { for (int ky = 0; ky < input.y; ky++) { var boundy = cj - ky; if (boundy >= 0 & boundy < filter.y & ky < input.y & ky >= 0) { for (int kx = 0; kx < input.x; kx++) { var boundx = ci - kx; if (boundx >= 0 & boundx < filter.x & kx < input.x & kx >= 0) { result[ci - minx, cj - miny, ck - minz] = result[ci - minx, cj - miny, ck - minz] + input[kx, ky, kz] * filter[boundx, boundy, boundz]; } } } } } } } } } } }
// Expand a matrix A[x][y] by [ex][ey] public static void Expand(ManagedArray A, int expandx, int expandy, ManagedArray output) { var outputx = A.x * expandx; var outputy = A.y * expandy; output.Resize(outputx, outputy, false); for (int y = 0; y < A.y; y++) { for (int x = 0; x < A.x; x++) { for (int SZy = 0; SZy < expandy; SZy++) { for (int SZx = 0; SZx < expandx; SZx++) { output[x * expandx + SZx, y *expandy + SZy] = A[x, y]; } } } } }
// 2D Matrix multiplication public static void Multiply(ManagedArray result, ManagedArray A, ManagedArray B) { if (A.x == B.y) { result.Resize(B.x, A.y, false); for (int y = 0; y < A.y; y++) { for (int x = 0; x < B.x; x++) { result[x, y] = 0.0; for (int k = 0; k < A.x; k++) { result[x, y] = result[x, y] + A[k, y] * B[x, k]; } } } } else { Console.WriteLine("Incompatible dimensions"); } }