ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

matrix.h

2022-06-24 18:33:37  阅读:125  来源: 互联网

标签:__ const matrix ._ type impl



  /**
   * 
   * 
   *  
   * 
   * 
   * 
   * 
  */


#ifndef __IGS__matrix_H
#define __IGS__matrix_H

#include <iterator>
#include <iostream>


namespace IGS
{
  namespace detail
  {
      namespace ns_matrix
      {
  
  template<typename _MatPtr>
    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<typename _Tp, typename _Alloc = std::allocator<_Tp> >
    class matrix
    {
	  
  static_assert(std::is_same<typename std::remove_cv<_Tp>::type, _Tp>::value,
  "IGS::matrix must have a non-const, non-volatile value_type");
	  
  static_assert(std::is_same<typename _Alloc::value_type, _Tp>::value,
  "IGS::matrix must have the same value_type as its allocator");
	  
	protected:
      typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
	rebind<_Tp>::other										_Tp_alloc_type;

      typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type>		_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<size_type, size_type>		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<pointer>
	  {
	  	_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<pointer>(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;
	  }
	  
      /**
       *  @brief  Swaps data with another %matrix.
       *  @param  __t  A %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
      /**
       *  @brief  Subscript access to the data contained in the %matrix.
       *  @return  Read/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[__x * this->_M_impl._M_col + __y]; }
	  
      /**
       *  @brief  Subscript access to the data contained in the %matrix.
       *  @return  Read-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[__x * this->_M_impl._M_col + __y]; }
	  
      /**
       *  @brief  Provides access to the data contained in the %matrix.
       *  @return  Read/write reference to data.
       *  @throw  std::out_of_range  If @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);
	  }
	  
      /**
       *  @brief  Provides access to the data contained in the %matrix.
       *  @return  Read-only (constant) reference to data.
       *  @throw  std::out_of_range  If @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_type, size_type>
	  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;
	  }
	  
      /**
       *  @brief  Apply a function to the matrix.
       *  @param  __func  Function of value_type or
	   *  reference or const_reference to apply.
       */
	template<typename _Function>
	  	typename std::enable_if<std::is_function<typename
  std::remove_pointer<_Function>::type>::value, matrix&>::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<typename _Up>		\
	  matrix&		\
	  operator _Op (const matrix<_Up>& __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[__i] _Op __rhs._M_impl._M_mat[__i];		\
		}		\
		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[__i] = -__tmp._M_impl._M_mat[__i];
		}
  		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[__i] != __rhs._M_impl._M_mat[__i])
	    		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<typename T, typename A>		\
	matrix<T, A>		\
	operator _Op (const matrix<T, A>& __m, const T& __x)		\
	{		\
		matrix<T, A> __tmp(__m);		\
		return __tmp _Op##= __x;		\
	}		\
  template<typename T, typename A>		\
	matrix<T, A>		\
	operator _Op (const T& __x, const matrix<T, A>& __m)		\
	{		\
		matrix<T, A> __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<typename T, typename A>		\
	matrix<T, A>		\
	operator _Op (const matrix<T, A>& __lhs, const matrix<T, A>& __rhs)		\
	{		\
		matrix<T, A> __tmp(__lhs);		\
		return __tmp _Op##= __rhs;		\
	}
  
__IGS_FunctionDefinitionHelperFor_matrix_operators_11(+)
__IGS_FunctionDefinitionHelperFor_matrix_operators_11(-)
__IGS_FunctionDefinitionHelperFor_matrix_operators_11(*)
  
  template<typename T, typename A>
    inline std::string
    to_string(const matrix<T, A>& __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<typename _CharT, typename _Traits, typename T, typename A>
    inline std::basic_ostream<_CharT, _Traits>&
    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
				const matrix<T, A>& __x)
    {
	  	if (__x.empty()) return __os;
	  	std::size_t __row = __x.shape().first;
		std::size_t __col = __x.shape().second;
	  	std::size_t __i = 0, __j;
  	  	while (__i < __row)
  	  	{
  		  __j = 0;
  		  while (__j < __col)
  		  {
  		  	__os << __x(__i, __j);
  		  	__os << ' ';
  			++__j;
  		  }
  		  __os << '\n';
  		  ++__i;
  		}
	  	return __os;
	}
  //@}
  
  /// See IGS::matrix::swap().
  template<typename T, typename A>
    inline void
    swap(matrix<T, A>& __lhs, matrix<T, A>& __rhs)
    { __lhs.swap(__rhs); }
  
}  // namespace IGS




#endif  // #ifndef __IGS__matrix_H

标签:__,const,matrix,._,type,impl
来源: https://www.cnblogs.com/gyan083/p/matrix_h.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有