Skip to content

Commit dce4850

Browse files
committed
Revamped basic np.unique
1 parent 2bdbc90 commit dce4850

File tree

4 files changed

+102
-17
lines changed

4 files changed

+102
-17
lines changed

src/NumSharp.Core/APIs/np.array_manipulation.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,11 @@ public static NDArray transpose(NDArray x, int[] axes = null)
2020
=> x.TensorEngine.Transpose(x, axes: axes);
2121

2222
/// <summary>
23-
/// Find the unique elements of an array.
24-
///
25-
/// Returns the sorted unique elements of an array.There are three optional outputs in addition to the unique elements:
26-
/// * the indices of the input array that give the unique values
27-
/// * the indices of the unique array that reconstruct the input array
28-
/// * the number of times each unique value comes up in the input array
23+
/// Find the unique elements of an array.
2924
/// </summary>
30-
public static NDArray unique<T>(NDArray a)
31-
=> a.unique<T>();
25+
/// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html</remarks>
26+
public static NDArray unique(NDArray a)
27+
=> a.unique();
28+
3229
}
3330
}

src/NumSharp.Core/Backends/NDArray.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ protected internal unsafe void* Address
273273

274274
public int[] strides => Storage.Shape.Strides;
275275

276-
//TODO! when reshaping a slice is done - this should not clone in case of a sliced shape.
277276
/// <summary>
278277
/// A 1-D iterator over the array.
279278
/// </summary>
Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,41 @@
1-
namespace NumSharp
1+
using System;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using NumSharp.Backends;
5+
using NumSharp.Backends.Unmanaged;
6+
using NumSharp.Utilities;
7+
8+
namespace NumSharp
29
{
310
public partial class NDArray
411
{
12+
public NDArray unique()
13+
{
14+
switch (typecode)
15+
{
16+
#if _REGEN
17+
%foreach supported_dtypes,supported_dtypes_lowercase%
18+
case NPTypeCode.#1: return unique<#2>();
19+
%
20+
default: throw new NotSupportedException();
21+
#else
22+
case NPTypeCode.Boolean: return unique<bool>();
23+
case NPTypeCode.Byte: return unique<byte>();
24+
case NPTypeCode.Int16: return unique<short>();
25+
case NPTypeCode.UInt16: return unique<ushort>();
26+
case NPTypeCode.Int32: return unique<int>();
27+
case NPTypeCode.UInt32: return unique<uint>();
28+
case NPTypeCode.Int64: return unique<long>();
29+
case NPTypeCode.UInt64: return unique<ulong>();
30+
case NPTypeCode.Char: return unique<char>();
31+
case NPTypeCode.Double: return unique<double>();
32+
case NPTypeCode.Single: return unique<float>();
33+
case NPTypeCode.Decimal: return unique<decimal>();
34+
default: throw new NotSupportedException();
35+
#endif
36+
}
37+
}
38+
539
/// <summary>
640
/// Find the unique elements of an array.
741
///
@@ -12,16 +46,35 @@ public partial class NDArray
1246
/// </summary>
1347
/// <typeparam name="T"></typeparam>
1448
/// <returns></returns>
15-
public NDArray unique<T>()
49+
protected NDArray unique<T>() where T : unmanaged
1650
{
17-
return null;
18-
//var nd = new NDArray(dtype);
19-
//var data = Storage.GetData<T>().Distinct().ToArray();
20-
//nd.Storage.ReplaceData(data);
51+
unsafe
52+
{
53+
var hashset = new Hashset<T>();
54+
if (Shape.IsContiguous)
55+
{
56+
var src = (T*)this.Address;
57+
int len = this.size;
58+
for (int i = 0; i < len; i++) //we do not use Parellel.For because of the internal lock
59+
hashset.Add(src[i]);
2160

22-
//nd.Storage.Reshape(data.Length);
61+
var ret = new NDArray(typeof(T), Shape.Vector(hashset.Count));
62+
Hashset<T>.CopyTo(hashset, (ArraySlice<T>)ret.Array);
63+
return ret;
64+
}
65+
else
66+
{
67+
int len = this.size;
68+
var flat = this.flat;
69+
var src = (T*)flat.Address;
70+
Func<int, int> getOffset = flat.Shape.GetOffset_1D;
71+
Parallel.For(0, len, i => hashset.Add(src[getOffset(i)])); //we use parallel to speed up offset computation
2372

24-
//return nd;
73+
var dst = new NDArray(typeof(T), Shape.Vector(hashset.Count));
74+
Hashset<T>.CopyTo(hashset, (ArraySlice<T>)dst.Array);
75+
return dst;
76+
}
77+
}
2578
}
2679
}
2780
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using System.Linq;
3+
using FluentAssertions;
4+
using Microsoft.VisualStudio.TestTools.UnitTesting;
5+
using NumSharp.Backends;
6+
using NumSharp.UnitTest.Utilities;
7+
8+
namespace NumSharp.UnitTest.Manipulation
9+
{
10+
[TestClass]
11+
public class NDArray_unique_Test : TestClass
12+
{
13+
[TestMethod]
14+
public void Case1()
15+
{
16+
arange(10).unique()
17+
.Should().BeShaped(10).And.BeOfValues(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
18+
}
19+
20+
[TestMethod]
21+
public void Case2()
22+
{
23+
np.repeat(arange(10), 10).reshape(10,10).unique()
24+
.Should().BeShaped(10).And.BeOfValues(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
25+
}
26+
27+
[TestMethod]
28+
public void Case2_Sliced()
29+
{
30+
var arr = np.repeat(arange(10), 10).reshape(10, 10)[":, 0"];
31+
Console.WriteLine((string)arr);
32+
Console.WriteLine((string)arr.unique());
33+
arr.unique().Should().BeShaped(10).And.BeOfValues(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)