Every now and then, I refactor a machine learning program from Python/NumPy to C#. A mildly troublesome detail occurs when the Python/NumPy code multiplies a 2D matrix and a 1D vector together. In theory, this shouldn’t even be possible, but Python/NumPy allows the operation.
Ordinary matrix multiplication isn’t a problem for C#. For example, it’s easy to implement a MatMultiply() function that accepts, say, a 3×4 matrix A, and a 4×5 matrix B, and returns the 3×5 result.
But suppose matrix A is shape 3×4 and vector v has length 4. Then np.matmul(A, v) returns a vector with length 3. In essence, the np.matmul() converts the vector v to a 4×1 matrix, then applies standard matrix multiplication, giving a 3×1 matrix, which is then flattened to a vector with length 3.
The same idea works for np.matmul(w, A). Suppose w is a vector with length 3 and A is a matrix with shape 3×4. The w vector is converted to a 1×3 matrix and then the matrix multiplication result is 1×4, which is then flattened to a vector with length 4.
Now to implement multiplying a matrix and a vector together using C#, there are two possibilities. The first approach would be to explicitly convert the vector parameter to a matrix, perform matrix multiplication, then explicitly convert the result to a vector.
The second approach is to directly compute the vector result, and skip all the conversions to and from matrix and vectors. I usually use the second, simpler approach.
I guess there’s no big moral to the story, except that when working with matrices and vectors, it’s important to keep the shapes and lengths synchronized correctly.

There’s an interesting effect called spontaneous synchronization. If you set up a sequence of metronomes, and start them at random times, they will eventually synchronize themselves. The trick is that the metronomes must be indirectly connected. In the image above, the five metronomes are all on the same wooden base and vibrations can travel between the metronomes.
The bottom photo shows some sort of Asian baseball cheerleaders who are exhibiting excellent synchronization. I speculate that the cheerleaders might get vibration input through the platform they’re standing on, which may help them stay synchronized.
Demo program. Replace “lt” with Boolean less than operator symbol.
using System;
using System.IO;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("\nMultiplying a matrix and a" +
" vector together using C# ");
double[][] A = new double[3][]; // A is 3x4
A[0] = new double[] { 1.0, 2.0, 3.0, 4.0 };
A[1] = new double[] { 5.0, 6.0, 7.0, 8.0 };
A[2] = new double[] { 1.0, 9.0, 5.0, 2.0 };
double[] v = new double[] { 2.0, 4.0, 6.0, 8.0 };
double[] w = new double[] { 3.0, 5.0, 7.0 };
Console.WriteLine("\nA: ");
MatShow(A, 1, 5);
Console.WriteLine("\nv = ");
VecShow(v, 1, 5);
Console.WriteLine("\nw = ");
VecShow(w, 1, 5);
double[] Av = MatVecProd(A, v);
Console.WriteLine("\nA * v = ");
VecShow(Av, 1, 8);
double[] wA = VecMatProd(w, A);
Console.WriteLine("\nw * A = ");
VecShow(wA, 1, 8);
Console.WriteLine("\nEnd demo ");
Console.ReadLine();
} // Main()
static double[] MatVecProd(double[][] M, double[] v)
{
// return a regular vector
int nRows = M.Length;
int nCols = M[0].Length;
int n = v.Length;
if (nCols != n)
throw new Exception("non-comform in MatVecProd");
double[] result = new double[nRows];
for (int i = 0; i "lt" nRows; ++i)
for (int k = 0; k "lt" nCols; ++k)
result[i] += M[i][k] * v[k];
return result;
}
static double[] VecMatProd(double[] v, double[][] M)
{
// return a regular vector
int nRows = M.Length;
int nCols = M[0].Length;
int n = v.Length;
if (n != nRows)
throw new Exception("non-comform in VecMatProd");
double[] result = new double[nCols];
for (int j = 0; j "lt" nCols; ++j)
for (int k = 0; k "lt" n; ++k)
result[j] += v[k] * M[k][j];
return result;
}
static void MatShow(double[][] M, int dec, int wid)
{
double small = 1.0 / Math.Pow(10, dec);
for (int i = 0; i "lt" M.Length; ++i)
{
for (int j = 0; j "lt" M[0].Length; ++j)
{
double v = M[i][j];
if (Math.Abs(v) "lt" small) v = 0.0; // avoid "-0.0"
Console.Write(v.ToString("F" + dec).PadLeft(wid));
}
Console.WriteLine("");
}
}
static void VecShow(double[] vec, int dec, int wid)
{
for (int i = 0; i "lt" vec.Length; ++i)
{
double x = vec[i];
if (Math.Abs(x) "lt" 1.0e-5) x = 0.0; // avoid "-0.00"
Console.Write(x.ToString("F" + dec).PadLeft(wid));
}
Console.WriteLine("");
}
} // class Program
} // ns

.NET Test Automation Recipes
Software Testing
SciPy Programming Succinctly
Keras Succinctly
R Programming
2026 Visual Studio Live
2025 Summer MLADS Conference
2025 DevIntersection Conference
2025 Machine Learning Week
2025 Ai4 Conference
2025 G2E Conference
2025 iSC West Conference
You must be logged in to post a comment.