diff options
author | Sam Gross <colesbury@gmail.com> | 2017-01-27 18:15:56 -0500 |
---|---|---|
committer | Soumith Chintala <soumith@gmail.com> | 2017-01-27 18:15:56 -0500 |
commit | 887002e93216a64e0fc4bad2d1090df13f5cf1c2 (patch) | |
tree | 3769b8fc21480f2c36132b176d3738f83d969df6 | |
parent | 31dea5ff236a73c47d68f9ea0a1891daccc4002a (diff) | |
download | pytorch-887002e93216a64e0fc4bad2d1090df13f5cf1c2.tar.gz pytorch-887002e93216a64e0fc4bad2d1090df13f5cf1c2.tar.bz2 pytorch-887002e93216a64e0fc4bad2d1090df13f5cf1c2.zip |
Add bindings to CUDA tensors and storages in THPP (#615)
-rw-r--r-- | torch/lib/THPP/CMakeLists.txt | 15 | ||||
-rw-r--r-- | torch/lib/THPP/Storage.hpp | 2 | ||||
-rw-r--r-- | torch/lib/THPP/Tensor.hpp | 6 | ||||
-rw-r--r-- | torch/lib/THPP/Traits.hpp | 20 | ||||
-rw-r--r-- | torch/lib/THPP/TraitsCuda.cpp | 7 | ||||
-rw-r--r-- | torch/lib/THPP/TraitsCuda.hpp | 14 | ||||
-rw-r--r-- | torch/lib/THPP/Type.hpp | 3 | ||||
-rw-r--r-- | torch/lib/THPP/storages/THCStorage.cpp | 11 | ||||
-rw-r--r-- | torch/lib/THPP/storages/THCStorage.hpp | 61 | ||||
-rw-r--r-- | torch/lib/THPP/storages/THStorage.hpp | 2 | ||||
-rw-r--r-- | torch/lib/THPP/storages/generic/THCStorage.cpp | 125 | ||||
-rw-r--r-- | torch/lib/THPP/storages/generic/THCStorage.hpp | 10 | ||||
-rw-r--r-- | torch/lib/THPP/storages/generic/THStorage.cpp | 10 | ||||
-rw-r--r-- | torch/lib/THPP/tensors/THCTensor.cpp | 9 | ||||
-rw-r--r-- | torch/lib/THPP/tensors/THCTensor.hpp | 157 | ||||
-rw-r--r-- | torch/lib/THPP/tensors/THTensor.hpp | 6 | ||||
-rw-r--r-- | torch/lib/THPP/tensors/generic/THCTensor.cpp | 620 | ||||
-rw-r--r-- | torch/lib/THPP/tensors/generic/THCTensor.hpp | 10 | ||||
-rw-r--r-- | torch/lib/THPP/tensors/generic/THTensor.cpp | 31 |
19 files changed, 1113 insertions, 6 deletions
diff --git a/torch/lib/THPP/CMakeLists.txt b/torch/lib/THPP/CMakeLists.txt index 11b199d031..64b32c75e8 100644 --- a/torch/lib/THPP/CMakeLists.txt +++ b/torch/lib/THPP/CMakeLists.txt @@ -18,7 +18,7 @@ FUNCTION(EXCLUDE_DIR list_name dir_name) ENDFUNCTION() ################################################################################ - + if(${CMAKE_VERSION} VERSION_LESS "2.8.12") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else(${CMAKE_VERSION} VERSION_LESS "2.8.12") @@ -31,6 +31,12 @@ IF(NOT Torch_FOUND) FIND_PACKAGE(Torch REQUIRED) ENDIF() +FIND_PACKAGE(CUDA 5.5) +IF(CUDA_FOUND) + INCLUDE_DIRECTORIES(${CUDA_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES("${CUDA_SDK_ROOT_DIR}/common/inc") +ENDIF() + # Can be compiled standalone IF(NOT THPP_INSTALL_BIN_DIR OR NOT THPP_INSTALL_LIB_DIR OR NOT THPP_INSTALL_INCLUDE_DIR) SET(THPP_INSTALL_BIN_DIR "bin" CACHE PATH "THPP install binary subdirectory") @@ -46,6 +52,13 @@ SET(all_h ${base_h}) EXCLUDE_DIR(all_cpp ".*/generic/.*\\.cpp$") +IF(NOT CUDA_FOUND) + EXCLUDE_DIR(all_h ".*THC.*.hpp$") + EXCLUDE_DIR(all_cpp ".*THC.*.cpp$") + EXCLUDE_DIR(all_cpp "TraitsCuda.cpp") +ENDIF() + + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) ADD_LIBRARY(THPP SHARED ${all_cpp}) SET_TARGET_PROPERTIES(THPP PROPERTIES VERSION 1 SOVERSION 1) diff --git a/torch/lib/THPP/Storage.hpp b/torch/lib/THPP/Storage.hpp index 544366b8c4..cfa7ea6039 100644 --- a/torch/lib/THPP/Storage.hpp +++ b/torch/lib/THPP/Storage.hpp @@ -30,6 +30,8 @@ struct Storage { virtual Storage& resize(long new_size) = 0; virtual thpp::Type type() const = 0; + virtual bool isCuda() const = 0; + virtual int getDevice() const = 0; virtual std::unique_ptr<Tensor> newTensor() const = 0; }; diff --git a/torch/lib/THPP/Tensor.hpp b/torch/lib/THPP/Tensor.hpp index e613444fa1..4a0f886e9b 100644 --- a/torch/lib/THPP/Tensor.hpp +++ b/torch/lib/THPP/Tensor.hpp @@ -36,6 +36,8 @@ struct Tensor { virtual bool isContiguous() const = 0; virtual void* data() = 0; virtual const void* data() const = 0; + virtual void* cdata() = 0; + virtual const void* cdata() const = 0; virtual Tensor& retain() = 0; virtual Tensor& free() = 0; @@ -60,6 +62,7 @@ struct Tensor { virtual Tensor& gather(const Tensor& src, int dimension, const Tensor& index) = 0; virtual Tensor& scatter(int dimension, const Tensor& index, const Tensor& src) = 0; virtual Tensor& neg(const Tensor& src) = 0; + virtual Tensor& cadd(const Tensor& src1, const Tensor& src2) = 0; virtual Tensor& cinv(const Tensor& src) = 0; virtual Tensor& cmul(const Tensor& src1, const Tensor& src2) = 0; virtual Tensor& cpow(const Tensor& src1, const Tensor& src2) = 0; @@ -79,8 +82,11 @@ struct Tensor { virtual Tensor& cross(const Tensor& src1, const Tensor& src2, int dimension) = 0; virtual Tensor& cmax(const Tensor& src1, const Tensor& src2) = 0; virtual Tensor& cmin(const Tensor& src1, const Tensor& src2) = 0; + virtual Tensor& zero() = 0; virtual thpp::Type type() const = 0; + virtual bool isCuda() const = 0; + virtual int getDevice() const = 0; virtual std::unique_ptr<Tensor> newTensor() const = 0; }; diff --git a/torch/lib/THPP/Traits.hpp b/torch/lib/THPP/Traits.hpp index 24c6e215b0..64b9b0092a 100644 --- a/torch/lib/THPP/Traits.hpp +++ b/torch/lib/THPP/Traits.hpp @@ -12,77 +12,89 @@ namespace thpp { +template<typename T> +struct type_traits {}; + template<typename real> struct interface_traits { using scalar_type = typename std::conditional< - std::is_floating_point<real>::value, + type_traits<real>::is_floating_point, double, long long>::type; using tensor_interface_type = TensorScalarInterface<scalar_type>; using storage_interface_type = StorageScalarInterface<scalar_type>; }; -template<typename T> -struct type_traits {}; - template<> struct type_traits<char> { static constexpr Type type = Type::CHAR; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<unsigned char> { static constexpr Type type = Type::UCHAR; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<float> { static constexpr Type type = Type::FLOAT; + static constexpr bool is_floating_point = true; }; template<> struct type_traits<double> { static constexpr Type type = Type::DOUBLE; + static constexpr bool is_floating_point = true; }; template<> struct type_traits<short> { static constexpr Type type = Type::SHORT; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<unsigned short> { static constexpr Type type = Type::USHORT; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<int> { static constexpr Type type = Type::INT; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<unsigned int> { static constexpr Type type = Type::UINT; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<long> { static constexpr Type type = Type::LONG; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<unsigned long> { static constexpr Type type = Type::ULONG; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<long long> { static constexpr Type type = Type::LONG_LONG; + static constexpr bool is_floating_point = false; }; template<> struct type_traits<unsigned long long> { static constexpr Type type = Type::ULONG_LONG; + static constexpr bool is_floating_point = false; }; template<typename T> diff --git a/torch/lib/THPP/TraitsCuda.cpp b/torch/lib/THPP/TraitsCuda.cpp new file mode 100644 index 0000000000..179e8974d3 --- /dev/null +++ b/torch/lib/THPP/TraitsCuda.cpp @@ -0,0 +1,7 @@ +#include "TraitsCuda.hpp" + +namespace thpp { + +constexpr Type type_traits<half>::type; + +} // namespace thpp diff --git a/torch/lib/THPP/TraitsCuda.hpp b/torch/lib/THPP/TraitsCuda.hpp new file mode 100644 index 0000000000..9e83fc8cf1 --- /dev/null +++ b/torch/lib/THPP/TraitsCuda.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "Traits.hpp" +#include <THC/THCHalf.h> + +namespace thpp { + +template<> +struct type_traits<half> { + static constexpr Type type = Type::HALF; + static constexpr bool is_floating_point = true; +}; + +} // namespace thpp diff --git a/torch/lib/THPP/Type.hpp b/torch/lib/THPP/Type.hpp index ba188ac90f..0b947cf08d 100644 --- a/torch/lib/THPP/Type.hpp +++ b/torch/lib/THPP/Type.hpp @@ -13,6 +13,7 @@ enum class Type : char { UCHAR = 'B', FLOAT = 'f', DOUBLE = 'd', + HALF = 'a', SHORT = 'h', USHORT = 'H', INT = 'i', @@ -27,7 +28,7 @@ enum class Type : char { }; inline bool isFloat(Type t) { - return (t == Type::FLOAT || t == Type::DOUBLE); + return (t == Type::FLOAT || t == Type::DOUBLE || t == Type::HALF); } inline bool isObject(Type t) { diff --git a/torch/lib/THPP/storages/THCStorage.cpp b/torch/lib/THPP/storages/THCStorage.cpp new file mode 100644 index 0000000000..e4598bb32c --- /dev/null +++ b/torch/lib/THPP/storages/THCStorage.cpp @@ -0,0 +1,11 @@ +#include "THCStorage.hpp" +#include "../Traits.hpp" + +#include "../tensors/THCTensor.hpp" + +namespace thpp { + +#include "generic/THCStorage.cpp" +#include <THC/THCGenerateAllTypes.h> + +} // namespace thpp diff --git a/torch/lib/THPP/storages/THCStorage.hpp b/torch/lib/THPP/storages/THCStorage.hpp new file mode 100644 index 0000000000..ea726fdc85 --- /dev/null +++ b/torch/lib/THPP/storages/THCStorage.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include <THC/THC.h> + +// We're defining THCStorage as a custom class +#undef THCStorage +#undef THStorage +#define THCRealStorage TH_CONCAT_3(TH,CReal,Storage) + +#include "../Storage.hpp" +#include "../TraitsCuda.hpp" + +namespace thpp { + +template<typename real> +struct thc_storage_traits {}; + +#include "storages/generic/THCStorage.hpp" +#include <THC/THCGenerateAllTypes.h> + + +template<typename real> +struct THCStorage : public interface_traits<real>::storage_interface_type { +private: + using interface_type = typename interface_traits<real>::storage_interface_type; +public: + using storage_type = typename thc_storage_traits<real>::storage_type; + using scalar_type = typename interface_type::scalar_type; + + THCStorage(THCState* state); + THCStorage(THCState* state, storage_type *wrapped); + THCStorage(THCState* state, std::size_t size); + virtual ~THCStorage(); + + virtual std::size_t elementSize() const override; + virtual std::size_t size() const override; + virtual void* data() override; + virtual const void* data() const override; + virtual THCStorage& retain() override; + virtual THCStorage& free() override; + + virtual THCStorage& resize(long new_size) override; + virtual THCStorage& fill(scalar_type value) override; + virtual THCStorage& set(std::size_t ind, scalar_type value) override; + virtual THCStorage& fast_set(std::size_t ind, scalar_type value) override; + virtual scalar_type get(std::size_t ind) override; + virtual scalar_type fast_get(std::size_t ind) override; + + virtual thpp::Type type() const override; + virtual bool isCuda() const override; + virtual int getDevice() const override; + + virtual std::unique_ptr<Tensor> newTensor() const override; + virtual storage_type *getRaw() const; + +protected: + storage_type *storage; + THCState* state; +}; + +} // namespace thpp diff --git a/torch/lib/THPP/storages/THStorage.hpp b/torch/lib/THPP/storages/THStorage.hpp index 17a2fdecbd..dc37358f4d 100644 --- a/torch/lib/THPP/storages/THStorage.hpp +++ b/torch/lib/THPP/storages/THStorage.hpp @@ -49,6 +49,8 @@ public: virtual scalar_type fast_get(std::size_t ind) override; virtual thpp::Type type() const override; + virtual bool isCuda() const override; + virtual int getDevice() const override; virtual std::unique_ptr<Tensor> newTensor() const override; virtual storage_type *getRaw() const; diff --git a/torch/lib/THPP/storages/generic/THCStorage.cpp b/torch/lib/THPP/storages/generic/THCStorage.cpp new file mode 100644 index 0000000000..6fa7ef7bea --- /dev/null +++ b/torch/lib/THPP/storages/generic/THCStorage.cpp @@ -0,0 +1,125 @@ +#ifndef THC_GENERIC_FILE +#define THC_GENERIC_FILE "storages/generic/THCStorage.cpp" +#else + +template<> +THCStorage<real>::THCStorage(THCState* state): + storage(THCStorage_(new)(state)), state(state) {} + +template<> +THCStorage<real>::THCStorage(THCState* state, storage_type* storage): + storage(storage), state(state) {} + +template<> +THCStorage<real>::THCStorage(THCState* state, std::size_t storage_size) + : storage(THCStorage_(newWithSize)(state, storage_size)), state(state) {} + +template<> +THCStorage<real>::~THCStorage() { + THCStorage_(free)(state, storage); +} + +template<> +std::size_t THCStorage<real>::elementSize() const { + return sizeof(real); +} + +template<> +std::size_t THCStorage<real>::size() const { + return storage->size; +} + +template<> +void* THCStorage<real>::data() { + return storage->data; +} + +template<> +const void* THCStorage<real>::data() const { + return storage->data; +} + +template<> +auto THCStorage<real>::retain() -> THCStorage& { + THCStorage_(retain)(state, storage); + return *this; +} + +template<> +auto THCStorage<real>::free() -> THCStorage& { + THCStorage_(free)(state, storage); + return *this; +} + +template<> +auto THCStorage<real>::resize(long new_size) -> THCStorage& { + THCStorage_(resize)(state, storage, new_size); + return *this; +} + +#ifdef THC_REAL_IS_HALF +#define cast_scalar(v) THC_float2half(v) +#else +#define cast_scalar(v) v +#endif + +template<> +auto THCStorage<real>::fill(scalar_type value) -> THCStorage& { + THCStorage_(fill)(state, storage, cast_scalar(value)); + return *this; +} + +template<> +auto THCStorage<real>::set(std::size_t ind, scalar_type value) -> THCStorage& { + THCStorage_(set)(state, storage, ind, cast_scalar(value)); + return *this; +} + +template<> +auto THCStorage<real>::fast_set(std::size_t ind, scalar_type value) -> THCStorage& { + throw std::runtime_error("unsupported operation 'fast_set'"); +} + +template<> +auto THCStorage<real>::get(std::size_t ind) -> scalar_type { + auto v = THCStorage_(get)(state, storage, ind); +#ifdef THC_REAL_IS_HALF + return THC_half2float(v); +#else + return v; +#endif +} + +template<> +auto THCStorage<real>::fast_get(std::size_t ind) -> scalar_type { + throw std::runtime_error("unsupported operation 'fast_get'"); +} + +template<> +thpp::Type THCStorage<real>::type() const { + return thpp::type_traits<real>::type; +} + +template<> +bool THCStorage<real>::isCuda() const { + return true; +} + +template<> +int THCStorage<real>::getDevice() const { + return storage->device; +} + +template<> +std::unique_ptr<Tensor> THCStorage<real>::newTensor() const { + return std::unique_ptr<Tensor>(new THCTensor<real>(state)); +} + +template<> +THCStorage<real>::storage_type *THCStorage<real>::getRaw() const { + return storage; +} + +#undef cast_scalar + +#endif diff --git a/torch/lib/THPP/storages/generic/THCStorage.hpp b/torch/lib/THPP/storages/generic/THCStorage.hpp new file mode 100644 index 0000000000..2c32279621 --- /dev/null +++ b/torch/lib/THPP/storages/generic/THCStorage.hpp @@ -0,0 +1,10 @@ +#ifndef THC_GENERIC_FILE +#define THC_GENERIC_FILE "storages/generic/THCStorage.hpp" +#else + +template<> +struct thc_storage_traits<real> { + using storage_type = THCRealStorage; +}; + +#endif diff --git a/torch/lib/THPP/storages/generic/THStorage.cpp b/torch/lib/THPP/storages/generic/THStorage.cpp index 0402e159b0..c0dc2bd579 100644 --- a/torch/lib/THPP/storages/generic/THStorage.cpp +++ b/torch/lib/THPP/storages/generic/THStorage.cpp @@ -89,6 +89,16 @@ thpp::Type THStorage<real>::type() const { } template<> +bool THStorage<real>::isCuda() const { + return false; +} + +template<> +int THStorage<real>::getDevice() const { + return -1; +} + +template<> std::unique_ptr<Tensor> THStorage<real>::newTensor() const { return std::unique_ptr<Tensor>(new THTensor<real>()); } diff --git a/torch/lib/THPP/tensors/THCTensor.cpp b/torch/lib/THPP/tensors/THCTensor.cpp new file mode 100644 index 0000000000..55db9b5c25 --- /dev/null +++ b/torch/lib/THPP/tensors/THCTensor.cpp @@ -0,0 +1,9 @@ +#include "THCTensor.hpp" +#include "../TraitsCuda.hpp" + +namespace thpp { + +#include "generic/THCTensor.cpp" +#include <THC/THCGenerateAllTypes.h> + +} // namespace thpp diff --git a/torch/lib/THPP/tensors/THCTensor.hpp b/torch/lib/THPP/tensors/THCTensor.hpp new file mode 100644 index 0000000000..be8b875539 --- /dev/null +++ b/torch/lib/THPP/tensors/THCTensor.hpp @@ -0,0 +1,157 @@ +#pragma once + +#include <THC/THC.h> + +// We're defining THCTensor as a custom class +#undef THCTensor +#define THCRealTensor TH_CONCAT_3(TH,CReal,Tensor) + +#include "../Tensor.hpp" +#include "../Traits.hpp" + +namespace thpp { + +template<typename real> +struct thc_tensor_traits {}; + +#include "tensors/generic/THCTensor.hpp" +#include <THC/THCGenerateAllTypes.h> + +} // namespace thpp + +#include "../storages/THCStorage.hpp" + +namespace thpp { + +template<typename real> +struct THCTensor : public interface_traits<real>::tensor_interface_type { + friend class THCTensor<unsigned char>; + friend class THCTensor<char>; + friend class THCTensor<short>; + friend class THCTensor<int>; + friend class THCTensor<long>; + friend class THCTensor<float>; + friend class THCTensor<double>; + friend class THCTensor<half>; + +private: + using interface_type = typename interface_traits<real>::tensor_interface_type; +public: + using tensor_type = typename thc_tensor_traits<real>::tensor_type; + using scalar_type = typename interface_type::scalar_type; + using long_range = Tensor::long_range; + + THCTensor(THCState* state); + THCTensor(THCState* state, tensor_type *wrapped); + virtual ~THCTensor(); + + virtual THCTensor* clone() const override; + virtual THCTensor* clone_shallow() override; + + virtual int nDim() const override; + virtual long_range sizes() const override; + virtual long_range strides() const override; + virtual const long* rawSizes() const override; + virtual const long* rawStrides() const override; + virtual std::size_t storageOffset() const override; + virtual std::size_t elementSize() const override; + virtual long long numel() const override; + virtual bool isContiguous() const override; + virtual void* data() override; + virtual const void* data() const override; + virtual void* cdata() override; + virtual const void* cdata() const override; + virtual THCTensor& retain() override; + virtual THCTensor& free() override; + + virtual THCTensor& resize(const std::initializer_list<long>& new_size) override; + virtual THCTensor& resize(const std::vector<long>& new_size) override; + virtual THCTensor& resize(THLongStorage *size, + THLongStorage *stride) override; + virtual THCTensor& resizeAs(const Tensor& src) override; + virtual THCTensor& set(const Tensor& src) override; + virtual THCTensor& setStorage(const Storage& storage, + ptrdiff_t storageOffset, + THLongStorage *size, + THLongStorage *stride) override; + + virtual THCTensor& narrow(const Tensor& src, int dimension, + long firstIndex, long size) override; + virtual THCTensor& select(const Tensor& src, int dimension, + long sliceIndex) override; + virtual THCTensor& transpose(const Tensor& src, int dimension1, + int dimension2) override; + virtual THCTensor& unfold(const Tensor& src, int dimension, + long size, long step) override; + + virtual THCTensor& fill(scalar_type value) override; + + virtual THCTensor& gather(const Tensor& src, int dimension, const Tensor& index) override; + virtual THCTensor& scatter(int dimension, const Tensor& index, const Tensor& src) override; + virtual THCTensor& scatterFill(int dimension, const Tensor& index, scalar_type value) override; + virtual scalar_type dot(const Tensor& source) override; + virtual scalar_type minall() override; + virtual scalar_type maxall() override; + virtual scalar_type sumall() override; + virtual scalar_type prodall() override; + virtual THCTensor& neg(const Tensor& src) override; + virtual THCTensor& cinv(const Tensor& src) override; + virtual THCTensor& add(const Tensor& src, scalar_type value) override; + virtual THCTensor& sub(const Tensor& src, scalar_type value) override; + virtual THCTensor& mul(const Tensor& src, scalar_type value) override; + virtual THCTensor& div(const Tensor& src, scalar_type value) override; + virtual THCTensor& fmod(const Tensor& src, scalar_type value) override; + virtual THCTensor& remainder(const Tensor& src, scalar_type value) override; + virtual THCTensor& clamp(const Tensor& src, scalar_type min_value, scalar_type max_value) override; + virtual THCTensor& cadd(const Tensor& src1, const Tensor& src2) override; + virtual THCTensor& cadd(const Tensor& src1, scalar_type value, const Tensor& src2) override; + virtual THCTensor& csub(const Tensor& src1, scalar_type value, const Tensor& src2) override; + virtual THCTensor& cmul(const Tensor& src1, const Tensor& src2) override; + virtual THCTensor& cpow(const Tensor& src1, const Tensor& src2) override; + virtual THCTensor& cdiv(const Tensor& src1, const Tensor& src2) override; + virtual THCTensor& cfmod(const Tensor& src1, const Tensor& src2) override; + virtual THCTensor& cremainder(const Tensor& src1, const Tensor& src2) override; + virtual THCTensor& addcmul(const Tensor& src1, scalar_type value, const Tensor& src2, const Tensor& src3) override; + virtual THCTensor& addcdiv(const Tensor& src1, scalar_type value, const Tensor& src2, const Tensor& src3) override; + virtual THCTensor& addmv(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& mat, const Tensor& vec) override; + virtual THCTensor& addmm(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& mat1, const Tensor& mat2) override; + virtual THCTensor& addr(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& vec1, const Tensor& vec2) override; + virtual THCTensor& addbmm(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& batch1, const Tensor& batch2) override; + virtual THCTensor& baddbmm(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& batch1, const Tensor& batch2) override; + virtual THCTensor& match(const Tensor& m1, const Tensor& m2, scalar_type gain) override; + virtual THCTensor& max(const Tensor& indices_, const Tensor& src, int dimension) override; + virtual THCTensor& min(const Tensor& indices_, const Tensor& src, int dimension) override; + virtual THCTensor& kthvalue(const Tensor& indices_, const Tensor& src, long k, int dimension) override; + virtual THCTensor& mode(const Tensor& indices_, const Tensor& src, int dimension) override; + virtual THCTensor& median(const Tensor& indices_, const Tensor& src, int dimension) override; + virtual THCTensor& sum(const Tensor& src, int dimension) override; + virtual THCTensor& prod(const Tensor& src, int dimension) override; + virtual THCTensor& cumsum(const Tensor& src, int dimension) override; + virtual THCTensor& cumprod(const Tensor& src, int dimension) override; + virtual THCTensor& sign(const Tensor& source) override; + virtual scalar_type trace() override; + virtual THCTensor& cross(const Tensor& src1, const Tensor& src2, int dimension) override; + virtual THCTensor& cmax(const Tensor& src1, const Tensor& src2) override; + virtual THCTensor& cmin(const Tensor& src1, const Tensor& src2) override; + virtual THCTensor& cmaxValue(const Tensor& src, scalar_type value) override; + virtual THCTensor& cminValue(const Tensor& src, scalar_type value) override; + virtual THCTensor& zero() override; + + virtual thpp::Type type() const override; + virtual bool isCuda() const override; + virtual int getDevice() const override; + virtual std::unique_ptr<Tensor> newTensor() const override; + +private: + template<typename iterator> + THCTensor& resize(const iterator& begin, const iterator& end); + template<typename iterator> + THCTensor& resize(const iterator& size_begin, const iterator& size_end, + const iterator& stride_begin, const iterator& stride_end); + +protected: + tensor_type *tensor; + THCState *state; +}; + +} diff --git a/torch/lib/THPP/tensors/THTensor.hpp b/torch/lib/THPP/tensors/THTensor.hpp index 1d6d4f3c9b..0f96a76f8a 100644 --- a/torch/lib/THPP/tensors/THTensor.hpp +++ b/torch/lib/THPP/tensors/THTensor.hpp @@ -58,6 +58,8 @@ public: virtual bool isContiguous() const override; virtual void* data() override; virtual const void* data() const override; + virtual void* cdata() override; + virtual const void* cdata() const override; virtual THTensor& retain() override; virtual THTensor& free() override; @@ -100,6 +102,7 @@ public: virtual THTensor& fmod(const Tensor& src, scalar_type value) override; virtual THTensor& remainder(const Tensor& src, scalar_type value) override; virtual THTensor& clamp(const Tensor& src, scalar_type min_value, scalar_type max_value) override; + virtual THTensor& cadd(const Tensor& src1, const Tensor& src2) override; virtual THTensor& cadd(const Tensor& src1, scalar_type value, const Tensor& src2) override; virtual THTensor& csub(const Tensor& src1, scalar_type value, const Tensor& src2) override; virtual THTensor& cmul(const Tensor& src1, const Tensor& src2) override; @@ -131,8 +134,11 @@ public: virtual THTensor& cmin(const Tensor& src1, const Tensor& src2) override; virtual THTensor& cmaxValue(const Tensor& src, scalar_type value) override; virtual THTensor& cminValue(const Tensor& src, scalar_type value) override; + virtual THTensor& zero() override; virtual thpp::Type type() const override; + virtual bool isCuda() const override; + virtual int getDevice() const override; virtual std::unique_ptr<Tensor> newTensor() const override; private: diff --git a/torch/lib/THPP/tensors/generic/THCTensor.cpp b/torch/lib/THPP/tensors/generic/THCTensor.cpp new file mode 100644 index 0000000000..c2e21601c1 --- /dev/null +++ b/torch/lib/THPP/tensors/generic/THCTensor.cpp @@ -0,0 +1,620 @@ +#ifndef THC_GENERIC_FILE +#define THC_GENERIC_FILE "tensors/generic/THCTensor.cpp" +#else + +template<> +THCTensor<real>::THCTensor(THCState* state): + tensor(THCTensor_(new)(state)), state(state) + {}; + +template<> +THCTensor<real>::THCTensor(THCState* state, THCRealTensor *wrapped): + tensor(wrapped), state(state) + {}; + +template<> +THCTensor<real>::~THCTensor() { + if (tensor) + THCTensor_(free)(state, tensor); +} + +template<> +auto THCTensor<real>::clone() const -> THCTensor* { + return new THCTensor(state, THCTensor_(newClone)(state, tensor)); +} + +template<> +auto THCTensor<real>::clone_shallow() -> THCTensor* { + THCTensor_(retain)(state, tensor); + return new THCTensor(state, tensor); +} + +template<> +int THCTensor<real>::nDim() const { + return tensor->nDimension; +} + +template<> +auto THCTensor<real>::sizes() const -> long_range { + return std::vector<long>(tensor->size, tensor->size + tensor->nDimension); +} + +template<> +const long* THCTensor<real>::rawSizes() const { + return tensor->size; +} + +template<> +auto THCTensor<real>::strides() const -> long_range { + return long_range(tensor->stride, tensor->stride + tensor->nDimension); +} + +template<> +const long* THCTensor<real>::rawStrides() const { + return tensor->stride; +} + +template<> +std::size_t THCTensor<real>::storageOffset() const { + return tensor->storageOffset; +} + +template<> +std::size_t THCTensor<real>::elementSize() const { + return sizeof(real); +} + +template<> +long long THCTensor<real>::numel() const { + return THCTensor_(numel)(state, tensor); +} + +template<> +bool THCTensor<real>::isContiguous() const { + return THCTensor_(isContiguous)(state, tensor); +} + +template<> +void* THCTensor<real>::data() { + return THCTensor_(data)(state, tensor); +} + +template<> +const void* THCTensor<real>::data() const { + return THCTensor_(data)(state, tensor); +} + +template<> +void* THCTensor<real>::cdata() { + return tensor; +} + +template<> +const void* THCTensor<real>::cdata() const { + return tensor; +} + +template<> +auto THCTensor<real>::resize(const std::initializer_list<long> &new_size) -> THCTensor& { + return resize(new_size.begin(), new_size.end()); +} + +template<> +auto THCTensor<real>::resize(const std::vector<long> &new_size) -> THCTensor& { + return resize(new_size.begin(), new_size.end()); +} + +template<> +auto THCTensor<real>::resize(THLongStorage *size, + THLongStorage *stride) -> THCTensor& { + THCTensor_(resize)(state, tensor, size, stride); + return *this; +} + +template<> +auto THCTensor<real>::resizeAs(const Tensor& src) -> THCTensor& { + THCTensor_(resizeAs)(state, tensor, dynamic_cast<const THCTensor<real>&>(src).tensor); + return *this; +} + +template<> +template<typename iterator> +auto THCTensor<real>::resize(const iterator& begin, const iterator& end) -> THCTensor& { + THLongStorage *sizes = THLongStorage_newWithSize(std::distance(begin, end)); + long *sizes_d = sizes->data; + for (auto it = begin; it != end; ++it) + *sizes_d++ = *it; + // TODO this might leak on error + THCTensor_(resize)(state, tensor, sizes, nullptr); + THLongStorage_free(sizes); + return *this; +} + +template<> +auto THCTensor<real>::set(const Tensor& src) -> THCTensor& { + THCTensor_(set)(state, + tensor, + (dynamic_cast<const THCTensor<real>&>(src)).tensor + ); + return *this; +} + +template<> +auto THCTensor<real>::setStorage(const Storage& storage, + ptrdiff_t storageOffset, + THLongStorage *size, + THLongStorage *stride) -> THCTensor& { + THCTensor_(setStorage)(state, + tensor, + (dynamic_cast<const THCStorage<real>&>(storage)).getRaw(), + storageOffset, + size, + stride + ); + return *this; +} + +template<> +auto THCTensor<real>::narrow(const Tensor& src, + int dimension, + long firstIndex, + long size) -> THCTensor& { + THCTensor_(narrow)(state, + tensor, + (dynamic_cast<const THCTensor<real>&>(src)).tensor, + dimension, + firstIndex, + size + ); + return *this; +} + +template<> +auto THCTensor<real>::select(const Tensor& src, int dimension, + long sliceIndex) -> THCTensor& { + THCTensor_(select)(state, + tensor, + (dynamic_cast<const THCTensor<real>&>(src)).tensor, + dimension, + sliceIndex + ); + return *this; +} + +template<> +auto THCTensor<real>::transpose(const Tensor& src, int dimension1, + int dimension2) -> THCTensor& { + auto src_raw = (dynamic_cast<const THCTensor<real>&>(src)).tensor; + if (tensor != src_raw) + set(src); + THCTensor_(transpose)(state, tensor, src_raw, dimension1, dimension2); + return *this; +} + +template<> +auto THCTensor<real>::unfold(const Tensor& src, int dimension, + long size, long step) ->THCTensor& { + auto src_raw = (dynamic_cast<const THCTensor<real>&>(src)).tensor; + if (tensor != src_raw) + set(src); + THCTensor_(unfold)(state, tensor, src_raw, dimension, size, step); + return *this; +} + +#ifdef THC_REAL_IS_HALF +#define cast_scalar(v) THC_float2half(v) +#define uncast_scalar(v) THC_half2float(v) +#else +#define cast_scalar(v) v +#define uncast_scalar(v) v +#endif + +template<> +auto THCTensor<real>::fill(scalar_type value) -> THCTensor& { + THCTensor_(fill)(state, tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::retain() -> THCTensor& { + THCTensor_(retain)(state, tensor); + return *this; +} + +template<> +auto THCTensor<real>::free() -> THCTensor& { + THCTensor_(free)(state, tensor); + return *this; +} + +#define non_const_cast(tensor) const_cast<THCTensor&>(dynamic_cast<const THCTensor&>(tensor)) +#define non_const_long_cast(tensor) const_cast<THCTensor<long>&>(dynamic_cast<const THCTensor<long>&>(tensor)) + +template<> +auto THCTensor<real>::gather(const Tensor& src, int dimension, const Tensor& index) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor<long> &index_t = non_const_long_cast(index); + THCTensor_(gather)(state, tensor, src_t.tensor, dimension, index_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::scatter(int dimension, const Tensor& index, const Tensor& src) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor<long> &index_t = non_const_long_cast(index); + THCTensor_(scatter)(state, tensor, dimension, index_t.tensor, src_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::scatterFill(int dimension, const Tensor& index, scalar_type value) -> THCTensor& { + THCTensor<long> &index_t = non_const_long_cast(index); + THCTensor_(scatterFill)(state, tensor, dimension, index_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::dot(const Tensor &src) -> scalar_type { + THCTensor &src_t = non_const_cast(src); + return THCTensor_(dot)(state, tensor, src_t.tensor); +} + +template<> +auto THCTensor<real>::minall() -> scalar_type { + return uncast_scalar(THCTensor_(minall)(state, tensor)); +} + +template<> +auto THCTensor<real>::maxall() -> scalar_type { + return uncast_scalar(THCTensor_(maxall)(state, tensor)); +} + +template<> +auto THCTensor<real>::sumall() -> scalar_type { + return THCTensor_(sumall)(state, tensor); +} + +template<> +auto THCTensor<real>::prodall() -> scalar_type { + return THCTensor_(prodall)(state, tensor); +} + +template<> +auto THCTensor<real>::neg(const Tensor &src) -> THCTensor& { +#if defined(TH_REAL_IS_FLOAT) || defined(TH_REAL_IS_DOUBLE) + THCTensor &src_t = non_const_cast(src); + THCTensor_(neg)(state, tensor, src_t.tensor); +#else + throw std::runtime_error("neg is only available for `float` and `double` types"); +#endif // defined(TH_REAL_IS_FLOAT) || defined(TH_REAL_IS_DOUBLE) + return *this; +} + +template<> +auto THCTensor<real>::cinv(const Tensor &src) -> THCTensor& { +#if defined(TH_REAL_IS_FLOAT) || defined(TH_REAL_IS_DOUBLE) + THCTensor &src_t = non_const_cast(src); + THCTensor_(cinv)(state, tensor, src_t.tensor); +#else + throw std::runtime_error("cinv is only available for `float` and `double` types"); +#endif // defined(TH_REAL_IS_FLOAT) || defined(TH_REAL_IS_DOUBLE) + return *this; +} + +template<> +auto THCTensor<real>::add(const Tensor &src, scalar_type value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(add)(state, tensor, src_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::sub(const Tensor &src, scalar_type value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(sub)(state, tensor, src_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::mul(const Tensor &src, scalar_type value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(mul)(state, tensor, src_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::div(const Tensor &src, scalar_type value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(div)(state, tensor, src_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::fmod(const Tensor &src, scalar_type value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(fmod)(state, tensor, src_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::remainder(const Tensor &src, scalar_type value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(remainder)(state, tensor, src_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::clamp(const Tensor &src, scalar_type min_value, scalar_type max_value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(clamp)(state, tensor, src_t.tensor, cast_scalar(min_value), cast_scalar(max_value)); + return *this; +} + +template<> +auto THCTensor<real>::cadd(const Tensor& src1, scalar_type value, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cadd)(state, tensor, src1_t.tensor, cast_scalar(value), src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::cadd(const Tensor& src1, const Tensor& src2) -> THCTensor& { + return cadd(src1, static_cast<scalar_type>(1), src2); +} + +template<> +auto THCTensor<real>::csub(const Tensor& src1, scalar_type value, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(csub)(state, tensor, src1_t.tensor, cast_scalar(value), src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::cmul(const Tensor& src1, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cmul)(state, tensor, src1_t.tensor, src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::cpow(const Tensor& src1, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cpow)(state, tensor, src1_t.tensor, src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::cdiv(const Tensor& src1, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cdiv)(state, tensor, src1_t.tensor, src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::cfmod(const Tensor& src1, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cfmod)(state, tensor, src1_t.tensor, src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::cremainder(const Tensor& src1, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cremainder)(state, tensor, src1_t.tensor, src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::addcmul(const Tensor& src1, scalar_type value, const Tensor& src2, const Tensor& src3) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor &src3_t = non_const_cast(src3); + THCTensor_(addcmul)(state, tensor, src1_t.tensor, cast_scalar(value), src2_t.tensor, src3_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::addcdiv(const Tensor& src1, scalar_type value, const Tensor& src2, const Tensor& src3) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor &src3_t = non_const_cast(src3); + THCTensor_(addcdiv)(state, tensor, src1_t.tensor, cast_scalar(value), src2_t.tensor, src3_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::addmv(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& mat, const Tensor& vec) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor &mat_t = non_const_cast(mat); + THCTensor &vec_t = non_const_cast(vec); + THCTensor_(addmv)(state, tensor, cast_scalar(beta), src_t.tensor, cast_scalar(alpha), mat_t.tensor, vec_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::addmm(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& mat1, const Tensor& mat2) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor &mat1_t = non_const_cast(mat1); + THCTensor &mat2_t = non_const_cast(mat2); + THCTensor_(addmm)(state, tensor, cast_scalar(beta), src_t.tensor, cast_scalar(alpha), mat1_t.tensor, mat2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::addr(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& vec1, const Tensor& vec2) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor &vec1_t = non_const_cast(vec1); + THCTensor &vec2_t = non_const_cast(vec2); + THCTensor_(addr)(state, tensor, cast_scalar(beta), src_t.tensor, cast_scalar(alpha), vec1_t.tensor, vec2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::addbmm(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& batch1, const Tensor& batch2) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor &batch1_t = non_const_cast(batch1); + THCTensor &batch2_t = non_const_cast(batch2); + THCTensor_(addbmm)(state, tensor, cast_scalar(beta), src_t.tensor, cast_scalar(alpha), batch1_t.tensor, batch2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::baddbmm(scalar_type beta, const Tensor& src, scalar_type alpha, const Tensor& batch1, const Tensor& batch2) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor &batch1_t = non_const_cast(batch1); + THCTensor &batch2_t = non_const_cast(batch2); + THCTensor_(baddbmm)(state, tensor, cast_scalar(beta), src_t.tensor, cast_scalar(alpha), batch1_t.tensor, batch2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::match(const Tensor& m1, const Tensor& m2, scalar_type gain) -> THCTensor& { + throw std::runtime_error("unsupported operation 'match'"); +} + +template<> +auto THCTensor<real>::max(const Tensor& indices_, const Tensor& src, int dimension) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor<long> &indices__t = non_const_long_cast(indices_); + THCTensor_(max)(state, tensor, indices__t.tensor, src_t.tensor, dimension); + return *this; +} + +template<> +auto THCTensor<real>::min(const Tensor& indices_, const Tensor& src, int dimension) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor<long> &indices__t = non_const_long_cast(indices_); + THCTensor_(min)(state, tensor, indices__t.tensor, src_t.tensor, dimension); + return *this; +} + +template<> +auto THCTensor<real>::kthvalue(const Tensor& indices_, const Tensor& src, long k, int dimension) -> THCTensor& { + throw std::runtime_error("unsupported operation 'kthvalue'"); +} + +template<> +auto THCTensor<real>::mode(const Tensor& indices_, const Tensor& src, int dimension) -> THCTensor& { + throw std::runtime_error("unsupported operation 'mode'"); +} + +template<> +auto THCTensor<real>::median(const Tensor& indices_, const Tensor& src, int dimension) -> THCTensor& { + throw std::runtime_error("unsupported operation 'median'"); +} + +template<> +auto THCTensor<real>::sum(const Tensor& src, int dimension) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(sum)(state, tensor, src_t.tensor, dimension); + return *this; +} + +template<> +auto THCTensor<real>::prod(const Tensor& src, int dimension) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(prod)(state, tensor, src_t.tensor, dimension); + return *this; +} + +template<> +auto THCTensor<real>::cumsum(const Tensor& src, int dimension) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(cumsum)(state, tensor, src_t.tensor, dimension); + return *this; +} + +template<> +auto THCTensor<real>::cumprod(const Tensor& src, int dimension) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(cumprod)(state, tensor, src_t.tensor, dimension); + return *this; +} + +template<> +auto THCTensor<real>::sign(const Tensor& src) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(sign)(state, tensor, src_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::trace() -> scalar_type { + return THCTensor_(trace)(state, tensor); +} + +template<> +auto THCTensor<real>::cross(const Tensor& src1, const Tensor& src2, int dimension) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cross)(state, tensor, src1_t.tensor, src2_t.tensor, dimension); + return *this; +} + +template<> +auto THCTensor<real>::cmax(const Tensor& src1, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cmax)(state, tensor, src1_t.tensor, src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::cmin(const Tensor& src1, const Tensor& src2) -> THCTensor& { + THCTensor &src1_t = non_const_cast(src1); + THCTensor &src2_t = non_const_cast(src2); + THCTensor_(cmin)(state, tensor, src1_t.tensor, src2_t.tensor); + return *this; +} + +template<> +auto THCTensor<real>::cmaxValue(const Tensor& src, scalar_type value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(cmaxValue)(state, tensor, src_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::cminValue(const Tensor& src, scalar_type value) -> THCTensor& { + THCTensor &src_t = non_const_cast(src); + THCTensor_(cminValue)(state, tensor, src_t.tensor, cast_scalar(value)); + return *this; +} + +template<> +auto THCTensor<real>::zero() -> THCTensor& { + THCTensor_(zero)(state, tensor); + return *this; +} + +template<> +thpp::Type THCTensor<real>::type() const { + return thpp::type_traits<real>::type; +} + +template<> +bool THCTensor<real>::isCuda() const { + return true; +} + +template<> +int THCTensor<real>::getDevice() const { + return tensor->storage->device; +} + +template<> +std::unique_ptr<Tensor> THCTensor<real>::newTensor() const { + return std::unique_ptr<Tensor>(new THCTensor<real>(state)); +} + +#undef cast_scalar +#undef uncast_scalar + +#endif diff --git a/torch/lib/THPP/tensors/generic/THCTensor.hpp b/torch/lib/THPP/tensors/generic/THCTensor.hpp new file mode 100644 index 0000000000..d275373d0a --- /dev/null +++ b/torch/lib/THPP/tensors/generic/THCTensor.hpp @@ -0,0 +1,10 @@ +#ifndef THC_GENERIC_FILE +#define THC_GENERIC_FILE "tensors/generic/THCTensor.hpp" +#else + +template<> +struct thc_tensor_traits<real> { + using tensor_type = THCRealTensor; +}; + +#endif diff --git a/torch/lib/THPP/tensors/generic/THTensor.cpp b/torch/lib/THPP/tensors/generic/THTensor.cpp index 5296205ace..1b45111f76 100644 --- a/torch/lib/THPP/tensors/generic/THTensor.cpp +++ b/torch/lib/THPP/tensors/generic/THTensor.cpp @@ -85,6 +85,16 @@ const void* THTensor<real>::data() const { } template<> +void* THTensor<real>::cdata() { + return tensor; +} + +template<> +const void* THTensor<real>::cdata() const { + return tensor; +} + +template<> auto THTensor<real>::resize(const std::initializer_list<long> &new_size) -> THTensor& { return resize(new_size.begin(), new_size.end()); } @@ -341,6 +351,11 @@ auto THTensor<real>::cadd(const Tensor& src1, scalar_type value, const Tensor& s } template<> +auto THTensor<real>::cadd(const Tensor& src1, const Tensor& src2) -> THTensor& { + return cadd(src1, static_cast<scalar_type>(1), src2); +} + +template<> auto THTensor<real>::csub(const Tensor& src1, scalar_type value, const Tensor& src2) -> THTensor& { THTensor &src1_t = non_const_cast(src1); THTensor &src2_t = non_const_cast(src2); @@ -578,11 +593,27 @@ auto THTensor<real>::cminValue(const Tensor& src, scalar_type value) -> THTensor } template<> +auto THTensor<real>::zero() -> THTensor& { + THTensor_(zero)(tensor); + return *this; +} + +template<> thpp::Type THTensor<real>::type() const { return thpp::type_traits<real>::type; } template<> +bool THTensor<real>::isCuda() const { + return false; +} + +template<> +int THTensor<real>::getDevice() const { + return -1; +} + +template<> std::unique_ptr<Tensor> THTensor<real>::newTensor() const { return std::unique_ptr<Tensor>(new THTensor<real>()); } |