提交 7cc864ea 编写于 作者: 朔-望's avatar 朔-望

update for google code style

上级 75ba2f3d
...@@ -51,12 +51,13 @@ struct Print; ...@@ -51,12 +51,13 @@ struct Print;
struct Print { struct Print {
friend struct ToLog; friend struct ToLog;
template <typename T> Print &operator<<(T const &value) { template <typename T>
Print &operator<<(T const &value) {
buffer_ << value; buffer_ << value;
return *this; return *this;
} }
private: private:
void print(LogLevel level) { void print(LogLevel level) {
buffer_ << std::endl; buffer_ << std::endl;
if (level == kLOG_ERROR) { if (level == kLOG_ERROR) {
...@@ -76,14 +77,15 @@ struct ToLog { ...@@ -76,14 +77,15 @@ struct ToLog {
printer_ << logs[level] << " " << info << ":" << std::string(blanks, ' '); printer_ << logs[level] << " " << info << ":" << std::string(blanks, ' ');
} }
template <typename T> ToLog &operator<<(T const &value) { template <typename T>
ToLog &operator<<(T const &value) {
printer_ << value; printer_ << value;
return *this; return *this;
} }
~ToLog() { printer_.print(level_); } ~ToLog() { printer_.print(level_); }
private: private:
LogLevel level_; LogLevel level_;
Print printer_; Print printer_;
}; };
...@@ -109,16 +111,16 @@ private: ...@@ -109,16 +111,16 @@ private:
<< (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__) \ << (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__) \
<< "] [line: " << __LINE__ << "] ") \ << "] [line: " << __LINE__ << "] ") \
.str()) .str())
} // namespace paddle_mobile } // namespace paddle_mobile
#define LOGF(level, format, ...) \ #define LOGF(level, format, ...) \
if (level > paddle_mobile::log_level) { \ if (level > paddle_mobile::log_level) { \
} else \ } else \
printf(format, ##__VA_ARGS__) printf(format, ##__VA_ARGS__)
#define DLOGF(format, ...) \ #define DLOGF(format, ...) \
if (paddle_mobile::kLOG_DEBUG > paddle_mobile::log_level) { \ if (paddle_mobile::kLOG_DEBUG > paddle_mobile::log_level) { \
} else \ } else \
printf(format, ##__VA_ARGS__) printf(format, ##__VA_ARGS__)
#else #else
...@@ -140,30 +142,34 @@ enum LogLevel { ...@@ -140,30 +142,34 @@ enum LogLevel {
struct ToLog; struct ToLog;
struct Print { struct Print {
friend struct ToLog; friend struct ToLog;
template <typename T> Print &operator<<(T const &value) {} template <typename T>
Print &operator<<(T const &value) {}
private: private:
}; };
struct ToLog { struct ToLog {
ToLog(LogLevel level) {} ToLog(LogLevel level) {}
template <typename T> ToLog &operator<<(T const &value) { return *this; } template <typename T>
ToLog &operator<<(T const &value) {
return *this;
}
}; };
#define LOG(level) \ #define LOG(level) \
if (true) { \ if (true) { \
} else \ } else \
paddle_mobile::ToLog(level) paddle_mobile::ToLog(level)
#define DLOG \ #define DLOG \
if (true) { \ if (true) { \
} else \ } else \
paddle_mobile::ToLog(paddle_mobile::kLOG_DEBUG) paddle_mobile::ToLog(paddle_mobile::kLOG_DEBUG)
#define LOGF(level, format, ...) #define LOGF(level, format, ...)
#define DLOGF(format, ...) #define DLOGF(format, ...)
} // namespace paddle_mobile } // namespace paddle_mobile
#endif #endif
...@@ -17,18 +17,19 @@ SOFTWARE. ...@@ -17,18 +17,19 @@ SOFTWARE.
==============================================================================*/ ==============================================================================*/
#pragma once; #pragma once;
#include "framework/attribute.h"
#include <map> #include <map>
#include <string> #include <string>
#include "framework/attribute.h"
namespace paddle_mobile { namespace paddle_mobile {
namespace framework { namespace framework {
template <typename Dtype> class OperatorBase; template <typename Dtype>
class OperatorBase;
class OpDesc; class OpDesc;
class BlockDesc; class BlockDesc;
class InferShapeContext; class InferShapeContext;
} // namespace framework } // namespace framework
using VariableNameMap = std::map<std::string, std::vector<std::string>>; using VariableNameMap = std::map<std::string, std::vector<std::string>>;
...@@ -49,4 +50,4 @@ using InferVarTypeFN = std::function<void(const framework::OpDesc & /*op_desc*/, ...@@ -49,4 +50,4 @@ using InferVarTypeFN = std::function<void(const framework::OpDesc & /*op_desc*/,
framework::BlockDesc * /*block*/)>; framework::BlockDesc * /*block*/)>;
using InferShapeFN = std::function<void(framework::InferShapeContext *)>; using InferShapeFN = std::function<void(framework::InferShapeContext *)>;
}; // namespace paddle_mobile }; // namespace paddle_mobile
...@@ -24,7 +24,8 @@ enum class Precision : int { FP32 = 0 }; ...@@ -24,7 +24,8 @@ enum class Precision : int { FP32 = 0 };
//! device type //! device type
enum DeviceTypeEnum { kINVALID = -1, kCPU = 0, kFPGA = 1, kGPU_MALI = 2 }; enum DeviceTypeEnum { kINVALID = -1, kCPU = 0, kFPGA = 1, kGPU_MALI = 2 };
template <DeviceTypeEnum T> struct DeviceType {}; template <DeviceTypeEnum T>
struct DeviceType {};
typedef DeviceType<kCPU> CPU; typedef DeviceType<kCPU> CPU;
typedef DeviceType<kFPGA> FPGA; typedef DeviceType<kFPGA> FPGA;
...@@ -60,4 +61,4 @@ enum PMStatus { ...@@ -60,4 +61,4 @@ enum PMStatus {
PMUnImplError = 0x07, /*!< Unimplement error. */ PMUnImplError = 0x07, /*!< Unimplement error. */
PMWrongDevice = 0x08 /*!< un-correct device. */ PMWrongDevice = 0x08 /*!< un-correct device. */
}; };
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -21,9 +21,13 @@ SOFTWARE. ...@@ -21,9 +21,13 @@ SOFTWARE.
#pragma once #pragma once
namespace paddle_mobile { namespace paddle_mobile {
template <int ID, typename Type> struct IDToType { typedef Type type_t; }; template <int ID, typename Type>
struct IDToType {
typedef Type type_t;
};
template <typename F, typename... Ts> struct VariantHelper { template <typename F, typename... Ts>
struct VariantHelper {
static const size_t size = sizeof(F) > VariantHelper<Ts...>::size static const size_t size = sizeof(F) > VariantHelper<Ts...>::size
? sizeof(F) ? sizeof(F)
: VariantHelper<Ts...>::size; : VariantHelper<Ts...>::size;
...@@ -37,7 +41,8 @@ template <typename F, typename... Ts> struct VariantHelper { ...@@ -37,7 +41,8 @@ template <typename F, typename... Ts> struct VariantHelper {
} }
}; };
template <typename F> struct VariantHelper<F> { template <typename F>
struct VariantHelper<F> {
static const size_t size = sizeof(F); static const size_t size = sizeof(F);
inline static void Destroy(size_t id, void *data) { inline static void Destroy(size_t id, void *data) {
if (id == typeid(F).hash_code()) { if (id == typeid(F).hash_code()) {
...@@ -48,8 +53,9 @@ template <typename F> struct VariantHelper<F> { ...@@ -48,8 +53,9 @@ template <typename F> struct VariantHelper<F> {
} }
}; };
template <size_t size> class RawData { template <size_t size>
public: class RawData {
public:
char data[size]; char data[size];
RawData() {} RawData() {}
RawData(const RawData &raw_data) { strcpy(data, raw_data.data); } RawData(const RawData &raw_data) { strcpy(data, raw_data.data); }
...@@ -58,7 +64,8 @@ public: ...@@ -58,7 +64,8 @@ public:
// } // }
}; };
template <typename... Ts> struct Variant { template <typename... Ts>
struct Variant {
Variant(const Variant &variant) { Variant(const Variant &variant) {
// std::cout << " 赋值构造函数 " << std::endl; // std::cout << " 赋值构造函数 " << std::endl;
type_id = variant.type_id; type_id = variant.type_id;
...@@ -70,13 +77,15 @@ template <typename... Ts> struct Variant { ...@@ -70,13 +77,15 @@ template <typename... Ts> struct Variant {
// helper::Destroy(type_id, &data); // helper::Destroy(type_id, &data);
} }
template <typename T, typename... Args> void Set(Args &&... args) { template <typename T, typename... Args>
void Set(Args &&... args) {
helper::Destroy(type_id, &data); helper::Destroy(type_id, &data);
new (&data) T(std::forward<Args>(args)...); new (&data) T(std::forward<Args>(args)...);
type_id = typeid(T).hash_code(); type_id = typeid(T).hash_code();
} }
template <typename T> T &Get() const { template <typename T>
T &Get() const {
if (type_id == typeid(T).hash_code()) { if (type_id == typeid(T).hash_code()) {
return *const_cast<T *>(reinterpret_cast<const T *>(&data)); return *const_cast<T *>(reinterpret_cast<const T *>(&data));
} else { } else {
...@@ -87,13 +96,16 @@ template <typename... Ts> struct Variant { ...@@ -87,13 +96,16 @@ template <typename... Ts> struct Variant {
size_t TypeId() const { return type_id; } size_t TypeId() const { return type_id; }
private: private:
static inline size_t invalid_type() { return typeid(void).hash_code(); } static inline size_t invalid_type() { return typeid(void).hash_code(); }
typedef VariantHelper<Ts...> helper; typedef VariantHelper<Ts...> helper;
size_t type_id; size_t type_id;
RawData<helper::size> data; RawData<helper::size> data;
}; };
template <typename T> struct Vistor { typedef T type_t; }; template <typename T>
struct Vistor {
typedef T type_t;
};
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -18,4 +18,4 @@ SOFTWARE. ...@@ -18,4 +18,4 @@ SOFTWARE.
namespace paddle_mobile { namespace paddle_mobile {
namespace framework {} namespace framework {}
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -27,80 +27,84 @@ namespace framework { ...@@ -27,80 +27,84 @@ namespace framework {
class BlockDesc; class BlockDesc;
class Attribute { class Attribute {
public: public:
static Attribute GetAttrValue(const proto::OpDesc::Attr &attr_desc) { static Attribute GetAttrValue(const proto::OpDesc::Attr &attr_desc) {
// std::cout << "begin get attr value" << std::endl; // std::cout << "begin get attr value" << std::endl;
Attribute attr; Attribute attr;
switch (attr_desc.type()) { switch (attr_desc.type()) {
case proto::AttrType::BOOLEAN: { case proto::AttrType::BOOLEAN: {
attr.Set<bool>(attr_desc.b()); attr.Set<bool>(attr_desc.b());
break; break;
}
case proto::AttrType::INT: {
attr.Set<int>(attr_desc.i());
break;
}
case proto::AttrType::FLOAT: {
attr.Set<float>(attr_desc.f());
break;
}
case proto::AttrType::STRING: {
attr.Set<std::string>(attr_desc.s());
break;
}
case proto::AttrType::BOOLEANS: {
std::vector<bool> val(attr_desc.bools_size());
for (int i = 0; i < attr_desc.bools_size(); ++i) {
val[i] = attr_desc.bools(i);
} }
attr.Set<std::vector<bool>>(val); case proto::AttrType::INT: {
break; attr.Set<int>(attr_desc.i());
} break;
case proto::AttrType::INTS: {
std::vector<int> val(attr_desc.ints_size());
for (int i = 0; i < attr_desc.ints_size(); ++i) {
val[i] = attr_desc.ints(i);
} }
attr.Set<std::vector<int>>(val); case proto::AttrType::FLOAT: {
break; attr.Set<float>(attr_desc.f());
} break;
case proto::AttrType::FLOATS: {
std::vector<float> val(attr_desc.floats_size());
for (int i = 0; i < attr_desc.floats_size(); ++i) {
val[i] = attr_desc.floats(i);
} }
attr.Set<std::vector<float>>(val); case proto::AttrType::STRING: {
break; attr.Set<std::string>(attr_desc.s());
} break;
case proto::AttrType::STRINGS: {
std::vector<std::string> val(attr_desc.strings_size());
for (int i = 0; i < attr_desc.strings_size(); ++i) {
val[i] = attr_desc.strings(i);
} }
attr.Set<std::vector<std::string>>(val); case proto::AttrType::BOOLEANS: {
break; std::vector<bool> val(attr_desc.bools_size());
} for (int i = 0; i < attr_desc.bools_size(); ++i) {
case proto::AttrType::LONG: { val[i] = attr_desc.bools(i);
attr.Set<int64_t>(attr_desc.l()); }
break; attr.Set<std::vector<bool>>(val);
} break;
default: }
// std::cout << " not support " << std::endl; case proto::AttrType::INTS: {
break; std::vector<int> val(attr_desc.ints_size());
for (int i = 0; i < attr_desc.ints_size(); ++i) {
val[i] = attr_desc.ints(i);
}
attr.Set<std::vector<int>>(val);
break;
}
case proto::AttrType::FLOATS: {
std::vector<float> val(attr_desc.floats_size());
for (int i = 0; i < attr_desc.floats_size(); ++i) {
val[i] = attr_desc.floats(i);
}
attr.Set<std::vector<float>>(val);
break;
}
case proto::AttrType::STRINGS: {
std::vector<std::string> val(attr_desc.strings_size());
for (int i = 0; i < attr_desc.strings_size(); ++i) {
val[i] = attr_desc.strings(i);
}
attr.Set<std::vector<std::string>>(val);
break;
}
case proto::AttrType::LONG: {
attr.Set<int64_t>(attr_desc.l());
break;
}
default:
// std::cout << " not support " << std::endl;
break;
} }
// std::cout << "end get attr value" << std::endl; // std::cout << "end get attr value" << std::endl;
return attr; return attr;
} }
Attribute() {} Attribute() {}
template <typename T, typename... Args> Attribute &Set(Args &&... args) { template <typename T, typename... Args>
Attribute &Set(Args &&... args) {
variant_.Set<T>(args...); variant_.Set<T>(args...);
return *this; return *this;
} }
template <typename T> T &Get() const { return variant_.Get<T>(); } template <typename T>
T &Get() const {
return variant_.Get<T>();
}
private: private:
Variant<int, float, std::string, std::vector<int>, std::vector<float>, Variant<int, float, std::string, std::vector<int>, std::vector<float>,
std::vector<std::string>, bool, std::vector<bool>, BlockDesc *, std::vector<std::string>, bool, std::vector<bool>, BlockDesc *,
int64_t> int64_t>
...@@ -110,10 +114,11 @@ private: ...@@ -110,10 +114,11 @@ private:
using AttributeMap = std::unordered_map<std::string, Attribute>; using AttributeMap = std::unordered_map<std::string, Attribute>;
class AttrReader { class AttrReader {
public: public:
explicit AttrReader(const AttributeMap &attrs) : attrs_(attrs) {} explicit AttrReader(const AttributeMap &attrs) : attrs_(attrs) {}
template <typename T> inline T Get(const std::string &name) const { template <typename T>
inline T Get(const std::string &name) const {
// PADDLE_ENFORCE(attrs_.count(name) != 0, "%s should // PADDLE_ENFORCE(attrs_.count(name) != 0, "%s should
// be in // be in
// AttributeMap", // AttributeMap",
...@@ -121,9 +126,9 @@ public: ...@@ -121,9 +126,9 @@ public:
return ((Attribute)attrs_.at(name)).Get<T>(); return ((Attribute)attrs_.at(name)).Get<T>();
} }
private: private:
const AttributeMap &attrs_; const AttributeMap &attrs_;
}; };
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -46,5 +46,5 @@ BlockDesc::BlockDesc(const proto::BlockDesc &desc) : desc_(desc) { ...@@ -46,5 +46,5 @@ BlockDesc::BlockDesc(const proto::BlockDesc &desc) : desc_(desc) {
} }
} }
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -27,7 +27,7 @@ namespace paddle_mobile { ...@@ -27,7 +27,7 @@ namespace paddle_mobile {
namespace framework { namespace framework {
class BlockDesc : PaddleMobileObject { class BlockDesc : PaddleMobileObject {
public: public:
BlockDesc(const proto::BlockDesc &desc); BlockDesc(const proto::BlockDesc &desc);
const int &ID() const { return desc_.idx(); } const int &ID() const { return desc_.idx(); }
...@@ -45,18 +45,19 @@ public: ...@@ -45,18 +45,19 @@ public:
std::vector<std::shared_ptr<VarDesc>> Vars() const; std::vector<std::shared_ptr<VarDesc>> Vars() const;
std::vector<std::shared_ptr<OpDesc>> Ops() const; std::vector<std::shared_ptr<OpDesc>> Ops() const;
private: private:
proto::BlockDesc desc_; proto::BlockDesc desc_;
std::vector<std::shared_ptr<OpDesc>> ops_; std::vector<std::shared_ptr<OpDesc>> ops_;
std::unordered_map<std::string, std::shared_ptr<VarDesc>> vars_; std::unordered_map<std::string, std::shared_ptr<VarDesc>> vars_;
}; };
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
namespace std { namespace std {
template <> struct hash<paddle_mobile::framework::BlockDesc> { template <>
struct hash<paddle_mobile::framework::BlockDesc> {
typedef paddle_mobile::framework::BlockDesc argument_type; typedef paddle_mobile::framework::BlockDesc argument_type;
typedef std::size_t result_type; typedef std::size_t result_type;
result_type operator()(argument_type const &s) const noexcept { result_type operator()(argument_type const &s) const noexcept {
...@@ -66,4 +67,4 @@ template <> struct hash<paddle_mobile::framework::BlockDesc> { ...@@ -66,4 +67,4 @@ template <> struct hash<paddle_mobile::framework::BlockDesc> {
} }
}; };
} // namespace std } // namespace std
...@@ -46,15 +46,15 @@ inline DataLayout StringToDataLayout(const std::string &str) { ...@@ -46,15 +46,15 @@ inline DataLayout StringToDataLayout(const std::string &str) {
inline std::string DataLayoutToString(const DataLayout &data_layout) { inline std::string DataLayoutToString(const DataLayout &data_layout) {
switch (data_layout) { switch (data_layout) {
case DataLayout::kNHWC: case DataLayout::kNHWC:
return "NHWC"; return "NHWC";
case DataLayout::kNCHW: case DataLayout::kNCHW:
return "NCHW"; return "NCHW";
case DataLayout::kAnyLayout: case DataLayout::kAnyLayout:
return "ANY_LAYOUT"; return "ANY_LAYOUT";
default: default:
break; break;
// std::cout << "unknown DataLayou %d", data_layout; // std::cout << "unknown DataLayou %d", data_layout;
} }
} }
...@@ -63,5 +63,5 @@ inline std::ostream &operator<<(std::ostream &out, const DataLayout &l) { ...@@ -63,5 +63,5 @@ inline std::ostream &operator<<(std::ostream &out, const DataLayout &l) {
return out; return out;
} }
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -88,5 +88,5 @@ void CopyVariableWithTensor(const Variable &in_var, const Tensor &tensor, ...@@ -88,5 +88,5 @@ void CopyVariableWithTensor(const Variable &in_var, const Tensor &tensor,
// } // }
} }
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -37,5 +37,5 @@ void DataTransform(const OpKernelType &expected_kernel_type, ...@@ -37,5 +37,5 @@ void DataTransform(const OpKernelType &expected_kernel_type,
void CopyVariableWithTensor(const Variable &in_var, const Tensor &tensor, void CopyVariableWithTensor(const Variable &in_var, const Tensor &tensor,
Variable &out_var); Variable &out_var);
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -40,4 +40,4 @@ namespace framework { ...@@ -40,4 +40,4 @@ namespace framework {
// } // }
// } // }
} }
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -19,49 +19,53 @@ namespace framework { ...@@ -19,49 +19,53 @@ namespace framework {
/// @cond HIDDEN /// @cond HIDDEN
template <int i> Dim<i> make_dim(const int64_t *d) { template <int i>
Dim<i> make_dim(const int64_t *d) {
return Dim<i>(*d, make_dim<i - 1>(d + 1)); return Dim<i>(*d, make_dim<i - 1>(d + 1));
} }
template <> Dim<0> make_dim<0>(const int64_t *d) { return Dim<0>(*d); } template <>
Dim<0> make_dim<0>(const int64_t *d) {
return Dim<0>(*d);
}
void make_ddim(DDim &ddim, const int64_t *dims, int n) { void make_ddim(DDim &ddim, const int64_t *dims, int n) {
switch (n) { switch (n) {
case 0: case 0:
ddim = make_dim<0>(dims); ddim = make_dim<0>(dims);
break; break;
case 1: case 1:
ddim = make_dim<1>(dims); ddim = make_dim<1>(dims);
break; break;
case 2: case 2:
ddim = make_dim<2>(dims); ddim = make_dim<2>(dims);
break; break;
case 3: case 3:
ddim = make_dim<3>(dims); ddim = make_dim<3>(dims);
break; break;
case 4: case 4:
ddim = make_dim<4>(dims); ddim = make_dim<4>(dims);
break; break;
case 5: case 5:
ddim = make_dim<5>(dims); ddim = make_dim<5>(dims);
break; break;
case 6: case 6:
ddim = make_dim<6>(dims); ddim = make_dim<6>(dims);
break; break;
case 7: case 7:
ddim = make_dim<7>(dims); ddim = make_dim<7>(dims);
break; break;
case 8: case 8:
ddim = make_dim<8>(dims); ddim = make_dim<8>(dims);
break; break;
case 9: case 9:
ddim = make_dim<9>(dims); ddim = make_dim<9>(dims);
break; break;
default: default:
// std::cout << "Dynamic dimensions must have between [1, // std::cout << "Dynamic dimensions must have between [1,
// 9] // 9]
// dimensions."; // dimensions.";
break; break;
} }
} }
...@@ -90,24 +94,28 @@ DDim make_ddim(const std::vector<int> &dims) { ...@@ -90,24 +94,28 @@ DDim make_ddim(const std::vector<int> &dims) {
// XXX For some reason, putting this in an anonymous namespace causes // XXX For some reason, putting this in an anonymous namespace causes
// errors // errors
struct DynamicMutableIndexer : Vistor<int64_t &> { struct DynamicMutableIndexer : Vistor<int64_t &> {
public: public:
explicit DynamicMutableIndexer(int idx) : idx_(idx) {} explicit DynamicMutableIndexer(int idx) : idx_(idx) {}
template <int D> int64_t &operator()(Dim<D> &dim) const { return dim[idx_]; } template <int D>
int64_t &operator()(Dim<D> &dim) const {
return dim[idx_];
}
private: private:
int idx_; int idx_;
}; };
struct DynamicConstIndexer : public Vistor<int64_t> { struct DynamicConstIndexer : public Vistor<int64_t> {
public: public:
explicit DynamicConstIndexer(int idx) : idx_(idx) {} explicit DynamicConstIndexer(int idx) : idx_(idx) {}
template <int D> int64_t operator()(const Dim<D> &dim) const { template <int D>
int64_t operator()(const Dim<D> &dim) const {
return dim[idx_]; return dim[idx_];
} }
private: private:
int idx_; int idx_;
}; };
...@@ -182,7 +190,8 @@ struct VectorizeVisitor : Vistor<void> { ...@@ -182,7 +190,8 @@ struct VectorizeVisitor : Vistor<void> {
explicit VectorizeVisitor(std::vector<int64_t> &v) : vector(v) {} explicit VectorizeVisitor(std::vector<int64_t> &v) : vector(v) {}
template <typename T> void operator()(const T &t) { template <typename T>
void operator()(const T &t) {
vector.push_back(t.head); vector.push_back(t.head);
this->operator()(t.tail); this->operator()(t.tail);
} }
...@@ -207,7 +216,8 @@ std::vector<int> vectorize2int(const DDim &ddim) { ...@@ -207,7 +216,8 @@ std::vector<int> vectorize2int(const DDim &ddim) {
} }
struct ProductVisitor : Vistor<int64_t> { struct ProductVisitor : Vistor<int64_t> {
template <int D> int64_t operator()(const Dim<D> &dim) { template <int D>
int64_t operator()(const Dim<D> &dim) {
return product(dim); return product(dim);
} }
}; };
...@@ -233,7 +243,8 @@ struct SliceVectorizeVisitor : Vistor<void> { ...@@ -233,7 +243,8 @@ struct SliceVectorizeVisitor : Vistor<void> {
// ddim slice."); // ddim slice.");
} }
template <int S> void operator()(const Dim<S> &dim) { template <int S>
void operator()(const Dim<S> &dim) {
if (begin == 0) { if (begin == 0) {
vector.push_back(dim.head); vector.push_back(dim.head);
} else { } else {
...@@ -264,7 +275,10 @@ DDim slice_ddim(const DDim &ddim, int begin, int end) { ...@@ -264,7 +275,10 @@ DDim slice_ddim(const DDim &ddim, int begin, int end) {
/// \cond HIDDEN /// \cond HIDDEN
struct ArityVisitor : Vistor<int> { struct ArityVisitor : Vistor<int> {
template <int D> int operator()(Dim<D>) const { return D; } template <int D>
int operator()(Dim<D>) const {
return D;
}
}; };
/// \endcond /// \endcond
...@@ -282,11 +296,12 @@ int arity(const DDim &d) { ...@@ -282,11 +296,12 @@ int arity(const DDim &d) {
struct OSVistor : Vistor<std::ostream &> { struct OSVistor : Vistor<std::ostream &> {
OSVistor(std::ostream &os) : os_(os) {} OSVistor(std::ostream &os) : os_(os) {}
template <int D> std::ostream &operator()(Dim<D> dim) const { template <int D>
std::ostream &operator()(Dim<D> dim) const {
return os_ << dim; return os_ << dim;
} }
private: private:
std::ostream &os_; std::ostream &os_;
}; };
...@@ -326,5 +341,5 @@ DDim stride_numel(const framework::DDim &ddim) { ...@@ -326,5 +341,5 @@ DDim stride_numel(const framework::DDim &ddim) {
return framework::make_ddim(strides); return framework::make_ddim(strides);
} }
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -14,12 +14,12 @@ limitations under the License. */ ...@@ -14,12 +14,12 @@ limitations under the License. */
#pragma once #pragma once
#include "common/variant.h"
#include "dim.h"
#include <assert.h> #include <assert.h>
#include <initializer_list> #include <initializer_list>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "common/variant.h"
#include "dim.h"
namespace paddle_mobile { namespace paddle_mobile {
namespace framework { namespace framework {
...@@ -66,11 +66,15 @@ struct DDim { ...@@ -66,11 +66,15 @@ struct DDim {
DDim() { var.Set<Dim<1>>(Dim<1>()); } DDim() { var.Set<Dim<1>>(Dim<1>()); }
template <int D> explicit DDim(const Dim<D> &in) { var.Set<Dim<D>>(in); } template <int D>
explicit DDim(const Dim<D> &in) {
var.Set<Dim<D>>(in);
}
/*implicit*/ DDim(std::initializer_list<int64_t> init_list); /*implicit*/ DDim(std::initializer_list<int64_t> init_list);
template <int D> DDim &operator=(const Dim<D> &in) { template <int D>
DDim &operator=(const Dim<D> &in) {
var.Set<Dim<D>>(in); var.Set<Dim<D>>(in);
return *this; return *this;
} }
...@@ -159,5 +163,5 @@ DDim flatten_to_1d(const DDim &src); ...@@ -159,5 +163,5 @@ DDim flatten_to_1d(const DDim &src);
DDim stride(const DDim &ddim); DDim stride(const DDim &ddim);
DDim stride_numel(const DDim &ddim); DDim stride_numel(const DDim &ddim);
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -24,7 +24,8 @@ namespace paddle_mobile { ...@@ -24,7 +24,8 @@ namespace paddle_mobile {
namespace framework { namespace framework {
// Statically sized, statically indexed dimension // Statically sized, statically indexed dimension
template <int i> struct Dim { template <int i>
struct Dim {
static constexpr int dimensions = i; static constexpr int dimensions = i;
template <typename... Args> template <typename... Args>
...@@ -70,7 +71,8 @@ template <int i> struct Dim { ...@@ -70,7 +71,8 @@ template <int i> struct Dim {
}; };
// Base case specialization // Base case specialization
template <> struct Dim<0> { template <>
struct Dim<0> {
static constexpr int dimensions = 0; static constexpr int dimensions = 0;
HOSTDEVICE HOSTDEVICE
...@@ -105,28 +107,37 @@ template <> struct Dim<0> { ...@@ -105,28 +107,37 @@ template <> struct Dim<0> {
namespace { namespace {
// Helper for accessing Dim classes // Helper for accessing Dim classes
template <int i> struct DimGetter { template <int i>
struct DimGetter {
// Return a copy if Dim is const // Return a copy if Dim is const
template <typename D> HOSTDEVICE static int64_t impl(const D &d) { template <typename D>
HOSTDEVICE static int64_t impl(const D &d) {
return DimGetter<i - 1>::impl(d.tail); return DimGetter<i - 1>::impl(d.tail);
} }
// Return a reference if Dim is mutable // Return a reference if Dim is mutable
template <typename D> HOSTDEVICE static int64_t &impl(D &d) { template <typename D>
HOSTDEVICE static int64_t &impl(D &d) {
return DimGetter<i - 1>::impl(d.tail); return DimGetter<i - 1>::impl(d.tail);
} }
}; };
// Eureka! We found the element! // Eureka! We found the element!
template <> struct DimGetter<0> { template <>
struct DimGetter<0> {
// Return a copy if Dim is const // Return a copy if Dim is const
template <typename D> HOSTDEVICE static int64_t impl(const D &d) { template <typename D>
HOSTDEVICE static int64_t impl(const D &d) {
return d.head; return d.head;
} }
// Return a reference if Dim is mutable // Return a reference if Dim is mutable
template <typename D> HOSTDEVICE static int64_t &impl(D &d) { return d.head; } template <typename D>
HOSTDEVICE static int64_t &impl(D &d) {
return d.head;
}
}; };
template <int D> HOSTDEVICE int64_t &indexer(Dim<D> &dim, int idx) { template <int D>
HOSTDEVICE int64_t &indexer(Dim<D> &dim, int idx) {
#ifndef __CUDA_ARCH__ #ifndef __CUDA_ARCH__
if (idx < 0) { if (idx < 0) {
throw std::invalid_argument("Tried to access a negative dimension"); throw std::invalid_argument("Tried to access a negative dimension");
...@@ -140,7 +151,8 @@ template <int D> HOSTDEVICE int64_t &indexer(Dim<D> &dim, int idx) { ...@@ -140,7 +151,8 @@ template <int D> HOSTDEVICE int64_t &indexer(Dim<D> &dim, int idx) {
return indexer(dim.tail, idx - 1); return indexer(dim.tail, idx - 1);
} }
template <> HOSTDEVICE int64_t &indexer<0>(Dim<0> &dim, int idx) { template <>
HOSTDEVICE int64_t &indexer<0>(Dim<0> &dim, int idx) {
#ifndef __CUDA_ARCH__ #ifndef __CUDA_ARCH__
throw std::invalid_argument("Invalid index"); throw std::invalid_argument("Invalid index");
#else #else
...@@ -156,7 +168,8 @@ template <> HOSTDEVICE int64_t &indexer<0>(Dim<0> &dim, int idx) { ...@@ -156,7 +168,8 @@ template <> HOSTDEVICE int64_t &indexer<0>(Dim<0> &dim, int idx) {
#endif #endif
} }
template <int D> HOSTDEVICE int64_t indexer(const Dim<D> &dim, int idx) { template <int D>
HOSTDEVICE int64_t indexer(const Dim<D> &dim, int idx) {
#ifndef __CUDA_ARCH__ #ifndef __CUDA_ARCH__
if (idx < 0) { if (idx < 0) {
throw std::invalid_argument("Tried to access a negative dimension"); throw std::invalid_argument("Tried to access a negative dimension");
...@@ -170,7 +183,8 @@ template <int D> HOSTDEVICE int64_t indexer(const Dim<D> &dim, int idx) { ...@@ -170,7 +183,8 @@ template <int D> HOSTDEVICE int64_t indexer(const Dim<D> &dim, int idx) {
return indexer(dim.tail, idx - 1); return indexer(dim.tail, idx - 1);
} }
template <> HOSTDEVICE int64_t indexer<0>(const Dim<0> &dim, int idx) { template <>
HOSTDEVICE int64_t indexer<0>(const Dim<0> &dim, int idx) {
#ifndef __CUDA_ARCH__ #ifndef __CUDA_ARCH__
throw std::invalid_argument("Invalid index"); throw std::invalid_argument("Invalid index");
#else #else
...@@ -186,25 +200,29 @@ template <> HOSTDEVICE int64_t indexer<0>(const Dim<0> &dim, int idx) { ...@@ -186,25 +200,29 @@ template <> HOSTDEVICE int64_t indexer<0>(const Dim<0> &dim, int idx) {
#endif #endif
} }
} // namespace } // namespace
// Static access to constant Dim // Static access to constant Dim
template <int i, int l> HOSTDEVICE int64_t get(const Dim<l> &d) { template <int i, int l>
HOSTDEVICE int64_t get(const Dim<l> &d) {
return DimGetter<i>::impl(d); return DimGetter<i>::impl(d);
} }
// Static access to mutable Dim // Static access to mutable Dim
template <int i, int l> HOSTDEVICE int64_t &get(Dim<l> &d) { template <int i, int l>
HOSTDEVICE int64_t &get(Dim<l> &d) {
return DimGetter<i>::impl(d); return DimGetter<i>::impl(d);
} }
// Dynamic access to constant Dim // Dynamic access to constant Dim
template <int l> HOSTDEVICE int64_t Dim<l>::operator[](int i) const { template <int l>
HOSTDEVICE int64_t Dim<l>::operator[](int i) const {
// std::cout << "l: " << l << std::endl; // std::cout << "l: " << l << std::endl;
return indexer(*this, i); return indexer(*this, i);
} }
// Dynamic access to mutable Dim // Dynamic access to mutable Dim
template <int l> HOSTDEVICE int64_t &Dim<l>::operator[](int i) { template <int l>
HOSTDEVICE int64_t &Dim<l>::operator[](int i) {
return indexer(*this, i); return indexer(*this, i);
} }
...@@ -247,13 +265,15 @@ HOSTDEVICE inline int64_t linearize(const Dim<0> &a, const Dim<0> &b) { ...@@ -247,13 +265,15 @@ HOSTDEVICE inline int64_t linearize(const Dim<0> &a, const Dim<0> &b) {
} }
// Product of a Dim // Product of a Dim
template <int i> HOSTDEVICE int64_t product(const Dim<i> &a, int prod = 1) { template <int i>
HOSTDEVICE int64_t product(const Dim<i> &a, int prod = 1) {
return prod * a.head * product(a.tail); return prod * a.head * product(a.tail);
} }
// Base case product of a Dim // Base case product of a Dim
// Notice it is inline because it is no longer a template // Notice it is inline because it is no longer a template
template <> HOSTDEVICE inline int64_t product(const Dim<0> &a, int prod) { template <>
HOSTDEVICE inline int64_t product(const Dim<0> &a, int prod) {
return prod; return prod;
} }
...@@ -282,7 +302,8 @@ HOSTDEVICE Dim<i> ex_prefix_mul(const Dim<i> &src, int mul = 1) { ...@@ -282,7 +302,8 @@ HOSTDEVICE Dim<i> ex_prefix_mul(const Dim<i> &src, int mul = 1) {
///\cond HIDDEN ///\cond HIDDEN
// Base case of ex_prefix_mul // Base case of ex_prefix_mul
// Notice it is inline because it is no longer a template // Notice it is inline because it is no longer a template
template <> HOSTDEVICE inline Dim<0> ex_prefix_mul(const Dim<0> &src, int mul) { template <>
HOSTDEVICE inline Dim<0> ex_prefix_mul(const Dim<0> &src, int mul) {
return Dim<0>(); return Dim<0>();
} }
///\endcond ///\endcond
...@@ -290,7 +311,8 @@ template <> HOSTDEVICE inline Dim<0> ex_prefix_mul(const Dim<0> &src, int mul) { ...@@ -290,7 +311,8 @@ template <> HOSTDEVICE inline Dim<0> ex_prefix_mul(const Dim<0> &src, int mul) {
/** /**
* Add two dimensions together * Add two dimensions together
*/ */
template <int i> HOSTDEVICE Dim<i> dim_plus(const Dim<i> &a, const Dim<i> &b) { template <int i>
HOSTDEVICE Dim<i> dim_plus(const Dim<i> &a, const Dim<i> &b) {
return Dim<i>(a.head + b.head, dim_plus(a.tail, b.tail)); return Dim<i>(a.head + b.head, dim_plus(a.tail, b.tail));
} }
...@@ -308,7 +330,8 @@ HOSTDEVICE Dim<i> operator+(const Dim<i> &lhs, const Dim<i> &rhs) { ...@@ -308,7 +330,8 @@ HOSTDEVICE Dim<i> operator+(const Dim<i> &lhs, const Dim<i> &rhs) {
/** /**
* Multiply two dimensions together * Multiply two dimensions together
*/ */
template <int i> HOSTDEVICE Dim<i> dim_mult(const Dim<i> &a, const Dim<i> &b) { template <int i>
HOSTDEVICE Dim<i> dim_mult(const Dim<i> &a, const Dim<i> &b) {
return Dim<i>(a.head * b.head, dim_mult(a.tail, b.tail)); return Dim<i>(a.head * b.head, dim_mult(a.tail, b.tail));
} }
...@@ -365,8 +388,8 @@ HOSTDEVICE Dim<sizeof...(Args)> make_dim(Args... idxes) { ...@@ -365,8 +388,8 @@ HOSTDEVICE Dim<sizeof...(Args)> make_dim(Args... idxes) {
// Allows us to output a Dim // Allows us to output a Dim
// XXX For some reason, overloading fails to resolve this correctly // XXX For some reason, overloading fails to resolve this correctly
template <int i> template <int i>
typename std::enable_if<(i > 1), std::ostream &>::type typename std::enable_if<(i > 1), std::ostream &>::type operator<<(
operator<<(std::ostream &os, const Dim<i> &d) { std::ostream &os, const Dim<i> &d) {
os << d.head << ", " << d.tail; os << d.head << ", " << d.tail;
return os; return os;
} }
...@@ -374,8 +397,8 @@ operator<<(std::ostream &os, const Dim<i> &d) { ...@@ -374,8 +397,8 @@ operator<<(std::ostream &os, const Dim<i> &d) {
// Base case that allows us to output a Dim // Base case that allows us to output a Dim
// XXX I wish this could be an overload instead of a template // XXX I wish this could be an overload instead of a template
template <int i> template <int i>
typename std::enable_if<(i == 1), std::ostream &>::type typename std::enable_if<(i == 1), std::ostream &>::type operator<<(
operator<<(std::ostream &os, const Dim<i> &d) { std::ostream &os, const Dim<i> &d) {
os << d.head; os << d.head;
return os; return os;
} }
...@@ -384,7 +407,8 @@ inline std::ostream &operator<<(std::ostream &os, const Dim<0> &d) { ...@@ -384,7 +407,8 @@ inline std::ostream &operator<<(std::ostream &os, const Dim<0> &d) {
return os; return os;
} }
template <int i> HOST std::string Dim<i>::to_string() const { template <int i>
HOST std::string Dim<i>::to_string() const {
std::stringstream stream; std::stringstream stream;
stream << *this; stream << *this;
...@@ -406,5 +430,5 @@ HOSTDEVICE Dim<D> linear_to_dimension(int linear_index, Dim<D> extents) { ...@@ -406,5 +430,5 @@ HOSTDEVICE Dim<D> linear_to_dimension(int linear_index, Dim<D> extents) {
return result; return result;
} }
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -90,5 +90,5 @@ void Executor<Dtype>::predict(const Tensor &t, int block_id) { ...@@ -90,5 +90,5 @@ void Executor<Dtype>::predict(const Tensor &t, int block_id) {
template class Executor<CPU>; template class Executor<CPU>;
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
...@@ -34,15 +34,16 @@ SOFTWARE. ...@@ -34,15 +34,16 @@ SOFTWARE.
namespace paddle_mobile { namespace paddle_mobile {
namespace framework { namespace framework {
template <typename Dtype> class Executor { template <typename Dtype>
public: class Executor {
public:
Executor(); Executor();
Executor(const Program<Dtype> p); Executor(const Program<Dtype> p);
std::shared_ptr<Tensor> predict(Tensor &t); std::shared_ptr<Tensor> predict(Tensor &t);
public: public:
const framework::Program<Dtype> program_; const framework::Program<Dtype> program_;
std::shared_ptr<ProgramDesc> to_predict_program_; std::shared_ptr<ProgramDesc> to_predict_program_;
...@@ -54,5 +55,5 @@ public: ...@@ -54,5 +55,5 @@ public:
bool use_optimize_ = false; bool use_optimize_ = false;
}; };
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
此差异已折叠。
此差异已折叠。
...@@ -13,10 +13,10 @@ See the License for the specific language governing permissions and ...@@ -13,10 +13,10 @@ See the License for the specific language governing permissions and
limitations under the License. */ limitations under the License. */
#include "lod_tensor.h" #include "lod_tensor.h"
#include <algorithm>
#include <iterator>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <algorithm>
#include <iterator>
namespace paddle_mobile { namespace paddle_mobile {
namespace framework { namespace framework {
...@@ -105,8 +105,7 @@ LoD SliceInLevel(const LoD &in, size_t level, size_t elem_begin, ...@@ -105,8 +105,7 @@ LoD SliceInLevel(const LoD &in, size_t level, size_t elem_begin,
LoD ToAbsOffset(const LoD &in) { LoD ToAbsOffset(const LoD &in) {
// the lowest level stores relative offsets // the lowest level stores relative offsets
if (in.empty() || in.size() == 1) if (in.empty() || in.size() == 1) return in;
return in;
LoD result = in; LoD result = in;
for (auto level = static_cast<int>(in.size() - 2); level >= 0; level--) { for (auto level = static_cast<int>(in.size() - 2); level >= 0; level--) {
for (size_t i = 0; i < in[level].size(); ++i) { for (size_t i = 0; i < in[level].size(); ++i) {
...@@ -138,23 +137,19 @@ bool operator==(const LoD &a, const LoD &b) { ...@@ -138,23 +137,19 @@ bool operator==(const LoD &a, const LoD &b) {
} }
bool CheckLoD(const LoD &in, int tensor_height) { bool CheckLoD(const LoD &in, int tensor_height) {
if (in.empty()) if (in.empty()) return true;
return true;
for (const auto &level : in) { for (const auto &level : in) {
// check: there should be more than 2 offsets existing in each // check: there should be more than 2 offsets existing in each
// level. // level.
if (level.size() < 2) if (level.size() < 2) return false;
return false;
// check: the first offset(the begin offset) of each level // check: the first offset(the begin offset) of each level
// should be 0. // should be 0.
if (level.front() != 0) if (level.front() != 0) return false;
return false;
// check: all the offsets in a level should be ascending(no same // check: all the offsets in a level should be ascending(no same
// items // items
// allows). // allows).
if (!std::is_sorted(level.begin(), level.begin(), [](size_t a, size_t b) { if (!std::is_sorted(level.begin(), level.begin(), [](size_t a, size_t b) {
if (a < b) if (a < b) return true;
return true;
return false; return false;
})) { })) {
std::cout << "ascending error"; std::cout << "ascending error";
...@@ -174,22 +169,19 @@ bool CheckLoD(const LoD &in, int tensor_height) { ...@@ -174,22 +169,19 @@ bool CheckLoD(const LoD &in, int tensor_height) {
// goes // goes
// first. // first.
for (size_t level = 0; level < in.size() - 1; level++) { for (size_t level = 0; level < in.size() - 1; level++) {
if (in[level].back() != in[level + 1].size() - 1) if (in[level].back() != in[level + 1].size() - 1) return false;
return false;
} }
return true; return true;
} }
bool CheckAbsLoD(const LoD &in, int tensor_height) { bool CheckAbsLoD(const LoD &in, int tensor_height) {
if (in.empty()) if (in.empty()) return true;
return true;
for (const auto &level : in) { for (const auto &level : in) {
// check: all the offsets in a level should be ascending(no same // check: all the offsets in a level should be ascending(no same
// items // items
// allows). // allows).
if (!std::is_sorted(level.begin(), level.begin(), [](size_t a, size_t b) { if (!std::is_sorted(level.begin(), level.begin(), [](size_t a, size_t b) {
if (a < b) if (a < b) return true;
return true;
return false; return false;
})) { })) {
return false; return false;
...@@ -197,14 +189,12 @@ bool CheckAbsLoD(const LoD &in, int tensor_height) { ...@@ -197,14 +189,12 @@ bool CheckAbsLoD(const LoD &in, int tensor_height) {
// check: there should be more than 2 offsets existing in each // check: there should be more than 2 offsets existing in each
// level. // level.
if (level.size() < 2) if (level.size() < 2) return false;
return false;
// check: the first offset of each level should be 0, and the // check: the first offset of each level should be 0, and the
// last should be // last should be
// the same(the height of underlying tensor). // the same(the height of underlying tensor).
if (level.front() != 0) if (level.front() != 0) return false;
return false;
if (tensor_height < 0) { if (tensor_height < 0) {
tensor_height = level.back(); tensor_height = level.back();
} else if ((size_t)tensor_height != level.back()) { } else if ((size_t)tensor_height != level.back()) {
...@@ -242,7 +232,7 @@ void AppendLoD(LoD *lod, const LoD &lod_length) { ...@@ -242,7 +232,7 @@ void AppendLoD(LoD *lod, const LoD &lod_length) {
// lod."); // lod.");
if (lod->empty()) { if (lod->empty()) {
for (size_t i = 0; i < lod_length.size(); ++i) { for (size_t i = 0; i < lod_length.size(); ++i) {
lod->emplace_back(1, 0); // size = 1, value = 0; lod->emplace_back(1, 0); // size = 1, value = 0;
} }
*lod = LoD(lod_length.size(), std::vector<size_t>({0})); *lod = LoD(lod_length.size(), std::vector<size_t>({0}));
} }
...@@ -255,7 +245,7 @@ void AppendLoD(LoD *lod, const LoD &lod_length) { ...@@ -255,7 +245,7 @@ void AppendLoD(LoD *lod, const LoD &lod_length) {
} }
void SerializeToStream(std::ostream &os, const LoDTensor &tensor) { void SerializeToStream(std::ostream &os, const LoDTensor &tensor) {
{ // the 1st field, uint32_t version for LoDTensor { // the 1st field, uint32_t version for LoDTensor
constexpr uint32_t version = 0; constexpr uint32_t version = 0;
os.write(reinterpret_cast<const char *>(&version), sizeof(version)); os.write(reinterpret_cast<const char *>(&version), sizeof(version));
} }
...@@ -307,5 +297,5 @@ void DeserializeFromStream(std::istream &is, LoDTensor *tensor) { ...@@ -307,5 +297,5 @@ void DeserializeFromStream(std::istream &is, LoDTensor *tensor) {
TensorFromStream(is, static_cast<Tensor *>(tensor)); TensorFromStream(is, static_cast<Tensor *>(tensor));
} }
} // namespace framework } // namespace framework
} // namespace paddle_mobile } // namespace paddle_mobile
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册