@@ -57,3 +57,80 @@ proc argsort*[T](t: Tensor[T], order = SortOrder.Ascending, toCopy = false): Ten
57
57
result = newTensorUninit[int ](t.shape)
58
58
for i in 0 ..< t.size:
59
59
result [i] = tups[i][1 ]
60
+
61
+ proc unique* [T](t: Tensor[T], isSorted=false): Tensor[T] =
62
+ ## Return a new Tensor with the unique elements of the input Tensor in the order they first appear
63
+ ##
64
+ ## Note that this is the *"unsorted"* version of this procedure which returns
65
+ ## the unique values in the order in which they first appear on the input.
66
+ ## Do not get confused by the `isSorted` argument which is not used to sort
67
+ ## the output, but to make the algorithm more efficient when the input tensor
68
+ ## is already sorted.
69
+ ##
70
+ ## There is another version of this procedure which gets an `order` argument
71
+ ## that let's you sort the output (in ascending or descending order).
72
+ ##
73
+ ## Inputs:
74
+ ## - t: The input Tensor
75
+ ## - isSorted: Set this to `true` if the input tensor is already sorted,
76
+ ## in order to use a more efficient algorithm for finding the
77
+ ## unique of the input Tensor. Be careful however when using
78
+ ## this option, since if the input tensor is not really sorted,
79
+ ## the output will be wrong.
80
+ ##
81
+ ## Result:
82
+ ## - A new Tensor with the unique elements of the input Tensor in the order
83
+ ## in which they first appear on the input Tensor.
84
+ ##
85
+ ## Examples:
86
+ ## ```nim
87
+ ## let
88
+ ## dup = [1, 3, 2, 4, 1, 8, 2, 1, 4].toTensor
89
+ # # assert dup.unique == [1, 3, 2, 4, 8].toTensor
90
+ # #
91
+ # # # Use `isSorted = true` only if the input tensor is already sorted
92
+ # # assert dup.sorted.unique(isSorted = true) == [1, 3, 2, 4, 8].toTensor
93
+ # # ```
94
+
95
+ if t.is_C_contiguous:
96
+ # Note that since deduplicate returns a new sequence, it is safe to apply it
97
+ # to a view of the raw data of the input tensor
98
+ toOpenArray(t.toUnsafeView, 0 , t.size - 1 ).deduplicate(isSorted = isSorted).toTensor
99
+ else :
100
+ # Clone the tensor in order to make it C continuous and then make it unique
101
+ unique(t.clone(), isSorted = isSorted)
102
+
103
+ proc unique* [T](t: Tensor[T], order: SortOrder): Tensor[T] =
104
+ ## Return a new sorted Tensor with the unique elements of the input Tensor
105
+ ##
106
+ ## Note that this is the "sorted" version of this procedure. There is
107
+ ## another version which doesn't get a `sort` argument that returns the
108
+ ## unique elements int he order in which they first appear ont he input.
109
+ ##
110
+ ## Inputs:
111
+ ## - t: The input Tensor
112
+ ## - order: The order in which elements are sorted (`SortOrder.Ascending` or `SortOrder.Descending`)
113
+ ##
114
+ ## Result:
115
+ ## - A new Tensor with the unique elements of the input Tensor sorted in the specified order.
116
+ ##
117
+ ## Examples:
118
+ ## ```nim
119
+ ## let
120
+ ## dup = [1, 3, 2, 4, 1, 8, 2, 1, 4].toTensor
121
+ # # unique_ascending_sort = dup.unique(order = SortOrder.Ascending)
122
+ # # unique_descending_sort = dup.unique(order = SortOrder.Descending)
123
+ # # assert unique_ascending_sort == [1, 2, 3, 4, 8].toTensor
124
+ # # assert unique_descending_sort == [8, 4, 3, 2, 1].toTensor
125
+ # # ```
126
+
127
+ if t.is_C_contiguous:
128
+ # Note that since sorted returns a new sequence, it is safe to apply it
129
+ # to a view of the raw data of the input tensor
130
+ sorted(toOpenArray(t.toUnsafeView, 0 , t.size - 1 ),
131
+ order = order)
132
+ .deduplicate(isSorted = true ).toTensor
133
+ else :
134
+ # We need to clone the tensor in order to make it C continuous
135
+ # and then we can make it unique assuming that it is already sorted
136
+ sorted(t, order = order).unique(isSorted = true )
0 commit comments