Skip to content

Commit be33b39

Browse files
Implement VStack
1 parent 8fa41dc commit be33b39

4 files changed

Lines changed: 23 additions & 114 deletions

File tree

src/NumSharp.Core/Creation/NdArray.VStack.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@ public partial class NDArray
1515
/// <typeparam name="T">The type dtype to return.</typeparam>
1616
/// <param name="tup">The arrays must have the same shape along all but the first axis. 1-D arrays must have the same length.</param>
1717
/// <returns>https://docs.scipy.org/doc/numpy/reference/generated/numpy.vstack.html</returns>
18-
public NDArray vstack<T>(params NDArray[] tup) where T : unmanaged
18+
public NDArray vstack(params NDArray[] tup)
1919
{
20-
return np.vstack<T>(this.Yield().Concat(tup).ToArray());
20+
if (tup == null)
21+
throw new ArgumentNullException(nameof(tup));
22+
23+
NDArray[] list = new NDArray[1 + tup.Length];
24+
list[0] = this;
25+
tup.CopyTo(list, 1);
26+
return np.vstack(list);
2127
}
2228
}
2329
}

src/NumSharp.Core/Creation/np.hstack.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ public static partial class np
1010
/// <summary>
1111
/// Stack arrays in sequence horizontally (column wise).
1212
/// This is equivalent to concatenation along the second axis, except for 1-D arrays where it concatenates along the first axis.Rebuilds arrays divided by hsplit.
13-
/// This function makes most sense for arrays with up to 3 dimensions.For instance, for pixel-data with a height(first axis), width(second axis), and r/g/b channels(third axis). The functions concatenate, stack and block provide more general stacking and concatenation operations.
13+
/// This function makes most sense for arrays with up to 3 dimensions.For instance, for pixel-data with a height(first axis), width(second axis),
14+
/// and r/g/b channels(third axis). The functions concatenate, stack and block provide more general stacking and concatenation operations.
1415
/// </summary>
1516
/// <param name="tup">The arrays must have the same shape along all but the second axis, except 1-D arrays which can be any length.</param>
1617
/// <returns>The array formed by stacking the given arrays.</returns>

src/NumSharp.Core/Creation/np.vstack.cs

Lines changed: 10 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -9,50 +9,6 @@ namespace NumSharp
99
{
1010
public static partial class np
1111
{
12-
/// <summary>
13-
/// Stack arrays in sequence vertically (row wise).<br></br>
14-
/// This is equivalent to concatenation along the first axis after 1-D arrays of shape(N,) have been reshaped to(1, N). Rebuilds arrays divided by vsplit.
15-
/// </summary>
16-
/// <typeparam name="T">The type dtype to return.</typeparam>
17-
/// <param name="tup">The arrays must have the same shape along all but the first axis. 1-D arrays must have the same length.</param>
18-
/// <returns>The array formed by stacking the given arrays, will be at least 2-D.</returns>
19-
/// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.vstack.html</remarks>
20-
public static NDArray vstack<T>(params NDArray[] tup) where T : unmanaged
21-
{
22-
if (tup == null || tup.Length == 0)
23-
throw new Exception("Input arrays can not be empty");
24-
25-
NDArray ret = new NDArray(typeof(T), Shape.Vector(tup.Sum(n => n.size)));
26-
Shape commonShape = tup[0].shape;
27-
unsafe
28-
{
29-
var retaddr = (byte*)ret.Address;
30-
int accoffset = 0;
31-
foreach (NDArray curr in tup)
32-
{
33-
if (commonShape != curr.Shape)
34-
throw new Exception("Arrays mush have same shapes");
35-
var data = curr.Storage.GetData<T>();
36-
var len = data.Count * data.ItemLength;
37-
Buffer.MemoryCopy(data.Address, (retaddr + accoffset), len, len);
38-
accoffset += len;
39-
}
40-
}
41-
42-
if (commonShape.NDim == 1) //all dims are equal across all ndarrays
43-
{
44-
ret.Storage.Reshape(Shape.Matrix(tup.Length, commonShape[0]));
45-
}
46-
else
47-
{
48-
int[] shapes = commonShape.dimensions;
49-
shapes[0] *= tup.Length;
50-
ret.Storage.Reshape(new Shape(shapes));
51-
}
52-
53-
return ret;
54-
}
55-
5612
/// <summary>
5713
/// Stack arrays in sequence vertically (row wise).<br></br>
5814
/// This is equivalent to concatenation along the first axis after 1-D arrays of shape(N,) have been reshaped to(1, N). Rebuilds arrays divided by vsplit.
@@ -63,43 +19,21 @@ public static NDArray vstack<T>(params NDArray[] tup) where T : unmanaged
6319
/// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.vstack.html</remarks>
6420
public static NDArray vstack(params NDArray[] tup)
6521
{
66-
var common_type = np._FindCommonType(tup);
67-
if (tup == null || tup.Length == 0)
68-
throw new Exception("Input arrays can not be empty");
22+
if (tup == null)
23+
throw new ArgumentNullException(nameof(tup));
24+
25+
if (tup.Length == 0)
26+
throw new ArgumentException("Value cannot be an empty collection.", nameof(tup));
6927

70-
NDArray ret = new NDArray(common_type, Shape.Vector(tup.Sum(n => n.size)));
71-
Shape commonShape = tup[0].shape;
72-
unsafe
28+
NDArray[] reshaped = (NDArray[])tup.Clone();
29+
for (int i = 0; i < tup.Length; i++)
7330
{
74-
var retaddr = (byte*)ret.Address;
75-
int accBytesOffset = 0;
76-
foreach (NDArray curr in tup)
31+
if (tup[i].shape.Length == 1)
7732
{
78-
if (commonShape != curr.Shape)
79-
throw new Exception("Arrays mush have same shapes");
80-
var data = curr.Storage.InternalArray;
81-
var bytesLen = data.Count * data.ItemLength;
82-
if (data.TypeCode != common_type)
83-
data.CastTo(ret.Array, bytesOffset: accBytesOffset);
84-
else
85-
Buffer.MemoryCopy(data.Address, (retaddr + accBytesOffset), bytesLen, bytesLen);
86-
accBytesOffset += bytesLen;
33+
reshaped[i] = np.expand_dims(tup[i], 0);
8734
}
8835
}
89-
90-
if (commonShape.NDim == 1) //all dims are equal across all ndarrays
91-
{
92-
ret.Storage.Reshape(Shape.Matrix(tup.Length, commonShape[0]));
93-
}
94-
else
95-
{
96-
int[] shapes = commonShape.dimensions;
97-
shapes[0] *= tup.Length;
98-
ret.Storage.Reshape(new Shape(shapes));
99-
}
100-
101-
return ret;
36+
return np.concatenate(reshaped, 0);
10237
}
103-
10438
}
10539
}

test/NumSharp.UnitTest/Extensions/NdArray.VStack.Test.cs

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public void VStackNDArrays()
2121
var n2 = np.array(new double[] {2, 3, 4});
2222
var n3 = np.array(new double[] {3, 4, 5});
2323

24-
var n = np.vstack<double>(n1, n2).MakeGeneric<double>();
24+
var n = np.vstack(n1, n2).MakeGeneric<double>();
2525

2626
Assert.IsTrue(n.size == (n1.size + n2.size));
2727

@@ -33,7 +33,7 @@ public void VStackNDArrays()
3333
n1 = np.array(new double[][] {new double[] {1}, new double[] {2}, new double[] {3}});
3434
n2 = np.array(new double[][] {new double[] {4}, new double[] {5}, new double[] {6}});
3535

36-
n = np.vstack<double>(n1, n2).MakeGeneric<double>();
36+
n = np.vstack(n1, n2).MakeGeneric<double>();
3737

3838
Assert.IsTrue(n.size == (n1.size + n2.size));
3939

@@ -49,7 +49,7 @@ public void VStackNDArrays()
4949
n2 = np.array(new double[][] {new double[] {4}, new double[] {5}, new double[] {6}});
5050
n3 = np.array(new double[][] {new double[] {7}, new double[] {8}, new double[] {9}});
5151

52-
n = np.vstack<double>(n1, n2, n3).MakeGeneric<double>();
52+
n = np.vstack(n1, n2, n3).MakeGeneric<double>();
5353

5454
Assert.IsTrue(n.size == (n1.size + n2.size + n3.size));
5555

@@ -63,37 +63,5 @@ public void VStackNDArrays()
6363
Assert.IsTrue(n[7, 0] == 8);
6464
Assert.IsTrue(n[8, 0] == 9);
6565
}
66-
67-
[TestMethod]
68-
public void VStackNDArrays_Typeless()
69-
{
70-
//1D
71-
var n1 = np.array(new double[] {1, 2, 3});
72-
var n2 = np.array(new int[] {2, 3, 4});
73-
var n3 = np.array(new float[] {3, 4, 5});
74-
75-
var n = np.vstack(n1, n2).MakeGeneric<double>();
76-
77-
Assert.IsTrue(n.size == (n1.size + n2.size));
78-
79-
Assert.IsTrue(n[0, 0] == 1);
80-
Assert.IsTrue(n[1, 0] == 2);
81-
Assert.IsTrue(n[1, 2] == 4);
82-
83-
//2D
84-
n1 = np.array(new double[][] {new double[] {1}, new double[] {2}, new double[] {3}});
85-
n2 = np.array(new byte[][] {new byte[] {4}, new byte[] {5}, new byte[] {6}});
86-
87-
n = np.vstack(n1, n2).MakeGeneric<double>();
88-
89-
Assert.IsTrue(n.size == (n1.size + n2.size));
90-
91-
Assert.IsTrue(n[0, 0] == 1);
92-
Assert.IsTrue(n[1, 0] == 2);
93-
Assert.IsTrue(n[2, 0] == 3);
94-
Assert.IsTrue(n[3, 0] == 4);
95-
Assert.IsTrue(n[4, 0] == 5);
96-
Assert.IsTrue(n[5, 0] == 6);
97-
}
9866
}
9967
}

0 commit comments

Comments
 (0)