1 // The template and inlines for the -*- C++ -*- gslice class. 2 3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2004, 2005, 2006, 2009 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 3, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 /** @file gslice.h 27 * This is an internal header file, included by other library headers. 28 * You should not attempt to use it directly. 29 */ 30 31 // Written by Gabriel Dos Reis <Gabriel.Dos-Reis (at) DPTMaths.ENS-Cachan.Fr> 32 33 #ifndef _GSLICE_H 34 #define _GSLICE_H 1 35 36 #pragma GCC system_header 37 38 _GLIBCXX_BEGIN_NAMESPACE(std) 39 40 /** 41 * @addtogroup numeric_arrays 42 * @{ 43 */ 44 45 /** 46 * @brief Class defining multi-dimensional subset of an array. 47 * 48 * The slice class represents a multi-dimensional subset of an array, 49 * specified by three parameter sets: start offset, size array, and stride 50 * array. The start offset is the index of the first element of the array 51 * that is part of the subset. The size and stride array describe each 52 * dimension of the slice. Size is the number of elements in that 53 * dimension, and stride is the distance in the array between successive 54 * elements in that dimension. Each dimension's size and stride is taken 55 * to begin at an array element described by the previous dimension. The 56 * size array and stride array must be the same size. 57 * 58 * For example, if you have offset==3, stride[0]==11, size[1]==3, 59 * stride[1]==3, then slice[0,0]==array[3], slice[0,1]==array[6], 60 * slice[0,2]==array[9], slice[1,0]==array[14], slice[1,1]==array[17], 61 * slice[1,2]==array[20]. 62 */ 63 class gslice 64 { 65 public: 66 /// Construct an empty slice. 67 gslice(); 68 69 /** 70 * @brief Construct a slice. 71 * 72 * Constructs a slice with as many dimensions as the length of the @a l 73 * and @a s arrays. 74 * 75 * @param o Offset in array of first element. 76 * @param l Array of dimension lengths. 77 * @param s Array of dimension strides between array elements. 78 */ 79 gslice(size_t, const valarray<size_t>&, const valarray<size_t>&); 80 81 // XXX: the IS says the copy-ctor and copy-assignment operators are 82 // synthesized by the compiler but they are just unsuitable 83 // for a ref-counted semantic 84 /// Copy constructor. 85 gslice(const gslice&); 86 87 /// Destructor. 88 ~gslice(); 89 90 // XXX: See the note above. 91 /// Assignment operator. 92 gslice& operator=(const gslice&); 93 94 /// Return array offset of first slice element. 95 size_t start() const; 96 97 /// Return array of sizes of slice dimensions. 98 valarray<size_t> size() const; 99 100 /// Return array of array strides for each dimension. 101 valarray<size_t> stride() const; 102 103 private: 104 struct _Indexer 105 { 106 size_t _M_count; 107 size_t _M_start; 108 valarray<size_t> _M_size; 109 valarray<size_t> _M_stride; 110 valarray<size_t> _M_index; // Linear array of referenced indices 111 112 _Indexer() 113 : _M_count(1), _M_start(0), _M_size(), _M_stride(), _M_index() {} 114 115 _Indexer(size_t, const valarray<size_t>&, 116 const valarray<size_t>&); 117 118 void 119 _M_increment_use() 120 { ++_M_count; } 121 122 size_t 123 _M_decrement_use() 124 { return --_M_count; } 125 }; 126 127 _Indexer* _M_index; 128 129 template<typename _Tp> friend class valarray; 130 }; 131 132 inline size_t 133 gslice::start() const 134 { return _M_index ? _M_index->_M_start : 0; } 135 136 inline valarray<size_t> 137 gslice::size() const 138 { return _M_index ? _M_index->_M_size : valarray<size_t>(); } 139 140 inline valarray<size_t> 141 gslice::stride() const 142 { return _M_index ? _M_index->_M_stride : valarray<size_t>(); } 143 144 // _GLIBCXX_RESOLVE_LIB_DEFECTS 145 // 543. valarray slice default constructor 146 inline 147 gslice::gslice() 148 : _M_index(new gslice::_Indexer()) {} 149 150 inline 151 gslice::gslice(size_t __o, const valarray<size_t>& __l, 152 const valarray<size_t>& __s) 153 : _M_index(new gslice::_Indexer(__o, __l, __s)) {} 154 155 inline 156 gslice::gslice(const gslice& __g) 157 : _M_index(__g._M_index) 158 { if (_M_index) _M_index->_M_increment_use(); } 159 160 inline 161 gslice::~gslice() 162 { 163 if (_M_index && _M_index->_M_decrement_use() == 0) 164 delete _M_index; 165 } 166 167 inline gslice& 168 gslice::operator=(const gslice& __g) 169 { 170 if (__g._M_index) 171 __g._M_index->_M_increment_use(); 172 if (_M_index && _M_index->_M_decrement_use() == 0) 173 delete _M_index; 174 _M_index = __g._M_index; 175 return *this; 176 } 177 178 // @} group numeric_arrays 179 180 _GLIBCXX_END_NAMESPACE 181 182 #endif /* _GSLICE_H */ 183