#include #include #include "Matrix.hh" namespace qing { template Matrx::Matrx(): row(0), col(0) {} template Matrx::Matrx(const uint64_t row, const uint64_t col) : row(row), col(col) { /* 该构造函数用于从头开始构造 */ arr = std::vector(col * row); } template Matrx::Matrx(const uint64_t row, const uint64_t col, const std::vector& src) : row(row), col(col) { /* 该构造函数用于通过已有的vector进行构造 */ arr = src; } template const T& Matrx::get(uint64_t row, uint64_t col) const { /* 访问器 - 访问矩阵元素 */ return arr[col * this->row + row]; } template T& Matrx::witch(uint64_t row, uint64_t col) { /* 访问器 - 访问矩阵元素 */ return arr[col * this->row + row]; } template void Matrx::set(uint64_t row, uint64_t col, T v) { /* 设置矩阵元素 */ arr[col * this->row + row] = v; } template const std::vector& Matrx::get_data() const{ /* 访问器 - 用于获取原始数据 */ return arr; } template const uint64_t Matrx::get_col() const { /* 获取列数 */ return col; } template const uint64_t Matrx::get_row() const { /* 获取行数 */ return row; } template bool Matrx::has_same_shape(const Matrx& other) { /* 两个矩阵是否具有相同形状 */ return other.get_col() == this->get_col() && other.get_row() == this->get_row(); } template bool Matrx::has_dot_shape(const Matrx& other) { /* 具有矩阵乘法的形状 */ return this->get_col() == other.get_row(); } template void Matrx::assert_same_shape(const Matrx& other) { /* 断言两个矩阵具有相同形状 */ if (!has_same_shape(other)) throw std::invalid_argument("The shapes of matrix are not same."); } template void Matrx::assert_dot_shape(const Matrx& other) { /* 断言两个矩阵具有点积前置形状 */ if (!has_dot_shape(other)) { throw std::invalid_argument("The shapes of matrix can not be dot."); } } template Matrx Matrx::operator+(const Matrx& other) { /* 加法操作符重定义 - 矩阵加法 */ //assert_same_shape(other); /* 检查两个矩阵形状是否一致 */ std::vector v0 = this->get_data(); std::vector vec = other.get_data(); for (auto it = v0.begin(), it_or = vec.begin(); it != v0.end(); ++it, ++it_or ) *it += *it_or; return Matrx{this->get_row(), this->get_col(), v0}; } template Matrx Matrx::operator+(T& item) { /* 矩阵加法广播 */ auto len = this->get_data().size(); auto v0 = std::vector (len, item); auto matrix = (*this) + Matrx(get_row(), get_col(), v0); //auto matrix = *this; //for (auto it = arr.begin(); it != arr.end(); ++it) // *it += item; return matrix; } template Matrx Matrx::operator-(const Matrx& other) { /* 操作符重载 - 矩阵减法 */ //assert_same_shape(other); /* 检查两个矩阵形状是否一致 */ std::vector v0 = this->get_data(); std::vector vec = other.get_data(); for (auto it = v0.begin(), it_or = vec.begin(); it != v0.end(); ++it, ++it_or ) *it -= *it_or; return Matrx{this->get_row(), this->get_col(), v0}; } template Matrx Matrx::operator-(T& item) { /* 操作符重载 - 矩阵减法广播 */ auto len = this->get_data().size(); auto v0 = std::vector (len, item); auto matrix = (*this) - Matrx(get_row(), get_col(), v0); //Matrx matrix = *this; //for (auto it = arr.begin(); it != arr.end(); ++it) // *it -= item; return matrix; } template Matrx Matrx::dot(const Matrx& other) { /* 操作符重载 - 矩阵乘法 */ //assert_dot_shape(other); /* 它们的形状是否能够点积 */ auto matrix = Matrx(this->get_row(), other.get_col()); for (uint64_t i=0; iget_row(); ++i) /* 点积运算 */ for (uint64_t j=0; jget_col(); ++k) sum += this->get(i, k) * other.get(k, j); matrix.witch(i, j) = sum; } return matrix; } template Matrx Matrx::operator*(T& item) { /* 操作符重载 - 矩阵乘法广播 */ std::vector vec = this->get_data(); for (auto it = vec.begin(); it != vec.end(); ++it) *it *= item; return Matrx{this->get_row(), this->get_col(), vec}; } template Matrx Matrx::operator*(const Matrx& other) { /* 加法操作符重定义 - 矩阵加法 */ //assert_same_shape(other); /* 检查两个矩阵形状是否一致 */ std::vector v0 = this->get_data(); std::vector vec = other.get_data(); for (auto it = v0.begin(), it_or = vec.begin(); it != v0.end(); ++it, ++it_or ) *it *= *it_or; return Matrx{this->get_row(), this->get_col(), v0}; } template Matrx Matrx::operator/(T& item) { /* 操作符重载 - 矩阵除法广播 */ std::vector vec = this->get_data(); for (auto it = vec.begin(); it != vec.end(); ++it) *it /= item; return Matrx(this->get_row(), this->get_col(), vec); } template Matrx Matrx::operator/(const Matrx& other) { /* 加法操作符重定义 - 矩阵加法 */ //assert_same_shape(other); /* 检查两个矩阵形状是否一致 */ std::vector v0 = this->get_data(); std::vector vec = other.get_data(); for (auto it = v0.begin(), it_or = vec.begin(); it != v0.end(); ++it, ++it_or ) *it /= *it_or; return Matrx{this->get_row(), this->get_col(), v0}; } template class Matrx; /* 显式实例化 */ template class Matrx; } /* FIXME: 形状不合法时返回空指针 */ using namespace qing; extern "C" { #ifdef _WIN64 _declspec(dllexport) #endif void* createMatrix(uint64_t row, uint64_t col) { return (void *) new Matrx(row, col); } #ifdef _WIN64 _declspec(dllexport) #endif void freeMatrix(void* M) { delete (Matrx*) M; } #ifdef _WIN64 _declspec(dllexport) #endif float* witchMatrix(void *m, uint64_t row, uint64_t col) { Matrx *M = (Matrx*) m; return &(M->witch(row, col)); } #ifdef _WIN64 _declspec(dllexport) #endif float getMatrix(void *m, uint64_t row, uint64_t col) { Matrx *M = (Matrx*) m; return M->get(row, col); } #ifdef _WIN64 _declspec(dllexport) #endif void setMatrix(void *m, uint64_t row, uint64_t col, float v) { Matrx *M = (Matrx*) m; M->set(row, col, v); } #ifdef _WIN64 _declspec(dllexport) #endif uint64_t getrowMatrix(void *m) { Matrx *M = (Matrx*) m; return M->get_row(); } #ifdef _WIN64 _declspec(dllexport) #endif uint64_t getcolMatrix(void *m) { Matrx *M = (Matrx*) m; return M->get_col(); } #ifdef _WIN64 _declspec(dllexport) #endif bool sameShapeMatrix(void *m, void *s) { Matrx *M = (Matrx*) m; Matrx *S = (Matrx*) s; return M->has_same_shape(*S); } #ifdef _WIN64 _declspec(dllexport) #endif bool dotShapeMatrix(void *m, void *s) { Matrx *M = (Matrx*) m; Matrx *S = (Matrx*) s; return M->has_dot_shape(*S); } #ifdef _WIN64 _declspec(dllexport) #endif void* plusMatrix(void *m, void *s) { Matrx *M = (Matrx*) m; Matrx *S = (Matrx*) s; auto a = new Matrx((*M) + (*S)); return (void *) a; } #ifdef _WIN64 _declspec(dllexport) #endif void* plusBroadcastMatrix(void *m, float t) { Matrx *M = (Matrx*) m; auto a = new Matrx ((*M) + t); return (void*) a; } #ifdef _WIN64 _declspec(dllexport) #endif void* subMatrix(void *m, void *s) { Matrx *M = (Matrx*) m; Matrx *S = (Matrx*) s; auto a = new Matrx((*M) - (*S)); return (void *) a; } #ifdef _WIN64 _declspec(dllexport) #endif void * subBroadcastMatrix(void *m, float t) { Matrx *M = (Matrx *) m; auto a = new Matrx ((*M) - t); return (void *) a; } #ifdef _WIN64 _declspec(dllexport) #endif void* multiMatrix(void *m, void *s) { Matrx *M = (Matrx*) m; Matrx *S = (Matrx*) s; auto a = new Matrx((*M) * (*S)); return (void *) a; } #ifdef _WIN64 _declspec(dllexport) #endif void* multiBroadcastMatrix(void *m, float t) { Matrx *M = (Matrx *) m; auto a = new Matrx((*M) * t); return (void*) a; } #ifdef _WIN64 _declspec(dllexport) #endif void* divMatrix(void *m, void *s) { Matrx *M = (Matrx*) m; Matrx *S = (Matrx*) s; auto a = new Matrx((*M) / (*S)); return (void *) a; } #ifdef _WIN64 _declspec(dllexport) #endif void* divBroadcastMatrix(void *m, float t) { Matrx *M = (Matrx *) m; auto a = new Matrx((*M) / t); return (void*) a; } #ifdef _WIN64 _declspec(dllexport) #endif void* dotMatrix(void *m, void *s) { Matrx *M = (Matrx*) m; Matrx *S = (Matrx*) s; auto a = new Matrx(M->dot(*S)); return (void *) a; } #ifdef _WIN64 _declspec(dllexport) #endif void* transposeMatrix(void *m) { Matrx *M = (Matrx *)m; auto N= new Matrx(M->get_col(), M->get_row()); for (uint64_t row = 0; row< N->get_row(); row++) { for (uint64_t col = 0; col < N->get_col(); col++) { N->witch(row, col) = M->get(col, row); } } return (void *)N; } /* 正态分布Xavier初始化 */ #ifdef _WIN64 _declspec(dllexport) #endif void* xavierNormalInit(uint64_t fan_in, uint64_t fan_out) { /* 构建空数组 */ std::vector weights(fan_in * fan_out); /* 高质量的随机数生成器 */ static std::mt19937 generator(std::random_device{}()); /* 计算标准差 */ float sigma = std::sqrt(2.0f / (fan_in + fan_out)); /* 创建正态分布对象,均值为0,标准差为sigma */ std::normal_distribution distribution(0.0f, sigma); /* 遍历权重矩阵,进行赋值 */ uint64_t k=0; for (uint64_t i=0; i(fan_in, fan_out, weights); return (void *)matrix; } /* 均匀分布Xavier初始化函数 */ #ifdef _WIN64 _declspec(dllexport) #endif void* xavierUniformInit(uint64_t fan_in, uint64_t fan_out) { /* 构建空的数组 */ auto weights = std::vector(fan_in * fan_out); /* 使用高质量的随机数生成器 */ static std::mt19937 generator(std::random_device{}()); /* 计算区间范围:sqrt(2 / (fan_in + fan_out)) */ float scale = std::sqrt(2.0f / (fan_in + fan_out)); /* 创建均匀分布对象,范围为[-scale, scale] */ std::uniform_real_distribution distribution(-scale, scale); /* 遍历权重矩阵,进行赋值 */ uint64_t k=0; for (uint64_t i=0; i (fan_in, fan_out, weights); return (void *)matrix; } #ifdef _WIN64 _declspec(dllexport) #endif void* Sigmoid_do(void *m) { Matrx *M = (Matrx*) m; std::vector v = M->get_data(); for (float& x: v) { x = 1.0 / (1.0 + std::exp(-x)); } auto N = new Matrx (M->get_row(), M->get_col(), v); return (void *)N; } #ifdef _WIN64 _declspec(dllexport) #endif void* Sigmoid_dot(void *m) { Matrx *M = (Matrx*) m; std::vector v = M->get_data(); for (float& o: v) { o = o * (1.0 - o); } auto N = new Matrx (M->get_row(), M->get_col(), v); return (void *)N; } #ifdef _WIN64 _declspec(dllexport) #endif void* ReLU_do(void *m) { Matrx *M = (Matrx*) m; std::vector v = M->get_data(); for (float& x: v) { x = x > 0 ? x : 0; } auto N = new Matrx (M->get_row(), M->get_col(), v); return (void *)N; } #ifdef _WIN64 _declspec(dllexport) #endif void* ReLU_dot(void *m) { Matrx *M = (Matrx*) m; std::vector v = M->get_data(); for (float& x: v) { x = x > 0 ? 1.0f : 0.0f; } auto N = new Matrx (M->get_row(), M->get_col(), v); return (void *)N; } #ifdef _WIN64 _declspec(dllexport) #endif void* Leaky_ReLU_do(void *m, float alpha) { Matrx *M = (Matrx*) m; std::vector v = M->get_data(); for (float& x: v) { x = x > 0 ? x : alpha * x; } auto N = new Matrx (M->get_row(), M->get_col(), v); return (void *)N; } #ifdef _WIN64 _declspec(dllexport) #endif void* Leaky_ReLU_dot(void *m, float alpha) { Matrx *M = (Matrx*) m; std::vector v = M->get_data(); for (float& x: v) { x = x > 0 ? 1.0 : alpha; } auto N = new Matrx (M->get_row(), M->get_col(), v); return (void *)N; } #ifdef _WIN64 _declspec(dllexport) #endif void* Tanh_do(void *m) { Matrx *M = (Matrx*) m; std::vector v = M->get_data(); for (float& x: v) { x = std::tanh(x); } auto N = new Matrx (M->get_row(), M->get_col(), v); return (void *)N; } #ifdef _WIN64 _declspec(dllexport) #endif void* Tanh_dot(void *m) { Matrx *M = (Matrx*) m; std::vector v = M->get_data(); for (float& x: v) { if (x > 20.0) x = 0.0; // tanh(x) ≈ 1, 导数≈0 else if (x < -20.0) x = 0.0; // tanh(x) ≈ -1, 导数≈0 else { float t = tanh(x); x = 1.0 - t * t; } } auto N = new Matrx (M->get_row(), M->get_col(), v); return (void *)N; } }