#include #include "ctorch.h" namespace ctorch { template inline c10::ScalarType dtype() { return torch::kFloat64; } template <> inline c10::ScalarType dtype() { return torch::kFloat32; } template <> inline c10::ScalarType dtype() { return torch::kInt64; } template <> inline c10::ScalarType dtype() { return torch::kInt32; } inline torch::Tensor &cast(const TorchTensorHandle &tensor_handle) { return *static_cast(tensor_handle); } inline char *tensor_to_char(const torch::Tensor &tensor) { std::stringstream bufrep; bufrep << tensor; auto rep = bufrep.str(); char *crep = (char *)malloc(rep.length() + 1); std::strcpy(crep, rep.c_str()); return crep; } inline int device_to_int(const torch::Tensor &tensor) { return (tensor.device().type() == torch::kCPU) ? 0 : 1 + tensor.device().index(); } inline torch::Device int_to_device(int device_int) { return (device_int == 0) ? torch::kCPU : torch::Device(torch::kCUDA, device_int - 1); } inline std::vector to_vec_int(int *arr, int arr_size) { auto vec = std::vector(arr_size); vec.assign(arr, arr + arr_size); return vec; } inline std::vector to_index(int *arr, int arr_size) { std::vector index; for (int i = 0; i < arr_size; i++) { index.emplace_back(arr[i]); } return index; } template inline torch::Tensor from_blob(Dtype *data, std::vector shape, torch::Device device, bool copy) { return torch::from_blob(data, shape, dtype()).to(torch::TensorOptions().layout(torch::kStrided).device(device), false, copy); } template inline NumType get(const TorchTensorHandle &tensor_handle, int *index) { auto ten = ctorch::cast(tensor_handle); return ten.index(to_index(index, ten.dim())).item(); } template inline void set(TorchTensorHandle &tensor_handle, int *index, NumType value) { auto ten = ctorch::cast(tensor_handle); ten.index(to_index(index, ten.dim())) = value; } template inline torch::Tensor randn(std::vector shape, torch::Device device) { return torch::randn(shape, torch::TensorOptions().dtype(dtype()).layout(torch::kStrided).device(device)); } template inline torch::Tensor rand(std::vector shape, torch::Device device) { return torch::rand(shape, torch::TensorOptions().dtype(dtype()).layout(torch::kStrided).device(device)); } template inline torch::Tensor randint(long low, long high, std::vector shape, torch::Device device) { return torch::randint(low, high, shape, torch::TensorOptions().dtype(dtype()).layout(torch::kStrided).device(device)); } template inline torch::Tensor full(Dtype value, std::vector shape, torch::Device device) { return torch::full(shape, value, torch::TensorOptions().dtype(dtype()).layout(torch::kStrided).device(device)); } inline torch::Tensor hessian(const torch::Tensor &value, const torch::Tensor &variable) { auto nelem = variable.numel(); auto hess = value.new_zeros({nelem, nelem}); auto grad = torch::autograd::grad({value}, {variable}, {}, torch::nullopt, true)[0].view(nelem); int i = 0; for (int j = 0; j < nelem; j++) { auto row = grad[j].requires_grad() ? torch::autograd::grad({grad[i]}, {variable}, {}, true, true, true)[0].view(nelem).slice(0, j, nelem) : grad[j].new_zeros(nelem - j); hess[i].slice(0, i, nelem).add_(row.type_as(hess)); i++; } auto ndim = variable.dim(); auto sizes = variable.sizes().data(); auto shape = std::vector(ndim); shape.assign(sizes, sizes + ndim); shape.reserve(2 * ndim); std::copy_n(shape.begin(), ndim, std::back_inserter(shape)); return (hess + torch::triu(hess, 1).t()).view(shape); } } // namespace ctorch