197403Sobrien// The template and inlines for the -*- C++ -*- gslice class. 297403Sobrien 3169691Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2004, 2005 4132720Skan// Free Software Foundation, Inc. 597403Sobrien// 697403Sobrien// This file is part of the GNU ISO C++ Library. This library is free 797403Sobrien// software; you can redistribute it and/or modify it under the 897403Sobrien// terms of the GNU General Public License as published by the 997403Sobrien// Free Software Foundation; either version 2, or (at your option) 1097403Sobrien// any later version. 1197403Sobrien 1297403Sobrien// This library is distributed in the hope that it will be useful, 1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1597403Sobrien// GNU General Public License for more details. 1697403Sobrien 1797403Sobrien// You should have received a copy of the GNU General Public License along 1897403Sobrien// with this library; see the file COPYING. If not, write to the Free 19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 2097403Sobrien// USA. 2197403Sobrien 2297403Sobrien// As a special exception, you may use this file as part of a free software 2397403Sobrien// library without restriction. Specifically, if other files instantiate 2497403Sobrien// templates or use macros or inline functions from this file, or you compile 2597403Sobrien// this file and link it with other files to produce an executable, this 2697403Sobrien// file does not by itself cause the resulting executable to be covered by 2797403Sobrien// the GNU General Public License. This exception does not however 2897403Sobrien// invalidate any other reasons why the executable file might be covered by 2997403Sobrien// the GNU General Public License. 3097403Sobrien 3197403Sobrien/** @file gslice.h 3297403Sobrien * This is an internal header file, included by other library headers. 3397403Sobrien * You should not attempt to use it directly. 3497403Sobrien */ 3597403Sobrien 36169691Skan// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> 37169691Skan 38132720Skan#ifndef _GSLICE_H 39132720Skan#define _GSLICE_H 1 4097403Sobrien 4197403Sobrien#pragma GCC system_header 4297403Sobrien 43169691Skan_GLIBCXX_BEGIN_NAMESPACE(std) 44132720Skan 45132720Skan /** 46132720Skan * @brief Class defining multi-dimensional subset of an array. 47132720Skan * 48132720Skan * The slice class represents a multi-dimensional subset of an array, 49132720Skan * specified by three parameter sets: start offset, size array, and stride 50132720Skan * array. The start offset is the index of the first element of the array 51132720Skan * that is part of the subset. The size and stride array describe each 52132720Skan * dimension of the slice. Size is the number of elements in that 53132720Skan * dimension, and stride is the distance in the array between successive 54132720Skan * elements in that dimension. Each dimension's size and stride is taken 55132720Skan * to begin at an array element described by the previous dimension. The 56132720Skan * size array and stride array must be the same size. 57132720Skan * 58132720Skan * For example, if you have offset==3, stride[0]==11, size[1]==3, 59132720Skan * stride[1]==3, then slice[0,0]==array[3], slice[0,1]==array[6], 60132720Skan * slice[0,2]==array[9], slice[1,0]==array[14], slice[1,1]==array[17], 61132720Skan * slice[1,2]==array[20]. 62132720Skan */ 63169691Skan class gslice 64169691Skan { 65169691Skan public: 66169691Skan /// Construct an empty slice. 67169691Skan gslice (); 6897403Sobrien 69169691Skan /** 70169691Skan * @brief Construct a slice. 71169691Skan * 72169691Skan * Constructs a slice with as many dimensions as the length of the @a l 73169691Skan * and @a s arrays. 74169691Skan * 75169691Skan * @param o Offset in array of first element. 76169691Skan * @param l Array of dimension lengths. 77169691Skan * @param s Array of dimension strides between array elements. 78169691Skan */ 79169691Skan gslice(size_t, const valarray<size_t>&, const valarray<size_t>&); 80132720Skan 81169691Skan // XXX: the IS says the copy-ctor and copy-assignment operators are 82169691Skan // synthetized by the compiler but they are just unsuitable 83169691Skan // for a ref-counted semantic 84169691Skan /// Copy constructor. 85169691Skan gslice(const gslice&); 86132720Skan 87169691Skan /// Destructor. 88169691Skan ~gslice(); 89132720Skan 90169691Skan // XXX: See the note above. 91169691Skan /// Assignment operator. 92169691Skan gslice& operator=(const gslice&); 93132720Skan 94169691Skan /// Return array offset of first slice element. 95169691Skan size_t start() const; 96132720Skan 97169691Skan /// Return array of sizes of slice dimensions. 98169691Skan valarray<size_t> size() const; 99169691Skan 100169691Skan /// Return array of array strides for each dimension. 101169691Skan valarray<size_t> stride() const; 102132720Skan 103169691Skan private: 104169691Skan struct _Indexer 105169691Skan { 106169691Skan size_t _M_count; 107169691Skan size_t _M_start; 108169691Skan valarray<size_t> _M_size; 109169691Skan valarray<size_t> _M_stride; 110169691Skan valarray<size_t> _M_index; // Linear array of referenced indices 111169691Skan _Indexer(size_t, const valarray<size_t>&, 112169691Skan const valarray<size_t>&); 113169691Skan void 114169691Skan _M_increment_use() 115169691Skan { ++_M_count; } 116169691Skan 117169691Skan size_t 118169691Skan _M_decrement_use() 119169691Skan { return --_M_count; } 12097403Sobrien }; 121132720Skan 122169691Skan _Indexer* _M_index; 123132720Skan 124169691Skan template<typename _Tp> friend class valarray; 125169691Skan }; 126132720Skan 127169691Skan inline size_t 128169691Skan gslice::start () const 129169691Skan { return _M_index ? _M_index->_M_start : 0; } 130132720Skan 131169691Skan inline valarray<size_t> 132169691Skan gslice::size () const 133169691Skan { return _M_index ? _M_index->_M_size : valarray<size_t>(); } 13497403Sobrien 135169691Skan inline valarray<size_t> 136169691Skan gslice::stride () const 137169691Skan { return _M_index ? _M_index->_M_stride : valarray<size_t>(); } 13897403Sobrien 139169691Skan inline gslice::gslice () : _M_index(0) {} 140132720Skan 141169691Skan inline 142169691Skan gslice::gslice(size_t __o, const valarray<size_t>& __l, 143169691Skan const valarray<size_t>& __s) 144169691Skan : _M_index(new gslice::_Indexer(__o, __l, __s)) {} 14597403Sobrien 146169691Skan inline 147169691Skan gslice::gslice(const gslice& __g) : _M_index(__g._M_index) 148169691Skan { if (_M_index) _M_index->_M_increment_use(); } 149132720Skan 150169691Skan inline 151169691Skan gslice::~gslice() 152169691Skan { 153169691Skan if (_M_index && _M_index->_M_decrement_use() == 0) 154169691Skan delete _M_index; 155169691Skan } 156132720Skan 157169691Skan inline gslice& 158169691Skan gslice::operator= (const gslice& __g) 159169691Skan { 160169691Skan if (__g._M_index) 161169691Skan __g._M_index->_M_increment_use(); 162169691Skan if (_M_index && _M_index->_M_decrement_use() == 0) 163169691Skan delete _M_index; 164169691Skan _M_index = __g._M_index; 165169691Skan return *this; 166169691Skan } 16797403Sobrien 168169691Skan_GLIBCXX_END_NAMESPACE 16997403Sobrien 170132720Skan#endif /* _GSLICE_H */ 171