道家人 发表于 2022-8-9 14:45:30

matrix.h

/**   *    *    *   *    *    *    *   */#ifndef __IGS__matrix_H#define __IGS__matrix_H#include #include namespace IGS{namespace detail{      namespace ns_matrix      {    template    struct _Matrix_data    {      typedef _MatPtr                        _Mat_pointer;      typedef std::size_t                                                        size_type;                    size_type _M_row;          size_type _M_col;          _Mat_pointer _M_mat;                    _Matrix_data()          : _M_row(), _M_col(), _M_mat()          {}                    _Matrix_data(_Matrix_data&& __t)          : _M_row(__t._M_row), _M_col(__t._M_col), _M_mat(__t._M_mat)          {                  __t._M_row = __t._M_col = size_type();                  __t._M_mat = _Mat_pointer();          }                    void          _M_copy_data(const _Matrix_data& __t)          {          _M_row = __t._M_row;          _M_col = __t._M_col;          _M_mat = __t._M_mat;          }                    void          _M_swap_data(_Matrix_data& __t)          {          _Matrix_data __tmp;          __tmp._M_copy_data(*this);          _M_copy_data(__t);          __t._M_copy_data(__tmp);          }        };          }// namespace ns_matrix}// namespace details    template    class matrix    {          static_assert(std::is_same::value,"IGS::matrix must have a non-const, non-volatile value_type");          static_assert(std::is_same::value,"IGS::matrix must have the same value_type as its allocator");                  protected:      typedef typename __gnu_cxx::__alloc_traits::template        rebind::other                                                                                _Tp_alloc_type;      typedef __gnu_cxx::__alloc_traits                _Alloc_traits;              public:          typedef _Tp                                                                                value_type;          typedef typename _Alloc_traits::reference                                reference;          typedef typename _Alloc_traits::const_reference                const_reference;          typedef typename _Alloc_traits::pointer                                pointer;          typedef typename _Alloc_traits::const_pointer                        const_pointer;      typedef std::size_t                         size_type;      typedef std::ptrdiff_t                 difference_type;      typedef _Alloc                                 allocator_type;            typedef std::pair                shape_type;            /// Get a copy of the memory allocation object.      allocator_type      get_allocator() const noexcept      { return allocator_type(this->_M_impl); }                  protected:          _Tp_alloc_type&          _M_get_Tp_allocator() noexcept          { return this->_M_impl; }                    const _Tp_alloc_type&          _M_get_Tp_allocator() const noexcept          { return this->_M_impl; }                  protected:          struct _Matrix_impl          : public _Tp_alloc_type,                  public detail::ns_matrix::_Matrix_data          {                  _Matrix_impl()                  : _Tp_alloc_type()                  {}                                    _Matrix_impl(const _Tp_alloc_type& __a)                  : _Tp_alloc_type(__a)                  {}                                    _Matrix_impl(_Matrix_impl&&) = default;                                    _Matrix_impl(_Tp_alloc_type&& __a) noexcept                  : _Tp_alloc_type(std::move(__a))                  {}                                    _Matrix_impl(_Matrix_impl&& __m, _Tp_alloc_type&& __a)                  : _Tp_alloc_type(std::move(__a)),                  detail::ns_matrix::_Matrix_data(std::move(__m))                {}          };                    _Matrix_impl_M_impl;                    pointer          _M_allocate(size_type __n)          { return _Alloc_traits::allocate(_M_get_Tp_allocator(), __n); }                    void          _M_deallocate(pointer __p, size_type __n)          { _Alloc_traits::deallocate(_M_get_Tp_allocator(), __p, __n); }                    void          _M_construct(pointer __p, const_reference __x)          { _Alloc_traits::construct(_M_get_Tp_allocator(), __p, __x); }                    void          _M_construct(pointer __p, size_type __n, const_reference __x)          { _M_construct(__p, __p + __n, __x); }                    void          _M_construct(pointer __first, pointer __last, const_reference __x)          {                  while (__first != __last)                  {                          _Alloc_traits::construct(_M_get_Tp_allocator(), __first, __x);                        ++__first;                }          }                    void          _M_destroy(pointer __p, size_type __n)          {                  for (pointer __end = __p + __n; __p != __end; ++__p)                          _Alloc_traits::destroy(_M_get_Tp_allocator(), __p);          }                  public:          matrix() = default;                    matrix(const allocator_type& __a)          : _M_impl(__a)          {}                    matrix(matrix&&) noexcept = default;                    matrix(const matrix& __t)          : _M_impl()          { build(__t); }                    matrix(size_type __row, size_type __col,                                    const_reference __x = value_type(0))          { build(__row, __col, __x); }                    ~matrix() noexcept          {                clear();                _M_impl.~_Matrix_impl();          }                    void          build(size_type __row, size_type __col,                                  const_reference __x = value_type(0))          {                clear();                size_type __tot = __row * __col;                  this->_M_impl._M_row = __row;                  this->_M_impl._M_col = __col;                this->_M_impl._M_mat = _M_allocate(__tot);                _M_construct(this->_M_impl._M_mat, __tot, __x);          }                    void          build(const matrix& __t)          {                  clear();                if (__t.empty()) return;                                size_type __tot = __t._M_impl._M_row * __t._M_impl._M_col;                                  this->_M_impl._M_row = __t._M_impl._M_row;                  this->_M_impl._M_col = __t._M_impl._M_col;                                    pointer& __self = this->_M_impl._M_mat;                  const const_pointer& __other = __t._M_impl._M_mat;                                  __self = _M_allocate(__tot);                while (__tot--)                        _M_construct(__self + __tot, *(__other + __tot) );          }                    void          build(matrix&& __t)          {                  clear();                  if (__t.empty()) return;                  _M_impl._M_copy_data(__t._M_impl);          }                    void          build_square(size_type __n, const_reference __x = value_type(0))          { build(__n, __n, __x); }                    void          build_identity(size_type __n, const_reference __one = value_type(1),                                                    const_reference __zero = value_type(0))          { build_eye(__n, __n, __one, __zero); }                    void          build_eye(size_type __row, size_type __col,                                          const_reference __one = value_type(1),                                          const_reference __zero = value_type(0))          {                  clear();                const size_type __tot = __row * __col;                  size_type __n = std::min(__row, __col) - 1;                  pointer __p = this->_M_impl._M_mat = _M_allocate(__tot);                  while (__n--)                  {                        _M_construct(__p, __one);                        ++__p;                        _M_construct(__p, __p + __col, __zero);                        __p += __col;                }                _M_construct(__p, __one);                _M_construct(__p + 1, this->_M_impl._M_mat + __tot, __zero);                this->_M_impl._M_row = __row;                this->_M_impl._M_col = __col;          }                /**       *Erases all the elements, and deallocates the storage.       */          void          clear()          {                  if (empty()) return;                  size_type __tot = this->_M_impl._M_row * this->_M_impl._M_col;                _M_destroy(this->_M_impl._M_mat, __tot);                _M_deallocate(this->_M_impl._M_mat, __tot);                  this->_M_impl._M_mat = nullptr;                  this->_M_impl._M_row = 0;                this->_M_impl._M_col = 0;          }                /**       *@briefSwaps data with another %matrix.       *@param__tA %matrix of the same element and allocator types.       *       *This exchanges the elements between two matrices in constant time.       *Note that the global IGS::swap() function is specialized such that       *IGS::swap(m1,m2) will feed to this function.       *       *Whether the allocators are swapped depends on the allocator traits.       */          void          swap(matrix& __t)          {                  this->_M_impl._M_swap_data(__t);                  _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(),                                                                          __t._M_get_Tp_allocator());          }                /**       *Returns true if the %vector is empty.       */          bool          empty() const          { return this->_M_impl._M_mat == nullptr; }                  protected:          /// Safety check used only from at().          void      _M_range_check(size_type __x, size_type __y) const      {                if (__x >= shape().first || __y >= shape().second)          std::__throw_out_of_range_fmt("matrix::_M_range_check: __x"                                     " (which is %zu) >= shape().first "                                     "(which is %zu) || __y (which is %zu) "                                     ">= shape().second (which is %zu)",                                   __x, shape().first, __y, shape().second);      }            void      _M_matrix_multiplication_check(const matrix& __rhs) const      {                  if (this->_M_impl._M_col != __rhs._M_impl._M_row)                          std::__throw_invalid_argument("matrix::"                                                          "_M_matrix_multiplication_check");          }                  public:      // element access      /**       *@briefSubscript access to the data contained in the %matrix.       *@returnRead/write reference to data.       *       *This operator allows for easy, 2D subscript index, data access.       *Note that data access with this operator is unchecked and       *out_of_range lookups are not defined. (For checked lookups       *see at().)       */          reference          operator()(size_type __x, size_type __y)          { return this->_M_impl._M_mat; }                /**       *@briefSubscript access to the data contained in the %matrix.       *@returnRead-only (constant) reference to data.       *       *This operator allows for easy, array-style, data access.       *Note that data access with this operator is unchecked and       *out_of_range lookups are not defined. (For checked lookups       *see at().)       */          const_reference          operator()(size_type __x, size_type __y) const          { return this->_M_impl._M_mat; }                /**       *@briefProvides access to the data contained in the %matrix.       *@returnRead/write reference to data.       *@throwstd::out_of_rangeIf @a __n is an invalid index.       *       *This function provides for safer data access.The parameter       *is first checked that it is in the range of the matrix.The       *function throws out_of_range if the check fails.       */          reference          at(size_type __x, size_type __y)          {                  _M_range_check(__x, __y);                return this->operator()(__x, __y);          }                /**       *@briefProvides access to the data contained in the %matrix.       *@returnRead-only (constant) reference to data.       *@throwstd::out_of_rangeIf @a __n is an invalid index.       *       *This function provides for safer data access.The parameter       *is first checked that it is in the range of the matrix.The       *function throws out_of_range if the check fails.       */          const_reference          at(size_type __x, size_type __y) const          {                  _M_range_check(__x, __y);                return this->operator()(__x, __y);          }                    shape_type          shape() const          { return {_M_impl._M_row, _M_impl._M_col}; }                    std::pair          size() const          { return shape(); }                    std::string          to_string(std::string _btw_elt = " ", std::string _end_row = "\n") const          {                  std::string __result;                  if (empty()) return __result;                  size_type __i = 0, __j;                  while (__i < _M_impl._M_row)                  {                  __j = 0;                  while (__j < _M_impl._M_col)                  {                          __result.append(std::to_string( (*this)(__i, __j) ));                          __result.append(_btw_elt);                        ++__j;                  }                  __result.append(_end_row);                  ++__i;                }                  return __result;          }                /**       *@briefApply a function to the matrix.       *@param__funcFunction of value_type or           *reference or const_reference to apply.       */        template                  typename std::enable_if::type          apply(_Function __func)          {                  pointer __p = this->_M_impl._M_mat;                  pointer __end = __p + _M_impl._M_row * _M_impl._M_col;                  for (; __p != __end; ++__p) __func(*__p);                  return *this;          }                    matrix&          operator=(const matrix& __x)          {                  build(__x);                  return *this;          }          #define __IGS_FunctionDefinitionHelperFor_matrix_operators_00(_Op)        \          matrix&                        \          operator _Op (const_reference __x)                \          {                \                  pointer __p = this->_M_impl._M_mat;                \                  pointer __end = __p + _M_impl._M_row * _M_impl._M_col;                \                  for (; __p != __end; ++__p) *__p _Op __x;                \                  return *this;                \          }          __IGS_FunctionDefinitionHelperFor_matrix_operators_00(+=)__IGS_FunctionDefinitionHelperFor_matrix_operators_00(-=)__IGS_FunctionDefinitionHelperFor_matrix_operators_00(*=)__IGS_FunctionDefinitionHelperFor_matrix_operators_00(/=)__IGS_FunctionDefinitionHelperFor_matrix_operators_00(%=)          #define __IGS_FunctionDefinitionHelperFor_matrix_operators_10(_Op)        \        template                \          matrix&                \          operator _Op (const matrix& __rhs)                \          {                \          if (this->_M_impl._M_row != __rhs._M_impl._M_row                \                        || this->_M_impl._M_col != __rhs._M_impl._M_col)                \                          std::__throw_invalid_argument("matrix::operator"#_Op);                \                size_type __i = _M_impl._M_row * _M_impl._M_col;                \                  while (__i)                \                  {                \                  --__i;                \                  this->_M_impl._M_mat _Op __rhs._M_impl._M_mat;                \                }                \                return *this;                \          }          __IGS_FunctionDefinitionHelperFor_matrix_operators_10(+=)__IGS_FunctionDefinitionHelperFor_matrix_operators_10(-=)                    matrix&          operator*=(const matrix& __rhs)          {                /// Safaty check.                this->_M_matrix_multiplication_check(__rhs);                                size_type __i = this->_M_impl._M_row, __j, __k;                                while (__i--)                {                  __k = __rhs._M_impl._M_row;                  while (__k--)                  {                          __j = __rhs._M_impl._M_col;                          const_reference _S = this->operator()(__i, __k);                          while (__j--)                                  this->operator()(__i, __j) += _S * __rhs(__k, __j);                  }                }                return *this;          }                    matrix          operator+() const          { return *this; }                    matrix          operator-() const          {                  size_type __i = _M_impl._M_row * _M_impl._M_col;                  matrix __tmp(*this);                  while (__i > 0)                  {                        --__i;                        __tmp._M_impl._M_mat = -__tmp._M_impl._M_mat;                }                return __tmp;          }                    bool          operator==(const matrix& __rhs) const          {          if (this->_M_impl._M_mat == __rhs._M_impl._M_mat)                  return true;          if (this->_M_impl._M_row != __rhs._M_impl._M_row)                  return false;          if (this->_M_impl._M_col != __rhs._M_impl._M_col)                  return false;          size_type __i = this->_M_impl._M_row * this->_M_impl._M_col;          while (__i--)                  if (this->_M_impl._M_mat != __rhs._M_impl._M_mat)                          return false;          return true;          }          /// Based on operator==          bool          operator!=(const matrix& __rhs) const          { return !(*this == __rhs); }                  };// class matrix    #define __IGS_FunctionDefinitionHelperFor_matrix_operators_01(_Op)        \template                \        matrix                \        operator _Op (const matrix& __m, const T& __x)                \        {                \                matrix __tmp(__m);                \                return __tmp _Op##= __x;                \        }                \template                \        matrix                \        operator _Op (const T& __x, const matrix& __m)                \        {                \                matrix __tmp(__m);                \                return __tmp _Op##= __x;                \        }__IGS_FunctionDefinitionHelperFor_matrix_operators_01(+)__IGS_FunctionDefinitionHelperFor_matrix_operators_01(-)__IGS_FunctionDefinitionHelperFor_matrix_operators_01(*)__IGS_FunctionDefinitionHelperFor_matrix_operators_01(/)__IGS_FunctionDefinitionHelperFor_matrix_operators_01(%)#define __IGS_FunctionDefinitionHelperFor_matrix_operators_11(_Op)        \template                \        matrix                \        operator _Op (const matrix& __lhs, const matrix& __rhs)                \        {                \                matrix __tmp(__lhs);                \                return __tmp _Op##= __rhs;                \        }__IGS_FunctionDefinitionHelperFor_matrix_operators_11(+)__IGS_FunctionDefinitionHelperFor_matrix_operators_11(-)__IGS_FunctionDefinitionHelperFor_matrix_operators_11(*)    template    inline std::string    to_string(const matrix& __x, std::string _btw_elt = " ",                                std::string _end_row = "\n")    { return __x.to_string(_btw_elt, _end_row); }    //@{/**   *@brief Global Output operator for matrices.   *   *Direct Output between streams and matrices is supported.Output is   *straightforward.*/template    inline std::basic_ostream&    operator
页: [1]
查看完整版本: matrix.h