From 03d9bc7024850cc8582dcb8d02416e99f3ac2d26 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Fri, 13 Sep 2024 10:08:41 +0800 Subject: [PATCH] tmp update --- lib/algorithm/algorithm_func.h | 2 +- lib/core/array.h | 1273 ++++++++++++++------------------ lib/core/enum.h | 11 + lib/maths/mathfunc.cpp | 11 + lib/maths/mathfunc.h | 24 + 5 files changed, 606 insertions(+), 715 deletions(-) diff --git a/lib/algorithm/algorithm_func.h b/lib/algorithm/algorithm_func.h index 779d2c0..e0860f8 100644 --- a/lib/algorithm/algorithm_func.h +++ b/lib/algorithm/algorithm_func.h @@ -30,7 +30,7 @@ #include "../core/array.h" #include "../core/matrix.h" -#include "../maths/mathfunc_t.h" +#include "../maths/mathfunc.h" namespace gctl { diff --git a/lib/core/array.h b/lib/core/array.h index 77f5f1e..2ba4efa 100644 --- a/lib/core/array.h +++ b/lib/core/array.h @@ -484,6 +484,178 @@ namespace gctl * */ void show(std::ostream &os = std::cout, char sep = ' '); + + /** + * @brief Initialize the array with selected random types. + * + * @param[in] np1 Mean (Gauss) or low bound value (Even) + * @param[in] np2 Standard deviation (Gauss) or hig bound value (Even). + * @param[in] mode Random types. 'RdNormal' for Gaussian distributed numbers and + * 'RdUniform' for even distributed numbers. + * @param[in] seed Random seed. + */ + void random_float(ArrValType np1, ArrValType np2, random_type_e mode = RdNormal, unsigned int seed = 0); + + /** + * @brief Initialize the array with selected random types. + * + * @param[in] np1 Mean (Gauss) or low bound value (Even) + * @param[in] np2 Standard deviation (Gauss) or hig bound value (Even). + * @param[in] seed Random seed. + */ + void random_int(ArrValType np1, ArrValType np2, unsigned int seed = 0); + + /** + * @brief Set elements' value as a sequent. + * + * @param st_val Start value. + * @param inc Increasement. + */ + void sequence(ArrValType st_val, ArrValType inc); + + /** + * @brief + * + * @param rs + * @param rinc + * @param cs + * @param cinc + * @param rn + * @param cn + */ + void sequence2d(ArrValType rs, ArrValType rinc, ArrValType cs, ArrValType cinc, + size_t rn, size_t cn); + + /** + * @brief + * + * @param ls + * @param linc + * @param rs + * @param rinc + * @param cs + * @param cinc + * @param ln + * @param rn + * @param cn + */ + void sequence3d(ArrValType ls, ArrValType linc, + ArrValType rs, ArrValType rinc, + ArrValType cs, ArrValType cinc, + size_t ln, size_t rn, size_t cn); + + /** + * @brief Scale elements + * + * @param in_val input factor + */ + void scale(ArrValType in_val); + + /** + * @brief Dot product of two arrays. + * + * @param a Input array. Must be the same length_. + * @return dot product + */ + ArrValType dot(const array &a); + + /** + * @brief Return the mean value. + * + * @return mean value. + */ + ArrValType mean() const; + + /** + * @brief + * + * @return ArrValType + */ + ArrValType variance() const; + + /** + * @brief Return the standard deviation value. + * + * @return std value. + */ + ArrValType std() const; + + /** + * @brief + * + * @return ArrValType + */ + ArrValType std_unbiased() const; + + /** + * @brief Return the root mean square value. + * + * @return RMS value. + */ + ArrValType rms() const; + + /** + * @brief Return the maximal value. + * + * @return maximal value. + */ + ArrValType max() const; + + /** + * @brief Return the minimal value. + * + * @return minimal value. + */ + ArrValType min() const; + + /** + * @brief 计算数组的模长 + * + * @param[in] n_type 模长的计算类型 + * + * @return 返回的模长 + */ + ArrValType module(norm_type_e n_type = L2); + + /** + * @brief Normalize the array to the given module value + * + * @param norm targeting norm-value + * @param n_type Norm-type + * + * @return The module + */ + ArrValType normalize(ArrValType norm = 1.0, norm_type_e n_type = L2); + + /** + * @brief 计算一个向量相对于另一个向量的正交向量 + * + * @param b 输入的数组,计算后的正交向量以引用的形式返回 + */ + void orth(array &b); + + /** + * @brief + * + * @param base + * @param start + * @param inc + */ + void logspace(const ArrValType &base, const ArrValType &start, + const ArrValType &inc); + + /** + * @brief + * + * @param base + */ + void linear2log(ArrValType base); + + /** + * @brief + * + */ + void set2range(ArrValType min, ArrValType max, range_type_e rt = HardScale); }; template @@ -1072,268 +1244,403 @@ namespace gctl return os; } - template - void sequence(array &out_arr, const T &start, const T &inc) - { - static_assert(std::is_arithmetic::value, "gctl::sequence(...) could only be used with an arithmetic type."); - - for (size_t i = 0; i < out_arr.size(); i++) - { - out_arr[i] = start + i*inc; - } - return; - } - - template - void linespace(const T &start, const T &end, unsigned int size, array &out_arr) - { - //static_assert(std::is_arithmetic::value, "gctl::linespace(...) could only be used with an arithmetic type."); - if (size < 1) throw invalid_argument("Invalid array size. From gctl::linespace(...)"); - - out_arr.resize(size); - - if (size == 1) - { - out_arr[0] = 0.5*(start + end); - return; - } - - T space = 1.0/(size-1)*(end - start); - for (int i = 0; i < size; i++) - { - out_arr[i] = start + i*space; - } - return; - } - - template - void gridspace(const T &xs, const T &xe, const T &ys, const T &ye, unsigned int xn, - unsigned int yn, array &out_arr) - { - //static_assert(std::is_arithmetic::value, "gctl::gridspace(...) could only be used with an arithmetic type."); - if (xn < 1 || yn < 1) throw invalid_argument("Invalid grid size. From gctl::gridspace(...)"); - - array out_x, out_y; - linespace(xs, xe, xn, out_x); - linespace(ys, ye, yn, out_y); - - out_arr.resize(xn*yn); - for (int i = 0; i < yn; ++i) - { - for (int j = 0; j < xn; ++j) - { - out_arr[j+i*xn] = out_x[j] + out_y[i]; - } - } - return; - } - - template - void meshspace(const T &xs, const T &xe, const T &ys, const T &ye, const T &zs, const T &ze, - unsigned int xn, unsigned int yn, unsigned int zn, array &out_arr) - { - //static_assert(std::is_arithmetic::value, "gctl::meshspace(...) could only be used with an arithmetic type."); - if (xn < 1 || yn < 1 || zn < 1) throw invalid_argument("Invalid grid size. From gctl::meshspace(...)"); - - array out_x, out_y, out_z; - linespace(xs, xe, xn, out_x); - linespace(ys, ye, yn, out_y); - linespace(zs, ze, zn, out_z); - - out_arr.resize(xn*yn*zn); - for (int i = 0; i < zn; ++i) - { - for (int j = 0; j < yn; ++j) - { - for (int k = 0; k < xn; ++k) - { - out_arr[k+j*xn+i*xn*yn] = out_x[k] + out_y[j] + out_z[i]; - } - } - } - return; - } - - template - void logspace(const T &base, const T &start, const T &end, size_t size, array &out_arr) - { - static_assert(std::is_arithmetic::value, "gctl::logspace(...) could only be used with an arithmetic type."); - if (size < 1) throw invalid_argument("Invalid array size. From gctl::logspace(...)"); - - out_arr.resize(size); - - if (size == 1) - { - out_arr[0] = pow(base, 0.5*(start + end)); - return; - } - - T space = 1.0/(size-1)*(end - start); - for (size_t i = 0; i < size; i++) - { - out_arr[i] = pow(base, start + i*space); - } - return; - } - - template - void linear2log(const T &base, const array &in_arr, array &out_arr) - { - static_assert(std::is_arithmetic::value, "gctl::linear2log(...) could only be used with an arithmetic type."); - if (out_arr.size() != in_arr.size()) out_arr.resize(in_arr.size()); - - for (size_t i = 0; i < in_arr.size(); ++i) - { - out_arr[i] = log(in_arr[i])/log(base); - } - return; - } - - template - T mean(const array &val_arr, const T &zero = 0) - { - static_assert(std::is_arithmetic::value, "gctl::mn(...) could only be used with an arithmetic type."); - - int size = val_arr.size(); - - T mn = zero; - for (int i = 0; i < size; i++) - { - mn = mn + val_arr[i]; - } - return mn/size; - } - - template - T variance(const array &val_arr, const T &zero = 0) - { - static_assert(std::is_arithmetic::value, "gctl::variance(...) could only be used with an arithmetic type."); - - T mn = mean(val_arr); - int size = val_arr.size(); - - T d = zero; - for (int i = 0; i < size; i++) - { - d = d + (val_arr[i] - mn)*(val_arr[i] - mn); - } - return d/size; - } - - template - T std(const array &val_arr, const T &zero = 0) - { - static_assert(std::is_arithmetic::value, "gctl::std(...) could only be used with an arithmetic type."); - - T mn = mean(val_arr); - int size = val_arr.size(); - - T d = zero; - for (int i = 0; i < size; i++) - { - d = d + (val_arr[i] - mn)*(val_arr[i] - mn); - } - return sqrt(d/size); - } - - template - T std_unbiased(const array &val_arr, const T &zero = 0) - { - static_assert(std::is_arithmetic::value, "gctl::std_unbiased(...) could only be used with an arithmetic type."); - - T mn = mean(val_arr); - int size = val_arr.size(); - if (size < 2) throw std::runtime_error("[gctl::std_unbiased] Invalid array size."); - - T d = zero; - for (int i = 0; i < size; i++) - { - d = d + (val_arr[i] - mn)*(val_arr[i] - mn); - } - return sqrt(d/(size - 1)); - } - - template - T rms(const array &val_arr, const T &zero = 0) - { - static_assert(std::is_arithmetic::value, "gctl::rms(...) could only be used with an arithmetic type."); - - int size = val_arr.size(); - - T mn = zero; - for (int i = 0; i < size; i++) - { - mn = mn + val_arr[i]*val_arr[i]; - } - return sqrt(mn/size); - } - - template - T max(const array &val_arr) + template + void array::random_float(ArrValType np1, ArrValType np2, + random_type_e mode, unsigned int seed) { - static_assert(std::is_arithmetic::value, "gctl::max(...) could only be used with an arithmetic type."); + static_assert(std::is_floating_point::value, + "gctl::array::random_float(...) could only be used with a float point type."); - T m = val_arr[0]; - for (size_t i = 1; i < val_arr.size(); i++) + if (seed == 0) seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::default_random_engine generator(seed); + + if (mode == RdNormal) { - m = std::max(val_arr[i], m); + //添加高斯分布的随机值 + std::normal_distribution dist(np1, np2); + for (size_t i = 0; i < length_; i++) + { + val_[i] = dist(generator); + } + return; } - return m; - } - template - T min(const array &val_arr) - { - static_assert(std::is_arithmetic::value, "gctl::min(...) could only be used with an arithmetic type."); - - T m = val_arr[0]; - for (size_t i = 1; i < val_arr.size(); i++) + //添加均匀分布的随机值 + std::uniform_real_distribution dist(np1, np2); + for (size_t i = 0; i < length_; i++) { - m = std::min(val_arr[i], m); - } - return m; - } - - template - void scale(const array &val_arr, T factor) - { - static_assert(std::is_arithmetic::value, "gctl::scale(...) could only be used with an arithmetic type."); - - for (size_t i = 0; i < val_arr.size(); i++) - { - val_arr[i] = factor*val_arr[i]; + val_[i] = dist(generator); } return; } - /** - * @brief 范围约束类型 - * - */ - enum range_type_e - { - HardScale, // 所有数据按比例映射至min和max范围内 - SoftScale, // 所有数据按比例映射至max(min, min(arr))和min(max, max(arr))范围内 - CutOff, // 超过min和max范围数据直接设置为边界值 - }; - - template - void set2range(const array &arr, T min, T max, range_type_e rt = HardScale) + template + void array::random_int(ArrValType np1, ArrValType np2, unsigned int seed) { - static_assert(std::is_arithmetic::value, "gctl::set2range(...) could only be used with an arithmetic type."); + static_assert(std::is_integral::value, + "gctl::array::random_int(...) could only be used with an integral type."); - T amin = arr[0], amax = arr[0]; - for (size_t i = 1; i < arr.size(); i++) + if (seed == 0) seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::default_random_engine generator(seed); + + //添加均匀分布的随机值 + std::uniform_int_distribution dist(np1, np2); + for (size_t i = 0; i < length_; i++) + { + val_[i] = dist(generator); + } + return; + } + + template + void array::sequence(ArrValType st_val, ArrValType inc) + { + //static_assert(std::is_arithmetic::value, + // "gctl::array::sequence(...) could only be used with an arithmetic type."); + + for (size_t i = 0; i < length_; i++) + { + val_[i] = st_val + i*inc; + } + return; + } + + template + void array::sequence2d(ArrValType rs, ArrValType rinc, + ArrValType cs, ArrValType cinc, size_t rn, size_t cn) + { + //static_assert(std::is_arithmetic::value, + // "gctl::array::sequence2d(...) could only be used with an arithmetic type."); + + if (rn*cn != length_) + { + throw invalid_argument("[gctl::array::sequence2d] Invalid sequence sizes."); + } + + array out_x(cn), out_y(rn); + out_x.sequence(cs, cinc); + out_y.sequence(rs, rinc); + + for (size_t i = 0; i < rn; i++) { - amin = aminarr[i]?amax:arr[i]; + for (size_t j = 0; j < cn; j++) + { + val_[j + i*cn] = out_x[j] + out_y[i]; + } + } + return; + } + + template + void array::sequence3d(ArrValType ls, ArrValType linc, + ArrValType rs, ArrValType rinc, ArrValType cs, ArrValType cinc, + size_t ln, size_t rn, size_t cn) + { + //static_assert(std::is_arithmetic::value, + // "gctl::array::sequence3d(...) could only be used with an arithmetic type."); + + if (ln*rn*cn != length_) + { + throw invalid_argument("[gctl::array::sequence3d] Invalid sequence sizes."); + } + + array out_x(cn), out_y(rn), out_z(ln); + out_x.sequence(cs, cinc); + out_y.sequence(rs, rinc); + out_z.sequence(ls, linc); + + for (size_t k = 0; k < ln; k++) + { + for (size_t i = 0; i < rn; i++) + { + for (size_t j = 0; j < cn; j++) + { + val_[j + i*cn + k*rn*cn] = out_x[j] + out_y[i] + out_z[k]; + } + } + } + return; + } + + template + void array::scale(ArrValType in_val) + { + static_assert(std::is_arithmetic::value, + "gctl::array::scale(...) could only be used with an arithmetic type."); + + for (size_t i = 0; i < length_; i++) + { + val_[i] = val_[i]*in_val; + } + return; + } + + template + ArrValType array::dot(const array &a) + { + static_assert(std::is_arithmetic::value, + "gctl::array::dot(...) could only be used with an arithmetic type."); + + if (length_ != a.size()) + { + throw std::runtime_error("Incompatible array sizes. gctl::array::dot(...)"); + } + + ArrValType sum = 0; + for (size_t i = 0; i < length_; i++) + { + sum += val_[i]*a[i]; + } + return sum; + } + + template + ArrValType array::mean() const + { + static_assert(std::is_arithmetic::value, + "gctl::array::mean(...) could only be used with an arithmetic type."); + + if (length_ == 0) return 0; + + ArrValType m = 0; + for (size_t i = 0; i < length_; i++) + { + m = m + val_[i]; + } + return m/length_; + } + + template + ArrValType array::std() const + { + static_assert(std::is_arithmetic::value, + "gctl::array::std(...) could only be used with an arithmetic type."); + + if (length_ == 0 || length_ == 1) return 0; + + ArrValType m = mean(), s = 0; + for (size_t i = 0; i < length_; i++) + { + s += (val_[i] - m)*(val_[i] - m); + } + return sqrt(s/length_); + } + + template + ArrValType array::rms() const + { + static_assert(std::is_arithmetic::value, + "gctl::array::rms(...) could only be used with an arithmetic type."); + + if (length_ == 0) return 0; + + ArrValType m = 0; + for (size_t i = 0; i < length_; i++) + { + m += val_[i]*val_[i]; + } + return sqrt(m/length_); + } + + template + ArrValType array::max() const + { + static_assert(std::is_arithmetic::value, + "gctl::array::max(...) could only be used with an arithmetic type."); + + if (length_ == 0) return 0; + + ArrValType m = val_[0]; + for (size_t i = 1; i < length_; i++) + { + m = std::max(val_[i], m); + } + return m; + } + + template + ArrValType array::min() const + { + static_assert(std::is_arithmetic::value, + "gctl::array::min(...) could only be used with an arithmetic type."); + + if (length_ == 0) return 0; + + ArrValType m = val_[0]; + for (size_t i = 1; i < length_; i++) + { + m = std::min(val_[i], m); + } + return m; + } + + template + ArrValType array::module(norm_type_e n_type) + { + static_assert(std::is_arithmetic::value, + "gctl::array::module(...) could only be used with an arithmetic type."); + + ArrValType norm_sum = 0.0; + + if (n_type == L0) + { + int n = 0; + for (size_t i = 0; i < length_; i++) + { + if (val_[i] != 0.0) + { + n++; + } + } + norm_sum = (ArrValType) n; + } + + if (n_type == L1) + { + for (size_t i = 0; i < length_; i++) + { + norm_sum += GCTL_FABS(val_[i]); + } + } + + if (n_type == L2) + { + for (size_t i = 0; i < length_; i++) + { + norm_sum += val_[i] * val_[i]; + } + norm_sum = sqrt(norm_sum); + } + + if (n_type == Linf) + { + norm_sum = val_[0]; + for (int i = 1; i < length_; i++) + { + norm_sum = GCTL_MAX(norm_sum, val_[i]); + } + } + + return norm_sum; + } + + template + ArrValType array::normalize(ArrValType norm, norm_type_e n_type) + { + static_assert(std::is_arithmetic::value, + "gctl::array::normalize(...) could only be used with an arithmetic type."); + + ArrValType norm_sum = module(n_type); + + if (norm_sum <= GCTL_ZERO) return 0; + + for (size_t i = 0; i < length_; i++) + { + val_[i] = val_[i]*norm/norm_sum; + } + return norm_sum; + } + + template + void array::orth(array &b) + { + static_assert(std::is_arithmetic::value, + "gctl::array::orth(...) could only be used with an arithmetic type."); + + if (length_ != b.size()) + { + throw runtime_error("[gctl::array::orth] Incompatible array size."); + } + + ArrValType product = dot(b); + for (int i = 0; i < length_; i++) + { + b[i] = b[i] - product*val_[i]; + } + return; + } + + template + void array::logspace(const ArrValType &base, const ArrValType &start, + const ArrValType &inc) + { + static_assert(std::is_arithmetic::value, + "gctl::array::logspace(...) could only be used with an arithmetic type."); + + if (length_ == 0) return; + + for (size_t i = 0; i < length_; i++) + { + val_[i] = pow(base, start + i*inc); + } + return; + } + + template + void array::linear2log(ArrValType base) + { + static_assert(std::is_arithmetic::value, + "gctl::array::linear2log(...) could only be used with an arithmetic type."); + + for (size_t i = 0; i < length_; ++i) + { + val_[i] = log(val_[i])/log(base); + } + return; + } + + template + ArrValType array::variance() const + { + static_assert(std::is_arithmetic::value, + "gctl::array::variance(...) could only be used with an arithmetic type."); + + if (length_ == 0) return 0; + + ArrValType mn = mean(); + ArrValType d = 0; + for (size_t i = 0; i < length_; i++) + { + d = d + (val_[i] - mn)*(val_[i] - mn); + } + return d/length_; + } + + template + ArrValType array::std_unbiased() const + { + static_assert(std::is_arithmetic::value, + "gctl::array::std_unbiased(...) could only be used with an arithmetic type."); + + if (length_ < 2) return 0; + + ArrValType mn = mean(); + ArrValType d = 0; + for (size_t i = 0; i < length_; i++) + { + d = d + (val_[i] - mn)*(val_[i] - mn); + } + return sqrt(d/(length_ - 1)); + } + + template + void array::set2range(ArrValType min, ArrValType max, range_type_e rt) + { + static_assert(std::is_arithmetic::value, + "gctl::array::std_unbiased(...) could only be used with an arithmetic type."); + + ArrValType amin = val_[0], amax = val_[0]; + for (size_t i = 1; i < length_; i++) + { + amin = aminval_[i]?amax:val_[i]; } if (rt == HardScale) { - for (size_t i = 0; i < arr.size(); i++) + for (size_t i = 0; i < length_; i++) { - arr[i] = (max - min)*(arr[i] - amin)/(amax - amin) + min; + val_[i] = (max - min)*(val_[i] - amin)/(amax - amin) + min; } return; } @@ -1342,485 +1649,23 @@ namespace gctl if (rt == CutOff) { - for (size_t i = 0; i < arr.size(); i++) + for (size_t i = 0; i < length_; i++) { - if (arr[i] > max) arr[i] = max; - if (arr[i] < min) arr[i] = min; + if (val_[i] > max) val_[i] = max; + if (val_[i] < min) val_[i] = min; } return; } // Soft Scale - T min2 = amin>min?amin:min; - T max2 = amaxmin?amin:min; + ArrValType max2 = amax - T normalize(array &in_arr, T eps = 1e-8) - { - T norm_val = module(in_arr, L2); - if (norm_val < eps) - return 0.0; - - for (int i = 0; i < in_arr.size(); i++) - { - in_arr[i] /= norm_val; - } - return norm_val; - } - - template - void normalize(array &val_arr, T norm, norm_type_e n_type) - { - static_assert(std::is_arithmetic::value, "gctl::normalize(...) could only be used with an arithmetic type."); - - T norm_sum = 0; - if (n_type == L0) - { - int n = 0; - for (size_t i = 0; i < val_arr.size(); i++) - { - if (val_arr[i] != 0) - { - n++; - } - } - norm_sum = (T) n; - } - - if (n_type == L1) - { - for (size_t i = 0; i < val_arr.size(); i++) - { - norm_sum += GCTL_FABS(val_arr[i]); - } - } - - if (n_type == L2) - { - for (size_t i = 0; i < val_arr.size(); i++) - { - norm_sum += val_arr[i] * val_arr[i]; - } - norm_sum = sqrt(norm_sum); - } - - if (norm_sum <= GCTL_ZERO) - { - return; - } - - for (size_t i = 0; i < val_arr.size(); i++) - { - val_arr[i] = val_arr[i]*norm/norm_sum; - } - return; - } - - /** - * @brief Return a random number in the range [low, hig] - * - * @note Call srand(seed) to initiate the random squence before using this function. - * - * @tparam T Value type - * @param low Lower bound - * @param hig Higher bound - * @return T Random value - */ - template - T random(T low, T hig) - { - T f = (T) rand()/RAND_MAX; - return f*(hig-low)+low; - } - - template - void random(array &val_arr, T p1, T p2, random_type_e mode = RdNormal, unsigned int seed = 0) - { - static_assert(std::is_arithmetic::value, "gctl::random(...) could only be used with an arithmetic type."); - - size_t size = val_arr.size(); - - if (seed == 0) seed = std::chrono::system_clock::now().time_since_epoch().count(); - - std::default_random_engine generator(seed); - if (mode == RdNormal) - { - //添加高斯分布的随机值 - std::normal_distribution dist(p1, p2); - for (int i = 0; i < size; i++) - { - val_arr[i] = dist(generator); - } - return; - } - - //添加均匀分布的随机值 - std::uniform_real_distribution dist(p1, p2); - for (int i = 0; i < size; i++) - { - val_arr[i] = dist(generator); - } - return; - } - - /** - * @brief 计算数组的模长 - * - * @param[in] in_arr 输入数组 - * @param[in] n_type 模长的计算类型 - * - * @return 返回的模长 - */ - template - T module(const array &in_arr, norm_type_e n_type = L2) - { - static_assert(std::is_arithmetic::value, "gctl::module(...) could only be used with an arithmetic type."); - - T tmp = 0.0; - if (n_type == L0) - { - for (int i = 0; i < in_arr.size(); i++) - { - if (in_arr[i] != 0.0) - { - tmp += 1.0; - } - } - return tmp; - } - - if (n_type == L1) - { - for (int i = 0; i < in_arr.size(); i++) - { - tmp += GCTL_FABS(in_arr[i]); - } - return tmp; - } - - if (n_type == L2) - { - for (int i = 0; i < in_arr.size(); i++) - { - tmp += in_arr[i] * in_arr[i]; - } - return sqrt(tmp); - } - - tmp = in_arr[0]; - for (int i = 1; i < in_arr.size(); i++) - { - tmp = GCTL_MAX(tmp, in_arr[i]); - } - return sqrt(tmp); - } - - /** - * @brief 计算两个数组的点积 - * - * @param[in] a 输入的第一个数组 - * @param[in] b 输入的第二个数组 - * - * @return 数组的点积 - */ - template - T dot_product(const array &a, const array &b) - { - static_assert(std::is_arithmetic::value, "gctl::dot_product(...) could only be used with an arithmetic type."); - - if (a.size() != b.size()) - throw runtime_error("Incompatible arrays' sizes. Thrown by gctl::dot_product(...)"); - - T p = (T) 0; - for (size_t i = 0; i < a.size(); i++) - { - p = p + a[i]*b[i]; - } - return p; - } - - /** - * @brief 计算一个向量相对于另一个向量的正交向量 - * - * @param[in] a 输入的第一个数组 - * @param b 输入的第二个数组,计算后的正交向量以引用的形式返回 - */ - template - void orth(const array &a, array &b) - { - static_assert(std::is_arithmetic::value, "gctl::orth(...) could only be used with an arithmetic type."); - - if (a.size() != b.size()) - { - throw runtime_error("The arrays have different sizes. Thrown by gctl::orth(...)"); - } - - T product = dot_product(a, b); - for (int i = 0; i < a.size(); i++) - { - b[i] -= product*a[i]; - } - return; - } } -#endif // _GCTL_ARRAY_H - - -/** - * @brief Initialize the array with selected random types. - * - * @param[in] np1 Mean (Gauss) or low bound value (Even) - * @param[in] np2 Standard deviation (Gauss) or hig bound value (Even). - * @param[in] mode Random types. 'RdNormal' for Gaussian distributed numbers and - * 'RdUniform' for even distributed numbers. - */ -// void random(ArrValType np1, ArrValType np2, random_type_e mode = RdNormal, unsigned int seed = 0); - -/** - * @brief Set elements' value as a sequent. - * - * @param st_val Start value. - * @param inc Increasement. - */ -//void sequent(ArrValType st_val, ArrValType inc); - -/** - * @brief Scale elements - * - * @param in_val input factor - */ -//void scale(ArrValType in_val); - -/** - * @brief Dot product of two arrays. - * - * @param a Input array. Must be the same length_. - * @return dot product - */ -//ArrValType dot(const array &a); - -/** - * @brief Return the mean value. - * - * @return mean value. - */ -//ArrValType mean() const; - -/** - * @brief Return the standard deviation value. - * - * @return std value. - */ -//ArrValType std() const; - -/** - * @brief Return the root mean square value. - * - * @return RMS value. - */ -//ArrValType rms() const; - -/** - * @brief Return the maximal value. - * - * @return maximal value. - */ -//ArrValType max() const; - -/** - * @brief Return the minimal value. - * - * @return minimal value. - */ -//ArrValType min() const; - -/** - * @brief Normalize the array to the given module value - * - * @param norm targeting norm-value - * @param n_type Norm-type - */ -//void normalize(ArrValType norm = 1.0, norm_type_e n_type = L2); - -/* -template -void array::random(ArrValType np1, ArrValType np2, random_type_e mode, unsigned int seed) -{ - if (seed == 0) seed = std::chrono::system_clock::now().time_since_epoch().count(); - std::default_random_engine generator(seed); - - if (mode == RdNormal) - { - //添加高斯分布的随机值 - std::normal_distribution dist(np1, np2); - for (size_t i = 0; i < length_; i++) - { - val_[i] = dist(generator); - } - return; - } - - //添加均匀分布的随机值 - std::uniform_real_distribution dist(np1, np2); - for (size_t i = 0; i < length_; i++) - { - val_[i] = dist(generator); - } - return; -} - -template -void array::sequent(ArrValType st_val, ArrValType inc) -{ - for (size_t i = 0; i < length_; i++) - { - val_[i] = st_val + i*inc; - } - return; -} - -template -void array::scale(ArrValType in_val) -{ - for (size_t i = 0; i < length_; i++) - { - val_[i] *= in_val; - } - return; -} - -template -ArrValType array::dot(const array &a) -{ - if (length_ != a.size()) - { - throw std::runtime_error("Incompatible array sizes. gctl::array::dot(...)"); - } - - ArrValType sum = 0; - for (size_t i = 0; i < length_; i++) - { - sum += val_[i]*a[i]; - } - return sum; -} - -template -ArrValType array::mean() const -{ - if (length_ == 0) throw std::invalid_argument("Invalid array size. gctl::array::mean(...)"); - - ArrValType m = 0; - for (size_t i = 0; i < length_; i++) - { - m += val_[i]; - } - return m/length_; -} - -template -ArrValType array::std() const -{ - if (length_ == 0) throw std::invalid_argument("Invalid array size. gctl::array::std(...)"); - if (length_ == 1) return 0; - - ArrValType m = mean(), s = 0; - for (size_t i = 0; i < length_; i++) - { - s += (val_[i] - m)*(val_[i] - m); - } - return sqrt(s/length_); -} - -template -ArrValType array::rms() const -{ - if (length_ == 0) throw std::invalid_argument("Invalid array size. gctl::array::rms(...)"); - - ArrValType m = 0; - for (size_t i = 0; i < length_; i++) - { - m += val_[i]*val_[i]; - } - return sqrt(m/length_); -} - -template -ArrValType array::max() const -{ - if (length_ == 0) throw std::invalid_argument("Invalid array size. gctl::array::max(...)"); - - ArrValType m = val_[0]; - for (size_t i = 1; i < length_; i++) - { - m = std::max(val_[i], m); - } - return m; -} - -template -ArrValType array::min() const -{ - if (length_ == 0) throw std::invalid_argument("Invalid array size. gctl::array::min(...)"); - - ArrValType m = val_[0]; - for (size_t i = 1; i < length_; i++) - { - m = std::min(val_[i], m); - } - return m; -} - -template -void array::normalize(ArrValType norm, norm_type_e n_type) -{ - ArrValType norm_sum = 0.0; - if (n_type == L0) - { - int n = 0; - for (size_t i = 0; i < length_; i++) - { - if (val_[i] != 0.0) - { - n++; - } - } - norm_sum = (ArrValType) n; - } - - if (n_type == L1) - { - for (size_t i = 0; i < length_; i++) - { - norm_sum += GCTL_FABS(val_[i]); - } - } - - if (n_type == L2) - { - for (size_t i = 0; i < length_; i++) - { - norm_sum += val_[i] * val_[i]; - } - norm_sum = sqrt(norm_sum); - } - - if (norm_sum <= GCTL_ZERO) - { - return; - } - - for (size_t i = 0; i < length_; i++) - { - val_[i] = val_[i]*norm/norm_sum; - } - return; -} -*/ \ No newline at end of file +#endif // _GCTL_ARRAY_H \ No newline at end of file diff --git a/lib/core/enum.h b/lib/core/enum.h index cc45257..ba9cf47 100644 --- a/lib/core/enum.h +++ b/lib/core/enum.h @@ -235,6 +235,17 @@ namespace gctl Ellipsoidal, Polar, }; + + /** + * @brief 范围约束类型 + * + */ + enum range_type_e + { + HardScale, // 所有数据按比例映射至min和max范围内 + SoftScale, // 所有数据按比例映射至max(min, min(arr))和min(max, max(arr))范围内 + CutOff, // 超过min和max范围数据直接设置为边界值 + }; } #endif // _GCTL_ENUM_H \ No newline at end of file diff --git a/lib/maths/mathfunc.cpp b/lib/maths/mathfunc.cpp index 0bd0a0e..7da843a 100644 --- a/lib/maths/mathfunc.cpp +++ b/lib/maths/mathfunc.cpp @@ -27,6 +27,17 @@ #include "mathfunc.h" +int gctl::random(int low, int hig) +{ + return rand()%(hig - low + 1) + low; +} + +double gctl::random(double low, double hig) +{ + double f = (double) rand()/RAND_MAX; + return f*(hig-low) + low; +} + bool gctl::isequal(double f, double v, double eps) { return fabs(f - v) < eps; diff --git a/lib/maths/mathfunc.h b/lib/maths/mathfunc.h index 83b4f7e..d5976b4 100644 --- a/lib/maths/mathfunc.h +++ b/lib/maths/mathfunc.h @@ -41,6 +41,30 @@ namespace gctl { /** + * @brief Return a random number in the range [low, hig] + * + * @note Call srand(seed) to initiate the random squence before using this function. + * + * @tparam T Value type + * @param low Lower bound + * @param hig Higher bound + * @return T Random value + */ + int random(int low, int hig); + + /** + * @brief Return a random number in the range [low, hig] + * + * @note Call srand(seed) to initiate the random squence before using this function. + * + * @tparam T Value type + * @param low Lower bound + * @param hig Higher bound + * @return T Random value + */ + double random(double low, double hig); + + /** * @brief 比较两个浮点数。注意比较的精度为 eps 减一位,比如 eps 为1e-10则比较的精度为小数点后9位。 * * @param f 第一个浮点数