Skip to content

Commit 157e782

Browse files
committed
feat(csharp/Tensor.NET): add min and max method and api.
1 parent 5531718 commit 157e782

File tree

7 files changed

+292
-1
lines changed

7 files changed

+292
-1
lines changed

apis/numnet_c_cxx_apis.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,42 @@ Status *Mean(NativeTensor *inp, NativeTensor *oup, param::mean *param,
342342
}
343343
}
344344

345+
Status *Max(NativeTensor *inp, NativeTensor *oup, param::max *param,
346+
ProviderEnum provider) {
347+
Tensor t_inp, t_oup;
348+
inp->ToTensor(t_inp, false);
349+
oup->ToTensor(t_oup, true);
350+
OpBase *impl = GetImpl(provider);
351+
if (impl == nullptr) {
352+
return new Status(StatusCategory::NUMNET, StatusCode::INVALID_ARGUMENT,
353+
"Unsupported provider.");
354+
}
355+
auto status = impl->max(t_inp, t_oup, *param);
356+
if (status.is_ok()) {
357+
return nullptr;
358+
} else {
359+
return new Status(status);
360+
}
361+
}
362+
363+
Status *Min(NativeTensor *inp, NativeTensor *oup, param::min *param,
364+
ProviderEnum provider) {
365+
Tensor t_inp, t_oup;
366+
inp->ToTensor(t_inp, false);
367+
oup->ToTensor(t_oup, true);
368+
OpBase *impl = GetImpl(provider);
369+
if (impl == nullptr) {
370+
return new Status(StatusCategory::NUMNET, StatusCode::INVALID_ARGUMENT,
371+
"Unsupported provider.");
372+
}
373+
auto status = impl->min(t_inp, t_oup, *param);
374+
if (status.is_ok()) {
375+
return nullptr;
376+
} else {
377+
return new Status(status);
378+
}
379+
}
380+
345381
Status *Argmxx(NativeTensor *inp, NativeTensor *oup, param::argmxx *param,
346382
ProviderEnum provider) {
347383
Tensor t_inp, t_oup;

apis/numnet_c_cxx_apis.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ Status *Sum(NativeTensor *inp, NativeTensor *oup, param::sum *param,
8484
Status *Mean(NativeTensor *inp, NativeTensor *oup, param::mean *param,
8585
ProviderEnum provider);
8686

87+
Status *Max(NativeTensor *inp, NativeTensor *oup, param::max *param,
88+
ProviderEnum provider);
89+
90+
Status *Min(NativeTensor *inp, NativeTensor *oup, param::min *param,
91+
ProviderEnum provider);
92+
8793
Status *Argmxx(NativeTensor *inp, NativeTensor *oup, param::argmxx *param,
8894
ProviderEnum provider);
8995

csharp/Tensor.NET/Native/NativeApi.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ internal static class NativeApi{
4242
public static extern IntPtr Sum(IntPtr inp, IntPtr oup, IntPtr param, NativeProvider provider);
4343
[DllImport("libnumnet")]
4444
public static extern IntPtr Mean(IntPtr inp, IntPtr oup, IntPtr param, NativeProvider provider);
45+
[DllImport("libnumnet")]
46+
public static extern IntPtr Max(IntPtr inp, IntPtr oup, IntPtr param, NativeProvider provider);
47+
[DllImport("libnumnet")]
48+
public static extern IntPtr Min(IntPtr inp, IntPtr oup, IntPtr param, NativeProvider provider);
4549

4650

4751
[DllImport("libnumnet")]

csharp/Tensor.NET/Native/NativeParam.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ internal struct SumParam{
5858
internal struct MeanParam{
5959
internal IntPtr dims;
6060
}
61+
internal struct MaxParam{
62+
internal IntPtr dims;
63+
}
64+
internal struct MinParam{
65+
internal IntPtr dims;
66+
}
6167
internal struct TypeConvertParam{
6268
internal DType targetType;
6369
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using Tensornet.Native;
2+
using Tensornet.Exceptions;
3+
using Tensornet.Native.Param;
4+
5+
namespace Tensornet{
6+
public static class MaxExtension{
7+
public static Tensor<T> Max<T>(this Tensor<T> src, int[] axes, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible
8+
{
9+
Tensor<T> res = new Tensor<T>(DeduceLayout(src.TLayout, axes));
10+
res.TLayout.InitContiguousLayout();
11+
bool[] boolDims = new bool[src.TLayout.NDim];
12+
var span = boolDims.AsSpan();
13+
span.Fill(false);
14+
foreach(var axis in axes){
15+
span[axis] = true;
16+
}
17+
MaxInternal(src, res, boolDims, keepDims);
18+
return res;
19+
}
20+
public static Tensor<T> Max<T>(this Tensor<T> src, int axis, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible
21+
{
22+
Tensor<T> res = new Tensor<T>(DeduceLayout(src.TLayout, axis));
23+
res.TLayout.InitContiguousLayout();
24+
bool[] boolDims = new bool[src.TLayout.NDim];
25+
var span = boolDims.AsSpan();
26+
span.Fill(false);
27+
span[axis] = true;
28+
MaxInternal(src, res, boolDims, keepDims);
29+
return res;
30+
}
31+
public static Tensor<T> Max<T>(this Tensor<T> src, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible
32+
{
33+
Tensor<T> res = new Tensor<T>(DeduceLayout(src.TLayout));
34+
res.TLayout.InitContiguousLayout();
35+
bool[] boolDims = new bool[src.TLayout.NDim];
36+
boolDims.AsSpan().Fill(true);
37+
MaxInternal(src, res, boolDims, keepDims);
38+
return res;
39+
}
40+
private unsafe static void MaxInternal<T>(Tensor<T> src, Tensor<T> dst, bool[] dims, bool keepDims) where T : struct, IEquatable<T>, IConvertible{
41+
fixed(bool* ptr = dims){
42+
MaxParam p = new MaxParam() { dims = new IntPtr(ptr) };
43+
IntPtr status = NativeExecutor.Execute(NativeApi.Max, src.TMemory, dst.TMemory, src.TLayout, dst.TLayout, new IntPtr(&p), Tensor<T>.Provider);
44+
NativeStatus.AssertOK(status);
45+
}
46+
if(!keepDims){
47+
dst.TLayout.RemoveAllDanglingAxisInplace();
48+
}
49+
}
50+
private static TensorLayout DeduceLayout(TensorLayout src, int[] axes){
51+
var res = new TensorLayout(src, true);
52+
foreach(var dim in axes){
53+
res.Shape[dim] = 1;
54+
}
55+
return res;
56+
}
57+
private static TensorLayout DeduceLayout(TensorLayout src, int axis){
58+
var res = new TensorLayout(src, true);
59+
res.Shape[axis] = 1;
60+
return res;
61+
}
62+
private static TensorLayout DeduceLayout(TensorLayout src){
63+
var res = new TensorLayout(src, true);
64+
res.Shape.AsSpan().Fill(1);
65+
return res;
66+
}
67+
}
68+
69+
public static partial class Tensor{
70+
/// <Summary>
71+
/// Get the maximum elements of the tensor.
72+
/// </Summary>
73+
/// <typeparam name="T"></typeparam>
74+
/// <param name="src"> The tensor to get maximum elements. </param>
75+
/// <param name="axes"> The axes to execute. </param>
76+
/// <param name="keepDims"> Whether to keep the dims after the Max. If false, the NDim of the result may be different with the input. </param>
77+
/// <returns></returns>
78+
public static Tensor<T> Max<T>(Tensor<T> src, int[] axes, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible{
79+
return src.Max(axes, keepDims);
80+
}
81+
/// <Summary>
82+
/// Get the maximum elements of the tensor.
83+
/// </Summary>
84+
/// <typeparam name="T"></typeparam>
85+
/// <param name="src"> The tensor to get maximum elements. </param>
86+
/// <param name="axis"> The axis to execute. </param>
87+
/// <param name="keepDims"> Whether to keep the dims after the Max. If false, the NDim of the result may be different with the input. </param>
88+
/// <returns></returns>
89+
public static Tensor<T> Max<T>(Tensor<T> src, int axis, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible{
90+
return src.Max(axis, keepDims);
91+
}
92+
/// <Summary>
93+
/// Get the maximum elements of the tensor.
94+
/// </Summary>
95+
/// <typeparam name="T"></typeparam>
96+
/// <param name="src"> The tensor to get maximum elements. </param>
97+
/// <param name="keepDims"> Whether to keep the dims after the Max. If false, the NDim of the result may be different with the input. </param>
98+
/// <returns></returns>
99+
public static Tensor<T> Max<T>(Tensor<T> src, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible{
100+
return src.Max(keepDims);
101+
}
102+
}
103+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using Tensornet.Native;
2+
using Tensornet.Exceptions;
3+
using Tensornet.Native.Param;
4+
5+
namespace Tensornet{
6+
public static class MinExtension{
7+
public static Tensor<T> Min<T>(this Tensor<T> src, int[] axes, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible
8+
{
9+
Tensor<T> res = new Tensor<T>(DeduceLayout(src.TLayout, axes));
10+
res.TLayout.InitContiguousLayout();
11+
bool[] boolDims = new bool[src.TLayout.NDim];
12+
var span = boolDims.AsSpan();
13+
span.Fill(false);
14+
foreach(var axis in axes){
15+
span[axis] = true;
16+
}
17+
MinInternal(src, res, boolDims, keepDims);
18+
return res;
19+
}
20+
public static Tensor<T> Min<T>(this Tensor<T> src, int axis, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible
21+
{
22+
Tensor<T> res = new Tensor<T>(DeduceLayout(src.TLayout, axis));
23+
res.TLayout.InitContiguousLayout();
24+
bool[] boolDims = new bool[src.TLayout.NDim];
25+
var span = boolDims.AsSpan();
26+
span.Fill(false);
27+
span[axis] = true;
28+
MinInternal(src, res, boolDims, keepDims);
29+
return res;
30+
}
31+
public static Tensor<T> Min<T>(this Tensor<T> src, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible
32+
{
33+
Tensor<T> res = new Tensor<T>(DeduceLayout(src.TLayout));
34+
res.TLayout.InitContiguousLayout();
35+
bool[] boolDims = new bool[src.TLayout.NDim];
36+
boolDims.AsSpan().Fill(true);
37+
MinInternal(src, res, boolDims, keepDims);
38+
return res;
39+
}
40+
private unsafe static void MinInternal<T>(Tensor<T> src, Tensor<T> dst, bool[] dims, bool keepDims) where T : struct, IEquatable<T>, IConvertible{
41+
fixed(bool* ptr = dims){
42+
MinParam p = new MinParam() { dims = new IntPtr(ptr) };
43+
IntPtr status = NativeExecutor.Execute(NativeApi.Min, src.TMemory, dst.TMemory, src.TLayout, dst.TLayout, new IntPtr(&p), Tensor<T>.Provider);
44+
NativeStatus.AssertOK(status);
45+
}
46+
if(!keepDims){
47+
dst.TLayout.RemoveAllDanglingAxisInplace();
48+
}
49+
}
50+
private static TensorLayout DeduceLayout(TensorLayout src, int[] axes){
51+
var res = new TensorLayout(src, true);
52+
foreach(var dim in axes){
53+
res.Shape[dim] = 1;
54+
}
55+
return res;
56+
}
57+
private static TensorLayout DeduceLayout(TensorLayout src, int axis){
58+
var res = new TensorLayout(src, true);
59+
res.Shape[axis] = 1;
60+
return res;
61+
}
62+
private static TensorLayout DeduceLayout(TensorLayout src){
63+
var res = new TensorLayout(src, true);
64+
res.Shape.AsSpan().Fill(1);
65+
return res;
66+
}
67+
}
68+
69+
public static partial class Tensor{
70+
/// <Summary>
71+
/// Get the minimum elements of the tensor.
72+
/// </Summary>
73+
/// <typeparam name="T"></typeparam>
74+
/// <param name="src"> The tensor to get minimum elements. </param>
75+
/// <param name="axes"> The axes to execute. </param>
76+
/// <param name="keepDims"> Whether to keep the dims after the Min. If false, the NDim of the result may be different with the input. </param>
77+
/// <returns></returns>
78+
public static Tensor<T> Min<T>(Tensor<T> src, int[] axes, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible{
79+
return src.Min(axes, keepDims);
80+
}
81+
/// <Summary>
82+
/// Get the minimum elements of the tensor.
83+
/// </Summary>
84+
/// <typeparam name="T"></typeparam>
85+
/// <param name="src"> The tensor to get minimum elements. </param>
86+
/// <param name="axis"> The axis to execute. </param>
87+
/// <param name="keepDims"> Whether to keep the dims after the Min. If false, the NDim of the result may be different with the input. </param>
88+
/// <returns></returns>
89+
public static Tensor<T> Min<T>(Tensor<T> src, int axis, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible{
90+
return src.Min(axis, keepDims);
91+
}
92+
/// <Summary>
93+
/// Get the minimum elements of the tensor.
94+
/// </Summary>
95+
/// <typeparam name="T"></typeparam>
96+
/// <param name="src"> The tensor to get minimum elements. </param>
97+
/// <param name="keepDims"> Whether to keep the dims after the Min. If false, the NDim of the result may be different with the input. </param>
98+
/// <returns></returns>
99+
public static Tensor<T> Min<T>(Tensor<T> src, bool keepDims = false) where T : struct, IEquatable<T>, IConvertible{
100+
return src.Min(keepDims);
101+
}
102+
}
103+
}

csharp/Tensor.NET/Tensor.NET.csproj

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<Nullable>enable</Nullable>
77
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
88
<PackageId>Tensor.NET</PackageId>
9-
<Version>0.0.2</Version>
9+
<Version>0.0.7</Version>
1010
<Authors>AsakusaRinne</Authors>
1111
<Company>Null</Company>
1212
<Description>
@@ -15,4 +15,37 @@
1515
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
1616
</PropertyGroup>
1717

18+
<ItemGroup>
19+
<!-- <Content Include="./CppLibrary/libnumnet.dll">
20+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
21+
<Pack>true</Pack>
22+
<PackagePath>lib\$(TargetFramework)</PackagePath>
23+
</Content>
24+
<Content Include="./CppLibrary/libnumnet_core_base.dll">
25+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
26+
<Pack>true</Pack>
27+
<PackagePath>lib\$(TargetFramework)</PackagePath>
28+
</Content>
29+
<Content Include="./CppLibrary/libnumnet_core_op.dll">
30+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
31+
<Pack>true</Pack>
32+
<PackagePath>lib\$(TargetFramework)</PackagePath>
33+
</Content>
34+
<Content Include="./CppLibrary/libstdc++-6.dll">
35+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
36+
<Pack>true</Pack>
37+
<PackagePath>lib\$(TargetFramework)</PackagePath>
38+
</Content>
39+
<Content Include="./CppLibrary/libgcc_s_seh-1.dll">
40+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
41+
<Pack>true</Pack>
42+
<PackagePath>lib\$(TargetFramework)</PackagePath>
43+
</Content> -->
44+
<Content Include="libnumnet.so">
45+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
46+
<PackageCopyToOutput>true</PackageCopyToOutput>
47+
<pack>true</pack>
48+
</Content>
49+
</ItemGroup>
50+
1851
</Project>

0 commit comments

Comments
 (0)