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]