Skip to content

Commit 6ba6e01

Browse files
committed
optimize creation from array.
1 parent cf8aa9f commit 6ba6e01

5 files changed

Lines changed: 168 additions & 103 deletions

File tree

src/NumSharp.Core/Casting/Implicit/NdArray.Implicit.Array.cs

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,78 @@ namespace NumSharp
3030
{
3131
public partial class NDArray
3232
{
33-
34-
// User-defined conversion from double to Digit
35-
public static implicit operator NDArray(Array d)
33+
34+
/// <summary>
35+
/// User-defined conversion from double to Digit
36+
/// </summary>
37+
/// <param name="array"></param>
38+
public static implicit operator NDArray(Array array)
3639
{
37-
var ndArray = new NDArray(d.GetType().GetElementType());
40+
bool isArray = array.GetType().GetElementType().IsArray;
41+
42+
if (isArray)
43+
{
44+
var type = array.GetType().GetElementType();
3845

39-
if (d.GetType().GetElementType().IsArray)
40-
ndArray.FromJaggedArray(d);
46+
switch (array.GetType().GetArrayRank())
47+
{
48+
case 1:
49+
type = type.GetElementType();
50+
break;
51+
case 2:
52+
type = type.GetElementType().GetElementType();
53+
break;
54+
case 3:
55+
type = type.GetElementType().GetElementType().GetElementType();
56+
break;
57+
default:
58+
throw new NotImplementedException("implicit operator NDArray(Array array)");
59+
}
60+
61+
var nd = new NDArray(type);
62+
switch (Type.GetTypeCode(nd.dtype))
63+
{
64+
case TypeCode.Boolean:
65+
return nd.FromJaggedArray<bool>(array);
66+
case TypeCode.Int16:
67+
return nd.FromJaggedArray<short>(array);
68+
case TypeCode.Int32:
69+
return nd.FromJaggedArray<int>(array);
70+
case TypeCode.Int64:
71+
return nd.FromJaggedArray<long>(array);
72+
case TypeCode.Single:
73+
return nd.FromJaggedArray<float>(array);
74+
case TypeCode.Double:
75+
return nd.FromJaggedArray<double>(array);
76+
case TypeCode.Decimal:
77+
return nd.FromJaggedArray<decimal>(array);
78+
}
79+
}
4180
else
42-
ndArray.FromMultiDimArray(d);
81+
{
82+
var nd = new NDArray(array.GetType().GetElementType());
83+
switch (Type.GetTypeCode(nd.dtype))
84+
{
85+
case TypeCode.Boolean:
86+
return nd.FromMultiDimArray<bool>(array);
87+
case TypeCode.Int16:
88+
return nd.FromMultiDimArray<short>(array);
89+
case TypeCode.Int32:
90+
return nd.FromMultiDimArray<int>(array);
91+
case TypeCode.Int64:
92+
return nd.FromMultiDimArray<long>(array);
93+
case TypeCode.Single:
94+
return nd.FromMultiDimArray<float>(array);
95+
case TypeCode.Double:
96+
return nd.FromMultiDimArray<double>(array);
97+
case TypeCode.Decimal:
98+
return nd.FromMultiDimArray<decimal>(array);
99+
}
100+
}
43101

44-
return ndArray;
102+
throw new NotImplementedException("implicit operator NDArray(Array array)");
45103
}
104+
46105
public static implicit operator Array(NDArray nd)
47106
{
48107
var methods = nd.GetType().GetMethods().Where(x => x.Name.Equals("ToMuliDimArray") && x.IsGenericMethod && x.ReturnType.Name.Equals("Array"));

src/NumSharp.Core/Casting/NdArrayFromJaggedArr.cs

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,16 @@ namespace NumSharp
2929
{
3030
public partial class NDArray
3131
{
32-
public void FromJaggedArray(Array dotNetArray)
32+
/// <summary>
33+
/// low performance due to loop element-wise
34+
/// </summary>
35+
/// <param name="dotNetArray"></param>
36+
private NDArray FromJaggedArray<T>(Array dotNetArray)
3337
{
3438
if(!dotNetArray.GetType().GetElementType().IsArray)
3539
throw new Exception("Multi dim arrays are not allowed here!");
3640

37-
List<int> dimList = new List<int>();
41+
var dimList = new List<int>();
3842

3943
dimList.Add(dotNetArray.Length);
4044

@@ -47,35 +51,19 @@ public void FromJaggedArray(Array dotNetArray)
4751
currentArr = child;
4852
}
4953

50-
Type elementType = currentArr.GetType().GetElementType();
51-
52-
int[] dims = dimList.ToArray();
53-
54-
Shape shape = new Shape(dims);
55-
shape.ChangeTensorLayout();
56-
57-
NDArray nd = new NDArray(elementType,shape);
58-
59-
Array ndStrg = nd.Storage.GetData();
60-
61-
if(dims.Length == 1)
62-
{
63-
throw new NotImplementedException("FromJaggedArray dims.Length == 1");
64-
}
65-
else if (dims.Length == 2)
54+
switch (dimList.Count)
6655
{
67-
switch (dotNetArray)
68-
{
69-
case double[][] array:
70-
for (int i = 0; i < dims[0]; i++)
71-
for (int j = 0; j < dims[1]; j++)
72-
nd[i, j] = array[i][j];
73-
break;
74-
}
75-
56+
case 1:
57+
return np.array((T[])dotNetArray);
58+
case 2:
59+
return np.array((T[][])dotNetArray);
60+
case 3:
61+
return np.array((T[][][])dotNetArray);
62+
case 4:
63+
return np.array((T[][][][])dotNetArray);
7664
}
7765

78-
this.Storage = nd.Storage;
66+
throw new NotImplementedException("FromJaggedArray<T>(Array dotNetArray)");
7967
}
8068

8169
}

src/NumSharp.Core/Casting/NdArrayFromMultiDimArr.cs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,34 +29,28 @@ namespace NumSharp
2929
{
3030
public partial class NDArray
3131
{
32-
public void FromMultiDimArray(Array dotNetArray)
32+
/// <summary>
33+
/// low performance due to loop element-wise
34+
/// </summary>
35+
/// <param name="dotNetArray"></param>
36+
public NDArray FromMultiDimArray<T>(Array dotNetArray)
3337
{
3438
if(dotNetArray.GetType().GetElementType().IsArray)
3539
throw new Exception("Jagged arrays are not allowed here!");
3640

37-
int[] dims = new int[dotNetArray.Rank];
38-
39-
for(int idx = 0; idx < dims.Length;idx++)
40-
dims[idx] = dotNetArray.GetLength(idx);
41-
42-
Storage = BackendFactory.GetStorage(dotNetArray.GetType().GetElementType());
43-
44-
Storage.Allocate(new Shape(dims));
45-
46-
Array internalStrg = Storage.GetData();
47-
48-
var pufferShape = new Shape(dims);
49-
pufferShape.ChangeTensorLayout();
50-
51-
int[] idxDims = null;
52-
object valueIdx = null;
53-
54-
for(int idx = 0; idx < Storage.Shape.Size;idx++)
41+
switch (dotNetArray.Rank)
5542
{
56-
idxDims = pufferShape.GetDimIndexOutShape(idx);
57-
valueIdx = dotNetArray.GetValue(pufferShape.GetDimIndexOutShape(idx));
58-
internalStrg.SetValue(valueIdx,Storage.Shape.GetIndexInShape(slice, idxDims));
43+
case 1:
44+
return np.array((T[])dotNetArray);
45+
case 2:
46+
return np.array((T[,])dotNetArray);
47+
case 3:
48+
return np.array((T[,,])dotNetArray);
49+
case 4:
50+
return np.array((T[,,,])dotNetArray);
5951
}
52+
53+
throw new NotImplementedException("FromMultiDimArray<T>(Array dotNetArray)");
6054
}
6155

6256
}

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

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -28,69 +28,51 @@ public static NDArray array(Array array, Type dtype = null, int ndim = 1)
2828
return nd;
2929
}
3030

31-
/*public static NDArray array(System.Drawing.Bitmap image)
31+
public static NDArray array<T>(T[][] data)
3232
{
33-
var imageArray = new NDArray(typeof(Byte));
33+
var array = data.SelectMany(inner => inner).ToArray();
3434

35-
var bmpd = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, image.PixelFormat);
36-
var dataSize = bmpd.Stride * bmpd.Height;
35+
return new NDArray(array, new Shape(data.Length, data[0].Length));
36+
}
3737

38-
var bytes = new byte[dataSize];
39-
System.Runtime.InteropServices.Marshal.Copy(bmpd.Scan0, bytes, 0, dataSize);
40-
image.UnlockBits(bmpd);
38+
public static NDArray array<T>(T[][][] data)
39+
{
40+
var array = data.SelectMany(inner => inner
41+
.SelectMany(innerInner => innerInner))
42+
.ToArray();
4143

42-
imageArray.Storage.Allocate(typeof(byte),new Shape(bmpd.Height, bmpd.Width, System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8),1);
43-
imageArray.Storage.SetData(bytes);
44-
45-
return imageArray;
46-
}*/
44+
return new NDArray(array, new Shape(data.Length, data[0].Length, data[0][0].Length));
45+
}
4746

48-
public static NDArray array<T>(T[][] data)
47+
public static NDArray array<T>(T[][][][] data)
4948
{
50-
var nd = new NDArray(typeof(T), new Shape(data.Length, data[0].Length));
51-
52-
for (int row = 0; row < data.Length; row++)
53-
{
54-
for (int col = 0; col < data[row].Length; col++)
55-
{
56-
nd.SetData(data[row][col], row, col);
57-
}
58-
}
49+
var array = data.SelectMany(inner => inner
50+
.SelectMany(innerInner => innerInner
51+
.SelectMany(innerInnerInner => innerInnerInner)))
52+
.ToArray();
5953

60-
return nd;
54+
return new NDArray(array, new Shape(data.Length, data[0].Length, data[0][0].Length));
6155
}
6256

6357
public static NDArray array<T>(T[,] data)
6458
{
65-
var nd = new NDArray(typeof(T), new Shape(data.GetLength(0), data.GetLength(1)));
59+
var array = data.Cast<T>().ToArray();
6660

67-
for (int dim0 = 0; dim0 < data.GetLength(0); dim0++)
68-
{
69-
for (int dim1 = 0; dim1 < data.GetLength(1); dim1++)
70-
{
71-
nd.SetData(data[dim0, dim1], dim0, dim1);
72-
}
73-
}
74-
75-
return nd;
61+
return new NDArray(array, new Shape(data.GetLength(0), data.GetLength(1)));
7662
}
7763

7864
public static NDArray array<T>(T[,,] data)
7965
{
80-
var nd = new NDArray(typeof(T), new Shape(data.GetLength(0), data.GetLength(1), data.GetLength(2)));
66+
var array = data.Cast<T>().ToArray();
8167

82-
for (int dim0 = 0; dim0 < data.GetLength(0); dim0++)
83-
{
84-
for (int dim1 = 0; dim1 < data.GetLength(1); dim1++)
85-
{
86-
for (int dim2 = 0; dim2 < data.GetLength(2); dim2++)
87-
{
88-
nd.SetData(data[dim0, dim1, dim2], dim0, dim1, dim2);
89-
}
90-
}
91-
}
68+
return new NDArray(array, new Shape(data.GetLength(0), data.GetLength(1), data.GetLength(2)));
69+
}
9270

93-
return nd;
71+
public static NDArray array<T>(T[,,,] data)
72+
{
73+
var array = data.Cast<T>().ToArray();
74+
75+
return new NDArray(data.Cast<T>().ToArray(), new Shape(data.GetLength(0), data.GetLength(1), data.GetLength(2), data.GetLength(3)));
9476
}
9577

9678
public static NDArray array<T>(params T[] data)

test/NumSharp.UnitTest/Creation/NdArray.Array.Test.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,50 @@ public void Array2Dim()
3232
var n = np.array(list);
3333

3434
Assert.IsTrue(n.Data<int>(1, 0) == 3);
35+
36+
var list1 = new int[,]
37+
{
38+
{1, 2, 3},
39+
{2, 3, 1}
40+
};
41+
42+
var n1 = np.array(list1);
43+
Assert.IsTrue(Enumerable.SequenceEqual(n1.shape, new int[] { 2, 3 }));
44+
Assert.IsTrue(Enumerable.SequenceEqual(n1.Data<int>(), new int[] { 1, 2, 3, 2, 3, 1 }));
3545
}
3646

47+
[TestMethod]
48+
public void Array3Dim()
49+
{
50+
var list = new int[,,]
51+
{
52+
{{1, 2}, {3, 4}},
53+
{{2, 2}, {3, 3}},
54+
{{3, 2}, {3, 1}},
55+
};
56+
57+
var nd = np.array(list);
58+
Assert.IsTrue(Enumerable.SequenceEqual(nd.shape, new int[] { 3, 2, 2 }));
59+
Assert.IsTrue(Enumerable.SequenceEqual(nd.Data<int>(), new int[] { 1, 2, 3, 4, 2, 2, 3, 3, 3, 2, 3, 1}));
60+
}
61+
62+
/*public static NDArray array(System.Drawing.Bitmap image)
63+
{
64+
var imageArray = new NDArray(typeof(Byte));
65+
66+
var bmpd = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, image.PixelFormat);
67+
var dataSize = bmpd.Stride * bmpd.Height;
68+
69+
var bytes = new byte[dataSize];
70+
System.Runtime.InteropServices.Marshal.Copy(bmpd.Scan0, bytes, 0, dataSize);
71+
image.UnlockBits(bmpd);
72+
73+
imageArray.Storage.Allocate(typeof(byte),new Shape(bmpd.Height, bmpd.Width, System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8),1);
74+
imageArray.Storage.SetData(bytes);
75+
76+
return imageArray;
77+
}*/
78+
3779
[TestMethod]
3880
public void ArrayImage()
3981
{

0 commit comments

Comments
 (0)