Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add torch.histogram #960

Merged
merged 2 commits into from Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/Native/LibTorchSharp/THSTensor.cpp
Expand Up @@ -2015,6 +2015,52 @@ Tensor THSTensor_searchsorted_s(const Tensor sorted_sequence, const Scalar value
: torch::searchsorted(*sorted_sequence, *values, out_int32, right, c10::nullopt, *sorter));
}

Tensor THSTensor_histogram_t(const Tensor input, const Tensor bins, const Tensor weight, const bool density, Tensor* r_bin_edges)
{
std::tuple<at::Tensor, at::Tensor> res;

c10::optional<at::Tensor> weight_ = weight == nullptr ? c10::optional<at::Tensor>(c10::nullopt) : *weight;

CATCH(res = torch::histogram(*input, *bins, weight_, density););
*r_bin_edges = ResultTensor(std::get<1>(res));
return ResultTensor(std::get<0>(res));
}

Tensor THSTensor_histogram_i(const Tensor input, const int64_t bins, const double* range, const int length, const Tensor weight, const bool density, Tensor* r_bin_edges)
{
std::tuple<at::Tensor, at::Tensor> res;

auto range_ = range == nullptr ? c10::optional<at::ArrayRef<double>>() : c10::optional<at::ArrayRef<double>>(at::ArrayRef<double>(range, length));
c10::optional<at::Tensor> weight_ = weight == nullptr ? c10::optional<at::Tensor>(c10::nullopt) : *weight;

CATCH(res = torch::histogram(*input, bins, range_, weight_, density););
*r_bin_edges = ResultTensor(std::get<1>(res));
return ResultTensor(std::get<0>(res));
}

Tensor THSTensor_histogram_out_t(const Tensor input, const Tensor bins, const Tensor weight, const bool density, Tensor* hist, Tensor* bin_edges, Tensor* r_bin_edges)
{
std::tuple<at::Tensor, at::Tensor> res;

c10::optional<at::Tensor> weight_ = weight == nullptr ? c10::optional<at::Tensor>(c10::nullopt) : *weight;

CATCH(res = torch::histogram_outf(*input, *bins, weight_, density, **hist, **bin_edges););
*r_bin_edges = ResultTensor(std::get<1>(res));
return ResultTensor(std::get<0>(res));
}

Tensor THSTensor_histogram_out_i(const Tensor input, const int64_t bins, const double* range, const int length, const Tensor weight, const bool density, Tensor* hist, Tensor* bin_edges, Tensor* r_bin_edges)
{
std::tuple<at::Tensor, at::Tensor> res;

auto range_ = range == nullptr ? c10::optional<at::ArrayRef<double>>() : c10::optional<at::ArrayRef<double>>(at::ArrayRef<double>(range, length));
c10::optional<at::Tensor> weight_ = weight == nullptr ? c10::optional<at::Tensor>(c10::nullopt) : *weight;

CATCH(res = torch::histogram_outf(*input, bins, range_, weight_, density, **hist, **bin_edges););
*r_bin_edges = ResultTensor(std::get<1>(res));
return ResultTensor(std::get<0>(res));
}

bool THSTensor_has_names(Tensor tensor)
{
CATCH(
Expand Down
5 changes: 5 additions & 0 deletions src/Native/LibTorchSharp/THSTensor.h
Expand Up @@ -1188,6 +1188,11 @@ EXPORT_API(Tensor) THSTensor_scatter_add_(const Tensor tensor, const int64_t dim
EXPORT_API(Tensor) THSTensor_searchsorted_t(const Tensor sorted_sequence, const Tensor values, const bool out_int32, const bool right, const Tensor sorter);
EXPORT_API(Tensor) THSTensor_searchsorted_s(const Tensor sorted_sequence, const Scalar values, const bool out_int32, const bool right, const Tensor sorter);

EXPORT_API(Tensor) THSTensor_histogram_t(const Tensor input, const Tensor bins, const Tensor weight, const bool density, Tensor* r_bin_edges);
EXPORT_API(Tensor) THSTensor_histogram_i(const Tensor input, const int64_t bins, const double* range, const int length, const Tensor weight, const bool density, Tensor* r_bin_edges);
EXPORT_API(Tensor) THSTensor_histogram_out_t(const Tensor input, const Tensor bins, const Tensor weight, const bool density, Tensor* hist, Tensor* bin_edges, Tensor* r_bin_edges);
EXPORT_API(Tensor) THSTensor_histogram_out_i(const Tensor input, const int64_t bins, const double* range, const int length, const Tensor weight, const bool density, Tensor* hist, Tensor* bin_edges, Tensor* r_bin_edges);

EXPORT_API(Tensor) THSTensor_set_(Tensor tensor, const Tensor source);

EXPORT_API(Tensor) THSTensor_set_requires_grad(const Tensor tensor, const bool requires_grad);
Expand Down
11 changes: 10 additions & 1 deletion src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs
Expand Up @@ -2075,7 +2075,16 @@ internal static partial class LibTorchSharp

[DllImport("LibTorchSharp")]
internal static extern IntPtr THSTensor_searchsorted_t(IntPtr sorted_sequence, IntPtr values, bool out_int32, bool right, IntPtr sorter);
[DllImport("LibTorchSharp")]
[DllImport("LibTorchSharp")]
internal static extern IntPtr THSTensor_searchsorted_s(IntPtr sorted_sequence, IntPtr values, bool out_int32, bool right, IntPtr sorter);

[DllImport("LibTorchSharp")]
internal static extern IntPtr THSTensor_histogram_t(IntPtr input, IntPtr bins, IntPtr weight, bool density, out IntPtr r_bin_edges);
[DllImport("LibTorchSharp")]
internal static extern IntPtr THSTensor_histogram_i(IntPtr input, long bins, IntPtr range, int length, IntPtr weight, bool density, out IntPtr r_bin_edges);
[DllImport("LibTorchSharp")]
internal static extern IntPtr THSTensor_histogram_out_t(IntPtr input, IntPtr bins, IntPtr weight, bool density, out IntPtr hist, out IntPtr bin_edges, out IntPtr r_bin_edges);
[DllImport("LibTorchSharp")]
internal static extern IntPtr THSTensor_histogram_out_i(IntPtr input, long bins, IntPtr range, int length, IntPtr weight, bool density, out IntPtr hist, out IntPtr bin_edges, out IntPtr r_bin_edges);
}
}
151 changes: 151 additions & 0 deletions src/TorchSharp/Tensor/torch.ComparisonOps.cs
Expand Up @@ -276,6 +276,157 @@ public static Tensor searchsorted(Tensor sorted_sequence, Scalar values, bool ou
return new Tensor(res);
}

// https://pytorch.org/docs/stable/generated/torch.histogram.html
/// <summary>
/// Computes a histogram of the values in a tensor.
/// bins can be an integer or a 1D tensor.
/// If bins is an int, it specifies the number of equal-width bins. By default, the lower and upper range of the bins is determined by the minimum and maximum elements of the input tensor. The range argument can be provided to specify a range for the bins.
/// If bins is a 1D tensor, it specifies the sequence of bin edges including the rightmost edge. It should contain at least 2 elements and its elements should be increasing.
/// </summary>
/// <param name="input"> the input tensor. </param>
/// <param name="bins"> int or 1D Tensor. If int, defines the number of equal-width bins. If tensor, defines the sequence of bin edges including the rightmost edge. </param>
/// <param name="weight"> If provided, weight should have the same shape as input. Each value in input contributes its associated weight towards its bin’s result. </param>
/// <param name="density"> If False, the result will contain the count (or total weight) in each bin. If True, the result is the value of the probability density function over the bins, normalized such that the integral over the range of the bins is 1. </param>
/// <returns></returns>
public static (Tensor hist, Tensor bin_edges) histogram(Tensor input, Tensor bins, Tensor weight = null, bool density = false)
{
var res = PInvoke.LibTorchSharp.THSTensor_histogram_t(input.Handle, bins.Handle, weight is null ? IntPtr.Zero : weight.Handle, density, out var r_bin_edges);
if (res == IntPtr.Zero) CheckForErrors();
if (r_bin_edges == IntPtr.Zero) CheckForErrors();
return (new Tensor(res), new Tensor(r_bin_edges));
}

// https://pytorch.org/docs/stable/generated/torch.histogram.html
/// <summary>
/// Computes a histogram of the values in a tensor.
/// bins can be an integer or a 1D tensor.
/// If bins is an int, it specifies the number of equal-width bins. By default, the lower and upper range of the bins is determined by the minimum and maximum elements of the input tensor. The range argument can be provided to specify a range for the bins.
/// If bins is a 1D tensor, it specifies the sequence of bin edges including the rightmost edge. It should contain at least 2 elements and its elements should be increasing.
/// </summary>
/// <param name="input"> the input tensor. </param>
/// <param name="bins"> int or 1D Tensor. If int, defines the number of equal-width bins. If tensor, defines the sequence of bin edges including the rightmost edge. </param>
/// /// <param name="range"> Defines the range of the bins. </param>
/// <param name="weight"> If provided, weight should have the same shape as input. Each value in input contributes its associated weight towards its bin’s result. </param>
/// <param name="density"> If False, the result will contain the count (or total weight) in each bin. If True, the result is the value of the probability density function over the bins, normalized such that the integral over the range of the bins is 1. </param>
/// <returns></returns>
public static (Tensor hist, Tensor bin_edges) histogram(Tensor input, long bins, (double min, double max)? range = null, Tensor weight = null, bool density = false)
{
double[] _range = Array.Empty<double>();
if (range is not null)
_range = new double[] { range.Value.min, range.Value.max };
unsafe {
fixed (double* prange = _range) {
var res = _range == Array.Empty<double>()
? PInvoke.LibTorchSharp.THSTensor_histogram_i(input.Handle, bins, IntPtr.Zero, 0, weight is null ? IntPtr.Zero : weight.Handle, density, out var r_bin_edges)
: PInvoke.LibTorchSharp.THSTensor_histogram_i(input.Handle, bins, (IntPtr)prange, _range.Length, weight is null ? IntPtr.Zero : weight.Handle, density, out r_bin_edges);
if (res == IntPtr.Zero) CheckForErrors();
if (r_bin_edges == IntPtr.Zero) CheckForErrors();
return (new Tensor(res), new Tensor(r_bin_edges));
}
}
}

// https://pytorch.org/docs/stable/generated/torch.histogram.html
/// <summary>
/// Computes a histogram of the values in a tensor.
/// bins can be an integer or a 1D tensor.
/// If bins is an int, it specifies the number of equal-width bins. By default, the lower and upper range of the bins is determined by the minimum and maximum elements of the input tensor. The range argument can be provided to specify a range for the bins.
/// If bins is a 1D tensor, it specifies the sequence of bin edges including the rightmost edge. It should contain at least 2 elements and its elements should be increasing.
/// </summary>
/// <param name="input"> the input tensor. </param>
/// <param name="bins"> int or 1D Tensor. If int, defines the number of equal-width bins. If tensor, defines the sequence of bin edges including the rightmost edge. </param>
/// <param name="out_tensor"> the output tensor. (tuple, optional): The result tuple of two output tensors (hist, bin_edges). </param>
/// <returns></returns>
public static (Tensor hist, Tensor bin_edges) histogram(Tensor input, Tensor bins, out (Tensor hist, Tensor bin_edges) out_tensor)
=> histogram(input, bins, null, false, out out_tensor);

// https://pytorch.org/docs/stable/generated/torch.histogram.html
/// <summary>
/// Computes a histogram of the values in a tensor.
/// bins can be an integer or a 1D tensor.
/// If bins is an int, it specifies the number of equal-width bins. By default, the lower and upper range of the bins is determined by the minimum and maximum elements of the input tensor. The range argument can be provided to specify a range for the bins.
/// If bins is a 1D tensor, it specifies the sequence of bin edges including the rightmost edge. It should contain at least 2 elements and its elements should be increasing.
/// </summary>
/// <param name="input"> the input tensor. </param>
/// <param name="bins"> int or 1D Tensor. If int, defines the number of equal-width bins. If tensor, defines the sequence of bin edges including the rightmost edge. </param>
/// <param name="weight"> If provided, weight should have the same shape as input. Each value in input contributes its associated weight towards its bin’s result. </param>
/// <param name="density"> If False, the result will contain the count (or total weight) in each bin. If True, the result is the value of the probability density function over the bins, normalized such that the integral over the range of the bins is 1. </param>
/// <param name="out_tensor"> the output tensor. (tuple, optional): The result tuple of two output tensors (hist, bin_edges). </param>
/// <returns></returns>
public static (Tensor hist, Tensor bin_edges) histogram(Tensor input, Tensor bins, Tensor weight, bool density, out (Tensor hist, Tensor bin_edges) out_tensor)
{
var res = PInvoke.LibTorchSharp.THSTensor_histogram_out_t(input.Handle, bins.Handle, weight is null ? IntPtr.Zero : weight.Handle, density, out var hist, out var bin_edges, out var r_bin_edges);
if (res == IntPtr.Zero) CheckForErrors();
if (hist == IntPtr.Zero) CheckForErrors();
if (bin_edges == IntPtr.Zero) CheckForErrors();
if (r_bin_edges == IntPtr.Zero) CheckForErrors();
out_tensor = (new Tensor(hist), new Tensor(bin_edges));
return (new Tensor(res), new Tensor(r_bin_edges));
}

// https://pytorch.org/docs/stable/generated/torch.histogram.html
/// <summary>
/// Computes a histogram of the values in a tensor.
/// bins can be an integer or a 1D tensor.
/// If bins is an int, it specifies the number of equal-width bins. By default, the lower and upper range of the bins is determined by the minimum and maximum elements of the input tensor. The range argument can be provided to specify a range for the bins.
/// If bins is a 1D tensor, it specifies the sequence of bin edges including the rightmost edge. It should contain at least 2 elements and its elements should be increasing.
/// </summary>
/// <param name="input"> the input tensor. </param>
/// <param name="bins"> int or 1D Tensor. If int, defines the number of equal-width bins. If tensor, defines the sequence of bin edges including the rightmost edge. </param>
/// <param name="out_tensor"> the output tensor. (tuple, optional): The result tuple of two output tensors (hist, bin_edges). </param>
/// <returns></returns>
public static (Tensor hist, Tensor bin_edges) histogram(Tensor input, long bins, out (Tensor hist, Tensor bin_edges) out_tensor)
=> histogram(input, bins, null, null, false, out out_tensor);

// https://pytorch.org/docs/stable/generated/torch.histogram.html
/// <summary>
/// Computes a histogram of the values in a tensor.
/// bins can be an integer or a 1D tensor.
/// If bins is an int, it specifies the number of equal-width bins. By default, the lower and upper range of the bins is determined by the minimum and maximum elements of the input tensor. The range argument can be provided to specify a range for the bins.
/// If bins is a 1D tensor, it specifies the sequence of bin edges including the rightmost edge. It should contain at least 2 elements and its elements should be increasing.
/// </summary>
/// <param name="input"> the input tensor. </param>
/// <param name="bins"> int or 1D Tensor. If int, defines the number of equal-width bins. If tensor, defines the sequence of bin edges including the rightmost edge. </param>
/// <param name="range"> Defines the range of the bins. </param>
/// <param name="out_tensor"> the output tensor. (tuple, optional): The result tuple of two output tensors (hist, bin_edges). </param>
/// <returns></returns>
public static (Tensor hist, Tensor bin_edges) histogram(Tensor input, long bins, (double min, double max)? range, out (Tensor hist, Tensor bin_edges) out_tensor)
=> histogram(input, bins, range, null, false, out out_tensor);

// https://pytorch.org/docs/stable/generated/torch.histogram.html
/// <summary>
/// Computes a histogram of the values in a tensor.
/// bins can be an integer or a 1D tensor.
/// If bins is an int, it specifies the number of equal-width bins. By default, the lower and upper range of the bins is determined by the minimum and maximum elements of the input tensor. The range argument can be provided to specify a range for the bins.
/// If bins is a 1D tensor, it specifies the sequence of bin edges including the rightmost edge. It should contain at least 2 elements and its elements should be increasing.
/// </summary>
/// <param name="input"> the input tensor. </param>
/// <param name="bins"> int or 1D Tensor. If int, defines the number of equal-width bins. If tensor, defines the sequence of bin edges including the rightmost edge. </param>
/// <param name="range"> Defines the range of the bins. </param>
/// <param name="weight"> If provided, weight should have the same shape as input. Each value in input contributes its associated weight towards its bin’s result. </param>
/// <param name="density"> If False, the result will contain the count (or total weight) in each bin. If True, the result is the value of the probability density function over the bins, normalized such that the integral over the range of the bins is 1. </param>
/// <param name="out_tensor"> the output tensor. (tuple, optional): The result tuple of two output tensors (hist, bin_edges). </param>
/// <returns></returns>
public static (Tensor hist, Tensor bin_edges) histogram(Tensor input, long bins, (double min, double max)? range, Tensor weight, bool density, out (Tensor hist, Tensor bin_edges) out_tensor)
{
double[] _range = Array.Empty<double>();
if (range is not null)
_range = new double[] { range.Value.min, range.Value.max };
unsafe {
fixed (double* prange = _range) {
var res = _range == Array.Empty<double>()
? PInvoke.LibTorchSharp.THSTensor_histogram_out_i(input.Handle, bins, IntPtr.Zero, 0, weight is null ? IntPtr.Zero : weight.Handle, density, out var hist, out var bin_edges, out var r_bin_edges)
: PInvoke.LibTorchSharp.THSTensor_histogram_out_i(input.Handle, bins, (IntPtr)prange, _range.Length, weight is null ? IntPtr.Zero : weight.Handle, density, out hist, out bin_edges, out r_bin_edges);
if (res == IntPtr.Zero) CheckForErrors();
if (hist == IntPtr.Zero) CheckForErrors();
if (bin_edges == IntPtr.Zero) CheckForErrors();
if (r_bin_edges == IntPtr.Zero) CheckForErrors();
out_tensor = (new Tensor(hist), new Tensor(bin_edges));
return (new Tensor(res), new Tensor(r_bin_edges));
}
}
}

// https://pytorch.org/docs/stable/generated/torch.topk
/// <summary>
/// Returns the k largest elements of the given input tensor along a given dimension.
Expand Down