diff --git a/3rd/win/mnn/include/MNN/AutoTime.hpp b/3rd/win/mnn/include/MNN/AutoTime.hpp new file mode 100644 index 0000000..40e4774 --- /dev/null +++ b/3rd/win/mnn/include/MNN/AutoTime.hpp @@ -0,0 +1,58 @@ +// +// AutoTime.hpp +// MNN +// +// Created by MNN on 2018/07/27. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef AutoTime_hpp +#define AutoTime_hpp + +#include +#include +#include + +namespace MNN { + +class MNN_PUBLIC Timer { +public: + Timer(); + ~Timer(); + Timer(const Timer&) = delete; + Timer(const Timer&&) = delete; + Timer& operator=(const Timer&) = delete; + Timer& operator=(const Timer&&) = delete; + + // reset timer + void reset(); + // get duration (us) from init or latest reset. + uint64_t durationInUs(); + +protected: + uint64_t mLastResetTime; +}; + +/** time tracing util. prints duration between init and deinit. */ +class MNN_PUBLIC AutoTime : Timer { +public: + AutoTime(int line, const char* func); + ~AutoTime(); + AutoTime(const AutoTime&) = delete; + AutoTime(const AutoTime&&) = delete; + AutoTime& operator=(const AutoTime&) = delete; + AutoTime& operator=(const AutoTime&&) = delete; + +private: + int mLine; + char* mName; +}; +} // namespace MNN + +#ifdef MNN_OPEN_TIME_TRACE +#define AUTOTIME MNN::AutoTime ___t(__LINE__, __func__) +#else +#define AUTOTIME +#endif + +#endif /* AutoTime_hpp */ diff --git a/3rd/win/mnn/include/MNN/ErrorCode.hpp b/3rd/win/mnn/include/MNN/ErrorCode.hpp new file mode 100644 index 0000000..d326801 --- /dev/null +++ b/3rd/win/mnn/include/MNN/ErrorCode.hpp @@ -0,0 +1,34 @@ +// +// ErrorCode.hpp +// MNN +// +// Created by MNN on 2018/09/18. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef ErrorCode_h +#define ErrorCode_h + +namespace MNN { +enum ErrorCode { +#ifdef NO_ERROR +#undef NO_ERROR +#endif // NO_ERROR + NO_ERROR = 0, + OUT_OF_MEMORY = 1, + NOT_SUPPORT = 2, + COMPUTE_SIZE_ERROR = 3, + NO_EXECUTION = 4, + INVALID_VALUE = 5, + + // User error + INPUT_DATA_ERROR = 10, + CALL_BACK_STOP = 11, + + // Op Resize Error + TENSOR_NOT_SUPPORT = 20, + TENSOR_NEED_DIVIDE = 21, +}; +} // namespace MNN + +#endif /* ErrorCode_h */ diff --git a/3rd/win/mnn/include/MNN/HalideRuntime.h b/3rd/win/mnn/include/MNN/HalideRuntime.h new file mode 100644 index 0000000..bc4b0b5 --- /dev/null +++ b/3rd/win/mnn/include/MNN/HalideRuntime.h @@ -0,0 +1,307 @@ +#ifndef HALIDE_HALIDERUNTIME_H +#define HALIDE_HALIDERUNTIME_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Note that you should not use "inline" along with HALIDE_ALWAYS_INLINE; +// it is not necessary, and may produce warnings for some build configurations. +#ifdef _MSC_VER +#define HALIDE_ALWAYS_INLINE __forceinline +#define HALIDE_NEVER_INLINE __declspec(noinline) +#else +#define HALIDE_ALWAYS_INLINE __attribute__((always_inline)) inline +#define HALIDE_NEVER_INLINE __attribute__((noinline)) +#endif + +/** \file + * + * This file declares the routines used by Halide internally in its + * runtime. On platforms that support weak linking, these can be + * replaced with user-defined versions by defining an extern "C" + * function with the same name and signature. + * + * When doing Just In Time (JIT) compilation methods on the Func being + * compiled must be called instead. The corresponding methods are + * documented below. + * + * All of these functions take a "void *user_context" parameter as their + * first argument; if the Halide kernel that calls back to any of these + * functions has been compiled with the UserContext feature set on its Target, + * then the value of that pointer passed from the code that calls the + * Halide kernel is piped through to the function. + * + * Some of these are also useful to call when using the default + * implementation. E.g. halide_shutdown_thread_pool. + * + * Note that even on platforms with weak linking, some linker setups + * may not respect the override you provide. E.g. if the override is + * in a shared library and the halide object files are linked directly + * into the output, the builtin versions of the runtime functions will + * be called. See your linker documentation for more details. On + * Linux, LD_DYNAMIC_WEAK=1 may help. + * + */ + +// Forward-declare to suppress warnings if compiling as C. +struct halide_buffer_t; + +/** Types in the halide type system. They can be ints, unsigned ints, + * or floats (of various bit-widths), or a handle (which is always 64-bits). + * Note that the int/uint/float values do not imply a specific bit width + * (the bit width is expected to be encoded in a separate value). + */ +typedef enum halide_type_code_t +{ + halide_type_int = 0, //!< signed integers + halide_type_uint = 1, //!< unsigned integers + halide_type_float = 2, //!< floating point numbers + halide_type_handle = 3 //!< opaque pointer type (void *) +} halide_type_code_t; + +// Note that while __attribute__ can go before or after the declaration, +// __declspec apparently is only allowed before. +#ifndef HALIDE_ATTRIBUTE_ALIGN + #ifdef _MSC_VER + #define HALIDE_ATTRIBUTE_ALIGN(x) __declspec(align(x)) + #else + #define HALIDE_ATTRIBUTE_ALIGN(x) __attribute__((aligned(x))) + #endif +#endif + +/** A runtime tag for a type in the halide type system. Can be ints, + * unsigned ints, or floats of various bit-widths (the 'bits' + * field). Can also be vectors of the same (by setting the 'lanes' + * field to something larger than one). This struct should be + * exactly 32-bits in size. */ +struct halide_type_t { + /** The basic type code: signed integer, unsigned integer, or floating point. */ +#if __cplusplus >= 201103L + HALIDE_ATTRIBUTE_ALIGN(1) halide_type_code_t code; // halide_type_code_t +#else + HALIDE_ATTRIBUTE_ALIGN(1) uint8_t code; // halide_type_code_t +#endif + + /** The number of bits of precision of a single scalar value of this type. */ + HALIDE_ATTRIBUTE_ALIGN(1) uint8_t bits; + + /** How many elements in a vector. This is 1 for scalar types. */ + HALIDE_ATTRIBUTE_ALIGN(2) uint16_t lanes; + +#ifdef __cplusplus + /** Construct a runtime representation of a Halide type from: + * code: The fundamental type from an enum. + * bits: The bit size of one element. + * lanes: The number of vector elements in the type. */ + HALIDE_ALWAYS_INLINE halide_type_t(halide_type_code_t code, uint8_t bits, uint16_t lanes = 1) + : code(code), bits(bits), lanes(lanes) { + } + + /** Default constructor is required e.g. to declare halide_trace_event + * instances. */ + HALIDE_ALWAYS_INLINE halide_type_t() : code((halide_type_code_t)0), bits(0), lanes(0) {} + + /** Compare two types for equality. */ + HALIDE_ALWAYS_INLINE bool operator==(const halide_type_t &other) const { + return (code == other.code && + bits == other.bits && + lanes == other.lanes); + } + + HALIDE_ALWAYS_INLINE bool operator!=(const halide_type_t &other) const { + return !(*this == other); + } + + /** Size in bytes for a single element, even if width is not 1, of this type. */ + HALIDE_ALWAYS_INLINE int bytes() const { return (bits + 7) / 8; } +#endif +}; + +/** An opaque struct containing per-GPU API implementations of the + * device functions. */ +struct halide_device_interface_impl_t; + +/** Each GPU API provides a halide_device_interface_t struct pointing + * to the code that manages device allocations. You can access these + * functions directly from the struct member function pointers, or by + * calling the functions declared below. Note that the global + * functions are not available when using Halide as a JIT compiler. + * If you are using raw halide_buffer_t in that context you must use + * the function pointers in the device_interface struct. + * + * The function pointers below are currently the same for every GPU + * API; only the impl field varies. These top-level functions do the + * bookkeeping that is common across all GPU APIs, and then dispatch + * to more API-specific functions via another set of function pointers + * hidden inside the impl field. + */ +struct halide_device_interface_t { + int (*device_malloc)(void *user_context, struct halide_buffer_t *buf, + const struct halide_device_interface_t *device_interface); + int (*device_free)(void *user_context, struct halide_buffer_t *buf); + int (*device_sync)(void *user_context, struct halide_buffer_t *buf); + void (*device_release)(void *user_context, + const struct halide_device_interface_t *device_interface); + int (*copy_to_host)(void *user_context, struct halide_buffer_t *buf); + int (*copy_to_device)(void *user_context, struct halide_buffer_t *buf, + const struct halide_device_interface_t *device_interface); + int (*device_and_host_malloc)(void *user_context, struct halide_buffer_t *buf, + const struct halide_device_interface_t *device_interface); + int (*device_and_host_free)(void *user_context, struct halide_buffer_t *buf); + int (*buffer_copy)(void *user_context, struct halide_buffer_t *src, + const struct halide_device_interface_t *dst_device_interface, struct halide_buffer_t *dst); + int (*device_crop)(void *user_context, const struct halide_buffer_t *src, + struct halide_buffer_t *dst); + int (*device_release_crop)(void *user_context, struct halide_buffer_t *buf); + int (*wrap_native)(void *user_context, struct halide_buffer_t *buf, uint64_t handle, + const struct halide_device_interface_t *device_interface); + int (*detach_native)(void *user_context, struct halide_buffer_t *buf); + const struct halide_device_interface_impl_t *impl; +}; + +typedef struct halide_dimension_t { + int32_t min, extent, stride; + + // Per-dimension flags. None are defined yet (This is reserved for future use). + uint32_t flags; + +#ifdef __cplusplus + HALIDE_ALWAYS_INLINE halide_dimension_t() : min(0), extent(0), stride(0), flags(0) {} + HALIDE_ALWAYS_INLINE halide_dimension_t(int32_t m, int32_t e, int32_t s, uint32_t f = 0) : + min(m), extent(e), stride(s), flags(f) {} + + HALIDE_ALWAYS_INLINE bool operator==(const halide_dimension_t &other) const { + return (min == other.min) && + (extent == other.extent) && + (stride == other.stride) && + (flags == other.flags); + } + + HALIDE_ALWAYS_INLINE bool operator!=(const halide_dimension_t &other) const { + return !(*this == other); + } +#endif +} halide_dimension_t; + +#ifdef __cplusplus +} // extern "C" +#endif + +typedef enum {halide_buffer_flag_host_dirty = 1, + halide_buffer_flag_device_dirty = 2} halide_buffer_flags; + +/** + * The raw representation of an image passed around by generated + * Halide code. It includes some stuff to track whether the image is + * not actually in main memory, but instead on a device (like a + * GPU). For a more convenient C++ wrapper, use Halide::Buffer. */ +typedef struct halide_buffer_t { + /** A device-handle for e.g. GPU memory used to back this buffer. */ + uint64_t device; + + /** The interface used to interpret the above handle. */ + const struct halide_device_interface_t *device_interface; + + /** A pointer to the start of the data in main memory. In terms of + * the Halide coordinate system, this is the address of the min + * coordinates (defined below). */ + uint8_t* host; + + /** flags with various meanings. */ + uint64_t flags; + + /** The type of each buffer element. */ + struct halide_type_t type; + + /** The dimensionality of the buffer. */ + int32_t dimensions; + + /** The shape of the buffer. Halide does not own this array - you + * must manage the memory for it yourself. */ + halide_dimension_t *dim; + + /** Pads the buffer up to a multiple of 8 bytes */ + void *padding; +} halide_buffer_t; + + +#ifdef __cplusplus + +namespace { +template struct check_is_pointer; +template struct check_is_pointer {}; +} + +/** Construct the halide equivalent of a C type */ +template +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + // Create a compile-time error if T is not a pointer (without + // using any includes - this code goes into the runtime). + check_is_pointer check; + (void)check; + return halide_type_t(halide_type_handle, 64); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_float, 32); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_float, 64); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_uint, 1); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_uint, 8); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_uint, 16); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_uint, 32); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_uint, 64); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_int, 8); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_int, 16); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_int, 32); +} + +template<> +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() { + return halide_type_t(halide_type_int, 64); +} + +#endif + +#endif // HALIDE_HALIDERUNTIME_H diff --git a/3rd/win/mnn/include/MNN/ImageProcess.hpp b/3rd/win/mnn/include/MNN/ImageProcess.hpp new file mode 100644 index 0000000..7fbd598 --- /dev/null +++ b/3rd/win/mnn/include/MNN/ImageProcess.hpp @@ -0,0 +1,145 @@ +// +// ImageProcess.hpp +// MNN +// +// Created by MNN on 2018/09/19. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef ImageProcess_hpp +#define ImageProcess_hpp + +#include +#include +#include + +namespace MNN { +namespace CV { +enum ImageFormat { + RGBA = 0, + RGB, + BGR, + GRAY, + BGRA, + YUV_NV21 = 11, + YUV_NV12 = 12, + YUV_I420 = 13, +}; + +enum Filter { NEAREST = 0, BILINEAR = 1, BICUBIC = 2 }; + +enum Wrap { CLAMP_TO_EDGE = 0, ZERO = 1, REPEAT = 2 }; + +/** + * handle image process for tensor. + * step: + * 1: Do transform compute and get points + * 2: Sample line and do format convert + * 3: Turn RGBA to float tensor, and do sub and normalize + */ +class MNN_PUBLIC ImageProcess { +public: + struct Inside; + struct Config { + /** data filter */ + Filter filterType = NEAREST; + /** format of source data */ + ImageFormat sourceFormat = RGBA; + /** format of destination data */ + ImageFormat destFormat = RGBA; + + // Only valid if the dest type is float + float mean[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float normal[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + + /** edge wrapper */ + Wrap wrap = CLAMP_TO_EDGE; + }; + +public: + /** + * @brief create image process with given config for given tensor. + * @param config given config. + * @param dstTensor given tensor. + * @return image processor. + */ + static ImageProcess* create(const Config& config, const Tensor* dstTensor = nullptr); + + /** + * @brief create image process with given config for given tensor. + * @param means given means + * @param meanCount given means count + * @param normals given normals + * @param normalCount given normal count + * @param sourceFormat format of source data + * @param destFormat format of destination data + * @param dstTensor given tensor. + * @return image processor. + */ + static ImageProcess* create(const ImageFormat sourceFormat = RGBA, const ImageFormat destFormat = RGBA, + const float* means = nullptr, const int meanCount = 0, const float* normals = nullptr, + const int normalCount = 0, const Tensor* dstTensor = nullptr); + + ~ImageProcess(); + + /** + * @brief get affine transform matrix. + * @return affine transform matrix. + */ + inline const Matrix& matrix() const { + return mTransform; + } + void setMatrix(const Matrix& matrix); + + /** + * @brief convert source data to given tensor. + * @param source source data. + * @param iw source width. + * @param ih source height. + * @param stride number of elements per row. eg: 100 width RGB contains at least 300 elements. + * @param dest given tensor. + * @return result code. + */ + ErrorCode convert(const uint8_t* source, int iw, int ih, int stride, Tensor* dest); + + /** + * @brief convert source data to given tensor. + * @param source source data. + * @param iw source width. + * @param ih source height. + * @param stride number of elements per row. eg: 100 width RGB contains at least 300 elements. + * @param dest dest data. + * @param ow output width. + * @param oh output height. + * @param outputBpp output bpp, if 0, set as the save and config.destFormat. + * @param outputStride output stride, if 0, set as ow * outputBpp. + * @param type Only support halide_type_of and halide_type_of. + * @return result code. + */ + ErrorCode convert(const uint8_t* source, int iw, int ih, int stride, void* dest, int ow, int oh, int outputBpp = 0, + int outputStride = 0, halide_type_t type = halide_type_of()); + + /** + * @brief create tensor with given data. + * @param w image width. + * @param h image height. + * @param bpp bytes per pixel. + * @param p pixel data pointer. + * @return created tensor. + */ + template + static Tensor* createImageTensor(int w, int h, int bpp, void* p = nullptr) { + return createImageTensor(halide_type_of(), w, h, bpp, p); + } + static Tensor* createImageTensor(halide_type_t type, int w, int h, int bpp, void* p = nullptr); + +private: + ImageProcess(const Config& config); + Matrix mTransform; + Matrix mTransformInvert; + Inside* mInside; +}; +} // namespace CV +} // namespace MNN + +#endif /* ImageProcess_hpp */ diff --git a/3rd/win/mnn/include/MNN/Interpreter.hpp b/3rd/win/mnn/include/MNN/Interpreter.hpp new file mode 100644 index 0000000..6e7713f --- /dev/null +++ b/3rd/win/mnn/include/MNN/Interpreter.hpp @@ -0,0 +1,340 @@ +// +// Interpreter.hpp +// MNN +// +// Created by MNN on 2018/07/23. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef Interpreter_hpp +#define Interpreter_hpp + +#include +#include +#include +#include +#include +#include +#include + +namespace MNN { + +/** session schedule config */ +struct ScheduleConfig { + /** which tensor should be kept */ + std::vector saveTensors; + /** forward type */ + MNNForwardType type = MNN_FORWARD_CPU; + /** number of threads in parallel */ + int numThread = 4; + + /** subpath to run */ + struct Path { + std::vector inputs; + std::vector outputs; + + enum Mode { + /** + * Op Mode + * - inputs means the source op, can NOT be empty. + * - outputs means the sink op, can be empty. + * The path will start from source op, then flow when encounter the sink op. + * The sink op will not be compute in this path. + */ + Op = 0, + + /** + * Tensor Mode (NOT supported yet) + * - inputs means the inputs tensors, can NOT be empty. + * - outputs means the outputs tensors, can NOT be empty. + * It will find the pipeline that compute outputs from inputs. + */ + Tensor = 1 + }; + + /** running mode */ + Mode mode = Op; + }; + Path path; + + /** backup backend used to create execution when desinated backend do NOT support any op */ + MNNForwardType backupType = MNN_FORWARD_CPU; + + /** extra backend config */ + BackendConfig* backendConfig = nullptr; +}; + +class Session; +struct Content; +class Tensor; +class Backend; +class Runtime; + +class MNN_PUBLIC OperatorInfo { + struct Info; + +public: + /** Operator's name*/ + const std::string& name() const; + + /** Operator's type*/ + const std::string& type() const; + + /** Operator's flops, in M*/ + float flops() const; + +protected: + OperatorInfo(); + ~OperatorInfo(); + Info* mContent; +}; + +typedef std::function&, const std::string& /*opName*/)> TensorCallBack; +typedef std::function&, const OperatorInfo*)> TensorCallBackWithInfo; +typedef std::pair>, std::shared_ptr> RuntimeInfo; + +/** net data holder. multiple sessions could share same net. */ +class MNN_PUBLIC Interpreter { +public: + /** + * @brief create net from file. + * @param file given file. + * @return created net if success, NULL otherwise. + */ + static Interpreter* createFromFile(const char* file); + /** + * @brief create net from buffer. + * @param buffer given data buffer. + * @param size size of data buffer. + * @return created net if success, NULL otherwise. + */ + static Interpreter* createFromBuffer(const void* buffer, size_t size); + ~Interpreter(); + + enum SessionMode { + /** About CallBack, Default Session_Debug*/ + /** runSessionWithCallBack is allowed and can get internal op info*/ + Session_Debug = 0, + /** runSessionWithCallBack is not valid and can't get any info of op in session*/ + Session_Release = 1, + + /** About input tenosr, Default Session_Input_Inside*/ + /** The input tensor is alloced by session, input data after session resized*/ + Session_Input_Inside = 2, + /** The input tensor is alloced by user, set input data before session resize*/ + Session_Input_User = 3, + }; + /** + * @brief The API shoud be called before create session. + * @param mode session mode + * @return void + */ + void setSessionMode(SessionMode mode); + + /** + * @brief The API shoud be called before create session. + * If the cache exist, try to load cache from file. + * After createSession, try to save cache to file. + * @param cacheFile cache file name + * @param keySize the first `keySize` bytes used as the key to check if the `cacheFile` exists. + * @return void + */ + void setCacheFile(const char* cacheFile, size_t keySize = 128); + +public: + /** + * @brief create runtimeInfo seperately with schedule config. + * @param config session schedule configs. + */ + static RuntimeInfo createRuntime(const std::vector& configs); + + /** + * @brief create session with schedule config. created session will be managed in net. + * @param config session schedule config. + * @return created session if success, NULL otherwise. + */ + Session* createSession(const ScheduleConfig& config); + + /** + * @brief create session with schedule config and user-specified runtime. + * @param config session schedule config, runtime runtimeInfo used by the created session. + * @return created session if success, NULL otherwise. + */ + Session* createSession(const ScheduleConfig& config, const RuntimeInfo& runtime); + + /** + * @brief create multi-path session with schedule configs. created session will be managed in net. + * @param configs session schedule configs. + * @return created session if success, NULL otherwise. + */ + Session* createMultiPathSession(const std::vector& configs); + + /** + * @brief create multi-path session with schedule configs and user-specified runtime. + created session will be managed in net. + * @param configs session schedule configs. + * @return created session if success, NULL otherwise. + */ + Session* createMultiPathSession(const std::vector& configs, const RuntimeInfo& runtime); + + /** + * @brief release session. + * @param session given session. + * @return true if given session is held by net and is freed. + */ + bool releaseSession(Session* session); + + /** + * @brief call this function to get tensors ready. output tensor buffer (host or deviceId) should be retrieved + * after resize of any input tensor. + * @param session given session. + */ + void resizeSession(Session* session); + + /** + * @brief call this function if don't need resize or create session any more, it will save a few memory that equal + * to the size of model buffer + */ + void releaseModel(); + + /** + * @brief Get the model buffer for user to save + * @return std::make_pair(modleBuffer, modelSize). + * @example: + * std::ofstream output("trainResult.alinn") + * auto buffer = net->getModelBuffer(); + * output.write((const char*)buffer.first, buffer.second); + */ + std::pair getModelBuffer() const; + + /** + * @brief update Session's Tensor to model's Const Op + * @param session given session. + * @return result of running. + */ + ErrorCode updateSessionToModel(Session* session); + + /** + * @brief run session. + * @param session given session. + * @return result of running. + */ + ErrorCode runSession(Session* session) const; + + /* + * @brief run session. + * @param session given session. + * @param before callback before each op. return true to run the op; return false to skip the op. + * @param after callback after each op. return true to continue running; return false to interrupt the session. + * @param sync synchronously wait for finish of execution or not. + * @return result of running. + */ + ErrorCode runSessionWithCallBack(const Session* session, const TensorCallBack& before, const TensorCallBack& end, + bool sync = false) const; + + /* + * @brief run session. + * @param session given session. + * @param before callback before each op. return true to run the op; return false to skip the op. + * @param after callback after each op. return true to continue running; return false to interrupt the session. + * @param sync synchronously wait for finish of execution or not. + * @return result of running. + */ + ErrorCode runSessionWithCallBackInfo(const Session* session, const TensorCallBackWithInfo& before, + const TensorCallBackWithInfo& end, bool sync = false) const; + + /** + * @brief get input tensor for given name. + * @param session given session. + * @param name given name. if NULL, return first input. + * @return tensor if found, NULL otherwise. + */ + Tensor* getSessionInput(const Session* session, const char* name); + /** + * @brief get output tensor for given name. + * @param session given session. + * @param name given name. if NULL, return first output. + * @return tensor if found, NULL otherwise. + */ + Tensor* getSessionOutput(const Session* session, const char* name); + + enum SessionInfoCode { + /** memory session used in MB, float* */ + MEMORY = 0, + + /** float operation needed in session in M, float* */ + FLOPS = 1, + + /** Backends in session in M, int*, length >= the configs when create session */ + BACKENDS = 2, + + ALL + }; + + /** + * @brief get session info + * @param session given session. + * @param code given info code. + * @param void* given info ptr, see SessionInfoCode for detail + * @return true if support the code, false otherwise. + */ + bool getSesionInfo(const Session* session, SessionInfoCode code, void* ptr); + + /** + * @brief get all output tensors. + * @param session given session. + * @return all output tensors mapped with name. + */ + const std::map& getSessionOutputAll(const Session* session) const; + /** + * @brief get all input tensors. + * @param session given session. + * @return all input tensors mapped with name. + */ + const std::map& getSessionInputAll(const Session* session) const; + +public: + /** + * @brief resize given tensor. + * @param tensor given tensor. + * @param dims new dims. at most 6 dims. + */ + void resizeTensor(Tensor* tensor, const std::vector& dims); + + /** + * @brief resize given tensor by nchw. + * @param batch / N. + * @param channel / C. + * @param height / H. + * @param width / W + */ + void resizeTensor(Tensor* tensor, int batch, int channel, int height, int width); + + /** + * @brief get backend used to create given tensor. + * @param session given session. + * @param tensor given tensor. + * @return backend used to create given tensor, may be NULL. + */ + const Backend* getBackend(const Session* session, const Tensor* tensor) const; + + /** + * @brief get business code (model identifier). + * @return business code. + */ + const char* bizCode() const; + +private: + static Interpreter* createFromBufferInternal(Content* net); + + Content* mNet = nullptr; + Interpreter(Content* net); + + Interpreter(const Interpreter&) = delete; + Interpreter(const Interpreter&&) = delete; + Interpreter& operator=(const Interpreter&) = delete; + Interpreter& operator=(const Interpreter&&) = delete; +}; +} // namespace MNN + +#endif /* Interpreter_hpp */ diff --git a/3rd/win/mnn/include/MNN/MNNDefine.h b/3rd/win/mnn/include/MNN/MNNDefine.h new file mode 100644 index 0000000..e03ef4c --- /dev/null +++ b/3rd/win/mnn/include/MNN/MNNDefine.h @@ -0,0 +1,64 @@ +// +// MNNDefine.h +// MNN +// +// Created by MNN on 2018/08/09. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef MNNDefine_h +#define MNNDefine_h + +#include +#include + +#if defined(__APPLE__) +#include +#if TARGET_OS_IPHONE +#define MNN_BUILD_FOR_IOS +#endif +#endif + +#ifdef MNN_USE_LOGCAT +#include +#define MNN_ERROR(format, ...) __android_log_print(ANDROID_LOG_ERROR, "MNNJNI", format, ##__VA_ARGS__) +#define MNN_PRINT(format, ...) __android_log_print(ANDROID_LOG_INFO, "MNNJNI", format, ##__VA_ARGS__) +#else +#define MNN_PRINT(format, ...) printf(format, ##__VA_ARGS__) +#define MNN_ERROR(format, ...) printf(format, ##__VA_ARGS__) +#endif + +#ifdef DEBUG +#define MNN_ASSERT(x) \ + { \ + int res = (x); \ + if (!res) { \ + MNN_ERROR("Error for %s, %d\n", __FILE__, __LINE__); \ + assert(res); \ + } \ + } +#else +#define MNN_ASSERT(x) +#endif + +#define FUNC_PRINT(x) MNN_PRINT(#x "=%d in %s, %d \n", x, __func__, __LINE__); +#define FUNC_PRINT_ALL(x, type) MNN_PRINT(#x "=" #type " %" #type " in %s, %d \n", x, __func__, __LINE__); + +#define MNN_CHECK(success, log) \ +if(!(success)){ \ +MNN_ERROR("Check failed: %s ==> %s\n", #success, #log); \ +} + +#if defined(_MSC_VER) +#if defined(BUILDING_MNN_DLL) +#define MNN_PUBLIC __declspec(dllexport) +#elif defined(USING_MNN_DLL) +#define MNN_PUBLIC __declspec(dllimport) +#else +#define MNN_PUBLIC +#endif +#else +#define MNN_PUBLIC __attribute__((visibility("default"))) +#endif + +#endif /* MNNDefine_h */ diff --git a/3rd/win/mnn/include/MNN/MNNForwardType.h b/3rd/win/mnn/include/MNN/MNNForwardType.h new file mode 100644 index 0000000..70e36d5 --- /dev/null +++ b/3rd/win/mnn/include/MNN/MNNForwardType.h @@ -0,0 +1,75 @@ +// +// MNNForwardType.h +// MNN +// +// Created by MNN on 2019/01/19. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef MNNForwardType_h +#define MNNForwardType_h +#include +#include + +typedef enum { + MNN_FORWARD_CPU = 0, + + /* + Firtly find the first available backends not equal to CPU + If no other backends, use cpu + */ + MNN_FORWARD_AUTO = 4, + + /*Hand write metal*/ + MNN_FORWARD_METAL = 1, + + /*NVIDIA GPU API*/ + MNN_FORWARD_CUDA = 2, + + /*Android / Common Device GPU API*/ + MNN_FORWARD_OPENCL = 3, + MNN_FORWARD_OPENGL = 6, + MNN_FORWARD_VULKAN = 7, + + /*Android 8.1's NNAPI, Not Support yet*/ + MNN_FORWARD_NN = 5, + + /*User can use API from Backend.hpp to add or search Backend*/ + MNN_FORWARD_USER_0 = 8, + MNN_FORWARD_USER_1 = 9, + MNN_FORWARD_USER_2 = 10, + MNN_FORWARD_USER_3 = 11, + + MNN_FORWARD_ALL, + + /* Apply arm extension instruction set to accelerate some Ops, this forward type + is only used in MNN internal, and will be active automatically when user set forward type + to be MNN_FORWARD_CPU and extension instruction set is valid on hardware. + */ + MNN_FORWARD_CPU_EXTENSION + +} MNNForwardType; +#ifdef __cplusplus +namespace MNN { +struct BackendConfig { + enum MemoryMode { Memory_Normal = 0, Memory_High, Memory_Low }; + + MemoryMode memory = Memory_Normal; + + enum PowerMode { Power_Normal = 0, Power_High, Power_Low }; + + PowerMode power = Power_Normal; + + enum PrecisionMode { Precision_Normal = 0, Precision_High, Precision_Low }; + + PrecisionMode precision = Precision_Normal; + + /** user defined context */ + union { + void* sharedContext = nullptr; + size_t flags; // Valid for CPU Backend + }; +}; +}; // namespace MNN +#endif +#endif /* MNNForwardType_h */ diff --git a/3rd/win/mnn/include/MNN/Matrix.h b/3rd/win/mnn/include/MNN/Matrix.h new file mode 100644 index 0000000..0d59f66 --- /dev/null +++ b/3rd/win/mnn/include/MNN/Matrix.h @@ -0,0 +1,1615 @@ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Generated by tools/bookmaker from include/core/Matrix.h and docs/SkMatrix_Reference.bmh + on 2018-07-13 08:15:11. Additional documentation and examples can be found at: + https://skia.org/user/api/SkMatrix_Reference + + You may edit either file directly. Structural changes to public interfaces require + editing both files. After editing docs/SkMatrix_Reference.bmh, run: + bookmaker -b docs -i include/core/Matrix.h -p + to create an updated version of this file. + */ + + +// +// Modified by jiangxiaotang on 2018/09/19. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef SkMatrix_DEFINED +#define SkMatrix_DEFINED + +#include +#include +#include + +namespace MNN { +namespace CV { + +/** \class Matrix + Matrix holds a 3x3 matrix for transforming coordinates. This allows mapping + Point and vectors with translation, scaling, skewing, rotation, and + perspective. + + Matrix elements are in row major order. Matrix does not have a constructor, + so it must be explicitly initialized. setIdentity() initializes Matrix + so it has no effect. setTranslate(), setScale(), setSkew(), setRotate(), set9 and setAll() + initializes all Matrix elements with the corresponding mapping. + + Matrix includes a hidden variable that classifies the type of matrix to + improve performance. Matrix is not thread safe unless getType() is called first. +*/ + +class MNN_PUBLIC Matrix { +public: + Matrix() { + setIdentity(); + } + + /** Sets Matrix to scale by (sx, sy). Returned matrix is: + + | sx 0 0 | + | 0 sy 0 | + | 0 0 1 | + + @param sx horizontal scale factor + @param sy vertical scale factor + @return Matrix with scale + */ + static Matrix MakeScale(float sx, float sy) { + Matrix m; + m.setScale(sx, sy); + return m; + } + + /** Sets Matrix to scale by (scale, scale). Returned matrix is: + + | scale 0 0 | + | 0 scale 0 | + | 0 0 1 | + + @param scale horizontal and vertical scale factor + @return Matrix with scale + */ + static Matrix MakeScale(float scale) { + Matrix m; + m.setScale(scale, scale); + return m; + } + + /** Sets Matrix to translate by (dx, dy). Returned matrix is: + + | 1 0 dx | + | 0 1 dy | + | 0 0 1 | + + @param dx horizontal translation + @param dy vertical translation + @return Matrix with translation + */ + static Matrix MakeTrans(float dx, float dy) { + Matrix m; + m.setTranslate(dx, dy); + return m; + } + + /** Sets Matrix to: + + | scaleX skewX transX | + | skewY scaleY transY | + | pers0 pers1 pers2 | + + @param scaleX horizontal scale factor + @param skewX horizontal skew factor + @param transX horizontal translation + @param skewY vertical skew factor + @param scaleY vertical scale factor + @param transY vertical translation + @param pers0 input x-axis perspective factor + @param pers1 input y-axis perspective factor + @param pers2 perspective scale factor + @return Matrix constructed from parameters + */ + static Matrix MakeAll(float scaleX, float skewX, float transX, float skewY, float scaleY, float transY, float pers0, + float pers1, float pers2) { + Matrix m; + m.setAll(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2); + return m; + } + + /** \enum Matrix::TypeMask + Enum of bit fields for mask returned by getType(). + Used to identify the complexity of Matrix, to optimize performance. + */ + enum TypeMask { + kIdentity_Mask = 0, //!< identity Matrix; all bits clear + kTranslate_Mask = 0x01, //!< translation Matrix + kScale_Mask = 0x02, //!< scale Matrix + kAffine_Mask = 0x04, //!< skew or rotate Matrix + kPerspective_Mask = 0x08, //!< perspective Matrix + }; + + /** Returns a bit field describing the transformations the matrix may + perform. The bit field is computed conservatively, so it may include + false positives. For example, when kPerspective_Mask is set, all + other bits are set. + + @return kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask, + kAffine_Mask, kPerspective_Mask + */ + TypeMask getType() const { + if (fTypeMask & kUnknown_Mask) { + fTypeMask = this->computeTypeMask(); + } + // only return the public masks + return (TypeMask)(fTypeMask & 0xF); + } + + /** Returns true if Matrix is identity. Identity matrix is: + + | 1 0 0 | + | 0 1 0 | + | 0 0 1 | + + @return true if Matrix has no effect + */ + bool isIdentity() const { + return this->getType() == 0; + } + + /** Returns true if Matrix at most scales and translates. Matrix may be identity, + contain only scale elements, only translate elements, or both. Matrix form is: + + | scale-x 0 translate-x | + | 0 scale-y translate-y | + | 0 0 1 | + + @return true if Matrix is identity; or scales, translates, or both + */ + bool isScaleTranslate() const { + return !(this->getType() & ~(kScale_Mask | kTranslate_Mask)); + } + + /** Returns true if Matrix is identity, or translates. Matrix form is: + + | 1 0 translate-x | + | 0 1 translate-y | + | 0 0 1 | + + @return true if Matrix is identity, or translates + */ + bool isTranslate() const { + return !(this->getType() & ~(kTranslate_Mask)); + } + + /** Returns true Matrix maps Rect to another Rect. If true, Matrix is identity, + or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all + cases, Matrix may also have translation. Matrix form is either: + + | scale-x 0 translate-x | + | 0 scale-y translate-y | + | 0 0 1 | + + or + + | 0 rotate-x translate-x | + | rotate-y 0 translate-y | + | 0 0 1 | + + for non-zero values of scale-x, scale-y, rotate-x, and rotate-y. + + Also called preservesAxisAlignment(); use the one that provides better inline + documentation. + + @return true if Matrix maps one Rect into another + */ + bool rectStaysRect() const { + if (fTypeMask & kUnknown_Mask) { + fTypeMask = this->computeTypeMask(); + } + return (fTypeMask & kRectStaysRect_Mask) != 0; + } + + /** Returns true Matrix maps Rect to another Rect. If true, Matrix is identity, + or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all + cases, Matrix may also have translation. Matrix form is either: + + | scale-x 0 translate-x | + | 0 scale-y translate-y | + | 0 0 1 | + + or + + | 0 rotate-x translate-x | + | rotate-y 0 translate-y | + | 0 0 1 | + + for non-zero values of scale-x, scale-y, rotate-x, and rotate-y. + + Also called rectStaysRect(); use the one that provides better inline + documentation. + + @return true if Matrix maps one Rect into another + */ + bool preservesAxisAlignment() const { + return this->rectStaysRect(); + } + + /** Matrix organizes its values in row order. These members correspond to + each value in Matrix. + */ + static constexpr int kMScaleX = 0; //!< horizontal scale factor + static constexpr int kMSkewX = 1; //!< horizontal skew factor + static constexpr int kMTransX = 2; //!< horizontal translation + static constexpr int kMSkewY = 3; //!< vertical skew factor + static constexpr int kMScaleY = 4; //!< vertical scale factor + static constexpr int kMTransY = 5; //!< vertical translation + static constexpr int kMPersp0 = 6; //!< input x perspective factor + static constexpr int kMPersp1 = 7; //!< input y perspective factor + static constexpr int kMPersp2 = 8; //!< perspective bias + + /** Affine arrays are in column major order to match the matrix used by + PDF and XPS. + */ + static constexpr int kAScaleX = 0; //!< horizontal scale factor + static constexpr int kASkewY = 1; //!< vertical skew factor + static constexpr int kASkewX = 2; //!< horizontal skew factor + static constexpr int kAScaleY = 3; //!< vertical scale factor + static constexpr int kATransX = 4; //!< horizontal translation + static constexpr int kATransY = 5; //!< vertical translation + + /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is + defined. + + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2 + @return value corresponding to index + */ + float operator[](int index) const { + MNN_ASSERT((unsigned)index < 9); + return fMat[index]; + } + + /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is + defined. + + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2 + @return value corresponding to index + */ + float get(int index) const { + MNN_ASSERT((unsigned)index < 9); + return fMat[index]; + } + + /** Returns scale factor multiplied by x-axis input, contributing to x-axis output. + With mapPoints(), scales Point along the x-axis. + + @return horizontal scale factor + */ + float getScaleX() const { + return fMat[kMScaleX]; + } + + /** Returns scale factor multiplied by y-axis input, contributing to y-axis output. + With mapPoints(), scales Point along the y-axis. + + @return vertical scale factor + */ + float getScaleY() const { + return fMat[kMScaleY]; + } + + /** Returns scale factor multiplied by x-axis input, contributing to y-axis output. + With mapPoints(), skews Point along the y-axis. + Skewing both axes can rotate Point. + + @return vertical skew factor + */ + float getSkewY() const { + return fMat[kMSkewY]; + } + + /** Returns scale factor multiplied by y-axis input, contributing to x-axis output. + With mapPoints(), skews Point along the x-axis. + Skewing both axes can rotate Point. + + @return horizontal scale factor + */ + float getSkewX() const { + return fMat[kMSkewX]; + } + + /** Returns translation contributing to x-axis output. + With mapPoints(), moves Point along the x-axis. + + @return horizontal translation factor + */ + float getTranslateX() const { + return fMat[kMTransX]; + } + + /** Returns translation contributing to y-axis output. + With mapPoints(), moves Point along the y-axis. + + @return vertical translation factor + */ + float getTranslateY() const { + return fMat[kMTransY]; + } + + /** Returns factor scaling input x-axis relative to input y-axis. + + @return input x-axis perspective factor + */ + float getPerspX() const { + return fMat[kMPersp0]; + } + + /** Returns factor scaling input y-axis relative to input x-axis. + + @return input y-axis perspective factor + */ + float getPerspY() const { + return fMat[kMPersp1]; + } + + /** Returns writable Matrix value. Asserts if index is out of range and SK_DEBUG is + defined. Clears internal cache anticipating that caller will change Matrix value. + + Next call to read Matrix state may recompute cache; subsequent writes to Matrix + value must be followed by dirtyMatrixTypeCache(). + + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2 + @return writable value corresponding to index + */ + float& operator[](int index) { + MNN_ASSERT((unsigned)index < 9); + this->setTypeMask(kUnknown_Mask); + return fMat[index]; + } + + /** Sets Matrix value. Asserts if index is out of range and SK_DEBUG is + defined. Safer than operator[]; internal cache is always maintained. + + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2 + @param value scalar to store in Matrix + */ + void set(int index, float value) { + MNN_ASSERT((unsigned)index < 9); + fMat[index] = value; + this->setTypeMask(kUnknown_Mask); + } + + /** Sets horizontal scale factor. + + @param v horizontal scale factor to store + */ + void setScaleX(float v) { + this->set(kMScaleX, v); + } + + /** Sets vertical scale factor. + + @param v vertical scale factor to store + */ + void setScaleY(float v) { + this->set(kMScaleY, v); + } + + /** Sets vertical skew factor. + + @param v vertical skew factor to store + */ + void setSkewY(float v) { + this->set(kMSkewY, v); + } + + /** Sets horizontal skew factor. + + @param v horizontal skew factor to store + */ + void setSkewX(float v) { + this->set(kMSkewX, v); + } + + /** Sets horizontal translation. + + @param v horizontal translation to store + */ + void setTranslateX(float v) { + this->set(kMTransX, v); + } + + /** Sets vertical translation. + + @param v vertical translation to store + */ + void setTranslateY(float v) { + this->set(kMTransY, v); + } + + /** Sets input x-axis perspective factor, which causes mapXY() to vary input x-axis values + inversely proportional to input y-axis values. + + @param v perspective factor + */ + void setPerspX(float v) { + this->set(kMPersp0, v); + } + + /** Sets input y-axis perspective factor, which causes mapXY() to vary input y-axis values + inversely proportional to input x-axis values. + + @param v perspective factor + */ + void setPerspY(float v) { + this->set(kMPersp1, v); + } + + /** Sets all values from parameters. Sets matrix to: + + | scaleX skewX transX | + | skewY scaleY transY | + | persp0 persp1 persp2 | + + @param scaleX horizontal scale factor to store + @param skewX horizontal skew factor to store + @param transX horizontal translation to store + @param skewY vertical skew factor to store + @param scaleY vertical scale factor to store + @param transY vertical translation to store + @param persp0 input x-axis values perspective factor to store + @param persp1 input y-axis values perspective factor to store + @param persp2 perspective scale factor to store + */ + void setAll(float scaleX, float skewX, float transX, float skewY, float scaleY, float transY, float persp0, + float persp1, float persp2) { + fMat[kMScaleX] = scaleX; + fMat[kMSkewX] = skewX; + fMat[kMTransX] = transX; + fMat[kMSkewY] = skewY; + fMat[kMScaleY] = scaleY; + fMat[kMTransY] = transY; + fMat[kMPersp0] = persp0; + fMat[kMPersp1] = persp1; + fMat[kMPersp2] = persp2; + this->setTypeMask(kUnknown_Mask); + } + + /** Copies nine scalar values contained by Matrix into buffer, in member value + ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2. + + @param buffer storage for nine scalar values + */ + void get9(float buffer[9]) const { + memcpy(buffer, fMat, 9 * sizeof(float)); + } + + /** Sets Matrix to nine scalar values in buffer, in member value ascending order: + kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1, + kMPersp2. + + Sets matrix to: + + | buffer[0] buffer[1] buffer[2] | + | buffer[3] buffer[4] buffer[5] | + | buffer[6] buffer[7] buffer[8] | + + In the future, set9 followed by get9 may not return the same values. Since Matrix + maps non-homogeneous coordinates, scaling all nine values produces an equivalent + transformation, possibly improving precision. + + @param buffer nine scalar values + */ + void set9(const float buffer[9]); + + /** Sets Matrix to identity; which has no effect on mapped Point. Sets Matrix to: + + | 1 0 0 | + | 0 1 0 | + | 0 0 1 | + + Also called setIdentity(); use the one that provides better inline + documentation. + */ + void reset(); + + /** Sets Matrix to identity; which has no effect on mapped Point. Sets Matrix to: + + | 1 0 0 | + | 0 1 0 | + | 0 0 1 | + + Also called reset(); use the one that provides better inline + documentation. + */ + void setIdentity() { + this->reset(); + } + + /** Sets Matrix to translate by (dx, dy). + + @param dx horizontal translation + @param dy vertical translation + */ + void setTranslate(float dx, float dy); + + /** Sets Matrix to scale by sx and sy, about a pivot point at (px, py). + The pivot point is unchanged when mapped with Matrix. + + @param sx horizontal scale factor + @param sy vertical scale factor + @param px pivot x + @param py pivot y + */ + void setScale(float sx, float sy, float px, float py); + + /** Sets Matrix to scale by sx and sy about at pivot point at (0, 0). + + @param sx horizontal scale factor + @param sy vertical scale factor + */ + void setScale(float sx, float sy); + + /** Sets Matrix to rotate by degrees about a pivot point at (px, py). + The pivot point is unchanged when mapped with Matrix. + + Positive degrees rotates clockwise. + + @param degrees angle of axes relative to upright axes + @param px pivot x + @param py pivot y + */ + void setRotate(float degrees, float px, float py); + + /** Sets Matrix to rotate by degrees about a pivot point at (0, 0). + Positive degrees rotates clockwise. + + @param degrees angle of axes relative to upright axes + */ + void setRotate(float degrees); + + /** Sets Matrix to rotate by sinValue and cosValue, about a pivot point at (px, py). + The pivot point is unchanged when mapped with Matrix. + + Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1). + Vector length specifies scale. + + @param sinValue rotation vector x-axis component + @param cosValue rotation vector y-axis component + @param px pivot x-axis + @param py pivot y-axis + */ + void setSinCos(float sinValue, float cosValue, float px, float py); + + /** Sets Matrix to rotate by sinValue and cosValue, about a pivot point at (0, 0). + + Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1). + Vector length specifies scale. + + @param sinValue rotation vector x-axis component + @param cosValue rotation vector y-axis component + */ + void setSinCos(float sinValue, float cosValue); + + /** Sets Matrix to skew by kx and ky, about a pivot point at (px, py). + The pivot point is unchanged when mapped with Matrix. + + @param kx horizontal skew factor + @param ky vertical skew factor + @param px pivot x + @param py pivot y + */ + void setSkew(float kx, float ky, float px, float py); + + /** Sets Matrix to skew by kx and ky, about a pivot point at (0, 0). + + @param kx horizontal skew factor + @param ky vertical skew factor + */ + void setSkew(float kx, float ky); + + /** Sets Matrix to Matrix a multiplied by Matrix b. Either a or b may be this. + + Given: + + | A B C | | J K L | + a = | D E F |, b = | M N O | + | G H I | | P Q R | + + sets Matrix to: + + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | + a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | + + @param a Matrix on left side of multiply expression + @param b Matrix on right side of multiply expression + */ + void setConcat(const Matrix& a, const Matrix& b); + + /** Sets Matrix to Matrix multiplied by Matrix constructed from translation (dx, dy). + This can be thought of as moving the point to be mapped before applying Matrix. + + Given: + + | A B C | | 1 0 dx | + Matrix = | D E F |, T(dx, dy) = | 0 1 dy | + | G H I | | 0 0 1 | + + sets Matrix to: + + | A B C | | 1 0 dx | | A B A*dx+B*dy+C | + Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F | + | G H I | | 0 0 1 | | G H G*dx+H*dy+I | + + @param dx x-axis translation before applying Matrix + @param dy y-axis translation before applying Matrix + */ + void preTranslate(float dx, float dy); + + /** Sets Matrix to Matrix multiplied by Matrix constructed from scaling by (sx, sy) + about pivot point (px, py). + This can be thought of as scaling about a pivot point before applying Matrix. + + Given: + + | A B C | | sx 0 dx | + Matrix = | D E F |, S(sx, sy, px, py) = | 0 sy dy | + | G H I | | 0 0 1 | + + where + + dx = px - sx * px + dy = py - sy * py + + sets Matrix to: + + | A B C | | sx 0 dx | | A*sx B*sy A*dx+B*dy+C | + Matrix * S(sx, sy, px, py) = | D E F | | 0 sy dy | = | D*sx E*sy D*dx+E*dy+F | + | G H I | | 0 0 1 | | G*sx H*sy G*dx+H*dy+I | + + @param sx horizontal scale factor + @param sy vertical scale factor + @param px pivot x + @param py pivot y + */ + void preScale(float sx, float sy, float px, float py); + + /** Sets Matrix to Matrix multiplied by Matrix constructed from scaling by (sx, sy) + about pivot point (0, 0). + This can be thought of as scaling about the origin before applying Matrix. + + Given: + + | A B C | | sx 0 0 | + Matrix = | D E F |, S(sx, sy) = | 0 sy 0 | + | G H I | | 0 0 1 | + + sets Matrix to: + + | A B C | | sx 0 0 | | A*sx B*sy C | + Matrix * S(sx, sy) = | D E F | | 0 sy 0 | = | D*sx E*sy F | + | G H I | | 0 0 1 | | G*sx H*sy I | + + @param sx horizontal scale factor + @param sy vertical scale factor + */ + void preScale(float sx, float sy); + + /** Sets Matrix to Matrix multiplied by Matrix constructed from rotating by degrees + about pivot point (px, py). + This can be thought of as rotating about a pivot point before applying Matrix. + + Positive degrees rotates clockwise. + + Given: + + | A B C | | c -s dx | + Matrix = | D E F |, R(degrees, px, py) = | s c dy | + | G H I | | 0 0 1 | + + where + + c = cos(degrees) + s = sin(degrees) + dx = s * py + (1 - c) * px + dy = -s * px + (1 - c) * py + + sets Matrix to: + + | A B C | | c -s dx | | Ac+Bs -As+Bc A*dx+B*dy+C | + Matrix * R(degrees, px, py) = | D E F | | s c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F | + | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc G*dx+H*dy+I | + + @param degrees angle of axes relative to upright axes + @param px pivot x + @param py pivot y + */ + void preRotate(float degrees, float px, float py); + + /** Sets Matrix to Matrix multiplied by Matrix constructed from rotating by degrees + about pivot point (0, 0). + This can be thought of as rotating about the origin before applying Matrix. + + Positive degrees rotates clockwise. + + Given: + + | A B C | | c -s 0 | + Matrix = | D E F |, R(degrees, px, py) = | s c 0 | + | G H I | | 0 0 1 | + + where + + c = cos(degrees) + s = sin(degrees) + + sets Matrix to: + + | A B C | | c -s 0 | | Ac+Bs -As+Bc C | + Matrix * R(degrees, px, py) = | D E F | | s c 0 | = | Dc+Es -Ds+Ec F | + | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc I | + + @param degrees angle of axes relative to upright axes + */ + void preRotate(float degrees); + + /** Sets Matrix to Matrix multiplied by Matrix constructed from skewing by (kx, ky) + about pivot point (px, py). + This can be thought of as skewing about a pivot point before applying Matrix. + + Given: + + | A B C | | 1 kx dx | + Matrix = | D E F |, K(kx, ky, px, py) = | ky 1 dy | + | G H I | | 0 0 1 | + + where + + dx = -kx * py + dy = -ky * px + + sets Matrix to: + + | A B C | | 1 kx dx | | A+B*ky A*kx+B A*dx+B*dy+C | + Matrix * K(kx, ky, px, py) = | D E F | | ky 1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F | + | G H I | | 0 0 1 | | G+H*ky G*kx+H G*dx+H*dy+I | + + @param kx horizontal skew factor + @param ky vertical skew factor + @param px pivot x + @param py pivot y + */ + void preSkew(float kx, float ky, float px, float py); + + /** Sets Matrix to Matrix multiplied by Matrix constructed from skewing by (kx, ky) + about pivot point (0, 0). + This can be thought of as skewing about the origin before applying Matrix. + + Given: + + | A B C | | 1 kx 0 | + Matrix = | D E F |, K(kx, ky) = | ky 1 0 | + | G H I | | 0 0 1 | + + sets Matrix to: + + | A B C | | 1 kx 0 | | A+B*ky A*kx+B C | + Matrix * K(kx, ky) = | D E F | | ky 1 0 | = | D+E*ky D*kx+E F | + | G H I | | 0 0 1 | | G+H*ky G*kx+H I | + + @param kx horizontal skew factor + @param ky vertical skew factor + */ + void preSkew(float kx, float ky); + + /** Sets Matrix to Matrix multiplied by Matrix other. + This can be thought of mapping by other before applying Matrix. + + Given: + + | A B C | | J K L | + Matrix = | D E F |, other = | M N O | + | G H I | | P Q R | + + sets Matrix to: + + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | + Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | + + @param other Matrix on right side of multiply expression + */ + void preConcat(const Matrix& other); + + /** Sets Matrix to Matrix constructed from translation (dx, dy) multiplied by Matrix. + This can be thought of as moving the point to be mapped after applying Matrix. + + Given: + + | J K L | | 1 0 dx | + Matrix = | M N O |, T(dx, dy) = | 0 1 dy | + | P Q R | | 0 0 1 | + + sets Matrix to: + + | 1 0 dx | | J K L | | J+dx*P K+dx*Q L+dx*R | + T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R | + | 0 0 1 | | P Q R | | P Q R | + + @param dx x-axis translation after applying Matrix + @param dy y-axis translation after applying Matrix + */ + void postTranslate(float dx, float dy); + + /** Sets Matrix to Matrix constructed from scaling by (sx, sy) about pivot point + (px, py), multiplied by Matrix. + This can be thought of as scaling about a pivot point after applying Matrix. + + Given: + + | J K L | | sx 0 dx | + Matrix = | M N O |, S(sx, sy, px, py) = | 0 sy dy | + | P Q R | | 0 0 1 | + + where + + dx = px - sx * px + dy = py - sy * py + + sets Matrix to: + + | sx 0 dx | | J K L | | sx*J+dx*P sx*K+dx*Q sx*L+dx+R | + S(sx, sy, px, py) * Matrix = | 0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R | + | 0 0 1 | | P Q R | | P Q R | + + @param sx horizontal scale factor + @param sy vertical scale factor + @param px pivot x + @param py pivot y + */ + void postScale(float sx, float sy, float px, float py); + + /** Sets Matrix to Matrix constructed from scaling by (sx, sy) about pivot point + (0, 0), multiplied by Matrix. + This can be thought of as scaling about the origin after applying Matrix. + + Given: + + | J K L | | sx 0 0 | + Matrix = | M N O |, S(sx, sy) = | 0 sy 0 | + | P Q R | | 0 0 1 | + + sets Matrix to: + + | sx 0 0 | | J K L | | sx*J sx*K sx*L | + S(sx, sy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O | + | 0 0 1 | | P Q R | | P Q R | + + @param sx horizontal scale factor + @param sy vertical scale factor + */ + void postScale(float sx, float sy); + + /** Sets Matrix to Matrix constructed from scaling by (1/divx, 1/divy) about pivot point (px, py), multiplied by + Matrix. + + Returns false if either divx or divy is zero. + + Given: + + | J K L | | sx 0 0 | + Matrix = | M N O |, I(divx, divy) = | 0 sy 0 | + | P Q R | | 0 0 1 | + + where + + sx = 1 / divx + sy = 1 / divy + + sets Matrix to: + + | sx 0 0 | | J K L | | sx*J sx*K sx*L | + I(divx, divy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O | + | 0 0 1 | | P Q R | | P Q R | + + @param divx integer divisor for inverse scale in x + @param divy integer divisor for inverse scale in y + @return true on successful scale + */ + bool postIDiv(int divx, int divy); + + /** Sets Matrix to Matrix constructed from rotating by degrees about pivot point + (px, py), multiplied by Matrix. + This can be thought of as rotating about a pivot point after applying Matrix. + + Positive degrees rotates clockwise. + + Given: + + | J K L | | c -s dx | + Matrix = | M N O |, R(degrees, px, py) = | s c dy | + | P Q R | | 0 0 1 | + + where + + c = cos(degrees) + s = sin(degrees) + dx = s * py + (1 - c) * px + dy = -s * px + (1 - c) * py + + sets Matrix to: + + |c -s dx| |J K L| |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R| + R(degrees, px, py) * Matrix = |s c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R| + |0 0 1| |P Q R| | P Q R| + + @param degrees angle of axes relative to upright axes + @param px pivot x + @param py pivot y + */ + void postRotate(float degrees, float px, float py); + + /** Sets Matrix to Matrix constructed from rotating by degrees about pivot point + (0, 0), multiplied by Matrix. + This can be thought of as rotating about the origin after applying Matrix. + + Positive degrees rotates clockwise. + + Given: + + | J K L | | c -s 0 | + Matrix = | M N O |, R(degrees, px, py) = | s c 0 | + | P Q R | | 0 0 1 | + + where + + c = cos(degrees) + s = sin(degrees) + + sets Matrix to: + + | c -s dx | | J K L | | cJ-sM cK-sN cL-sO | + R(degrees, px, py) * Matrix = | s c dy | | M N O | = | sJ+cM sK+cN sL+cO | + | 0 0 1 | | P Q R | | P Q R | + + @param degrees angle of axes relative to upright axes + */ + void postRotate(float degrees); + + /** Sets Matrix to Matrix constructed from skewing by (kx, ky) about pivot point + (px, py), multiplied by Matrix. + This can be thought of as skewing about a pivot point after applying Matrix. + + Given: + + | J K L | | 1 kx dx | + Matrix = | M N O |, K(kx, ky, px, py) = | ky 1 dy | + | P Q R | | 0 0 1 | + + where + + dx = -kx * py + dy = -ky * px + + sets Matrix to: + + | 1 kx dx| |J K L| |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R| + K(kx, ky, px, py) * Matrix = |ky 1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R| + | 0 0 1| |P Q R| | P Q R| + + @param kx horizontal skew factor + @param ky vertical skew factor + @param px pivot x + @param py pivot y + */ + void postSkew(float kx, float ky, float px, float py); + + /** Sets Matrix to Matrix constructed from skewing by (kx, ky) about pivot point + (0, 0), multiplied by Matrix. + This can be thought of as skewing about the origin after applying Matrix. + + Given: + + | J K L | | 1 kx 0 | + Matrix = | M N O |, K(kx, ky) = | ky 1 0 | + | P Q R | | 0 0 1 | + + sets Matrix to: + + | 1 kx 0 | | J K L | | J+kx*M K+kx*N L+kx*O | + K(kx, ky) * Matrix = | ky 1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O | + | 0 0 1 | | P Q R | | P Q R | + + @param kx horizontal skew factor + @param ky vertical skew factor + */ + void postSkew(float kx, float ky); + + /** Sets Matrix to Matrix other multiplied by Matrix. + This can be thought of mapping by other after applying Matrix. + + Given: + + | J K L | | A B C | + Matrix = | M N O |, other = | D E F | + | P Q R | | G H I | + + sets Matrix to: + + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | + other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | + + @param other Matrix on left side of multiply expression + */ + void postConcat(const Matrix& other); + + /** \enum Matrix::ScaleToFit + ScaleToFit describes how Matrix is constructed to map one Rect to another. + ScaleToFit may allow Matrix to have unequal horizontal and vertical scaling, + or may restrict Matrix to square scaling. If restricted, ScaleToFit specifies + how Matrix maps to the side or center of the destination Rect. + */ + enum ScaleToFit { + kFill_ScaleToFit, //!< scales in x and y to fill destination Rect + kStart_ScaleToFit, //!< scales and aligns to left and top + kCenter_ScaleToFit, //!< scales and aligns to center + kEnd_ScaleToFit, //!< scales and aligns to right and bottom + }; + + /** Sets Matrix to scale and translate src Rect to dst Rect. stf selects whether + mapping completely fills dst or preserves the aspect ratio, and how to align + src within dst. Returns false if src is empty, and sets Matrix to identity. + Returns true if dst is empty, and sets Matrix to: + + | 0 0 0 | + | 0 0 0 | + | 0 0 1 | + + @param src Rect to map from + @param dst Rect to map to + @param stf one of: kFill_ScaleToFit, kStart_ScaleToFit, + kCenter_ScaleToFit, kEnd_ScaleToFit + @return true if Matrix can represent Rect mapping + */ + bool setRectToRect(const Rect& src, const Rect& dst, ScaleToFit stf); + + /** Returns Matrix set to scale and translate src Rect to dst Rect. stf selects + whether mapping completely fills dst or preserves the aspect ratio, and how to + align src within dst. Returns the identity Matrix if src is empty. If dst is + empty, returns Matrix set to: + + | 0 0 0 | + | 0 0 0 | + | 0 0 1 | + + @param src Rect to map from + @param dst Rect to map to + @param stf one of: kFill_ScaleToFit, kStart_ScaleToFit, + kCenter_ScaleToFit, kEnd_ScaleToFit + @return Matrix mapping src to dst + */ + static Matrix MakeRectToRect(const Rect& src, const Rect& dst, ScaleToFit stf) { + Matrix m; + m.setRectToRect(src, dst, stf); + return m; + } + + /** Sets Matrix to map src to dst. count must be zero or greater, and four or less. + + If count is zero, sets Matrix to identity and returns true. + If count is one, sets Matrix to translate and returns true. + If count is two or more, sets Matrix to map Point if possible; returns false + if Matrix cannot be constructed. If count is four, Matrix may include + perspective. + + @param src Point to map from + @param dst Point to map to + @param count number of Point in src and dst + @return true if Matrix was constructed successfully + */ + bool setPolyToPoly(const Point src[], const Point dst[], int count); + + /** Sets inverse to reciprocal matrix, returning true if Matrix can be inverted. + Geometrically, if Matrix maps from source to destination, inverse Matrix + maps from destination to source. If Matrix can not be inverted, inverse is + unchanged. + + @param inverse storage for inverted Matrix; may be nullptr + @return true if Matrix can be inverted + */ + bool invert(Matrix* inverse) const { + // Allow the trivial case to be inlined. + if (this->isIdentity()) { + if (inverse) { + inverse->reset(); + } + return true; + } + return this->invertNonIdentity(inverse); + } + + /** Fills affine with identity values in column major order. + Sets affine to: + + | 1 0 0 | + | 0 1 0 | + + Affine 3x2 matrices in column major order are used by OpenGL and XPS. + + @param affine storage for 3x2 affine matrix + */ + static void SetAffineIdentity(float affine[6]); + + /** Fills affine in column major order. Sets affine to: + + | scale-x skew-x translate-x | + | skew-y scale-y translate-y | + + If Matrix contains perspective, returns false and leaves affine unchanged. + + @param affine storage for 3x2 affine matrix; may be nullptr + @return true if Matrix does not contain perspective + */ + bool asAffine(float affine[6]) const; + + /** Sets Matrix to affine values, passed in column major order. Given affine, + column, then row, as: + + | scale-x skew-x translate-x | + | skew-y scale-y translate-y | + + Matrix is set, row, then column, to: + + | scale-x skew-x translate-x | + | skew-y scale-y translate-y | + | 0 0 1 | + + @param affine 3x2 affine matrix + */ + void setAffine(const float affine[6]); + + /** Maps src Point array of length count to dst Point array of equal or greater + length. Point are mapped by multiplying each Point by Matrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + where + + for (i = 0; i < count; ++i) { + x = src[i].fX + y = src[i].fY + } + + each dst Point is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + src and dst may point to the same storage. + + @param dst storage for mapped Point + @param src Point to transform + @param count number of Point to transform + */ + void mapPoints(Point dst[], const Point src[], int count) const { + MNN_ASSERT((dst && src && count > 0) || 0 == count); + // no partial overlap + MNN_ASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]); + this->getMapPtsProc()(*this, dst, src, count); + } + + /** Maps pts Point array of length count in place. Point are mapped by multiplying + each Point by Matrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + where + + for (i = 0; i < count; ++i) { + x = pts[i].fX + y = pts[i].fY + } + + each resulting pts Point is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param pts storage for mapped Point + @param count number of Point to transform + */ + void mapPoints(Point pts[], int count) const { + this->mapPoints(pts, pts, count); + } + + /** Maps Point (x, y) to result. Point is mapped by multiplying by Matrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + result is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param x x-axis value of Point to map + @param y y-axis value of Point to map + @param result storage for mapped Point + */ + void mapXY(float x, float y, Point* result) const { + this->getMapXYProc()(*this, x, y, result); + } + + /** Returns Point (x, y) multiplied by Matrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + result is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param x x-axis value of Point to map + @param y y-axis value of Point to map + @return mapped Point + */ + Point mapXY(float x, float y) const { + Point result; + this->getMapXYProc()(*this, x, y, &result); + return result; + } + + /** Sets dst to bounds of src corners mapped by Matrix. + Returns true if mapped corners are dst corners. + + Returned value is the same as calling rectStaysRect(). + + @param dst storage for bounds of mapped Point + @param src Rect to map + @return true if dst is equivalent to mapped src + */ + bool mapRect(Rect* dst, const Rect& src) const; + + /** Sets rect to bounds of rect corners mapped by Matrix. + Returns true if mapped corners are computed rect corners. + + Returned value is the same as calling rectStaysRect(). + + @param rect rectangle to map, and storage for bounds of mapped corners + @return true if result is equivalent to mapped src + */ + bool mapRect(Rect* rect) const { + return this->mapRect(rect, *rect); + } + + /** Returns bounds of src corners mapped by Matrix. + + @param src rectangle to map + @return mapped bounds + */ + Rect mapRect(const Rect& src) const { + Rect dst; + (void)this->mapRect(&dst, src); + return dst; + } + + /** Sets dst to bounds of src corners mapped by Matrix. If matrix contains + elements other than scale or translate: asserts if SK_DEBUG is defined; + otherwise, results are undefined. + + @param dst storage for bounds of mapped Point + @param src Rect to map + */ + void mapRectScaleTranslate(Rect* dst, const Rect& src) const; + + /** Returns true if Matrix equals m, using an efficient comparison. + + Returns false when the sign of zero values is the different; when one + matrix has positive zero value and the other has negative zero value. + + Returns true even when both Matrix contain NaN. + + NaN never equals any value, including itself. To improve performance, NaN values + are treated as bit patterns that are equal if their bit patterns are equal. + + @param m Matrix to compare + @return true if m and Matrix are represented by identical bit patterns + */ + bool cheapEqualTo(const Matrix& m) const { + return 0 == memcmp(fMat, m.fMat, sizeof(fMat)); + } + + /** Compares a and b; returns true if a and b are numerically equal. Returns true + even if sign of zero values are different. Returns false if either Matrix + contains NaN, even if the other Matrix also contains NaN. + + @param a Matrix to compare + @param b Matrix to compare + @return true if Matrix a and Matrix b are numerically equal + */ + friend MNN_PUBLIC bool operator==(const Matrix& a, const Matrix& b); + + /** Compares a and b; returns true if a and b are not numerically equal. Returns false + even if sign of zero values are different. Returns true if either Matrix + contains NaN, even if the other Matrix also contains NaN. + + @param a Matrix to compare + @param b Matrix to compare + @return true if Matrix a and Matrix b are numerically not equal + */ + friend MNN_PUBLIC bool operator!=(const Matrix& a, const Matrix& b) { + return !(a == b); + } + + /** Writes text representation of Matrix to standard output. Floating point values + are written with limited precision; it may not be possible to reconstruct + original Matrix from output. + */ + void dump() const; + + /** Returns the minimum scaling factor of Matrix by decomposing the scaling and + skewing elements. + Returns -1 if scale factor overflows or Matrix contains perspective. + + @return minimum scale factor + */ + float getMinScale() const; + + /** Returns the maximum scaling factor of Matrix by decomposing the scaling and + skewing elements. + Returns -1 if scale factor overflows or Matrix contains perspective. + + @return maximum scale factor + */ + float getMaxScale() const; + + /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the + maximum scaling factor. Scaling factors are computed by decomposing + the Matrix scaling and skewing elements. + + Returns true if scaleFactors are found; otherwise, returns false and sets + scaleFactors to undefined values. + + @param scaleFactors storage for minimum and maximum scale factors + @return true if scale factors were computed correctly + */ + bool getMinMaxScales(float scaleFactors[2]) const; + + /** Returns reference to const identity Matrix. Returned Matrix is set to: + + | 1 0 0 | + | 0 1 0 | + | 0 0 1 | + + @return const identity Matrix + */ + static const Matrix& I(); + + /** Returns reference to a const Matrix with invalid values. Returned Matrix is set + to: + + | SK_ScalarMax SK_ScalarMax SK_ScalarMax | + | SK_ScalarMax SK_ScalarMax SK_ScalarMax | + | SK_ScalarMax SK_ScalarMax SK_ScalarMax | + + @return const invalid Matrix + */ + static const Matrix& InvalidMatrix(); + + /** Returns Matrix a multiplied by Matrix b. + + Given: + + | A B C | | J K L | + a = | D E F |, b = | M N O | + | G H I | | P Q R | + + sets Matrix to: + + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | + a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | + + @param a Matrix on left side of multiply expression + @param b Matrix on right side of multiply expression + @return Matrix computed from a times b + */ + static Matrix Concat(const Matrix& a, const Matrix& b) { + Matrix result; + result.setConcat(a, b); + return result; + } + + /** Sets internal cache to unknown state. Use to force update after repeated + modifications to Matrix element reference returned by operator[](int index). + */ + void dirtyMatrixTypeCache() { + this->setTypeMask(kUnknown_Mask); + } + + /** Initializes Matrix with scale and translate elements. + + | sx 0 tx | + | 0 sy ty | + | 0 0 1 | + + @param sx horizontal scale factor to store + @param sy vertical scale factor to store + @param tx horizontal translation to store + @param ty vertical translation to store + */ + void setScaleTranslate(float sx, float sy, float tx, float ty) { + fMat[kMScaleX] = sx; + fMat[kMSkewX] = 0; + fMat[kMTransX] = tx; + + fMat[kMSkewY] = 0; + fMat[kMScaleY] = sy; + fMat[kMTransY] = ty; + + fMat[kMPersp0] = 0; + fMat[kMPersp1] = 0; + fMat[kMPersp2] = 1; + + unsigned mask = 0; + if (sx != 1 || sy != 1) { + mask |= kScale_Mask; + } + if (tx || ty) { + mask |= kTranslate_Mask; + } + this->setTypeMask(mask | kRectStaysRect_Mask); + } + + /** Returns true if all elements of the matrix are finite. Returns false if any + element is infinity, or NaN. + + @return true if matrix has only finite elements + */ + +private: + /** Set if the matrix will map a rectangle to another rectangle. This + can be true if the matrix is scale-only, or rotates a multiple of + 90 degrees. + + This bit will be set on identity matrices + */ + static constexpr int kRectStaysRect_Mask = 0x10; + + /** Set if the perspective bit is valid even though the rest of + the matrix is Unknown. + */ + static constexpr int kOnlyPerspectiveValid_Mask = 0x40; + + static constexpr int kUnknown_Mask = 0x80; + + static constexpr int kORableMasks = kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask; + + static constexpr int kAllMasks = + kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask | kRectStaysRect_Mask; + + float fMat[9]; + mutable uint32_t fTypeMask; + + static void ComputeInv(float dst[9], const float src[9], double invDet, bool isPersp); + + uint8_t computeTypeMask() const; + uint8_t computePerspectiveTypeMask() const; + + void setTypeMask(int mask) { + // allow kUnknown or a valid mask + MNN_ASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask || + ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask) == + (kUnknown_Mask | kOnlyPerspectiveValid_Mask)); + fTypeMask = (uint8_t)(mask); + } + + void orTypeMask(int mask) { + MNN_ASSERT((mask & kORableMasks) == mask); + fTypeMask = (uint8_t)(fTypeMask | mask); + } + + void clearTypeMask(int mask) { + // only allow a valid mask + MNN_ASSERT((mask & kAllMasks) == mask); + fTypeMask = fTypeMask & ~mask; + } + + TypeMask getPerspectiveTypeMaskOnly() const { + if ((fTypeMask & kUnknown_Mask) && !(fTypeMask & kOnlyPerspectiveValid_Mask)) { + fTypeMask = this->computePerspectiveTypeMask(); + } + return (TypeMask)(fTypeMask & 0xF); + } + + /** Returns true if we already know that the matrix is identity; + false otherwise. + */ + bool isTriviallyIdentity() const { + if (fTypeMask & kUnknown_Mask) { + return false; + } + return ((fTypeMask & 0xF) == 0); + } + + inline void updateTranslateMask() { + if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) { + fTypeMask |= kTranslate_Mask; + } else { + fTypeMask &= ~kTranslate_Mask; + } + } + + typedef void (*MapXYProc)(const Matrix& mat, float x, float y, Point* result); + + static MapXYProc GetMapXYProc(TypeMask mask) { + MNN_ASSERT((mask & ~kAllMasks) == 0); + return gMapXYProcs[mask & kAllMasks]; + } + + MapXYProc getMapXYProc() const { + return GetMapXYProc(this->getType()); + } + + typedef void (*MapPtsProc)(const Matrix& mat, Point dst[], const Point src[], int count); + + static MapPtsProc GetMapPtsProc(TypeMask mask) { + MNN_ASSERT((mask & ~kAllMasks) == 0); + return gMapPtsProcs[mask & kAllMasks]; + } + + MapPtsProc getMapPtsProc() const { + return GetMapPtsProc(this->getType()); + } + + bool invertNonIdentity(Matrix* inverse) const; + + static void Identity_xy(const Matrix&, float, float, Point*); + static void Trans_xy(const Matrix&, float, float, Point*); + static void Scale_xy(const Matrix&, float, float, Point*); + static void ScaleTrans_xy(const Matrix&, float, float, Point*); + static void Rot_xy(const Matrix&, float, float, Point*); + static void RotTrans_xy(const Matrix&, float, float, Point*); + static void Persp_xy(const Matrix&, float, float, Point*); + + static const MapXYProc gMapXYProcs[]; + + static void Identity_pts(const Matrix&, Point[], const Point[], int); + static void Trans_pts(const Matrix&, Point dst[], const Point[], int); + static void Scale_pts(const Matrix&, Point dst[], const Point[], int); + static void ScaleTrans_pts(const Matrix&, Point dst[], const Point[], int count); + static void Persp_pts(const Matrix&, Point dst[], const Point[], int); + + static void Affine_vpts(const Matrix&, Point dst[], const Point[], int); + + static const MapPtsProc gMapPtsProcs[]; + static bool Poly2Proc(const Point srcPt[], Matrix* dst); + static bool Poly3Proc(const Point srcPt[], Matrix* dst); + static bool Poly4Proc(const Point srcPt[], Matrix* dst); +}; +} // namespace CV +} // namespace MNN +#endif diff --git a/3rd/win/mnn/include/MNN/Rect.h b/3rd/win/mnn/include/MNN/Rect.h new file mode 100644 index 0000000..91c4950 --- /dev/null +++ b/3rd/win/mnn/include/MNN/Rect.h @@ -0,0 +1,580 @@ +// +// Rect.h +// MNN +// +// Modified by jiangxiaotang on 2018/09/19. +// Copyright © 2018, Alibaba Group Holding Limited +// + +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Generated by tools/bookmaker from include/core/Rect.h and docs/SkRect_Reference.bmh + on 2018-07-13 08:15:11. Additional documentation and examples can be found at: + https://skia.org/user/api/SkRect_Reference + + You may edit either file directly. Structural changes to public interfaces require + editing both files. After editing docs/SkRect_Reference.bmh, run: + bookmaker -b docs -i include/core/Rect.h -p + to create an updated version of this file. + */ + +#ifndef SkRect_DEFINED +#define SkRect_DEFINED + +#include +#include +#include +#include + +namespace MNN { +namespace CV { + +struct Point { + float fX; + float fY; + + void set(float x, float y) { + fX = x; + fY = y; + } +}; + +/** \struct Rect + Rect holds four float coordinates describing the upper and + lower bounds of a rectangle. Rect may be created from outer bounds or + from position, width, and height. Rect describes an area; if its right + is less than or equal to its left, or if its bottom is less than or equal to + its top, it is considered empty. +*/ +struct MNN_PUBLIC Rect { + float fLeft; //!< smaller x-axis bounds + float fTop; //!< smaller y-axis bounds + float fRight; //!< larger x-axis bounds + float fBottom; //!< larger y-axis bounds + + /** Returns constructed Rect set to (0, 0, 0, 0). + Many other rectangles are empty; if left is equal to or greater than right, + or if top is equal to or greater than bottom. Setting all members to zero + is a convenience, but does not designate a special empty rectangle. + + @return bounds (0, 0, 0, 0) + */ + static constexpr Rect MakeEmpty() { + return Rect{0, 0, 0, 0}; + } + +#ifdef SK_SUPPORT_LEGACY_RECTMAKELARGEST + /** Deprecated. + */ + static Rect MakeLargest() { + return {SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax}; + } +#endif + + /** Returns constructed Rect set to float values (0, 0, w, h). Does not + validate input; w or h may be negative. + + Passing integer values may generate a compiler warning since Rect cannot + represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle. + + @param w float width of constructed Rect + @param h float height of constructed Rect + @return bounds (0, 0, w, h) + */ + static constexpr Rect MakeWH(float w, float h) { + return Rect{0, 0, w, h}; + } + + /** Returns constructed Rect set to integer values (0, 0, w, h). Does not validate + input; w or h may be negative. + + Use to avoid a compiler warning that input may lose precision when stored. + Use SkIRect for an exact integer rectangle. + + @param w integer width of constructed Rect + @param h integer height of constructed Rect + @return bounds (0, 0, w, h) + */ + static Rect MakeIWH(int w, int h) { + Rect r; + r.set(0, 0, (float)(w), (float)(h)); + return r; + } + + /** Returns constructed Rect set to (l, t, r, b). Does not sort input; Rect may + result in fLeft greater than fRight, or fTop greater than fBottom. + + @param l float stored in fLeft + @param t float stored in fTop + @param r float stored in fRight + @param b float stored in fBottom + @return bounds (l, t, r, b) + */ + static constexpr Rect MakeLTRB(float l, float t, float r, float b) { + return Rect{l, t, r, b}; + } + + /** Returns constructed Rect set to (x, y, x + w, y + h). Does not validate input; + w or h may be negative. + + @param x stored in fLeft + @param y stored in fTop + @param w added to x and stored in fRight + @param h added to y and stored in fBottom + @return bounds at (x, y) with width w and height h + */ + static constexpr Rect MakeXYWH(float x, float y, float w, float h) { + return Rect{x, y, x + w, y + h}; + } + + /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal + to or greater than fBottom. Call sort() to reverse rectangles with negative + width() or height(). + + @return true if width() or height() are zero or negative + */ + bool isEmpty() const { + // We write it as the NOT of a non-empty rect, so we will return true if any values + // are NaN. + return !(fLeft < fRight && fTop < fBottom); + } + + /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal + to or less than fBottom. Call sort() to reverse rectangles with negative + width() or height(). + + @return true if width() or height() are zero or positive + */ + bool isSorted() const { + return fLeft <= fRight && fTop <= fBottom; + } + + /** Returns left edge of Rect, if sorted. Call isSorted() to see if Rect is valid. + Call sort() to reverse fLeft and fRight if needed. + + @return fLeft + */ + float x() const { + return fLeft; + } + + /** Returns top edge of Rect, if sorted. Call isEmpty() to see if Rect may be invalid, + and sort() to reverse fTop and fBottom if needed. + + @return fTop + */ + float y() const { + return fTop; + } + + /** Returns left edge of Rect, if sorted. Call isSorted() to see if Rect is valid. + Call sort() to reverse fLeft and fRight if needed. + + @return fLeft + */ + float left() const { + return fLeft; + } + + /** Returns top edge of Rect, if sorted. Call isEmpty() to see if Rect may be invalid, + and sort() to reverse fTop and fBottom if needed. + + @return fTop + */ + float top() const { + return fTop; + } + + /** Returns right edge of Rect, if sorted. Call isSorted() to see if Rect is valid. + Call sort() to reverse fLeft and fRight if needed. + + @return fRight + */ + float right() const { + return fRight; + } + + /** Returns bottom edge of Rect, if sorted. Call isEmpty() to see if Rect may be invalid, + and sort() to reverse fTop and fBottom if needed. + + @return fBottom + */ + float bottom() const { + return fBottom; + } + + /** Returns span on the x-axis. This does not check if Rect is sorted, or if + result fits in 32-bit float; result may be negative or infinity. + + @return fRight minus fLeft + */ + float width() const { + return fRight - fLeft; + } + + /** Returns span on the y-axis. This does not check if Rect is sorted, or if + result fits in 32-bit float; result may be negative or infinity. + + @return fBottom minus fTop + */ + float height() const { + return fBottom - fTop; + } + + /** Returns average of left edge and right edge. Result does not change if Rect + is sorted. Result may overflow to infinity if Rect is far from the origin. + + @return midpoint in x + */ + float centerX() const { + // don't use floatHalf(fLeft + fBottom) as that might overflow before the 0.5 + return 0.5f * (fLeft) + 0.5f * (fRight); + } + + /** Returns average of top edge and bottom edge. Result does not change if Rect + is sorted. + + @return midpoint in y + */ + float centerY() const { + // don't use floatHalf(fTop + fBottom) as that might overflow before the 0.5 + return 0.5f * (fTop) + 0.5f * (fBottom); + } + + /** Sets Rect to (0, 0, 0, 0). + + Many other rectangles are empty; if left is equal to or greater than right, + or if top is equal to or greater than bottom. Setting all members to zero + is a convenience, but does not designate a special empty rectangle. + */ + void setEmpty() { + *this = MakeEmpty(); + } + + /** Sets Rect to (left, top, right, bottom). + left and right are not sorted; left is not necessarily less than right. + top and bottom are not sorted; top is not necessarily less than bottom. + + @param left stored in fLeft + @param top stored in fTop + @param right stored in fRight + @param bottom stored in fBottom + */ + void set(float left, float top, float right, float bottom) { + fLeft = left; + fTop = top; + fRight = right; + fBottom = bottom; + } + + /** Sets Rect to (left, top, right, bottom). + left and right are not sorted; left is not necessarily less than right. + top and bottom are not sorted; top is not necessarily less than bottom. + + @param left stored in fLeft + @param top stored in fTop + @param right stored in fRight + @param bottom stored in fBottom + */ + void setLTRB(float left, float top, float right, float bottom) { + this->set(left, top, right, bottom); + } + + /** Sets Rect to (left, top, right, bottom). + All parameters are promoted from integer to scalar. + left and right are not sorted; left is not necessarily less than right. + top and bottom are not sorted; top is not necessarily less than bottom. + + @param left promoted to float and stored in fLeft + @param top promoted to float and stored in fTop + @param right promoted to float and stored in fRight + @param bottom promoted to float and stored in fBottom + */ + void iset(int left, int top, int right, int bottom) { + fLeft = (float)(left); + fTop = (float)(top); + fRight = (float)(right); + fBottom = (float)(bottom); + } + + /** Sets Rect to (0, 0, width, height). + width and height may be zero or negative. width and height are promoted from + integer to float, large values may lose precision. + + @param width promoted to float and stored in fRight + @param height promoted to float and stored in fBottom + */ + void isetWH(int width, int height) { + fLeft = fTop = 0; + fRight = (float)(width); + fBottom = (float)(height); + } + + /** Sets Rect to (x, y, x + width, y + height). Does not validate input; + width or height may be negative. + + @param x stored in fLeft + @param y stored in fTop + @param width added to x and stored in fRight + @param height added to y and stored in fBottom + */ + void setXYWH(float x, float y, float width, float height) { + fLeft = x; + fTop = y; + fRight = x + width; + fBottom = y + height; + } + + /** Sets Rect to (0, 0, width, height). Does not validate input; + width or height may be negative. + + @param width stored in fRight + @param height stored in fBottom + */ + void setWH(float width, float height) { + fLeft = 0; + fTop = 0; + fRight = width; + fBottom = height; + } + + /** Returns Rect offset by (dx, dy). + + If dx is negative, Rect returned is moved to the left. + If dx is positive, Rect returned is moved to the right. + If dy is negative, Rect returned is moved upward. + If dy is positive, Rect returned is moved downward. + + @param dx added to fLeft and fRight + @param dy added to fTop and fBottom + @return Rect offset on axes, with original width and height + */ + Rect makeOffset(float dx, float dy) const { + return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy); + } + + /** Returns Rect, inset by (dx, dy). + + If dx is negative, Rect returned is wider. + If dx is positive, Rect returned is narrower. + If dy is negative, Rect returned is taller. + If dy is positive, Rect returned is shorter. + + @param dx added to fLeft and subtracted from fRight + @param dy added to fTop and subtracted from fBottom + @return Rect inset symmetrically left and right, top and bottom + */ + Rect makeInset(float dx, float dy) const { + return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy); + } + + /** Returns Rect, outset by (dx, dy). + + If dx is negative, Rect returned is narrower. + If dx is positive, Rect returned is wider. + If dy is negative, Rect returned is shorter. + If dy is positive, Rect returned is taller. + + @param dx subtracted to fLeft and added from fRight + @param dy subtracted to fTop and added from fBottom + @return Rect outset symmetrically left and right, top and bottom + */ + Rect makeOutset(float dx, float dy) const { + return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy); + } + + /** Offsets Rect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom. + + If dx is negative, moves Rect to the left. + If dx is positive, moves Rect to the right. + If dy is negative, moves Rect upward. + If dy is positive, moves Rect downward. + + @param dx offset added to fLeft and fRight + @param dy offset added to fTop and fBottom + */ + void offset(float dx, float dy) { + fLeft += dx; + fTop += dy; + fRight += dx; + fBottom += dy; + } + + /** Offsets Rect so that fLeft equals newX, and fTop equals newY. width and height + are unchanged. + + @param newX stored in fLeft, preserving width() + @param newY stored in fTop, preserving height() + */ + void offsetTo(float newX, float newY) { + fRight += newX - fLeft; + fBottom += newY - fTop; + fLeft = newX; + fTop = newY; + } + + /** Insets Rect by (dx, dy). + + If dx is positive, makes Rect narrower. + If dx is negative, makes Rect wider. + If dy is positive, makes Rect shorter. + If dy is negative, makes Rect taller. + + @param dx added to fLeft and subtracted from fRight + @param dy added to fTop and subtracted from fBottom + */ + void inset(float dx, float dy) { + fLeft += dx; + fTop += dy; + fRight -= dx; + fBottom -= dy; + } + + /** Outsets Rect by (dx, dy). + + If dx is positive, makes Rect wider. + If dx is negative, makes Rect narrower. + If dy is positive, makes Rect taller. + If dy is negative, makes Rect shorter. + + @param dx subtracted to fLeft and added from fRight + @param dy subtracted to fTop and added from fBottom + */ + void outset(float dx, float dy) { + this->inset(-dx, -dy); + } + +private: + static bool Intersects(float al, float at, float ar, float ab, float bl, float bt, float br, float bb) { + float L = std::max(al, bl); + float R = std::min(ar, br); + float T = std::max(at, bt); + float B = std::min(ab, bb); + return L < R && T < B; + } + +public: + /** Constructs Rect to intersect from (left, top, right, bottom). Does not sort + construction. + + Returns true if Rect intersects construction. + Returns false if either construction or Rect is empty, or do not intersect. + + @param left x-axis minimum of constructed Rect + @param top y-axis minimum of constructed Rect + @param right x-axis maximum of constructed Rect + @param bottom y-axis maximum of constructed Rect + @return true if construction and Rect have area in common + */ + bool intersects(float left, float top, float right, float bottom) const { + return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom); + } + + /** Returns true if Rect intersects r. + Returns false if either r or Rect is empty, or do not intersect. + + @param r Rect to intersect + @return true if r and Rect have area in common + */ + bool intersects(const Rect& r) const { + return Intersects(fLeft, fTop, fRight, fBottom, r.fLeft, r.fTop, r.fRight, r.fBottom); + } + + /** Returns true if a intersects b. + Returns false if either a or b is empty, or do not intersect. + + @param a Rect to intersect + @param b Rect to intersect + @return true if a and b have area in common + */ + static bool Intersects(const Rect& a, const Rect& b) { + return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom, b.fLeft, b.fTop, b.fRight, b.fBottom); + } + + /** Sets Rect to the union of itself and r. + + Asserts if r is empty and SK_DEBUG is defined. + If Rect is empty, sets Rect to r. + + May produce incorrect results if r is empty. + + @param r expansion Rect + */ + void joinNonEmptyArg(const Rect& r) { + MNN_ASSERT(!r.isEmpty()); + // if we are empty, just assign + if (fLeft >= fRight || fTop >= fBottom) { + *this = r; + } else { + this->joinPossiblyEmptyRect(r); + } + } + + /** Sets Rect to the union of itself and the construction. + + May produce incorrect results if Rect or r is empty. + + @param r expansion Rect + */ + void joinPossiblyEmptyRect(const Rect& r) { + fLeft = std::min(fLeft, r.left()); + fTop = std::min(fTop, r.top()); + fRight = std::max(fRight, r.right()); + fBottom = std::max(fBottom, r.bottom()); + } + + /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom. + Returns false if Rect is empty. + + @param x test Point x-coordinate + @param y test Point y-coordinate + @return true if (x, y) is inside Rect + */ + bool contains(float x, float y) const { + return x >= fLeft && x < fRight && y >= fTop && y < fBottom; + } + + /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps + fTop and fBottom if fTop is greater than fBottom. Result may be empty; + and width() and height() will be zero or positive. + */ + void sort() { + using std::swap; + if (fLeft > fRight) { + swap(fLeft, fRight); + } + + if (fTop > fBottom) { + swap(fTop, fBottom); + } + } + + /** Returns Rect with fLeft and fRight swapped if fLeft is greater than fRight; and + with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty; + and width() and height() will be zero or positive. + + @return sorted Rect + */ + Rect makeSorted() const { + return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom), std::max(fLeft, fRight), + std::max(fTop, fBottom)); + } + + /** Returns pointer to first scalar in Rect, to treat it as an array with four + entries. + + @return pointer to fLeft + */ + const float* asScalars() const { + return &fLeft; + } +}; + +} // namespace CV +} // namespace MNN +#endif diff --git a/3rd/win/mnn/include/MNN/Tensor.hpp b/3rd/win/mnn/include/MNN/Tensor.hpp new file mode 100644 index 0000000..5819015 --- /dev/null +++ b/3rd/win/mnn/include/MNN/Tensor.hpp @@ -0,0 +1,278 @@ +// +// Tensor.hpp +// MNN +// +// Created by MNN on 2018/08/14. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef Tensor_hpp +#define Tensor_hpp + +#include +#include +#include +#define MNN_MAX_TENSOR_DIM 6 + +namespace MNN { + +/** + * data container. + * data for host tensor is saved in `host` field. its memory is allocated malloc directly. + * data for device tensor is saved in `deviceId` field. its memory is allocated by session's backend. + * usually, device tensors are created by engine (like net, session). + * meanwhile, host tensors could be created by engine or user. + */ +class MNN_PUBLIC Tensor { +public: + struct InsideDescribe; + + /** dimension type used to create tensor */ + enum DimensionType { + /** for tensorflow net type. uses NHWC as data format. */ + TENSORFLOW, + /** for caffe net type. uses NCHW as data format. */ + CAFFE, + /** for caffe net type. uses NC4HW4 as data format. */ + CAFFE_C4 + }; + + /** handle type */ + enum HandleDataType { + /** default handle type */ + HANDLE_NONE = 0, + /** string handle type */ + HANDLE_STRING = 1 + }; + +public: + /** + * @brief create a tensor with dimension size and type without acquire memory for data. + * @param dimSize dimension size. + * @param type dimension type. + */ + Tensor(int dimSize = 4, DimensionType type = CAFFE); + + /** + * @brief create a tensor with same shape as given tensor. + * @param tensor shape provider. + * @param type dimension type. + * @param allocMemory acquire memory for data or not. + * @warning tensor data won't be copied. + */ + Tensor(const Tensor* tensor, DimensionType type = CAFFE, bool allocMemory = true); + + /** deinitializer */ + ~Tensor(); + +private: + // remove all assignment operator + Tensor(const Tensor& tensor) = delete; + Tensor(const Tensor&& tensor) = delete; + Tensor& operator=(const Tensor&) = delete; + Tensor& operator=(const Tensor&&) = delete; + +public: + /** + * @brief create tensor with shape, data type and dimension type. + * @param shape tensor shape. + * @param type data type. + * @param dimType dimension type. + * @return created tensor. + * @warning memory for data won't be acquired. call backend's onAcquireBuffer to get memory ready. + */ + static Tensor* createDevice(const std::vector& shape, halide_type_t type, DimensionType dimType = TENSORFLOW); + + /** + * @brief create tensor with shape and dimension type. data type is represented by `T`. + * @param shape tensor shape. + * @param dimType dimension type. + * @return created tensor. + * @warning memory for data won't be acquired. call backend's onAcquireBuffer to get memory ready. + */ + template + static Tensor* createDevice(const std::vector& shape, DimensionType dimType = TENSORFLOW) { + return createDevice(shape, halide_type_of(), dimType); + } + + /** + * @brief create tensor with shape, data type, data and dimension type. + * @param shape tensor shape. + * @param type data type. + * @param data data to save. + * @param dimType dimension type. + * @return created tensor. + */ + static Tensor* create(const std::vector& shape, halide_type_t type, void* data = NULL, + DimensionType dimType = TENSORFLOW); + + /** + * @brief create tensor with shape, data and dimension type. data type is represented by `T`. + * @param shape tensor shape. + * @param data data to save. + * @param dimType dimension type. + * @return created tensor. + */ + template + static Tensor* create(const std::vector& shape, void* data = NULL, DimensionType dimType = TENSORFLOW) { + return create(shape, halide_type_of(), data, dimType); + } + +public: + /** + * @brief for DEVICE tensor, copy data from given host tensor. + * @param hostTensor host tensor, the data provider. + * @return true for DEVICE tensor, and false for HOST tensor. + */ + bool copyFromHostTensor(const Tensor* hostTensor); + + /** + * @brief for DEVICE tensor, copy data to given host tensor. + * @param hostTensor host tensor, the data consumer. + * @return true for DEVICE tensor, and false for HOST tensor. + */ + bool copyToHostTensor(Tensor* hostTensor) const; + + /** + * @brief create HOST tensor from DEVICE tensor, with or without data copying. + * @param deviceTensor given device tensor. + * @param copyData copy data or not. + * @return created host tensor. + */ + static Tensor* createHostTensorFromDevice(const Tensor* deviceTensor, bool copyData = true); + +public: + const halide_buffer_t& buffer() const { + return mBuffer; + } + halide_buffer_t& buffer() { + return mBuffer; + } + + /** + * @brief get dimension type. + * @return dimension type. + */ + DimensionType getDimensionType() const; + + /** + * @brief handle data type. used when data type code is halide_type_handle. + * @return handle data type. + */ + HandleDataType getHandleDataType() const; + + /** + * @brief set data type. + * @param type data type defined in 'Type_generated.h'. + */ + void setType(int type); + + /** + * @brief get data type. + * @return data type. + */ + inline halide_type_t getType() const { + return mBuffer.type; + } + + /** + * @brief visit host memory, data type is represented by `T`. + * @return data point in `T` type. + */ + template + T* host() const { + return (T*)mBuffer.host; + } + + /** + * @brief visit device memory. + * @return device data ID. what the ID means varies between backends. + */ + uint64_t deviceId() const { + return mBuffer.device; + } + +public: + int dimensions() const { + return mBuffer.dimensions; + } + + /** + * @brief get all dimensions' extent. + * @return dimensions' extent. + */ + std::vector shape() const; + + /** + * @brief calculate number of bytes needed to store data taking reordering flag into account. + * @return bytes needed to store data + */ + int size() const; + + /** + * @brief calculate number of elements needed to store data taking reordering flag into account. + * @return elements needed to store data + */ + inline int elementSize() const { + return size() / mBuffer.type.bytes(); + } + +public: + inline int width() const { + if (getDimensionType() == TENSORFLOW) { + return mBuffer.dim[2].extent; + } + + return mBuffer.dim[3].extent; + } + inline int height() const { + if (getDimensionType() == TENSORFLOW) { + return mBuffer.dim[1].extent; + } + return mBuffer.dim[2].extent; + } + inline int channel() const { + if (getDimensionType() == TENSORFLOW) { + return mBuffer.dim[3].extent; + } + return mBuffer.dim[1].extent; + } + inline int batch() const { + return mBuffer.dim[0].extent; + } + + // visit dimension's extent & stride + inline int stride(int index) const { + return mBuffer.dim[index].stride; + } + inline int length(int index) const { + return mBuffer.dim[index].extent; + } + inline void setStride(int index, int stride) { + mBuffer.dim[index].stride = stride; + } + inline void setLength(int index, int length) { + mBuffer.dim[index].extent = length; + } + +public: + /** + * @brief print tensor data. for DEBUG use only. + */ + void print() const; + + /** + *@brief print tensor shape + */ + void printShape() const; + +private: + halide_buffer_t mBuffer; + struct InsideDescribe* mDescribe; + +private: + friend class TensorUtils; +}; +} // namespace MNN + +#endif /* Tensor_hpp */ diff --git a/3rd/win/mnn/include/MNN/expr/Executor.hpp b/3rd/win/mnn/include/MNN/expr/Executor.hpp new file mode 100644 index 0000000..c3ac7ba --- /dev/null +++ b/3rd/win/mnn/include/MNN/expr/Executor.hpp @@ -0,0 +1,72 @@ +// +// Executor.hpp +// MNN +// +// Created by MNN on 2019/07/25. +// Copyright © 2018, Alibaba Group Holding Limited +// +#ifndef Executor_hpp +#define Executor_hpp +#include +#include +#include +#include +#include +#include +#include +#include +namespace MNN { +class Backend; +class Execution; +class Runtime; +struct Op; +namespace Express { +class MNN_PUBLIC Executor { +public: + class ComputeCache; + struct Unit; + static void setShapeDirty(ComputeCache* cache); + static void setContentDirty(ComputeCache* cache); + static void* mapOutput(ComputeCache* cache, int offset, Tensor* dest); + struct Requirement { + std::vector contentNeedContent; + std::vector shapeNeedContent; + }; + ~Executor(); + Requirement getRequirement(Expr* expr) const; + ErrorCode computeInfo(Expr* expr); + void makeCache(const std::vector& expr, bool forceCPU = false); + ErrorCode runCache(std::shared_ptr cache); + void setGlobalExecutorConfig(MNNForwardType type, const BackendConfig& config, int numberThread); + enum GCFlag { + FULL, + PART + }; + void gc(GCFlag flag = FULL); + static std::shared_ptr getGlobalExecutor(); + + static std::shared_ptr newExecutor(MNNForwardType type, + const BackendConfig& config, + int numberThread); + void resetProfile(); + void dumpProfile(); + void addOpCostTime(int op, float costTime); + void addOpCostTime(const std::string& type, float costTime); + void addOpFlops(const std::string& type, float flops); + class Profiler; + static RuntimeInfo getRuntime(); +private: + void _makeCache(const std::vector& outputs, bool forceCPU); + void _create(const std::vector& outputs, std::set>&& inputCaches, std::set>&& inputNode, bool forceCPU); + + void _visit(EXPRP expr, std::set>& inputCaches, std::set>& inputNode); + + Executor(std::shared_ptr backend, MNNForwardType type); + std::pair, MNNForwardType> mRuntime; + std::pair, MNNForwardType> mBackupRuntime; + std::mutex mMutex; + std::shared_ptr mProfiler; +}; +} // namespace Express +} // namespace MNN +#endif diff --git a/3rd/win/mnn/include/MNN/expr/Expr.hpp b/3rd/win/mnn/include/MNN/expr/Expr.hpp new file mode 100644 index 0000000..5cd0859 --- /dev/null +++ b/3rd/win/mnn/include/MNN/expr/Expr.hpp @@ -0,0 +1,264 @@ +// +// Expr.hpp +// MNN +// +// Created by MNN on 2019/06/10. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef Expr_hpp +#define Expr_hpp + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace MNN { +struct OpT; +struct Op; +struct NetT; +namespace Express { +class Variable; +class Expr; +class Executor; +typedef std::shared_ptr EXPRP; +typedef std::weak_ptr WeakEXPRP; +typedef std::vector INTS; +enum Dimensionformat { NHWC, NC4HW4, NCHW }; +class MNN_PUBLIC VARP { +public: + VARP() { + // Do nothing + } + VARP(std::shared_ptr c) { + mContent = std::move(c); + } + VARP(Variable* c) { + mContent.reset(c); + } + Variable* get() const { + return mContent.get(); + } + ~ VARP() { + // Do nothing + } + VARP(const VARP& var) { + mContent = var.mContent; + } + VARP(VARP&& var) { + mContent = std::move(var.mContent); + } + VARP operator+(VARP var) const; + VARP operator-(VARP var) const; + VARP operator*(VARP var) const; + VARP operator/(VARP var) const; + VARP mean(INTS dims) const; + VARP sum(INTS dims) const; + + bool operator==(const VARP& var) const { + return var.mContent == mContent; + } + bool operator<(const VARP& var) const { + return mContent < var.mContent; + } + bool operator<=(const VARP& var) const { + return mContent <= var.mContent; + } + VARP& operator=(const VARP& var) { + mContent = var.mContent; + return *this; + } + VARP& operator=(Variable* var) { + mContent.reset(var); + return *this; + } + Variable* operator->() const { + return mContent.get(); + } + enum InputType { + INPUT = 0, + CONSTANT = 1, + TRAINABLE = 2, + }; + bool fix(InputType type) const; +private: + friend class Variable; + std::shared_ptr mContent; +}; +inline bool operator==(Variable* src, VARP dst) { + return src == dst.get(); +} +inline bool operator!=(Variable* src, VARP dst) { + return src != dst.get(); +} +// inline bool operator<(VARP src, VARP dst) { +// return src.get() < dst.get(); +// } +typedef std::vector VARPS; + +class MNN_PUBLIC Variable { +public: + struct Info { + Dimensionformat order = NHWC; + INTS dim; + halide_type_t type; + int size; + void syncSize(); + }; + const std::string& name() const; + void setName(const std::string& name); + std::pair expr() const { + return std::make_pair(mFrom, mFromIndex); + } + // If compute info error, return nullptr + const Info* getInfo(); + bool resize(INTS dims); + template + const T* readMap() { + return (const T*)readInternal(); + } + + template + T* writeMap() { + return (T*)writeInternal(); + } + + //Depecerate + void unMap(); + + bool input(VARP src); + static void replace(VARP dst, VARP src); + + static VARP create(EXPRP expr, int index = 0); + + static std::vector load(const char* fileName); + static std::map loadMap(const char* fileName); + static std::vector load(const uint8_t* buffer, size_t length); + static std::map loadMap(const uint8_t* buffer, size_t length); + static std::pair, std::map> getInputAndOutput(const std::map& allVariable); + static std::vector mapToSequence(const std::map& source); + static std::vector getExecuteOrder(const std::vector& output); + static void save(const std::vector& vars, const char* fileName); + static void save(const std::vector& vars, NetT* dest); + + // Pack a few Variable to compute in one pipeline + static void prepareCompute(const std::vector& vars, bool forceCPU = false); + + size_t linkNumber() const; + const std::vector& toExprs() const; + void setExpr(EXPRP expr, int index) { + mFrom = expr; + mFromIndex = index; + } +private: + Variable(EXPRP expr, int index) { + mFrom = expr; + mFromIndex = index; + } + + void* readInternal(bool forShape = false); + void* writeInternal(bool inform=true); + void informDirty(); + + friend class Expr; + EXPRP mFrom; + int mFromIndex; +}; + +class MNN_PUBLIC Expr { +public: + struct Inside; + static EXPRP create(Variable::Info&& info, const void* ptr, VARP::InputType type, bool copy = true); + static EXPRP create(const OpT* op, std::vector inputs, int outputSize = 1); + static EXPRP create(std::pair, int> extra, std::vector&& inputs, int outputSize = 1); + static EXPRP create(std::unique_ptr&& op, std::vector inputs, int outputSize = 1) { + return create(op.get(), inputs, outputSize); + } + void setName(const std::string& name); + + const Op* get() const { + return mOp; + } + const std::vector& inputs() const { + return mInputs; + } + int outputSize() const { + return (int)mOutputNames.size(); + } + static void replace(EXPRP oldExpr, EXPRP newExpr); + bool requireInfo(); + void visitOutputs(const std::function& visit); + static void visit(EXPRP expr, const std::function& before, const std::function& after); + + const std::vector& outputs() const { + return mTo; + } + ~Expr(); + + bool visited() const { + return mVisited; + } + void setVisited(bool visited) { + mVisited = visited; + } + const std::string& name() const { + return mName; + } + const std::string& outputName(int index) { + return mOutputNames[index]; + } + + VARP::InputType inputType() const {return mType;} + Variable::Info* outputInfo(int index) const; + std::pair, int> extra() const { + return std::make_pair(mExtraBuffer, mOpBufferSize); + } + bool setInfoDirty(); + std::shared_ptr inside() const { + return mInside; + } + bool valid() const { + return mValid; + } + + void setEntry(const std::vector& entries) { + mEntries = entries; + } + + const std::vector& getEntry() const { + return mEntries; + } + +private: + static void _addLinkForInputs(EXPRP expr); + + Expr(int outputSize); + + friend class Variable; + friend class VARP; + VARP::InputType mType; + const Op* mOp; + std::vector mInputs; + std::vector mOutputNames; + + bool mValid = true; + std::shared_ptr mExtraBuffer; + int mOpBufferSize = 0; + std::string mName; + std::shared_ptr mInside = nullptr; + bool mVisited = false; + std::vector mTo; + + // Only the enter input has entries, and it helps to get info for enter + // input expression. + std::vector mEntries; +}; +} // namespace Express +} // namespace MNN + +#endif /* Expr_hpp */ diff --git a/3rd/win/mnn/include/MNN/expr/ExprCreator.hpp b/3rd/win/mnn/include/MNN/expr/ExprCreator.hpp new file mode 100644 index 0000000..0a89601 --- /dev/null +++ b/3rd/win/mnn/include/MNN/expr/ExprCreator.hpp @@ -0,0 +1,16 @@ +// +// ExprCreator.hpp +// MNN +// +// Created by MNN on 2019/06/27. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef ExprCreator_hpp +#define ExprCreator_hpp + +#include +#include +#include + +#endif diff --git a/3rd/win/mnn/include/MNN/expr/MathOp.hpp b/3rd/win/mnn/include/MNN/expr/MathOp.hpp new file mode 100644 index 0000000..b8156ed --- /dev/null +++ b/3rd/win/mnn/include/MNN/expr/MathOp.hpp @@ -0,0 +1,128 @@ +// +// MathOp.hpp +// MNN +// +// Created by MNN on 2019/06/27. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef MathOp_HPP +#define MathOp_HPP + +namespace MNN { +namespace Express { +//BinaryOPs +MNN_PUBLIC VARP _Add(VARP x, VARP y); +MNN_PUBLIC VARP _Subtract(VARP x, VARP y); +MNN_PUBLIC VARP _Multiply(VARP x, VARP y); +MNN_PUBLIC VARP _Divide(VARP x, VARP y); +MNN_PUBLIC VARP _Pow(VARP x, VARP y); +MNN_PUBLIC VARP _Minimum(VARP x, VARP y); +MNN_PUBLIC VARP _Maximum(VARP x, VARP y); +MNN_PUBLIC VARP _BiasAdd(VARP value, VARP bias); +MNN_PUBLIC VARP _Greater(VARP x, VARP y); +MNN_PUBLIC VARP _GreaterEqual(VARP x, VARP y); +MNN_PUBLIC VARP _Less(VARP x, VARP y); +MNN_PUBLIC VARP _FloorDiv(VARP x, VARP y); +MNN_PUBLIC VARP _SquaredDifference(VARP x, VARP y); +MNN_PUBLIC VARP _Equal(VARP x, VARP y); +MNN_PUBLIC VARP _LessEqual(VARP x, VARP y); +MNN_PUBLIC VARP _FloorMod(VARP x, VARP y); +MNN_PUBLIC VARP _Atan2(VARP x, VARP y); +MNN_PUBLIC VARP _LogicalOr(VARP x, VARP y); +MNN_PUBLIC VARP _NotEqual(VARP x, VARP y); + +//UnaryOPs +MNN_PUBLIC VARP _Sign(VARP a); +MNN_PUBLIC VARP _Abs(VARP x); +MNN_PUBLIC VARP _Negative(VARP x); +MNN_PUBLIC VARP _Floor(VARP x); +MNN_PUBLIC VARP _Round(VARP x); +MNN_PUBLIC VARP _Ceil(VARP x); +MNN_PUBLIC VARP _Square(VARP x); +MNN_PUBLIC VARP _Sqrt(VARP x); +MNN_PUBLIC VARP _Rsqrt(VARP x); +MNN_PUBLIC VARP _Exp(VARP x); +MNN_PUBLIC VARP _Log(VARP x); +MNN_PUBLIC VARP _Sin(VARP x); +MNN_PUBLIC VARP _Sinh(VARP x); +MNN_PUBLIC VARP _Cos(VARP x); +MNN_PUBLIC VARP _Cosh(VARP x); +MNN_PUBLIC VARP _Tan(VARP x); +MNN_PUBLIC VARP _Asin(VARP x); +MNN_PUBLIC VARP _Asinh(VARP x); +MNN_PUBLIC VARP _Acos(VARP x); +MNN_PUBLIC VARP _Acosh(VARP x); +MNN_PUBLIC VARP _Atan(VARP x); +MNN_PUBLIC VARP _Atanh(VARP x); +MNN_PUBLIC VARP _Reciprocal(VARP x); +MNN_PUBLIC VARP _Log1p(VARP x); +//Only one but not in UnaryOPs +MNN_PUBLIC VARP _Tanh(VARP x); +MNN_PUBLIC VARP _Sigmoid(VARP x); +MNN_PUBLIC VARP _Erf(VARP x); +MNN_PUBLIC VARP _Erfc(VARP x); +MNN_PUBLIC VARP _Erfinv(VARP x); +MNN_PUBLIC VARP _Expm1(VARP x); + + +//ReduceOPs +MNN_PUBLIC VARP _ReduceSum(VARP input_variable, INTS axis = {}, bool keepDims = false); +MNN_PUBLIC VARP _ReduceMean(VARP input_variable, INTS axis = {}, bool keepDims = false); +MNN_PUBLIC VARP _ReduceMax(VARP input_variable, INTS axis = {}, bool keepDims = false); +MNN_PUBLIC VARP _ReduceMin(VARP input_variable, INTS axis = {}, bool keepDims = false); +MNN_PUBLIC VARP _ReduceProd(VARP input_variable, INTS axis = {}, bool keepDims = false); +MNN_PUBLIC VARP _ReduceAny(VARP input_variable, INTS axis = {}, bool keepDims = false); +MNN_PUBLIC VARP _ReduceAll(VARP input_variable, INTS axis = {}, bool keepDims = false); + +MNN_PUBLIC VARP _ReduceSumMutable(VARP input_variable, VARP axis, bool keepDims = false); +MNN_PUBLIC VARP _ReduceMeanMutable(VARP input_variable, VARP axis, bool keepDims = false); +MNN_PUBLIC VARP _ReduceMaxMutable(VARP input_variable, VARP axis, bool keepDims = false); +MNN_PUBLIC VARP _ReduceMinMutable(VARP input_variable, VARP axis, bool keepDims = false); +MNN_PUBLIC VARP _ReduceProdMutable(VARP input_variable, VARP axis, bool keepDims = false); +MNN_PUBLIC VARP _ReduceAnyMutable(VARP input_variable, VARP axis, bool keepDims = false); +MNN_PUBLIC VARP _ReduceAllMutable(VARP input_variable, VARP axis, bool keepDims = false); + +//EltwiseOPs +MNN_PUBLIC VARP _Prod(VARP a, VARP b, std::vector coeff); +MNN_PUBLIC VARP _Sum(VARP a, VARP b, std::vector coeff); +MNN_PUBLIC VARP _Max(VARP a, VARP b, std::vector coeff); +MNN_PUBLIC VARP _Sub(VARP a, VARP b, std::vector coeff); +MNN_PUBLIC VARP _EltwiseProdInt8(VARP x, VARP y, + std::vector x_weight, std::vector x_bias, std::vector x_scale, std::vector x_tensorScale, + std::vector y_weight, std::vector y_bias, std::vector y_scale, std::vector y_tensorScale, + std::vector output_weight, std::vector output_bias, std::vector output_scale, std::vector output_tensorScale); +MNN_PUBLIC VARP _EltwiseSumInt8(VARP x, VARP y, + std::vector x_weight, std::vector x_bias, std::vector x_scale, std::vector x_tensorScale, + std::vector y_weight, std::vector y_bias, std::vector y_scale, std::vector y_tensorScale, + std::vector output_weight, std::vector output_bias, std::vector output_scale, std::vector output_tensorScale); +MNN_PUBLIC VARP _EltwiseSubInt8(VARP x, VARP y, + std::vector x_weight, std::vector x_bias, std::vector x_scale, std::vector x_tensorScale, + std::vector y_weight, std::vector y_bias, std::vector y_scale, std::vector y_tensorScale, + std::vector output_weight, std::vector output_bias, std::vector output_scale, std::vector output_tensorScale); +MNN_PUBLIC VARP _EltwiseMaxInt8(VARP x, VARP y, + std::vector x_weight, std::vector x_bias, std::vector x_scale, std::vector x_tensorScale, + std::vector y_weight, std::vector y_bias, std::vector y_scale, std::vector y_tensorScale, + std::vector output_weight, std::vector output_bias, std::vector output_scale, std::vector output_tensorScale); + + +//OtherOPs +template +VARP _Cast(VARP x) { + return _Cast(x, halide_type_of()); +} +MNN_PUBLIC VARP _Cast(VARP x, halide_type_t dtype); +MNN_PUBLIC VARP _MatMul(VARP a, VARP b, bool tranposeA = false, bool tranposeB = false); +MNN_PUBLIC VARP _Normalize(VARP x, int32_t acrossSpatial, int32_t channelShared, float eps, std::vector scale); +MNN_PUBLIC VARP _ArgMax(VARP input, int axis = 0); +MNN_PUBLIC VARP _ArgMin(VARP input, int axis = 0); +MNN_PUBLIC VARP _BatchMatMul(VARP x, VARP y, bool adj_x = false, bool adj_y = false); +MNN_PUBLIC VARP _UnravelIndex(VARP indices, VARP dims); +MNN_PUBLIC VARP _ScatterNd(VARP indices, VARP updates, VARP shape); +MNN_PUBLIC VARP _OneHot(VARP indices, VARP depth, VARP onValue, VARP offValue, int axis = -1); +MNN_PUBLIC VARP _BroadcastTo(VARP a, VARP shape); +MNN_PUBLIC VARP _LinSpace(VARP start, VARP stop, VARP num); +}; // namespace Express +}; // namespace MNN + +#endif /* MathOp_HPP */ diff --git a/3rd/win/mnn/include/MNN/expr/NeuralNetWorkOp.hpp b/3rd/win/mnn/include/MNN/expr/NeuralNetWorkOp.hpp new file mode 100644 index 0000000..b4cad22 --- /dev/null +++ b/3rd/win/mnn/include/MNN/expr/NeuralNetWorkOp.hpp @@ -0,0 +1,142 @@ +// +// NeuralNetWorkOp.hpp +// MNN +// +// Created by MNN on 2019/06/27. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#ifndef NeuralNetWorkOp_HPP +#define NeuralNetWorkOp_HPP + +namespace MNN { +namespace Express { +enum PaddingMode {CAFFE, VALID, SAME}; +enum PoolingMode {MAXPOOL, AVEPOOL}; +enum PadValueMode {CONSTANT, REFLECT, SYMMETRIC}; +MNN_PUBLIC VARP _Input(INTS shape = {}, Dimensionformat data_format = NC4HW4, halide_type_t dtype = halide_type_of()) ; +MNN_PUBLIC VARP _Clone(VARP source, bool deepCopy = false); + +MNN_PUBLIC VARP _Scalar(const void* ptr, halide_type_t type); + +template +VARP _Scalar(T value) { + return _Scalar(&value, halide_type_of()); +} + + +MNN_PUBLIC VARP _Const(float value, INTS shape = {}, Dimensionformat format = NHWC); +MNN_PUBLIC VARP _Const(const void* ptr, INTS shape = {}, Dimensionformat format = NHWC, + halide_type_t type = halide_type_of()); +MNN_PUBLIC VARP _TrainableParam(float value, INTS dims, Dimensionformat format); +MNN_PUBLIC VARP _TrainableParam(const void* ptr, INTS dims, Dimensionformat format, + halide_type_t type = halide_type_of()); +MNN_PUBLIC VARP _InnerProduct(std::vector&& weight, std::vector&& bias, VARP x, INTS outputShape); +MNN_PUBLIC VARP _Conv(VARP weight, VARP bias, VARP x, PaddingMode pad = VALID, INTS stride = {1, 1}, + INTS dilate = {1, 1}, int group = 1, INTS pads = {0, 0}); + +MNN_PUBLIC VARP _Conv(float weight, float bias, VARP x, INTS channel, INTS kernelSize, PaddingMode pad = VALID, + INTS stride = {1, 1}, INTS dilate = {1, 1}, int group = 1); +MNN_PUBLIC VARP _Conv(std::vector&& weight, std::vector&& bias, VARP x, INTS channel, INTS kernelSize, + PaddingMode pad = VALID, INTS stride = {1, 1}, INTS dilate = {1, 1}, int group = 1, INTS pads = {0, 0}, bool relu = false, bool relu6 = false, int nbits = 8); +MNN_PUBLIC VARP _Conv(std::vector&& weight, std::vector&& bias, VARP x, INTS channel, INTS kernelSize, + PaddingMode pad = VALID, INTS stride = {1, 1}, INTS dilate = {1, 1}, int group = 1, INTS pads = {0, 0}, bool relu = false, bool relu6 = false); +MNN_PUBLIC VARP _Deconv(VARP weight, VARP bias, VARP x, PaddingMode pad = VALID, INTS stride = {1, 1}, + INTS dilate = {1, 1}, int group = 1, INTS pads = {0, 0}); + +MNN_PUBLIC VARP _Deconv(std::vector&& weight, std::vector&& bias, VARP x, INTS channel, INTS kernelSize, +PaddingMode pad, INTS stride = {1, 1}, INTS dilate = {1, 1}, int group = 1, INTS pads = {0, 0}, bool relu = false, bool relu6 = false); + +MNN_PUBLIC VARP _MaxPool(VARP x, INTS kernel, INTS stride = {1, 1}, PaddingMode pad = VALID, INTS pads= {0, 0}); +MNN_PUBLIC VARP _AvePool(VARP x, INTS kernel, INTS stride = {1, 1}, PaddingMode pad = VALID, INTS pads= {0, 0}); +MNN_PUBLIC VARP _Reshape(VARP x, INTS shape, Dimensionformat original_format = NCHW); +MNN_PUBLIC VARP _Reshape(VARP x, VARP shape); +MNN_PUBLIC VARP _Scale(VARP x, int channels, std::vector&& scales, std::vector&& bias); + +MNN_PUBLIC VARP _Relu(VARP x, float slope = 0.0f); +MNN_PUBLIC VARP _Relu6(VARP x, float minValue = 0.0f, float maxValue = 6.0f); +MNN_PUBLIC VARP _PRelu(VARP x, std::vector &&slopes); +MNN_PUBLIC VARP _Softmax(VARP logits, int axis = -1); +MNN_PUBLIC VARP _Softplus(VARP features); +MNN_PUBLIC VARP _Softsign(VARP features); +MNN_PUBLIC std::vector _Split(VARP value, INTS size_splits, int axis = 0); +MNN_PUBLIC VARP _Slice(VARP x, VARP starts, VARP sizes); +MNN_PUBLIC VARP _StridedSlice(VARP input, VARP begin, VARP end, VARP strided, + int32_t beginMask, int32_t endMask, int32_t ellipsisMask, + int32_t newAxisMask, int32_t shrinkAxisMask); +MNN_PUBLIC VARP _Concat(VARPS values, int axis); +MNN_PUBLIC VARP _Convert(VARP input, Dimensionformat format); +MNN_PUBLIC VARP _Transpose(VARP x, INTS perm); +MNN_PUBLIC VARP _Transpose(VARP x, VARP perm); +MNN_PUBLIC VARP _ChannelShuffle(VARP x, int group); +MNN_PUBLIC VARP _ChangeInputFormat(VARP input, Dimensionformat format); +MNN_PUBLIC VARP _Conv2DBackPropFilter(VARP input, VARP inputGrad, INTS kernelSize, PaddingMode pad = VALID, INTS stride = {1, 1}, INTS dilate = {1, 1}, int group = 1, INTS pads = {0, 0}); +MNN_PUBLIC VARP _PoolGrad(VARP originInput, VARP originOutput, VARP inputGrad, INTS kernel, INTS stride, PoolingMode type, PaddingMode pad = VALID, INTS pads= {0, 0}); +// FIXME: move the api to Array Ops +MNN_PUBLIC VARP _ReverseSequence(VARP x, VARP y, int batchDim, int seqDim); +// FIXME: move the api to Image Ops +MNN_PUBLIC VARP _Crop(VARP images, VARP size, int axis, INTS offset); +MNN_PUBLIC VARP _Resize(VARP images, float xScale, float yScale); +MNN_PUBLIC VARP _Pad(VARP x, VARP paddings, PadValueMode mode = CONSTANT); +MNN_PUBLIC VARP _ExpandDims(VARP input, int axis); +MNN_PUBLIC VARP _ExpandDims(VARP input, VARP axis); + +MNN_PUBLIC VARP _Shape(VARP input, bool nchw = false); +MNN_PUBLIC VARP _Stack(VARPS values, int axis=0); +enum InterpolationMethod {BILINEAR, NEAREST}; +MNN_PUBLIC VARP _CropAndResize(VARP image, VARP boxes, VARP box_ind, VARP crop_size, + InterpolationMethod method, float extrapolation_value = 0.0); +MNN_PUBLIC VARP _Fill(VARP dims, VARP value); +MNN_PUBLIC VARP _Tile(VARP input, VARP multiples); +MNN_PUBLIC VARP _Gather(VARP params, VARP indices); +MNN_PUBLIC VARP _GatherV2(VARP params, VARP indices, VARP axis = nullptr); +MNN_PUBLIC VARP _Squeeze(VARP input, INTS axis = {}); +MNN_PUBLIC VARP _Unsqueeze(VARP input, INTS axis = {}); +MNN_PUBLIC VARP _BatchToSpaceND(VARP input, VARP block_shape, VARP crops); +MNN_PUBLIC VARP _GatherND(VARP params, VARP indices); +MNN_PUBLIC VARP _Selu(VARP features, float scale, float alpha); +MNN_PUBLIC VARP _Size(VARP input); +MNN_PUBLIC VARP _Elu(VARP features, float alpha=1.0); +MNN_PUBLIC VARP _Threshold(VARP features, float alpha=1.0); +MNN_PUBLIC VARP _MatrixBandPart(VARP input, VARP num_lower, VARP num_upper); +MNN_PUBLIC std::vector _Moments(VARP x, INTS axis, VARP shift, bool keepDims); +MNN_PUBLIC VARP _SetDiff1D(VARP x, VARP y); +MNN_PUBLIC VARP _SpaceToDepth(VARP input, int block_size); +MNN_PUBLIC VARP _SpaceToBatchND(VARP input, VARP block_shape, VARP paddings); +MNN_PUBLIC VARP _ZerosLike(VARP input); +MNN_PUBLIC std::vector _Unstack(VARP value, int axis=0); +MNN_PUBLIC VARP _Rank(VARP input); +MNN_PUBLIC VARP _Range(VARP start, VARP limit, VARP delta); +MNN_PUBLIC VARP _DepthToSpace(VARP input, int block_size); +MNN_PUBLIC VARP _PriorBox(VARP feature, VARP image, + std::vector min_size, std::vector max_size, std::vectoraspect_ratio, + bool flip, bool clip, std::vectorvariance, + unsigned int img_h, unsigned int img_w, float step_h, float step_w, float offset = 0.5); +MNN_PUBLIC VARP _Permute(VARP input, INTS dims); +MNN_PUBLIC VARP _DetectionOutput(VARP location, VARP confidence, VARP priorbox, + unsigned int num_classes, bool share_location, int background_label_id, + float nms_threshhold, int nms_topk, int code_type, + bool variance_encoded_in_target, + int keep_top_k, float confidence_threshold, float visualize_threshold); +MNN_PUBLIC std::vector _DetectionPostProcess(VARP encode_boxes, VARP class_predictions, VARP anchors, + int num_classes, int max_detections, + int max_class_per_detection, int detections_per_class, + float nms_threshold, float iou_threshold, + bool use_regular_nms, std::vector centersize_encoding); +MNN_PUBLIC VARP _Interp(VARPS xs, float widthScale, float heightScale, int outputWidth, int outputHeight, int resizeType, bool alignCorners); + +MNN_PUBLIC VARP _ZeroGrad(VARP x); + +// Int8 Inference +MNN_PUBLIC VARP _Conv(std::vector&& weight, std::vector&& bias, std::vector&& scale, VARP x, INTS channel, INTS kernelSize, + PaddingMode pad, INTS stride, INTS dilate, int group, INTS pads, bool relu, int nbits = 8); +MNN_PUBLIC VARP _CosineSimilarity(VARP input0, VARP input1, VARP inputDim); +MNN_PUBLIC VARP _FloatToInt8(VARP x, VARP scale, char minValue, char maxValue); +MNN_PUBLIC VARP _Int8ToFloat(VARP x, VARP scale); + +MNN_PUBLIC VARP _Select(VARP select, VARP input0, VARP input1); + +} // namespace Express +} // namespace MNN + +#endif /* NeuralNetWorkOp_HPP */ diff --git a/3rd/win/mnn/include/MNN/expr/Optimizer.hpp b/3rd/win/mnn/include/MNN/expr/Optimizer.hpp new file mode 100644 index 0000000..b1304c8 --- /dev/null +++ b/3rd/win/mnn/include/MNN/expr/Optimizer.hpp @@ -0,0 +1,64 @@ +// +// Optimizer.hpp +// MNN +// +// Created by MNN on 2019/08/20. +// Copyright © 2018, Alibaba Group Holding Limited +// +#ifndef Optimizer_hpp +#define Optimizer_hpp +#include +#include + +namespace MNN { +namespace Express { +class MNN_PUBLIC Optimizer { +public: + enum Device { + CPU = 0, + GPU = 1, + OTHER = 2, + AUTO = 3 + }; + struct Config { + Device device = CPU; + MNNForwardType forwardType = MNN_FORWARD_ALL; + int numThread = 4; + }; + static std::shared_ptr create(Config config); + struct Cost { + float compute; // MFlops + float memory; // MB + }; + class Parameters { + public: + Parameters(int n); + virtual ~Parameters(); + + float* get() const { + return mValue; + } + int size() const { + return mSize; + } + + private: + float* mValue; + int mSize; + }; + virtual std::shared_ptr onGetParameters(const std::vector& outputs) { + return nullptr; + } + + //Given paramters and measure cost, the parameters must be the same as onGetParameters + virtual Cost onMeasure(const std::vector& outputs, std::shared_ptr parameters = nullptr) = 0; + + //Modify the output directly, the parameters must be the same as onGetParameters + virtual bool onExecute(const std::vector& outputs, std::shared_ptr parameters = nullptr) = 0; + + Optimizer() = default; + virtual ~Optimizer() = default; +}; +} // namespace Express +} // namespace MNN +#endif diff --git a/3rd/win/mnn/x64/MNN.lib b/3rd/win/mnn/x64/MNN.lib new file mode 100644 index 0000000..200f30a Binary files /dev/null and b/3rd/win/mnn/x64/MNN.lib differ