Reputation: 571
I have a vector (1D array) of double values, say X. I need to copy this vector of values into a matrix (2D array), say Y, such that the first row of Y is the same as X transposed, the second row is the same as X shifted one value to the left, the third row of Y is the same as X shifted two values to the left and so on.
For example,
X = { 1.0, 2.0. 3.0, 4.0, 5.0 }
and I need
Y = 1.0 2.0 3.0 4.0 5.0
2.0 3.0 4.0 5.0 0.0
3.0 4.0 5.0 0.0 0.0
4.0 5.0 0.0 0.0 0.0
5.0 0.0 0.0 0.0 0.0
Some time ago Mathew Finlay posted code for copying 1D array to a 2D array for value types. I have modified the code as follows:
for (int targetRow = 0; targetRow < N; targetRow++)
{
Buffer.BlockCopy
(
X, // 1D source array
0, // source array offset
Y, // 2D target (destination) array
targetRow * Y.GetLength(targetRow) * sizeof(double), // target array offset
X.Length * sizeof(double) // count
);
}
I am not sure if this will do the trick and more importantly, whether this is the best way of doing this. This is part of a larger code and this part needs to be fast and efficient as the vector X and the matrix Y can get very large.
Also, to complicate things a bit more, I may sometines not require the full length (all the values) of vector X but only part of it so the matrix Y could be N x M where M <= N. I am not sure how to handle this in the code above.
Thank you in advance for any help or suggestions you may be able to provide.
EDIT: For those interested, here are some performance results.
I ran some speed tests on the two types of code suggested here (looping and Buffer.BlockCopy) and the results surprised me. I will designate the Buffer.BlockCopy as BC and looping as L. For 10x10 matrix BC = 00:00:00.0000017 and L = 00:00:00.0000030. For 100x100 matrix BC = 00:00:00.0000293 and L = 00:00:00.0000710. Finally, for 1000x1000 matrix BC = 00:00:00.0065340 and L = 00:00:00.0138396. So the Buffer.Block copy seems to outperform looping even for small matrices. I ran this on a Win 7 Ultimate (64) machine.
Upvotes: 1
Views: 1670
Reputation: 7313
What about?
double[] X = new double[]{ 1.0, 2.0, 3.0, 4.0, 5.0 };
var lbound = X.GetLowerBound(0);
var ubound = X.GetUpperBound(0);
double[,] Y = new double[ubound + 1, ubound + 1];
for (var i = lbound; i <= ubound; i++)
{
for (var j = lbound ; j <= ubound ; j++)
{
Y[i, j] = (i + j) > ubound ? 0.0 : X[i +j];
}
}
Edit
This works:
for (int targetRow = 0; targetRow <= ubound; targetRow++)
{
Buffer.BlockCopy
(
X, // 1D source array
targetRow * sizeof(double), // source array offset
Y, // 2D target (destination) array
(targetRow * X.Length) * sizeof(double), // target array offset
(X.Length - targetRow) * sizeof(double) // count
);
}
for (var i = 0; i <= ubound; i++)
{
for (var j = 0; j <= ubound; j++)
{
Console.Write(Y[i, j] + " ");
}
Console.WriteLine();
}
Console.ReadKey();
2nd Edit
To deal with your other requirement of changing 2nd dimension of the destination array, you need to change some of the BlockCopy
parameters targetArrayOffset
and count
, you can map them to the dimension of the destination array as below.
double[] X = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };
var lbound = X.GetLowerBound(0);
var ubound = X.GetUpperBound(0);
double[,] Y = new double[X.Length, 3];
int yLen = Y.GetUpperBound(1) + 1;
for (int targetRow = 0; targetRow <= ubound; targetRow++)
{
Buffer.BlockCopy
(
X, // 1D source array
(targetRow * sizeof(double)), // source array offset
Y, // 2D target (destination) array
((targetRow * yLen) * sizeof(double)),// target array offset
((X.Length - targetRow) > yLen ? yLen : (X.Length - targetRow)) * sizeof(double) // count
);
}
output:
Upvotes: 1
Reputation: 62002
Assuming x
is of type double[]
, use:
var y = new double[x.Length, x.Length];
for (int row = 0; row < x.Length; ++row)
{
for (int col = 0; col < x.Length - row; ++col)
{
y[row, col] = x[col - row];
}
}
or similar.
Upvotes: 0