summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2017-01-27 18:15:56 -0500
committerSoumith Chintala <soumith@gmail.com>2017-01-27 18:15:56 -0500
commit887002e93216a64e0fc4bad2d1090df13f5cf1c2 (patch)
tree3769b8fc21480f2c36132b176d3738f83d969df6
parent31dea5ff236a73c47d68f9ea0a1891daccc4002a (diff)
downloadpytorch-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.txt15
-rw-r--r--torch/lib/THPP/Storage.hpp2
-rw-r--r--torch/lib/THPP/Tensor.hpp6
-rw-r--r--torch/lib/THPP/Traits.hpp20
-rw-r--r--torch/lib/THPP/TraitsCuda.cpp7
-rw-r--r--torch/lib/THPP/TraitsCuda.hpp14
-rw-r--r--torch/lib/THPP/Type.hpp3
-rw-r--r--torch/lib/THPP/storages/THCStorage.cpp11
-rw-r--r--torch/lib/THPP/storages/THCStorage.hpp61
-rw-r--r--torch/lib/THPP/storages/THStorage.hpp2
-rw-r--r--torch/lib/THPP/storages/generic/THCStorage.cpp125
-rw-r--r--torch/lib/THPP/storages/generic/THCStorage.hpp10
-rw-r--r--torch/lib/THPP/storages/generic/THStorage.cpp10
-rw-r--r--torch/lib/THPP/tensors/THCTensor.cpp9
-rw-r--r--torch/lib/THPP/tensors/THCTensor.hpp157
-rw-r--r--torch/lib/THPP/tensors/THTensor.hpp6
-rw-r--r--torch/lib/THPP/tensors/generic/THCTensor.cpp620
-rw-r--r--torch/lib/THPP/tensors/generic/THCTensor.hpp10
-rw-r--r--torch/lib/THPP/tensors/generic/THTensor.cpp31
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>());
}