其他分享
首页 > 其他分享> > matrix.h

matrix.h

作者:互联网


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


#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