/********************************************************
* ██████╗ ██████╗████████╗██╗
* ██╔════╝ ██╔════╝╚══██╔══╝██║
* ██║ ███╗██║ ██║ ██║
* ██║ ██║██║ ██║ ██║
* ╚██████╔╝╚██████╗ ██║ ███████╗
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
* Geophysical Computational Tools & Library (GCTL)
*
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
*
* GCTL is distributed under a dual licensing scheme. You can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 2
* of the License, or (at your option) any later version. You should have
* received a copy of the GNU Lesser General Public License along with this
* program. If not, see .
*
* If the terms and conditions of the LGPL v.2. would prevent you from using
* the GCTL, please consider the option to obtain a commercial license for a
* fee. These licenses are offered by the GCTL's original author. As a rule,
* licenses are provided "as-is", unlimited in time for a one time fee. Please
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
* to include some description of your company and the realm of its activities.
* Also add information on how to contact you by electronic and paper mail.
******************************************************/
#ifndef _GCTL_ARRAY_H
#define _GCTL_ARRAY_H
// library's head files
#include "../gctl_config.h"
#include "enum.h"
#include "macro.h"
#include "vector_t.h"
#include "exceptions.h"
#include "random"
#include "chrono"
#ifdef GCTL_EIGEN
/*The followings bypass a bug that VsCode's IntelliSense reports incorrect errors when using eigen3 library*/
#if __INTELLISENSE__
#undef __ARM_NEON
#undef __ARM_NEON__
#endif
#include "Eigen/Dense"
#include "Eigen/Sparse"
#endif // GCTL_EIGEN
#ifdef GCTL_OPENMP
#include "omp.h"
#endif // GCTL_OPENMP
namespace gctl
{
template class array;
/*
* Here we define some commonly used array types.
*/
typedef array _1i_array; ///< 1-D integer array
typedef array _1f_array; ///< 1-D single-precision floating-point array
typedef array _1d_array; ///< 1-D double-precision floating-point array
typedef array _1s_array; ///< 1-D string array
typedef array> _1cf_array; ///< 1-D complex float array
typedef array> _1cd_array; ///< 1-D complex double array
/**
* @brief Iterator template. This could be used to enable the use of iteration algorithms for array-like objects.
*
*/
template
class iterator
{
private:
T *iter;
public:
iterator(T *para, size_t n) {iter = para + n;}
virtual ~iterator(){}
T &operator*() {return *iter;}
bool operator!=(const iterator &that) {return this->iter != that.iter;}
iterator &operator++() {++iter; return *this;}
};
/**
* @brief 1-D array class template
*
* @tparam ArrValType template array
*/
template
class array
{
protected:
ArrValType *val_; ///< Pointer of the array
size_t length_; ///< Length of the array
public:
/**
* @brief Default constructor.
*/
array();
/**
* @brief Construct an array with the given length.
*
* @param[in] len Length of the array. Must be equal to or bigger than zero.
*/
array(size_t len);
/**
* @brief Construct an array with the given length and initial values.
*
* @param[in] len Length of the array. Must be equal to or bigger than zero.
* @param[in] init_val Initial value of the elements.
*/
array(size_t len, ArrValType init_val);
/**
* @brief Construct an array with the given length and fill elements using a native c++ array.
*
* @note Note that if you use an native c++ array to initialize the array template, the pointer
* must be first variable and the length is last variable. This design is mainly to avoid unclear function
* calls. Consider an array of pointers array A(10, nullptr) means that the initial value of all
* elements is nullptr and array A((double**)B, 10) means that the element value of A is initialized
* with array B If the above expression is written as array A(10, B), the compiler cannot call the
* function correctly. Because it cannot be judged whether we want to use the initial value or
* the array to initialize the array.
*
* @param init_array Pointer of the native c++ array.
* @param[in] len Length of the input c++ array. Must be equal to or bigger than zero.
*/
array(ArrValType *init_array, size_t len);
/**
* @brief Copy constructor.
*
* @param[in] b Original array.
*/
array(const array &b);
/**
* @brief Construct a new array object from std::initializer
*
* @param init_val Initial values
*/
array(std::initializer_list init_val);
/**
* @brief Construct a new array object as a sequence
*
* @param s Size of the sequence.
* @param st Start value
* @param inc Invrease interval
*/
array(size_t s, ArrValType st, ArrValType inc);
/**
* @brief Overloaded assignment operator for the array template.
*
* @param[in] b Original array.
*
* @return Target array.
*/
array& operator= (const array &b);
/**
* @brief Overloaded assignment operator for the array template.
*
* @param v Initial value.
* @return Target array.
*/
array& operator= (ArrValType v);
/**
* @brief Overloaded summation operator for the array template.
*
* @param a Input array
* @param b Inpur array
* @return Target array
*/
array operator+ (const array &b);
/**
* @brief Overloaded minus operator for the array template.
*
* @param a Input array
* @param b Inpur array
* @return Target array
*/
array operator- (const array &b);
/**
* @brief Overloaded multiple operator for the array template.
*
* @param a Input array
* @param b Inpur array
* @return Target array
*/
array operator* (const array &b);
/**
* @brief Overloaded division operator for the array template.
*
* @param a Input array
* @param b Inpur array
* @return Target array
*/
array operator/ (const array &b);
/**
* @brief Overloaded summation operator for the array template.
*
* @param a Input array
* @param b Inpur array
* @return Target array
*/
array& operator+= (const array &b);
/**
* @brief Overloaded summation operator for the array template.
*
* @param a Input array
* @param b Inpur array
* @return Target array
*/
array& operator-= (const array &b);
/**
* @brief Overloaded multiple operator for the array template.
*
* @param a Input array
* @param b Inpur array
* @return Target array
*/
array& operator*= (const array &b);
/**
* @brief Overloaded division operator for the array template.
*
* @param a Input array
* @param b Inpur array
* @return Target array
*/
array& operator/= (const array &b);
/**
* @brief Overloaded summation operator for the array template.
*
* @param a Input array
* @param b Scale value
* @return Target array
*/
array operator+ (const ArrValType &b);
/**
* @brief Overloaded minus operator for the array template.
*
* @param a Input array
* @param b Scale value
* @return Target array
*/
array operator- (const ArrValType &b);
/**
* @brief Overloaded multiple operator for the array template.
*
* @param a Input array
* @param b Scale value
* @return Target array
*/
array operator* (const ArrValType &b);
/**
* @brief Overloaded division operator for the array template.
*
* @param a Input array
* @param b Scale value
* @return Target array
*/
array operator/ (const ArrValType &b);
/**
* @brief Overloaded summation operator for the array template.
*
* @param a Input array
* @param b Scale value
* @return Target array
*
*/
array& operator+= (const ArrValType &b);
/**
* @brief Overloaded summation operator for the array template.
*
* @param a Input array
* @param b Scale value
* @return Target array
*/
array& operator-= (const ArrValType &b);
/**
* @brief Overloaded multiple operator for the array template.
*
* @param a Input array
* @param b Scale value
* @return Target array
*/
array& operator*= (const ArrValType &b);
/**
* @brief Overloaded division operator for the array template.
*
* @param a Input array
* @param b Scale value
* @return Target array
*/
array& operator/= (const ArrValType &b);
/**
* @brief Compare two arraies.
*
* @return True if the two arraies are equal, false otherwise.
*/
bool operator== (const array &b) const;
/**
* @brief Compare two arraies.
*
* @return True if the two arraies are not equal, false otherwise.
*/
bool operator!= (const array &b) const;
/**
* @brief Compare two arraies.
*
* @param b Input array
* @param eps Tolerance for flaoting point number
*
* @return True if the two arraies are not equal, false otherwise.
*/
bool equals(const array &b, ArrValType eps = ArrValType{}) const;
/**
* @brief Destructor
*/
virtual ~array();
/**
* @brief Set the length of the array to the given value.
*
* @note If the input length is not equal to the existing length of the array,
* the previous array is destroyed and reconstructed.
*
* @param[in] len Length of the array. Must be equal to or bigger than zero.
*/
void resize(size_t len);
/**
* @brief Set the length of the array to the given value, and fill elements with initial values.
*
* @note If the input length is not equal to the existing length of the array,
* the previous array is destroyed and reconstructed.
*
* @param[in] len Length of the array. Must be equal to or bigger than zero.
* @param[in] init_val Initial value of the elements.
*/
void resize(size_t len, ArrValType init_val);
/**
* @brief Set the length of the array to the given value, and fill elements using a native c++ array.
*
* @note If the input length is not equal to the existing length of the array,
* the previous array is destroyed and reconstructed.
*
* @param init_array Pointer of the native c++ array.
* @param[in] len Length of the input c++ array. Must be equal to or bigger than zero.
*/
void resize(ArrValType *init_array, size_t len);
/**
* @brief Copy a array to the array.
*
* @note If the length of the input array is not equal to the existing length of the array,
* the previous array is destroyed and reconstructed.
*
* @param[in] b Original array
*/
void resize(const array &b);
/**
* @brief Resize a new array object from std::initializer
*
* @param init_val Initial values
*/
void resize(std::initializer_list init_val);
/**
* @brief Resize a new array object as a sequence
*
* @param s Size of the sequence.
* @param st Start value
* @param inc Invrease interval
*/
void resize(size_t s, ArrValType st, ArrValType inc);
/**
* @brief Clear memory space and reset variables.
*/
void clear();
/**
* @brief Set all elements to the given value.
*
* @param[in] in_val Input value.
*/
void assign(ArrValType in_val);
/**
* @brief Set value to segments of an array.
*
* @param in_val Input value
* @param st Starting index
* @param range segment range
*/
void assign(ArrValType in_val, size_t st, size_t range);
/**
* @brief Append an array to the end of the existing one
*
* @param b Input array
*/
void concat(const array &b);
/**
* @brief Extract an array
*
* @param b Output array. Must be initialized before use.
* @param st Start index
*/
void slice(array &b, size_t st = 0) const;
/**
* @brief Extract an array
*
* @param b Output array
* @param ids Index of the extracting elements. Must be initialized before use.
*/
void slice(array &b, const array &ids) const;
/**
* @brief Insert data from an input array
*
* @param b The input array
* @param st The inserting point. The default is zero
*/
void insert(array &b, size_t st = 0);
/**
* @brief Get element value at the given index.
*
* @note This function will check if the index was out of range.
*
* @param[in] index index value.
*
* @return element's value.
*/
ArrValType &at(size_t index);
/**
* @brief Get element value at the given index (Constant).
*
* @note This function will check if the index was out of range.
*
* @param[in] index index value.
*
* @return element's value.
*/
ArrValType &at(size_t index) const;
/**
* @brief Get element value at the given index.
*
* @note This function could not be called by a pointer.
*
* @param[in] index index value.
*
* @return element's value.
*/
ArrValType &operator[](size_t index) noexcept;
/**
* @brief Get element value at the given index .
*
* @note This function could not be called by a pointer.
*
* @param[in] index index value.
*
* @return element's value.
*/
ArrValType &operator[](size_t index) const noexcept;
/**
* @brief Get the first element
*
* @return element value
*/
ArrValType front() const;
/**
* @brief Get the last element
*
* @return element value
*/
ArrValType back() const;
/**
* @brief Return the begining of the iterator
*
* @return iterator
*/
iterator begin();
/**
* @brief Return the ending of the iterator
*
* @return iterator
*/
iterator end();
/**
* @brief Get the pointer to a element at the given index.
*
* @note This function will check if the index was out of range.
*
* @param[in] index index value.
*
* @return Pointer to the element
*/
ArrValType *get(size_t index = 0) const;
/**
* @brief Discriminate if the array is empty.
*
* @return True for empty. False other wise.
*/
bool empty() const noexcept;
/**
* @brief Return the length of the class member array.
*
* @return Length.
*/
size_t size() const noexcept;
/**
* @brief Copy the array to a vector.
*
* @param b Target vector.
*/
void output(std::vector &b) const;
/**
* @brief Copy the array from a vector.
*
* @param b Target vector.
*/
void input(const std::vector &b);
#ifdef GCTL_EIGEN
/**
* @brief Copy the array to a Eigen3 vector.
*
* @param b Target vector.
*/
void output(Eigen::VectorXd &b) const;
/**
* @brief Copy the array from a Eigen3 vector.
*
* @param b Target vector.
*/
void input(const Eigen::VectorXd &b);
#endif // GCTL_EIGEN
/**
* @brief element operate function pointer
*
*/
typedef void (*foreach_a_ptr)(ArrValType &ele_ptr, size_t id);
/**
* @brief 并行执行指定操作
*
* 对数组中的每个元素并行执行给定的操作,第一个参数为数组元素的引用,第二个参数为元素的索引。
* 例如:[](ArrValType &a, size_t i){do something here...}
*
* @tparam BiaryOp 二元操作类型 第一个参数为数组元素的引用,第二个参数为元素的索引
* @param op 要执行的操作
*/
template
void parallel_for_each(BiaryOp op)
{
#pragma omp parallel for
for (size_t i = 0; i < length_; i++)
{
op(val_[i], i);
}
}
/**
* @brief Display the elements.
*
*/
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. Input 0 to select the seed based on the current time.
*/
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 Low bound value.
* @param[in] np2 Hig bound value.
* @param[in] seed Random seed. Input 0 to select the seed based on the current time.
*/
void random_int(ArrValType np1, ArrValType np2, unsigned int seed = 0);
/**
* @brief Set elements' value as a sequent.
*
* @param st_val Start value of the sequent.
* @param inc Increasement of the sequent.
* @param st_id Start index. The default starts from the first element
* @param size Operating size. The default operates on all elements
* @param space Indexing spacing. you can skip elements when create the sequent. The default is no skipping.
*/
void sequence(ArrValType st_val, ArrValType inc, size_t st_id = 0,
size_t size = std::numeric_limits::max(), size_t space = 0);
/**
* @brief Assign values as a 2D sequence.
*
* @param rs Start value of the row sequence
* @param rinc Increase value of the row sequence
* @param cs Start value of the column sequence
* @param cinc Increase value of the column sequence
* @param rn Row nnumber
* @param cn Column number
*/
void sequence2d(ArrValType rs, ArrValType rinc, ArrValType cs, ArrValType cinc,
size_t rn, size_t cn);
/**
* @brief Assign values as a 3D sequence.
*
* @param ls Start value of the layer sequence
* @param linc Increase value of the layer sequence
* @param rs Start value of the row sequence
* @param rinc Increase value of the row sequence
* @param cs Start value of the column sequence
* @param cinc Increase value of the column sequence
* @param ln Layer number
* @param rn Row nnumber
* @param cn Column number
*/
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 sum of all elements.
*
* @return sum value.
*/
ArrValType sum() const;
/**
* @brief Return the mean value.
*
* @return mean value.
*/
ArrValType mean() const;
/**
* @brief Return the variance value.
*
* @return Variance value.
*/
ArrValType variance() const;
/**
* @brief Return the standard deviation value.
*
* @return std value.
*/
ArrValType std() const;
/**
* @brief Return the unbiased standard deviation value.
*
* @return std value.
*/
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 Assign values as a power sequence.
*
* @param base Power base
*/
void log2linear(const ArrValType &base);
/**
* @brief Convert values to a log root.
*
* @param base Log base
*/
void linear2log(ArrValType base);
/**
* @brief Set values to a range.
*
* @param min Lower bound
* @param max Higher bound
* @param rt Bounder type
*
*/
void set2range(ArrValType min, ArrValType max, range_type_e rt = HardScale);
/**
* @brief 检查是否存在等于指定值的元素
*
* @param value 要比较的值
* @return 如果存在等于指定值的元素返回true,否则返回false
*/
bool any_of(const ArrValType& value) const;
/**
* @brief 检查是否所有元素都等于指定值
*
* @param value 要比较的值
* @return 如果所有元素都等于指定值返回true,否则返回false
*/
bool all_of(const ArrValType& value) const;
/**
* @brief 统计等于指定值的元素个数
*
* @param value 要统计的值
* @return 等于指定值的元素个数
*/
size_t count(const ArrValType& value) const;
/**
* @brief 获取数组的内存使用量
*
* @return 数组占用的总内存量MB
*/
void memory_usage(std::ostream &os = std::cout) const noexcept;
};
template
array::array()
{
length_ = 0;
val_ = nullptr;
}
template
array::array(size_t len)
{
length_ = 0;
val_ = nullptr;
resize(len);
}
template
array::array(size_t len, ArrValType init_val)
{
length_ = 0;
val_ = nullptr;
resize(len, init_val);
}
template
array::array(ArrValType *init_array, size_t len)
{
length_ = 0;
val_ = nullptr;
resize(init_array, len);
}
template
array::array(const array &b)
{
length_ = 0;
val_ = nullptr;
resize(b);
}
template
array::array(std::initializer_list init_val)
{
length_ = 0;
val_ = nullptr;
resize(init_val);
}
template
array::array(size_t s, ArrValType st, ArrValType inc)
{
length_ = 0;
val_ = nullptr;
resize(s, st, inc);
}
template
array &array::operator= (const array &b)
{
resize(b.size());
for (size_t i = 0; i < length_; i++)
{
val_[i] = b[i];
}
return *this;
}
template
array &array::operator= (ArrValType v)
{
for (size_t i = 0; i < length_; i++)
{
val_[i] = v;
}
return *this;
}
template
array array::operator+ (const array &b)
{
#ifdef GCTL_CHECK_SIZE
if (b.size() != length_)
{
throw std::runtime_error("[gctl::array::operator+] Incompatible array sizes.");
}
#endif // GCTL_CHECK_SIZE
array out(length_);
for (size_t i = 0; i < length_; i++)
{
out[i] = val_[i] + b[i];
}
return out;
}
template
array array::operator- (const array &b)
{
#ifdef GCTL_CHECK_SIZE
if (b.size() != length_)
{
throw std::runtime_error("[gctl::array::operator-] Incompatible array sizes.");
}
#endif // GCTL_CHECK_SIZE
array out(length_);
for (size_t i = 0; i < length_; i++)
{
out[i] = val_[i] - b[i];
}
return out;
}
template
array array::operator* (const array &b)
{
#ifdef GCTL_CHECK_SIZE
if (b.size() != length_)
{
throw std::runtime_error("[gctl::array::operator*] Incompatible array sizes.");
}
#endif // GCTL_CHECK_SIZE
array out(length_);
for (size_t i = 0; i < length_; i++)
{
out[i] = val_[i] * b[i];
}
return out;
}
template
array array::operator/ (const array &b)
{
#ifdef GCTL_CHECK_SIZE
if (b.size() != length_)
{
throw std::runtime_error("[gctl::array::operator/] Incompatible array sizes.");
}
#endif // GCTL_CHECK_SIZE
array out(length_);
for (size_t i = 0; i < length_; i++)
{
out[i] = val_[i] / b[i];
}
return out;
}
template
array& array::operator+= (const array &b)
{
#ifdef GCTL_CHECK_SIZE
if (b.size() != length_)
{
throw std::runtime_error("[gctl::array::operator+=] Incompatible array sizes.");
}
#endif // GCTL_CHECK_SIZE
for (size_t i = 0; i < length_; i++)
{
val_[i] += b[i];
}
return *this;
}
template
array& array::operator-= (const array &b)
{
#ifdef GCTL_CHECK_SIZE
if (b.size() != length_)
{
throw std::runtime_error("[gctl::array::operator-=] Incompatible array sizes.");
}
#endif // GCTL_CHECK_SIZE
for (size_t i = 0; i < length_; i++)
{
val_[i] -= b[i];
}
return *this;
}
template
array& array::operator*= (const array &b)
{
#ifdef GCTL_CHECK_SIZE
if (b.size() != length_)
{
throw std::runtime_error("[gctl::array::operator*=] Incompatible array sizes.");
}
#endif // GCTL_CHECK_SIZE
for (size_t i = 0; i < length_; i++)
{
val_[i] *= b[i];
}
return *this;
}
template
array& array::operator/= (const array &b)
{
#ifdef GCTL_CHECK_SIZE
if (b.size() != length_)
{
throw std::runtime_error("[gctl::array::operator/=] Incompatible array sizes.");
}
#endif // GCTL_CHECK_SIZE
for (size_t i = 0; i < length_; i++)
{
val_[i] /= b[i];
}
return *this;
}
template
array array::operator+ (const ArrValType &b)
{
array out(length_);
for (size_t i = 0; i < length_; i++)
{
out[i] = val_[i] + b;
}
return out;
}
template
array array::operator- (const ArrValType &b)
{
array out(length_);
for (size_t i = 0; i < length_; i++)
{
out[i] = b - val_[i];
}
return out;
}
template
array array::operator* (const ArrValType &b)
{
array out(length_);
for (size_t i = 0; i < length_; i++)
{
out[i] = b*val_[i];
}
return out;
}
template
array array::operator/ (const ArrValType &b)
{
array out(length_);
for (size_t i = 0; i < length_; i++)
{
out[i] = b/val_[i];
}
return out;
}
template
array& array::operator+= (const ArrValType &b)
{
for (size_t i = 0; i < length_; i++)
{
val_[i] += b;
}
return *this;
}
template
array& array::operator-= (const ArrValType &b)
{
for (size_t i = 0; i < length_; i++)
{
val_[i] -= b;
}
return *this;
}
template
array& array::operator*= (const ArrValType &b)
{
for (size_t i = 0; i < length_; i++)
{
val_[i] *= b;
}
return *this;
}
template
array& array::operator/= (const ArrValType &b)
{
for (size_t i = 0; i < length_; i++)
{
val_[i] /= b;
}
return *this;
}
template
bool array::operator== (const array &b) const
{
if (length_ != b.size()) return false;
for (size_t i = 0; i < length_; i++)
{
if (val_[i] != b[i]) return false;
}
return true;
}
template
bool array::operator!= (const array &b) const
{
return !(*this == b);
}
template
bool array::equals(const array &b, ArrValType eps) const
{
if (length_ != b.size()) return false;
if (eps == ArrValType{})
{
for (size_t i = 0; i < length_; i++)
{
if (val_[i] != b[i]) return false;
}
}
else
{
for (size_t i = 0; i < length_; i++)
{
if (std::abs(val_[i] - b[i]) > eps) return false;
}
}
return true;
}
template
array::~array()
{
clear();
}
template
void array::resize(size_t len)
{
if (len == 0)
{
throw std::invalid_argument("[gctl::array::resize] Invalid array size.");
}
if (length_ != len)
{
clear();
length_ = len;
val_ = new ArrValType[len];
}
return;
}
template
void array::resize(size_t len, ArrValType init_val)
{
resize(len);
for (size_t i = 0; i < length_; i++)
{
val_[i] = init_val;
}
return;
}
template
void array::resize(ArrValType *init_array, size_t len)
{
if (init_array == nullptr)
{
throw std::domain_error("[gctl::array::resize] Invalid pointer.");
}
resize(len);
for (size_t i = 0; i < length_; i++)
{
val_[i] = init_array[i];
}
return;
}
template
void array::resize(const array &b)
{
if (!b.empty())
{
resize(b.size());
for (size_t i = 0; i < length_; i++)
{
val_[i] = b[i];
}
}
return;
}
template
void array::resize(std::initializer_list init_val)
{
resize(init_val.size());
typename std::initializer_list::iterator iter = init_val.begin();
for (size_t i = 0; i < length_; i++)
{
val_[i] = *iter;
iter++;
}
return;
}
template
void array::resize(size_t s, ArrValType st, ArrValType inc)
{
resize(s);
sequence(st, inc);
return;
}
template
void array::clear()
{
if (val_ != nullptr)
{
delete[] val_;
val_ = nullptr;
length_ = 0;
}
return;
}
template
void array::assign(ArrValType in_val)
{
for (size_t i = 0; i < length_; i++)
{
val_[i] = in_val;
}
return;
}
template
void array::assign(ArrValType in_val, size_t st, size_t range)
{
if (st + range <= length_)
{
for (size_t i = st; i < st + range; i++)
{
val_[i] = in_val;
}
return;
}
throw std::runtime_error("[gctl::array::assign] Invalid segment range.");
return;
}
template
void array::concat(const array &b)
{
ArrValType *t = new ArrValType [length_ + b.size()];
for (size_t i = 0; i < length_; i++)
{
t[i] = val_[i];
}
for (size_t i = 0; i < b.size(); i++)
{
t[i + length_] = b[i];
}
delete[] val_;
val_ = t;
length_ += b.size();
return;
}
template
void array::slice(array &b, size_t st) const
{
if (b.size() + st <= length_)
{
for (size_t i = 0; i < b.size(); i++)
{
b[i] = val_[i + st];
}
}
else
{
size_t c = 0;
for (size_t i = st; i < length_; i++)
{
b[c] = val_[i];
c++;
}
}
return;
}
template
void array::slice(array &b, const array &ids) const
{
b.resize(ids.size());
for (size_t i = 0; i < ids.size(); i++)
{
b[i] = val_[ids[i]];
}
return;
}
template
void array::insert(array &b, size_t st)
{
if (b.size() + st <= length_)
{
for (size_t i = 0; i < b.size(); i++)
{
val_[i + st] = b[i];
}
}
else
{
size_t c = 0;
for (size_t i = st; i < length_; i++)
{
val_[i] = b[c];
c++;
}
}
return;
}
template
ArrValType *array::get(size_t index) const
{
if (index >= length_)
throw std::out_of_range("[gctl::array::at] Invalid index.");
return &val_[index];
}
template
ArrValType &array::at(size_t index)
{
if (index >= length_)
throw std::out_of_range("[gctl::array::at] Invalid index.");
return val_[index];
}
template
ArrValType &array::at(size_t index) const
{
if (index >= length_)
throw std::out_of_range("[gctl::array::at] Invalid index.");
return val_[index];
}
template
ArrValType &array::operator[](size_t index) noexcept
{
return val_[index];
}
template
ArrValType &array::operator[](size_t index) const noexcept
{
return val_[index];
}
template
ArrValType array::front() const
{
return val_[0];
}
template
ArrValType array::back() const
{
return val_[length_-1];
}
template
iterator array::begin()
{
return iterator(this->val_, 0);
}
template
iterator array::end()
{
return iterator(this->val_, length_);
}
template
bool array::empty() const noexcept
{
if (length_ == 0) return true;
else return false;
}
template
size_t array::size() const noexcept
{
return length_;
}
template
void array::output(std::vector &b) const
{
if (!b.empty())
{
b.clear();
}
b.resize(length_);
for (size_t i = 0; i < length_; i++)
{
b[i] = val_[i];
}
return;
}
template
void array::input(const std::vector &b)
{
resize(b.size());
for (size_t i = 0; i < length_; i++)
{
val_[i] = b[i];
}
return;
}
#ifdef GCTL_EIGEN
template
void array::output(Eigen::VectorXd &b) const
{
b.resize(length_);
for (size_t i = 0; i < length_; i++)
{
b[i] = val_[i];
}
return;
}
template
void array::input(const Eigen::VectorXd &b)
{
resize(b.size());
for (size_t i = 0; i < length_; i++)
{
val_[i] = b[i];
}
return;
}
#endif // GCTL_EIGEN
/*
template
void array::for_each(foreach_a_ptr func)
{
for (size_t i = 0; i < length_; i++)
{
func(val_[i], i);
}
return;
}
*/
template
void array::show(std::ostream &os, char sep)
{
if (length_ != 0)
{
os << val_[0];
for (size_t i = 1; i < length_; i++)
{
os << sep << val_[i];
}
os << std::endl;
}
return;
}
template
std::ostream &operator <<(std::ostream &os, const array &a)
{
if (!a.empty())
{
os << a[0];
for (size_t i = 1; i < a.size(); i++)
{
os << " " << a[i];
}
}
return os;
}
template
std::istream &operator >>(std::istream &os, array &a)
{
for (size_t i = 0; i < a.size(); i++)
{
os >> a[i];
}
return os;
}
template
void array::random_float(ArrValType np1, ArrValType np2,
random_type_e mode, unsigned int seed)
{
static_assert(std::is_floating_point::value,
"gctl::array::random_float(...) could only be used with a float point type.");
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