Classes | Public Types | Public Member Functions | Protected Member Functions | Protected Attributes | Private Types | List of all members
lar::sparse_vector< T > Class Template Reference

A sparse vector. More...

#include <sparse_vector.h>

Classes

class  const_datarange_t
 A constant reference to a data range. More...
 
class  const_iterator
 Iterator to the sparse vector values. More...
 
class  const_reference
 Special little box to allow void elements to be treated as references. More...
 
class  datarange_t
 Range class, with range and data. More...
 
class  iterator
 Iterator to the sparse vector values. More...
 
class  reference
 A class representing a cell in a sparse vector. More...
 

Public Types

typedef T value_type
 type of the stored values More...
 
typedef std::vector< value_typevector_t
 type of STL vector holding this data More...
 
typedef vector_t::size_type size_type
 size type More...
 
typedef vector_t::difference_type difference_type
 index difference type More...
 
typedef vector_t::pointer pointer
 
typedef vector_t::const_pointer const_pointer
 
typedef std::vector< datarange_trange_list_t
 type of sparse vector data More...
 
typedef range_list_t::iterator range_iterator
 type of iterator over ranges More...
 
typedef range_list_t::const_iterator range_const_iterator
 type of constant iterator over ranges More...
 

Public Member Functions

 sparse_vector ()
 Default constructor: an empty vector. More...
 
 sparse_vector (size_type new_size)
 Constructor: a vector with new_size elements in the void. More...
 
 sparse_vector (const vector_t &from, size_type offset=0)
 Constructor: a solid vector from an existing STL vector. More...
 
 sparse_vector (sparse_vector const &)=default
 Copy constructor: default. More...
 
 sparse_vector (sparse_vector &&from)
 Move constructor. More...
 
sparse_vectoroperator= (sparse_vector const &)=default
 Copy assignment: default. More...
 
sparse_vectoroperator= (sparse_vector &&from)
 Move assignment. More...
 
 sparse_vector (vector_t &&from, size_type offset=0)
 Constructor: a solid vector from an existing STL vector. More...
 
 ~sparse_vector ()=default
 Destructor: default. More...
 
void clear ()
 Removes all the data, making the vector empty. More...
 
size_type size () const
 Returns the size of the vector. More...
 
bool empty () const
 Returns whether the vector is empty. More...
 
size_type capacity () const
 Returns the capacity of the vector (compatibility only) More...
 
value_type operator[] (size_type index) const
 Access to an element (read only) More...
 
reference operator[] (size_type index)
 Access to an element (read/write for non-void elements only!) More...
 
auto range_const_data (std::size_t i) const
 Like range_data() but with explicitly read-only access to data. More...
 
range_const_iterator begin_range () const
 Returns a constant iterator to the first data range. More...
 
range_const_iterator end_range () const
 Returns a constant iterator to after the last data range. More...
 
std::size_t find_range_number (size_type index) const
 Returns the number (0-based) of range containing index. More...
 
datarange_t make_void_around (size_type index)
 Casts the whole range with the specified item into the void. More...
 
bool is_valid () const
 Returns if the vector is in a valid state. More...
 
void make_void (iterator first, iterator last)
 Makes all the elements from first and before last void. More...
 
template<typename ITER >
const lar::sparse_vector< T >::datarange_tadd_range (size_type offset, ITER first, ITER last)
 
template<typename ITER , typename OP >
auto combine_range (size_type offset, ITER first, ITER last, OP &&op, value_type void_value) -> const datarange_t &
 
void resize (size_type new_size)
 Resizes the vector to the specified size, adding void. More...
 
void resize (size_type new_size, value_type def_value)
 Resizes the vector to the specified size, adding def_value. More...
 
iterator begin ()
 Standard iterators interface. More...
 
iterator end ()
 
const_iterator begin () const
 
const_iterator end () const
 
const_iterator cbegin () const
 
const_iterator cend () const
 
Cell test

The methods in this group test the single vector cells.

bool is_void (size_type index) const
 Returns whether the specified position is void. More...
 
bool back_is_void () const
 Returns whether the sparse vector ends with void. More...
 
size_type count () const
 Returns the number of non-void cells. More...
 
Cell set

The methods in this group access and/or change the cell values.

value_typeset_at (size_type index, value_type value)
 Writes into an element (creating or expanding a range if needed) More...
 
void unset_at (size_type index)
 Casts the element with the specified index into the void. More...
 
void push_back (value_type value)
 
void push_back (value_type value, value_type thr)
 Adds one element to the end of the vector (if zero, just adds void) More...
 
template<typename ITER >
void assign (ITER first, ITER last)
 Copies data from a sequence between two iterators. More...
 
template<typename CONT >
void assign (const CONT &new_data)
 Copies data from a container. More...
 
void assign (vector_t &&new_data)
 Moves data from a vector. More...
 
Ranges

A range is a contiguous region of the sparse vector which contains all non-void values.

A sparse vector is effectively a sorted collection of ranges. This interface allows:

  • iteration through all ranges (read only)
  • random access to a range by index (read only)
  • access to the data of a selected range (read/write)
  • look-up of the range containing a specified index (read/write; use write with care!)
  • addition (and more generically, combination with existing data) of a new range
  • extension of the sparse vector by appending a range at the end of it
  • remove the data of a range, making it void
const range_list_tget_ranges () const
 Returns the internal list of non-void ranges. More...
 
auto iterate_ranges () -> decltype(auto)
 
size_type n_ranges () const
 Returns the internal list of non-void ranges. More...
 
const datarange_trange (size_t i) const
 Returns the i-th non-void range (zero-based) More...
 
auto range_data (std::size_t i)
 Provides direct access to data of i-th non-void range (zero-based) More...
 
auto range_data (std::size_t const i) const
 
range_const_iterator find_range_iterator (size_type index) const
 Returns an iterator to the range containing the specified index. More...
 
range_iterator find_range_iterator (size_type index)
 
const datarange_tfind_range (size_type index) const
 Returns the range containing the specified index. More...
 
datarange_tfind_range (size_type index)
 
template<typename ITER >
const datarange_tadd_range (size_type offset, ITER first, ITER last)
 Adds a sequence of elements as a range with specified offset. More...
 
template<typename CONT >
const datarange_tadd_range (size_type offset, const CONT &new_data)
 Copies the elements in container to a range with specified offset. More...
 
const datarange_tadd_range (size_type offset, vector_t &&new_data)
 Adds a sequence of elements as a range with specified offset. More...
 
template<typename ITER , typename OP >
const datarange_tcombine_range (size_type offset, ITER first, ITER last, OP &&op, value_type void_value=value_zero)
 Combines a sequence of elements as a range with data at offset. More...
 
template<typename CONT , typename OP >
const datarange_tcombine_range (size_type offset, const CONT &other, OP &&op, value_type void_value=value_zero)
 Combines the elements in container with the data at offset. More...
 
template<typename ITER >
const datarange_tappend (ITER first, ITER last)
 Adds a sequence of elements as a range at the end of the vector. More...
 
template<typename CONT >
const datarange_tappend (const CONT &range_data)
 Adds a sequence of elements as a range at the end of the vector. More...
 
const datarange_tappend (vector_t &&range_data)
 Adds a sequence of elements as a range at the end of the vector. More...
 
datarange_t void_range (range_iterator const iRange)
 Turns the specified range into void. More...
 
datarange_t void_range (std::size_t const iRange)
 
bool optimize ()
 Performs internal optimization, returns whether the object was changed. More...
 
bool optimize (size_t)
 

Static Public Member Functions

Static members related to data size and optimization
static size_t expected_vector_size (size_t size)
 Returns the expected size taken by a vector of specified size. More...
 
static size_t min_gap ()
 Minimum optimal gap between ranges (a guess) More...
 
static bool should_merge (const typename datarange_t::base_t &a, const typename datarange_t::base_t &b)
 Returns if merging the two specified ranges would save memory. More...
 

Protected Member Functions

size_type minimum_size () const
 Returns the size determined by the ranges already present. More...
 
const datarange_tadd_range_before (size_type offset, vector_t &&new_data, range_iterator nextRange)
 Implementation detail of add_range(), with where to add the range. More...
 
range_iterator eat_range_head (range_iterator iRange, size_t index)
 Voids the starting elements up to index (excluded) of a given range. More...
 
datarange_tmerge_ranges (range_iterator iRange)
 Merges all the following contiguous ranges. More...
 
size_type fix_size ()
 Extends the vector size according to the last range. More...
 
range_iterator find_next_range_iter (size_type index)
 Returns an iterator to the range after index. More...
 
range_const_iterator find_next_range_iter (size_type index) const
 
range_iterator find_next_range_iter (size_type index, range_iterator rbegin)
 Returns an iterator to the range after index, or ranges.end() if none. More...
 
range_const_iterator find_next_range_iter (size_type index, range_const_iterator rbegin) const
 
range_iterator find_range_iter_at_or_after (size_type index)
 Returns an iterator to the range at or after index. More...
 
range_const_iterator find_range_iter_at_or_after (size_type index) const
 
range_iterator find_extending_range_iter (size_type index)
 Returns an iterator to the range no earlier than index, or end() if none. More...
 
range_const_iterator find_extending_range_iter (size_type index) const
 
range_iterator find_extending_range_iter (size_type index, range_iterator rbegin)
 Returns an iterator to the range that contains the first non-void element after index, or end() if none. More...
 
range_const_iterator find_extending_range_iter (size_type index, range_const_iterator rbegin) const
 
range_iterator insert_range (range_iterator iInsert, const datarange_t &data)
 Plug a new data range in the specified position; no check performed. More...
 
range_iterator insert_range (range_iterator iInsert, datarange_t &&data)
 

Protected Attributes

size_type nominal_size
 current size More...
 
range_list_t ranges
 list of ranges More...
 

Private Types

typedef sparse_vector< T > this_t
 

Static members for dealing with this type of value

static constexpr value_type value_zero {0}
 a representation of 0 More...
 
static value_type abs (value_type v)
 Returns the module of the specified value. More...
 
static value_type is_zero (value_type v)
 Returns whether the value is exactly zero. More...
 
static value_type is_zero (value_type v, value_type thr)
 Returns whether the value is zero below a given threshold. More...
 
static value_type is_equal (value_type a, value_type b)
 Returns whether two values are the same. More...
 
static value_type is_equal (value_type a, value_type b, value_type thr)
 Returns whether two values are the same below a given threshold. More...
 

Detailed Description

template<typename T>
class lar::sparse_vector< T >

A sparse vector.


Template Parameters
Ttype of data stored in the vector
Todo:
backward iteration; reverse iterators; iterator on non-void elements only; iterator on non-void elements only, returning a pair (index;value)

A sparse_vector is a container of items marked by consecutive indices (that is, a vector like std::vector), where only non-zero elements are actually stored. The implementation is a container of ranges of non-zero consecutive values; the zero elements are effectively not stored in the object, and a zero is returned whenever they are accessed. In the following, the regions of zeros between the non-zero ranges are collectively called "the void".

See sparse_vector_test.cc for examples of usage.

Although some level of dynamic assignment is present, the class is not very flexible and it is best assigned just once, by adding ranges (add_range(); or by push_back(), which is less efficient). While this class mimics a good deal of the STL vector interface, it is not a std::vector and it does not support all the tricks of it.

For the following, let's assume:

std::vector<double> buffer;

Supported usage

for (const auto& value: sv) std::cout << " " << value;
lar::sparse_vector<double>::const_iterator iValue = sv.cbegin(), vend = sv.cend();
while (iSV != sv.end()) std::cout << " " << *(iSV++);
for (auto value: sv) { ... }

Common iteration on all elements. Better to do a constant one. The first two examples print the full content of the sparse vector, void included.


sv[10] = 3.;

Assign to an existing (not void) element. Assigning to void elements is not supported, and there is no way to make an existing element to become void (assigning 0 will yield to an existing element with value 0).


sv.set_at(10, 3.);

Assign a value to an element. The element could be in the void; in any case, after this call the element will not be in the void anymore (even if the assigned value is zero; to cast a cell into the void, use unset_at()).


sv.add_range(20, buffer)
sv.add_range(20, buffer.begin(), buffer.end())
sv.add_range(20, std::move(buffer))

Add the content of buffer starting at the specified position. The last line will attempt to use the buffer directly (only happens if the start of the new range – 20 in the example – is in the void and therefore a new range will be added). The new range is merged with the existing ones when needed, and it overwrites their content in case of overlap. If the specified position is beyond the current end of the sparse vector, the gap will be filled by void.


sv.append(buffer)
sv.append(buffer.begin(), buffer.end())
sv.append(std::move(buffer))

Add the content of buffer at the end of the sparse vector. The last line will attempt to use the buffer directly (only happens if the end of the sparse vector is in the void and therefore a new range will be added).


sv.resize(30)

Resizes the sparse vector to the specified size. Truncation may occur, in which case the data beyond the new size is removed. If an extension occurs instead, the new area is void.


for (const lar::sparse_vector<double>::datarange_t& range: sv.get_ranges()) {
size_t first_item = range.begin_index(); // index of the first item
size_t nItems = range.size(); // number of items in this range
for (double value: range) { ... }
}

A sparse vector can be parsed range by range, skipping the void. Each range object itself supports iteration. Neither the content nor the shape of the ranges can be changed this way.

Possible future improvements

sv[10] = 3.;

is not supported if the vector is shorter than 11 (similarly to a std::vector too), and not even if the item #10 is currently in the void. This latter could be changed to create a new element/range; this would require to ship the pointer to the container with the reference (the return value of "sv[10]"), just in case an assignment will occur, or to create the element regardless, like for std::map (but this would provoke a disaster if the caller uses the non-constant operator[] for iteration). So far, set_at() is the closest thing to it.

Non-supported usage

sv.reserve(20);

This has no clear meaning. A usage analogous to STL would precede a sequence of push_back's. In that case, we should create a new empty range at the end of the vector, and reserve that. Empty ranges are currently not allowed. A replacement of this pattern is to create a new std::vector, reserve space for it and fill it, and finally use sparse_vector::append(). If the end of the vector is void, there will be no performance penalty, otherwise a reserve + copy will happen.


for (auto& value: sv) { ... }

In order to allow for assignment in an item which is currently not void, the non-constant iterators do not dereference directly into a reference to the vector element (which would be non-existent if in the void), but instead into a lightweight object (still called "reference"). These objects are semantically working as references, but they are formally rvalues (i.e., just values, not C++ references), so they can't be assigned to references (like "auto&"). Nevertheless they work as references and assigning to them does change the original value. Currently assigning to void cells is not supported (see above).

Definition at line 289 of file sparse_vector.h.

Member Typedef Documentation

template<typename T>
typedef vector_t::const_pointer lar::sparse_vector< T >::const_pointer

Definition at line 480 of file sparse_vector.h.

template<typename T>
typedef vector_t::difference_type lar::sparse_vector< T >::difference_type

index difference type

Definition at line 477 of file sparse_vector.h.

template<typename T>
typedef vector_t::pointer lar::sparse_vector< T >::pointer

Definition at line 479 of file sparse_vector.h.

type of constant iterator over ranges

Definition at line 498 of file sparse_vector.h.

template<typename T>
typedef range_list_t::iterator lar::sparse_vector< T >::range_iterator

type of iterator over ranges

Definition at line 496 of file sparse_vector.h.

template<typename T>
typedef std::vector<datarange_t> lar::sparse_vector< T >::range_list_t

type of sparse vector data

Definition at line 491 of file sparse_vector.h.

template<typename T>
typedef vector_t::size_type lar::sparse_vector< T >::size_type

size type

Definition at line 476 of file sparse_vector.h.

template<typename T>
typedef sparse_vector<T> lar::sparse_vector< T >::this_t
private

Definition at line 468 of file sparse_vector.h.

template<typename T>
typedef T lar::sparse_vector< T >::value_type

type of the stored values

Definition at line 473 of file sparse_vector.h.

template<typename T>
typedef std::vector<value_type> lar::sparse_vector< T >::vector_t

type of STL vector holding this data

Definition at line 474 of file sparse_vector.h.

Constructor & Destructor Documentation

template<typename T>
lar::sparse_vector< T >::sparse_vector ( )
inline

Default constructor: an empty vector.

Definition at line 505 of file sparse_vector.h.

505 : nominal_size(0), ranges() {}
range_list_t ranges
list of ranges
size_type nominal_size
current size
template<typename T>
lar::sparse_vector< T >::sparse_vector ( size_type  new_size)
inline

Constructor: a vector with new_size elements in the void.

Definition at line 509 of file sparse_vector.h.

509  : nominal_size(0), ranges()
510  { resize(new_size); }
void resize(size_type new_size)
Resizes the vector to the specified size, adding void.
range_list_t ranges
list of ranges
size_type nominal_size
current size
template<typename T>
lar::sparse_vector< T >::sparse_vector ( const vector_t from,
size_type  offset = 0 
)
inline

Constructor: a solid vector from an existing STL vector.

Parameters
fromvector to copy data from
offset(default: 0) index the data starts from (preceeded by void)

Definition at line 517 of file sparse_vector.h.

517  :
518  nominal_size(0), ranges()
519  { add_range(offset, from.begin(), from.end()); }
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
range_list_t ranges
list of ranges
size_type nominal_size
current size
template<typename T>
lar::sparse_vector< T >::sparse_vector ( sparse_vector< T > const &  )
default

Copy constructor: default.

template<typename T>
lar::sparse_vector< T >::sparse_vector ( sparse_vector< T > &&  from)
inline

Move constructor.

Definition at line 525 of file sparse_vector.h.

526  : nominal_size(from.nominal_size)
527  , ranges(std::move(from.ranges))
528  { from.nominal_size = 0; }
range_list_t ranges
list of ranges
def move(depos, offset)
Definition: depos.py:107
size_type nominal_size
current size
template<typename T>
lar::sparse_vector< T >::sparse_vector ( vector_t &&  from,
size_type  offset = 0 
)
inline

Constructor: a solid vector from an existing STL vector.

Parameters
fromvector to move data from
offset(default: 0) index the data starts from (preceeded by void)

Definition at line 547 of file sparse_vector.h.

547  :
548  nominal_size(0), ranges()
549  { add_range(offset, std::move(from)); }
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
range_list_t ranges
list of ranges
def move(depos, offset)
Definition: depos.py:107
size_type nominal_size
current size
template<typename T>
lar::sparse_vector< T >::~sparse_vector ( )
default

Destructor: default.

Member Function Documentation

template<typename T>
static value_type lar::sparse_vector< T >::abs ( value_type  v)
inlinestatic

Returns the module of the specified value.

Definition at line 1010 of file sparse_vector.h.

1010 { return (v < value_zero)? -v: v; }
static constexpr value_type value_zero
a representation of 0
template<typename T>
template<typename ITER >
const datarange_t& lar::sparse_vector< T >::add_range ( size_type  offset,
ITER  first,
ITER  last 
)

Adds a sequence of elements as a range with specified offset.

Template Parameters
ITERtype of iterator
Parameters
offsetwhere to add the elements
firstiterator to the first element to be added
lastiterator after the last element to be added
Returns
the range where the new data was added

If the offset is beyond the current end of the sparse vector, void is added before the new range.

Existing ranges can be merged with the new data if they overlap.

template<typename T>
template<typename CONT >
const datarange_t& lar::sparse_vector< T >::add_range ( size_type  offset,
const CONT &  new_data 
)
inline

Copies the elements in container to a range with specified offset.

Template Parameters
CONTtype of container supporting the standard begin/end interface
Parameters
offsetwhere to add the elements
new_datacontainer holding the data to be copied
Returns
the range where the new data was added

If the offset is beyond the current end of the sparse vector, void is added before the new range.

Existing ranges can be merged with the new data if they overlap.

Definition at line 837 of file sparse_vector.h.

838  { return add_range(offset, new_data.begin(), new_data.end()); }
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
template<typename T >
const lar::sparse_vector< T >::datarange_t & lar::sparse_vector< T >::add_range ( size_type  offset,
vector_t &&  new_data 
)

Adds a sequence of elements as a range with specified offset.

Parameters
offsetwhere to add the elements
new_datacontainer holding the data to be moved
Returns
the range where the new data was added

If the offset is beyond the current end of the sparse vector, void is added before the new range.

Existing ranges can be merged with the new data if they overlap. If no merging happens, new_data vector is directly used as the new range added; otherwise, it is just copied.

Definition at line 1967 of file sparse_vector.h.

1968 {
1969  // insert the new range before the existing range which starts after offset
1970  return add_range_before(offset, std::move(new_data),
1971  std::upper_bound(
1972  ranges.begin(), ranges.end(), offset,
1974  )
1975  );
1976 
1977 } // lar::sparse_vector<T>::add_range(vector)
const datarange_t & add_range_before(size_type offset, vector_t &&new_data, range_iterator nextRange)
Implementation detail of add_range(), with where to add the range.
static bool less(const range_t &a, const range_t &b)
Returns if a is "less" than b.
def move(depos, offset)
Definition: depos.py:107
bool(* less_int_range)(size_type, const range_t &b)
Helper type to be used for binary searches.
template<typename T>
template<typename ITER >
const lar::sparse_vector<T>::datarange_t& lar::sparse_vector< T >::add_range ( size_type  offset,
ITER  first,
ITER  last 
)

Definition at line 1946 of file sparse_vector.h.

1947 {
1948  // insert the new range before the existing range which starts after offset
1949  range_iterator iInsert = find_next_range_iter(offset);
1950 
1951  // is there a range before this, which includes the offset?
1952  if ((iInsert != ranges.begin()) && std::prev(iInsert)->borders(offset)) {
1953  // then we should extend it
1954  (--iInsert)->extend(offset, first, last);
1955  }
1956  else {
1957  // no range before the insertion one includes the offset of the new range;
1958  // ... we need to add it as a new range
1959  iInsert = insert_range(iInsert, { offset, first, last });
1960  }
1961  return merge_ranges(iInsert);
1962 } // lar::sparse_vector<T>::add_range<ITER>()
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
datarange_t & merge_ranges(range_iterator iRange)
Merges all the following contiguous ranges.
range_iterator insert_range(range_iterator iInsert, const datarange_t &data)
Plug a new data range in the specified position; no check performed.
range_list_t::iterator range_iterator
type of iterator over ranges
template<typename T >
const lar::sparse_vector< T >::datarange_t & lar::sparse_vector< T >::add_range_before ( size_type  offset,
vector_t &&  new_data,
range_iterator  nextRange 
)
protected

Implementation detail of add_range(), with where to add the range.

Definition at line 2224 of file sparse_vector.h.

2225 {
2226  // insert the new range before the existing range which starts after offset
2227  range_iterator iInsert = nextRange;
2228 
2229  // is there a range before this, which includes the offset?
2230  if ((iInsert != ranges.begin()) && (iInsert-1)->borders(offset)) {
2231  // then we should extend it
2232  (--iInsert)->extend(offset, new_data.begin(), new_data.end());
2233  }
2234  else {
2235  // no range before the insertion one includes the offset of the new range;
2236  // ... we need to add it as a new range;
2237  // it is not really clear to me [GP] why I need a std::move here, since
2238  // new_data is a rvalue already; in doubt, I have painted all this kind
2239  // of constructs with move()s, just in case
2240  iInsert = insert_range(iInsert, { offset, std::move(new_data) });
2241  }
2242  return merge_ranges(iInsert);
2243 } // lar::sparse_vector<T>::add_range_before(vector, iterator)
def move(depos, offset)
Definition: depos.py:107
datarange_t & merge_ranges(range_iterator iRange)
Merges all the following contiguous ranges.
range_iterator insert_range(range_iterator iInsert, const datarange_t &data)
Plug a new data range in the specified position; no check performed.
range_list_t::iterator range_iterator
type of iterator over ranges
template<typename T>
template<typename ITER >
const datarange_t& lar::sparse_vector< T >::append ( ITER  first,
ITER  last 
)
inline

Adds a sequence of elements as a range at the end of the vector.

Parameters
firstiterator to the first element to be added
lastiterator after the last element to be added
Returns
the range where the new data was added

The input range is copied at the end of the sparse vector. If the end of the sparse vector was the end of a range, that range is expanded, otherwise a new one is created.

Definition at line 927 of file sparse_vector.h.

928  { return add_range(size(), first, last); }
size_type size() const
Returns the size of the vector.
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
template<typename T>
template<typename CONT >
const datarange_t& lar::sparse_vector< T >::append ( const CONT &  range_data)
inline

Adds a sequence of elements as a range at the end of the vector.

Parameters
range_datacontained holding the data to be copied or moved
Returns
the range where the new data was added

The input data is copied at the end of the sparse vector. If the end of the sparse vector was the end of a range, that range is expanded, otherwise a new one is created.

Definition at line 940 of file sparse_vector.h.

941  { return add_range(size(), range_data); }
size_type size() const
Returns the size of the vector.
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
auto range_data(std::size_t i)
Provides direct access to data of i-th non-void range (zero-based)
template<typename T>
const datarange_t& lar::sparse_vector< T >::append ( vector_t &&  range_data)
inline

Adds a sequence of elements as a range at the end of the vector.

Parameters
range_datacontained holding the data to be copied or moved
Returns
the range where the new data was added

If there is a range at the end of the sparse vector, it will be expanded with the new data. Otherwise, this method will use the data vector directly as a new range added at the end of the sparse vector.

Definition at line 953 of file sparse_vector.h.

954  { return add_range(size(), std::move(range_data)); }
size_type size() const
Returns the size of the vector.
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
auto range_data(std::size_t i)
Provides direct access to data of i-th non-void range (zero-based)
def move(depos, offset)
Definition: depos.py:107
template<typename T>
template<typename ITER >
void lar::sparse_vector< T >::assign ( ITER  first,
ITER  last 
)
inline

Copies data from a sequence between two iterators.

Template Parameters
ITERtype of iterator
Parameters
firstiterator pointing to the first element to be copied
lastiterator pointing after the last element to be copied

The previous content of the sparse vector is lost.

Definition at line 669 of file sparse_vector.h.

669 { clear(); append(first, last); }
void clear()
Removes all the data, making the vector empty.
const datarange_t & append(ITER first, ITER last)
Adds a sequence of elements as a range at the end of the vector.
template<typename T>
template<typename CONT >
void lar::sparse_vector< T >::assign ( const CONT &  new_data)
inline

Copies data from a container.

Template Parameters
CONTtype of container supporting the standard begin/end interface
Parameters
new_datacontainer with the data to be copied

The previous content of the sparse vector is lost.

Definition at line 679 of file sparse_vector.h.

679 { clear(); append(new_data); }
void clear()
Removes all the data, making the vector empty.
const datarange_t & append(ITER first, ITER last)
Adds a sequence of elements as a range at the end of the vector.
template<typename T>
void lar::sparse_vector< T >::assign ( vector_t &&  new_data)
inline

Moves data from a vector.

Parameters
new_datavector with the data to be moved

The previous content of the sparse vector is lost.

Definition at line 687 of file sparse_vector.h.

687 { clear(); append(std::move(new_data)); }
void clear()
Removes all the data, making the vector empty.
def move(depos, offset)
Definition: depos.py:107
const datarange_t & append(ITER first, ITER last)
Adds a sequence of elements as a range at the end of the vector.
template<typename T>
bool lar::sparse_vector< T >::back_is_void ( ) const
inline

Returns whether the sparse vector ends with void.

See also
is_void()

Definition at line 612 of file sparse_vector.h.

613  { return ranges.empty() || (ranges.back().end_index() < size()); }
size_type size() const
Returns the size of the vector.
template<typename T >
lar::sparse_vector< T >::iterator lar::sparse_vector< T >::begin ( )
inline

Standard iterators interface.

Definition at line 1751 of file sparse_vector.h.

1752  { return iterator(*this, typename iterator::special::begin()); }
intermediate_table::iterator iterator
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
template<typename T >
lar::sparse_vector< T >::const_iterator lar::sparse_vector< T >::begin ( ) const
inline

Definition at line 1760 of file sparse_vector.h.

1761  { return const_iterator(*this, typename const_iterator::special::begin()); }
intermediate_table::const_iterator const_iterator
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
template<typename T>
range_const_iterator lar::sparse_vector< T >::begin_range ( ) const
inline

Returns a constant iterator to the first data range.

Definition at line 757 of file sparse_vector.h.

757 { return ranges.begin(); }
template<typename T>
size_type lar::sparse_vector< T >::capacity ( ) const
inline

Returns the capacity of the vector (compatibility only)

Definition at line 568 of file sparse_vector.h.

568 { return nominal_size; }
size_type nominal_size
current size
template<typename T>
const_iterator lar::sparse_vector< T >::cbegin ( ) const
inline

Definition at line 583 of file sparse_vector.h.

583 { return begin(); }
iterator begin()
Standard iterators interface.
template<typename T>
const_iterator lar::sparse_vector< T >::cend ( ) const
inline

Definition at line 584 of file sparse_vector.h.

584 { return end(); }
template<typename T>
void lar::sparse_vector< T >::clear ( )
inline

Removes all the data, making the vector empty.

Definition at line 558 of file sparse_vector.h.

558 { ranges.clear(); nominal_size = 0; }
size_type nominal_size
current size
template<typename T>
template<typename ITER , typename OP >
const datarange_t& lar::sparse_vector< T >::combine_range ( size_type  offset,
ITER  first,
ITER  last,
OP &&  op,
value_type  void_value = value_zero 
)

Combines a sequence of elements as a range with data at offset.

Template Parameters
ITERtype of iterator
OPcombination operation
Parameters
offsetwhere to add the elements
firstiterator to the first element to be added
lastiterator after the last element to be added
opoperation to be executed element by element
void_value(default: value_zero) the value to use for void cells
Returns
the range where the new data landed

This is a more generic version of add_range(), where instead of replacing the target data with the data in [ first, last [, the existing data is combined with the one in that interval. The operation op is a binary operation with signature equivalent to Data_t op(Data_t, Data_t), and the operation is equivalent to v[i + offset] = op(v[i + offset], *(first + offset)): op is a binary operation whose first operand is the existing value and the second one is the one being provided. If the cell i + offset is currently void, it will be created and the value used in the combination will be void_value.

If the offset is beyond the current end of the sparse vector, void is added before the new range.

Existing ranges can be merged with the new data if they overlap.

template<typename T>
template<typename CONT , typename OP >
const datarange_t& lar::sparse_vector< T >::combine_range ( size_type  offset,
const CONT &  other,
OP &&  op,
value_type  void_value = value_zero 
)
inline

Combines the elements in container with the data at offset.

Template Parameters
CONTtype of container supporting the standard begin/end interface
OPcombination operation
Parameters
offsetwhere to add the elements
othercontainer holding the data to be combined
opoperation to be executed element by element
void_value(default: value_zero) the value to use for void cells
Returns
the range where the new data was added
See also
combine_range()

This is equivalent to combine_range(size_type, ITER, ITER, OP, Data_t) using as the new data range the full content of other container.

Definition at line 905 of file sparse_vector.h.

909  {
910  return combine_range(offset, other.begin(), other.end(),
911  std::forward<OP>(op), void_value);
912  }
const datarange_t & combine_range(size_type offset, ITER first, ITER last, OP &&op, value_type void_value=value_zero)
Combines a sequence of elements as a range with data at offset.
template<typename T>
template<typename ITER , typename OP >
auto lar::sparse_vector< T >::combine_range ( size_type  offset,
ITER  first,
ITER  last,
OP &&  op,
value_type  void_value 
) -> const datarange_t&

Definition at line 1982 of file sparse_vector.h.

1987 {
1988  /*
1989  * This is a complicate enough task, that we go brute force:
1990  * 1) combine all the input elements within the datarange where offset falls
1991  * in
1992  * 2) create a new datarange combining void with the remaining input elements
1993  * 3) if the void area is over before the input elements are, repeat steps
1994  * (1) and (2) with the updated offset
1995  * 4) at this point we'll have a train of contiguous ranges, result of
1996  * combination of the input elements alternating with existing elements
1997  * and with void cells: apply the regular merge algorithm
1998  *
1999  */
2000 
2001  auto src = first;
2002  auto const insertionPoint = offset; // saved for later
2003  auto destRange = find_range_iter_at_or_after(offset);
2004  while (src != last) {
2005 
2006  //
2007  // (1) combine all the input elements within the datarange including offset
2008  // (NOT extending the range)
2009  //
2010  if ((destRange != end_range()) && destRange->includes(offset)) {
2011  // combine input data until this range is over (or input data is over)
2012  auto dest = destRange->get_iterator(offset);
2013 
2014  auto const end = destRange->end();
2015  while (src != last) {
2016  *dest = op(*dest, *src);
2017  ++src;
2018  ++offset;
2019  if (++dest == end) break;
2020  } // while
2021  if (src == last) break;
2022  offset = destRange->end_index();
2023  ++destRange;
2024  } // if
2025 
2026  //
2027  // (2) create a new datarange combining void with input elements
2028  //
2029  // at this point, offset is in the void, we do have more input data,
2030  // and `destRange` does _not_ contain the current insertion offset;
2031  // we fill as much void as we can with data, creating a new range.
2032  // When to stop? at the beginning of the next range, or when data is over
2033  //
2034  size_type const newRangeSize = (destRange == end_range())
2035  ? std::distance(src, last): (destRange->begin_index() - offset);
2036 
2037  // prepare the data (we'll plug it in directly)
2038  vector_t combinedData;
2039  combinedData.reserve(newRangeSize);
2040  size_type i = 0;
2041  while (i++ < newRangeSize) {
2042  combinedData.push_back(op(void_value, *src));
2043  if (++src == last) break; // no more data
2044  }
2045  // move the data as a new range inserted before the next range we just found
2046  // return value is the iterator to the inserted range
2047  destRange = insert_range(destRange, { offset, std::move(combinedData) });
2048 
2049  //
2050  // (3) if there is more input, repeat steps (1) and (2) with updated offset
2051  //
2052  offset = destRange->end_index();
2053  ++destRange;
2054  } // while
2055 
2056  //
2057  // (4) apply the regular merge algorithm;
2058  // since we did not extend existing ranges, it may happen that we have
2059  // created a new range at `insertionPoint` contiguous to the previous one;
2060  // so we take care of checking that too
2061  //
2062  return merge_ranges
2063  (find_extending_range_iter(insertionPoint == 0? 0: insertionPoint - 1));
2064 
2065 } // lar::sparse_vector<T>::combine_range<ITER>()
std::vector< value_type > vector_t
type of STL vector holding this data
range_iterator find_extending_range_iter(size_type index)
Returns an iterator to the range no earlier than index, or end() if none.
vector_t::size_type size_type
size type
def move(depos, offset)
Definition: depos.py:107
range_iterator find_range_iter_at_or_after(size_type index)
Returns an iterator to the range at or after index.
datarange_t & merge_ranges(range_iterator iRange)
Merges all the following contiguous ranges.
range_iterator insert_range(range_iterator iInsert, const datarange_t &data)
Plug a new data range in the specified position; no check performed.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
range_const_iterator end_range() const
Returns a constant iterator to after the last data range.
template<typename T >
lar::sparse_vector< T >::size_type lar::sparse_vector< T >::count ( ) const
inline

Returns the number of non-void cells.

Definition at line 1818 of file sparse_vector.h.

1820 {
1821  return std::accumulate(begin_range(), end_range(), size_type(0),
1822  [](size_type s, const datarange_t& rng) { return s + rng.size(); }
1823  );
1824 } // count()
vector_t::size_type size_type
size type
range_const_iterator begin_range() const
Returns a constant iterator to the first data range.
range_const_iterator end_range() const
Returns a constant iterator to after the last data range.
static QCString * s
Definition: config.cpp:1042
template<typename T >
lar::sparse_vector< T >::range_iterator lar::sparse_vector< T >::eat_range_head ( range_iterator  iRange,
size_t  index 
)
protected

Voids the starting elements up to index (excluded) of a given range.

Definition at line 2268 of file sparse_vector.h.

2269 {
2270  if (index <= iRange->begin_index()) return iRange;
2271  if (index >= iRange->end_index()) return ranges.erase(iRange);
2272  iRange->move_head(index);
2273  return iRange;
2274 } // lar::sparse_vector<T>::eat_range_head()
template<typename T>
bool lar::sparse_vector< T >::empty ( ) const
inline

Returns whether the vector is empty.

Definition at line 565 of file sparse_vector.h.

565 { return size() == 0; }
size_type size() const
Returns the size of the vector.
template<typename T >
lar::sparse_vector< T >::iterator lar::sparse_vector< T >::end ( )
inline

Definition at line 1755 of file sparse_vector.h.

1756  { return iterator(*this, typename iterator::special::end()); }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
intermediate_table::iterator iterator
template<typename T >
lar::sparse_vector< T >::const_iterator lar::sparse_vector< T >::end ( ) const
inline

Definition at line 1765 of file sparse_vector.h.

1766  { return const_iterator(*this, typename const_iterator::special::end()); }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
intermediate_table::const_iterator const_iterator
template<typename T>
range_const_iterator lar::sparse_vector< T >::end_range ( ) const
inline

Returns a constant iterator to after the last data range.

Definition at line 760 of file sparse_vector.h.

760 { return ranges.end(); }
template<typename T >
size_t lar::sparse_vector< T >::expected_vector_size ( size_t  size)
inlinestatic

Returns the expected size taken by a vector of specified size.

Definition at line 2288 of file sparse_vector.h.

2288  {
2289  // apparently, a chunk of heap memory takes at least 32 bytes;
2290  // that means that a vector of 1 or 5 32-bit integers takes the same
2291  // space; the overhead appears to be 8 bytes, which can be allocated
2292  return sizeof(vector_t)
2293  + std::max(size_t(32), (alignof(datarange_t)*size + 8));
2294 } // lar::sparse_vector<T>::expected_vector_size()
std::vector< value_type > vector_t
type of STL vector holding this data
size_type size() const
Returns the size of the vector.
static int max(int a, int b)
template<typename T>
range_iterator lar::sparse_vector< T >::find_extending_range_iter ( size_type  index)
inlineprotected

Returns an iterator to the range no earlier than index, or end() if none.

Parameters
indexthe absolute index
Returns
iterator to the range including index, or the next range if none

The returned iterator points to a range that "borders" the specified index, meaning that the cell at index is either within the range, or it is the one immediately after that range. If index is in the middle of the void, though (i.e. if the previous cell is void), the next range is returned instead. Finally, if there is no next range, end_range() is returned.

The result may be also interpreted as follow: if the start of the returned range is lower than index, then the cell at index belongs to that range. Otherwise, it initiates its own range (but that range might end up being contiguous to the next(.

Definition at line 1111 of file sparse_vector.h.

1112  { return find_extending_range_iter(index, ranges.begin()); }
range_iterator find_extending_range_iter(size_type index)
Returns an iterator to the range no earlier than index, or end() if none.
template<typename T>
range_const_iterator lar::sparse_vector< T >::find_extending_range_iter ( size_type  index) const
inlineprotected

Definition at line 1113 of file sparse_vector.h.

1114  { return find_extending_range_iter(index, ranges.cbegin()); }
range_iterator find_extending_range_iter(size_type index)
Returns an iterator to the range no earlier than index, or end() if none.
template<typename T >
lar::sparse_vector< T >::range_iterator lar::sparse_vector< T >::find_extending_range_iter ( size_type  index,
range_iterator  rbegin 
)
protected

Returns an iterator to the range that contains the first non-void element after index, or end() if none.

Parameters
indexthe absolute index
rbeginconsider only from this range on
Returns
iterator to the next range not including index, or ranges.end() if none

Note that the returned range can contain index as well.

Definition at line 2199 of file sparse_vector.h.

2200 {
2201  // this range has the offset (first index) above the index argument:
2202  auto it = find_next_range_iter(index, rbegin);
2203  // if index were not void, would it belong to the previous range?
2204  // if so, the previous range is the one we want
2205  return ((it != rbegin) && std::prev(it)->borders(index))? std::prev(it): it;
2206 } // lar::sparse_vector<T>::find_extending_range_iter()
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
template<typename T >
lar::sparse_vector< T >::range_const_iterator lar::sparse_vector< T >::find_extending_range_iter ( size_type  index,
range_const_iterator  rbegin 
) const
protected

Definition at line 2212 of file sparse_vector.h.

2213 {
2214  // this range has the offset (first index) above the index argument:
2215  auto it = find_next_range_iter(index, rbegin);
2216  // if index were not void, would it belong to the previous range?
2217  // if so, the previus range is the one we want
2218  return ((it != rbegin) && std::prev(it)->borders(index))? std::prev(it): it;
2219 } // lar::sparse_vector<T>::find_extending_range_iter() const
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
template<typename T>
range_iterator lar::sparse_vector< T >::find_next_range_iter ( size_type  index)
inlineprotected

Returns an iterator to the range after index.

Parameters
indexthe absolute index
Returns
iterator to the next range not including index, or ranges.end() if none

Definition at line 1056 of file sparse_vector.h.

1057  { return find_next_range_iter(index, ranges.begin()); }
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
template<typename T>
range_const_iterator lar::sparse_vector< T >::find_next_range_iter ( size_type  index) const
inlineprotected

Definition at line 1058 of file sparse_vector.h.

1059  { return find_next_range_iter(index, ranges.cbegin()); }
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
template<typename T >
lar::sparse_vector< T >::range_iterator lar::sparse_vector< T >::find_next_range_iter ( size_type  index,
range_iterator  rbegin 
)
protected

Returns an iterator to the range after index, or ranges.end() if none.

Parameters
indexthe absolute index
rbeginconsider only from this range on
Returns
iterator to the next range not including index, or ranges.end() if none

Definition at line 2150 of file sparse_vector.h.

2151 {
2152  // this range has the offset (first index) above the index argument:
2153  return std::upper_bound(
2154  rbegin, ranges.end(), index,
2156  );
2157 } // lar::sparse_vector<T>::find_next_range_iter()
static bool less(const range_t &a, const range_t &b)
Returns if a is "less" than b.
bool(* less_int_range)(size_type, const range_t &b)
Helper type to be used for binary searches.
template<typename T >
lar::sparse_vector< T >::range_const_iterator lar::sparse_vector< T >::find_next_range_iter ( size_type  index,
range_const_iterator  rbegin 
) const
protected

Definition at line 2162 of file sparse_vector.h.

2163 {
2164  // this range has the offset (first index) above the index argument:
2165  return std::upper_bound(
2166  rbegin, ranges.end(), index,
2168  );
2169 } // lar::sparse_vector<T>::find_next_range_iter() const
static bool less(const range_t &a, const range_t &b)
Returns if a is "less" than b.
bool(* less_int_range)(size_type, const range_t &b)
Helper type to be used for binary searches.
template<typename T >
const lar::sparse_vector< T >::datarange_t & lar::sparse_vector< T >::find_range ( size_type  index) const

Returns the range containing the specified index.

Parameters
indexabsolute index of the element to be sought
Returns
the containing range
Exceptions
std::out_of_rangeif index is in no range (how appropriate!)
See also
is_void()

Definition at line 1910 of file sparse_vector.h.

1911 {
1912  if (ranges.empty()) throw std::out_of_range("empty sparse vector");
1913  // range on the index:
1915  if (iNextRange == ranges.end())
1916  throw std::out_of_range("index in no range of the sparse vector");
1917  return *iNextRange;
1918 } // lar::sparse_vector<T>::find_range() const
range_list_t::const_iterator range_const_iterator
type of constant iterator over ranges
range_const_iterator find_range_iterator(size_type index) const
Returns an iterator to the range containing the specified index.
template<typename T >
lar::sparse_vector< T >::datarange_t & lar::sparse_vector< T >::find_range ( size_type  index)
inline

Definition at line 1922 of file sparse_vector.h.

1923 {
1924  return const_cast<datarange_t&>
1925  (const_cast<const this_t*>(this)->find_range(index));
1926 } // lar::sparse_vector<T>::find_range()
sparse_vector< T > this_t
const datarange_t & find_range(size_type index) const
Returns the range containing the specified index.
template<typename T >
lar::sparse_vector< T >::range_iterator lar::sparse_vector< T >::find_range_iter_at_or_after ( size_type  index)
protected

Returns an iterator to the range at or after index.

Parameters
indexthe absolute index
Returns
iterator to the next range including index or after it, or ranges.end() if none
See also
find_next_range_iter()

If index is in a range, an iterator to that range is returned. If index is in the void, an iterator to the next range after index is returned. If there is no such range after index, ranges.end() is returned.

Definition at line 2186 of file sparse_vector.h.

2187 {
2188  // this range has the offset (first index) above the index argument:
2189  auto after = find_next_range_iter(index);
2190  // if the previous range exists and contains index, that's the one we want
2191  return ((after != ranges.begin()) && (index < std::prev(after)->end_index()))
2192  ? std::prev(after): after;
2193 } // lar::sparse_vector<T>::find_range_iter_at_or_after()
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
template<typename T >
lar::sparse_vector< T >::range_const_iterator lar::sparse_vector< T >::find_range_iter_at_or_after ( size_type  index) const
protected

Definition at line 2174 of file sparse_vector.h.

2175 {
2176  // this range has the offset (first index) above the index argument:
2177  auto after = find_next_range_iter(index);
2178  // if the previous range exists and contains index, that's the one we want
2179  return ((after != ranges.begin()) && (index < std::prev(after)->end_index()))
2180  ? std::prev(after): after;
2181 } // lar::sparse_vector<T>::find_range_iter_at_or_after() const
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
template<typename T >
lar::sparse_vector< T >::range_const_iterator lar::sparse_vector< T >::find_range_iterator ( size_type  index) const

Returns an iterator to the range containing the specified index.

Parameters
indexabsolute index of the element to be sought
Returns
iterator to containing range, or get_ranges().end() if in void
Exceptions
std::out_of_rangeif index is not in the vector
See also
is_void()

Definition at line 1897 of file sparse_vector.h.

1898 {
1899  if (ranges.empty()) throw std::out_of_range("empty sparse vector");
1900  // range after the index:
1902  return ((iNextRange == ranges.begin())
1903  || (index >= (--iNextRange)->end_index()))?
1904  ranges.end(): iNextRange;
1905 } // lar::sparse_vector<T>::find_range_iterator() const
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
range_list_t::const_iterator range_const_iterator
type of constant iterator over ranges
template<typename T>
range_iterator lar::sparse_vector< T >::find_range_iterator ( size_type  index)
inline

Definition at line 772 of file sparse_vector.h.

773  { return ranges.begin() + find_range_number(index); }
std::size_t find_range_number(size_type index) const
Returns the number (0-based) of range containing index.
template<typename T>
std::size_t lar::sparse_vector< T >::find_range_number ( size_type  index) const
inline

Returns the number (0-based) of range containing index.

Parameters
indexabsolute index of the element to be sought
Returns
index of containing range, or n_ranges() if in void
Exceptions
std::out_of_rangeif index is not in the vector
See also
is_void()

Definition at line 783 of file sparse_vector.h.

784  { return find_range_iterator(index) - begin_range(); }
range_const_iterator begin_range() const
Returns a constant iterator to the first data range.
range_const_iterator find_range_iterator(size_type index) const
Returns an iterator to the range containing the specified index.
template<typename T >
lar::sparse_vector< T >::size_type lar::sparse_vector< T >::fix_size ( )
protected

Extends the vector size according to the last range.

Definition at line 2278 of file sparse_vector.h.

2278  {
2279  if (!ranges.empty())
2280  nominal_size = std::max(nominal_size, ranges.back().end_index());
2281  return nominal_size;
2282 } // lar::sparse_vector<T>::fix_size()
static int max(int a, int b)
size_type nominal_size
current size
template<typename T>
const range_list_t& lar::sparse_vector< T >::get_ranges ( ) const
inline

Returns the internal list of non-void ranges.

Definition at line 717 of file sparse_vector.h.

717 { return ranges; }
range_list_t ranges
list of ranges
template<typename T>
range_iterator lar::sparse_vector< T >::insert_range ( range_iterator  iInsert,
const datarange_t data 
)
inlineprotected

Plug a new data range in the specified position; no check performed.

Definition at line 1140 of file sparse_vector.h.

1141  { return data.empty()? iInsert: ranges.insert(iInsert, data); }
template<typename T>
range_iterator lar::sparse_vector< T >::insert_range ( range_iterator  iInsert,
datarange_t &&  data 
)
inlineprotected

Definition at line 1142 of file sparse_vector.h.

1143  { return data.empty()? iInsert: ranges.insert(iInsert, std::move(data)); }
def move(depos, offset)
Definition: depos.py:107
template<typename T>
static value_type lar::sparse_vector< T >::is_equal ( value_type  a,
value_type  b 
)
inlinestatic

Returns whether two values are the same.

Definition at line 1020 of file sparse_vector.h.

1021  { return is_zero(abs(a - b)); }
static value_type abs(value_type v)
Returns the module of the specified value.
const double a
static value_type is_zero(value_type v)
Returns whether the value is exactly zero.
static bool * b
Definition: config.cpp:1043
template<typename T>
static value_type lar::sparse_vector< T >::is_equal ( value_type  a,
value_type  b,
value_type  thr 
)
inlinestatic

Returns whether two values are the same below a given threshold.

Definition at line 1024 of file sparse_vector.h.

1025  { return is_zero(abs(a - b), thr); }
static value_type abs(value_type v)
Returns the module of the specified value.
G4double thr[100]
Definition: G4S2Light.cc:59
const double a
static value_type is_zero(value_type v)
Returns whether the value is exactly zero.
static bool * b
Definition: config.cpp:1043
template<typename T >
bool lar::sparse_vector< T >::is_valid ( ) const

Returns if the vector is in a valid state.

The vector is in a valid state if:

  • no ranges overlap or touch each other (a void gap must exist)
  • no range is empty
  • all ranges are sorted
  • the size of the vector is not smaller than the sum of the size of the ranges plus the internal gaps An invalid state can be the result of “too smart” use of this class, or of a bug, which should be reported to the author.

Definition at line 2126 of file sparse_vector.h.

2126  {
2127  // a sparse vector with no non-null elements can't be detected invalid
2128  if (ranges.empty()) return true;
2129 
2130  range_const_iterator iNext = ranges.begin(), rend = ranges.end();
2131  while (iNext != rend) {
2132  range_const_iterator iRange = iNext++;
2133  if (iRange->empty()) return false;
2134  if (iNext != rend) {
2135  if (!(*iRange < *iNext)) return false;
2136  if (!iRange->separate(*iNext)) return false;
2137  }
2138  } // while
2139  if (nominal_size < ranges.back().end_index()) return false;
2140  return true;
2141 } // lar::sparse_vector<T>::is_valid()
range_list_t::const_iterator range_const_iterator
type of constant iterator over ranges
size_type nominal_size
current size
template<typename T >
bool lar::sparse_vector< T >::is_void ( size_type  index) const

Returns whether the specified position is void.

Parameters
indexposition of the cell to be tested
Exceptions
out_of_rangeif index is not in the vector
See also
is_back_void()

Definition at line 1807 of file sparse_vector.h.

1807  {
1808  if (ranges.empty() || (index >= size()))
1809  throw std::out_of_range("empty sparse vector");
1810  // range after the index:
1812  return ((iNextRange == ranges.begin())
1813  || ((--iNextRange)->end_index() <= index));
1814 } // lar::sparse_vector<T>::is_void()
size_type size() const
Returns the size of the vector.
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
range_list_t::const_iterator range_const_iterator
type of constant iterator over ranges
template<typename T>
static value_type lar::sparse_vector< T >::is_zero ( value_type  v)
inlinestatic

Returns whether the value is exactly zero.

Definition at line 1013 of file sparse_vector.h.

1013 { return v == value_zero; }
static constexpr value_type value_zero
a representation of 0
template<typename T>
static value_type lar::sparse_vector< T >::is_zero ( value_type  v,
value_type  thr 
)
inlinestatic

Returns whether the value is zero below a given threshold.

Definition at line 1016 of file sparse_vector.h.

1017  { return abs(v - value_zero) <= thr; }
static value_type abs(value_type v)
Returns the module of the specified value.
G4double thr[100]
Definition: G4S2Light.cc:59
static constexpr value_type value_zero
a representation of 0
template<typename T>
auto lar::sparse_vector< T >::iterate_ranges ( ) -> decltype(auto)
template<typename T >
void lar::sparse_vector< T >::make_void ( iterator  first,
iterator  last 
)

Makes all the elements from first and before last void.

Definition at line 2069 of file sparse_vector.h.

2069  {
2070  // iterators have in "currentRange" either the range they point into,
2071  // or the range next to the void they point to
2072 
2073  if ((first.cont != this) || (last.cont != this)) {
2074  throw std::runtime_error
2075  ("lar::sparse_vector::make_void(): iterators from alien container");
2076  }
2077  // if first is after next, no range is identified
2078  if (first >= last) return;
2079 
2081  first_range
2082  = ranges.begin() + (first.get_current_range() - ranges.begin()),
2083  last_range = ranges.begin() + (last.get_current_range() - ranges.begin());
2084 
2085  //--- "first": void up to this iterator ---
2086  // if first in the last void region, there is nothing to erase
2087  if (first_range == ranges.end()) return;
2088 
2089  // if first is in the middle of a valid range instead, we have to resize it
2090  if (first.index > first_range->begin_index()) {
2091  if (first_range == last_range) {
2092  // we are going to erase a subset of a range;
2093  // this effectively creates two ranges;
2094  // first create the rightmost (last) range, and add it to the list
2095  last_range = ranges.emplace(++last_range, last.index,
2096  first_range->begin() + first_range->relative_index(last.index),
2097  first_range->end()
2098  );
2099  // then cut the existing one
2100  first_range->move_tail(first.index);
2101  return;
2102  }
2103  first_range->move_tail(first.index);
2104  ++first_range; // from next range on, start voiding
2105  }
2106 
2107  //--- "last"
2108  // if the index is inside a range, remove up to it
2109  if ((last_range != ranges.end()) && (last.index > last_range->begin_index()))
2110  eat_range_head(last_range, last.index);
2111 
2112  // finally, remove entirely the ranges in between
2113  ranges.erase(first_range, last_range);
2114 } // lar::sparse_vector<T>::make_void()
range_iterator eat_range_head(range_iterator iRange, size_t index)
Voids the starting elements up to index (excluded) of a given range.
range_list_t::iterator range_iterator
type of iterator over ranges
template<typename T >
auto lar::sparse_vector< T >::make_void_around ( size_type  index)

Casts the whole range with the specified item into the void.

Parameters
indexabsolute index of the element whose range is cast to void
Returns
the range just voided
Exceptions
std::out_of_rangeif index is not in the vector
See also
unset(), make_void()

Definition at line 1930 of file sparse_vector.h.

1930  {
1931  if (ranges.empty() || (index >= size()))
1932  throw std::out_of_range("empty sparse vector");
1933  // range after the index:
1935  if ((iNextRange == ranges.begin())
1936  || ((--iNextRange)->end_index() <= index))
1937  {
1938  return {};
1939  }
1940  return void_range(iNextRange);
1941 } // lar::sparse_vector<T>::make_void_around()
size_type size() const
Returns the size of the vector.
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
range_list_t::iterator range_iterator
type of iterator over ranges
datarange_t void_range(range_iterator const iRange)
Turns the specified range into void.
template<typename T >
lar::sparse_vector< T >::datarange_t & lar::sparse_vector< T >::merge_ranges ( range_iterator  iRange)
protected

Merges all the following contiguous ranges.

Parameters
iRangeiterator to the range to merge the following ones into
Returns
iterator to the merged range

Starting from the range next to iRange, if that range is contiguous to iRange the two are merged. The merging continues while there are ranges contiguous to iRange. In the end, an iterator is returned pointing to a range that has the same starting point that iRange had, and that is not followed by a contiuguous range, since all contiguous ranges have been merged into it.

Definition at line 2248 of file sparse_vector.h.

2249 {
2250  range_iterator iNext = iRange + 1;
2251  while (iNext != ranges.end()) {
2252  if (!iRange->borders(iNext->begin_index())) break;
2253  // iRange content dominates, but if iNext has data beyond it,
2254  // then we copy it
2255  if (iNext->end_index() > iRange->end_index()) {
2256  iRange->extend
2257  (iRange->end_index(), iNext->get_iterator(iRange->end_index()), iNext->end());
2258  }
2259  iNext = ranges.erase(iNext);
2260  } // while
2261  fix_size();
2262  return *iRange;
2263 } // lar::sparse_vector<T>::merge_ranges()
size_type fix_size()
Extends the vector size according to the last range.
range_list_t::iterator range_iterator
type of iterator over ranges
template<typename T >
size_t lar::sparse_vector< T >::min_gap ( )
inlinestatic

Minimum optimal gap between ranges (a guess)

Definition at line 2298 of file sparse_vector.h.

2298  {
2299  // we assume here that there is no additional overhead by alignment;
2300  // the gap adds the space of another datarange_t, including the vector,
2301  // its data and overhead from heap (apparently, 8 bytes);
2302  //
2303  return (sizeof(datarange_t) + 8) / sizeof(value_type) + 1; // round up
2304 } // lar::sparse_vector<T>::min_gap()
T value_type
type of the stored values
template<typename T>
size_type lar::sparse_vector< T >::minimum_size ( ) const
inlineprotected

Returns the size determined by the ranges already present.

Definition at line 1135 of file sparse_vector.h.

1136  { return ranges.empty()? 0: ranges.back().end_index(); }
template<typename T>
size_type lar::sparse_vector< T >::n_ranges ( ) const
inline

Returns the internal list of non-void ranges.

Definition at line 721 of file sparse_vector.h.

721 { return ranges.size(); }
template<typename T>
sparse_vector& lar::sparse_vector< T >::operator= ( sparse_vector< T > const &  )
default

Copy assignment: default.

template<typename T>
sparse_vector& lar::sparse_vector< T >::operator= ( sparse_vector< T > &&  from)
inline

Move assignment.

Definition at line 534 of file sparse_vector.h.

535  {
536  ranges = std::move(from.ranges);
537  nominal_size = from.nominal_size;
538  from.nominal_size = 0;
539  return *this;
540  } // operator= (sparse_vector&&)
def move(depos, offset)
Definition: depos.py:107
size_type nominal_size
current size
template<typename T >
lar::sparse_vector< T >::value_type lar::sparse_vector< T >::operator[] ( size_type  index) const

Access to an element (read only)

Definition at line 1770 of file sparse_vector.h.

1771 {
1772  // first range not including the index
1774 
1775  // if not even the first range includes the index, we are in the void
1776  // (or in some negative index space, if index signedness allowed);
1777  if (iNextRange == ranges.begin()) return value_zero;
1778 
1779  // otherwise, let's take the previous range;
1780  // if it includes the index, we return its value;
1781  // or it precedes it, and our index is in the void: return zero
1782  const datarange_t& range(*--iNextRange);
1783  return (index < range.end_index())? range[index]: value_zero;
1784 } // lar::sparse_vector<T>::operator[]
const datarange_t & range(size_t i) const
Returns the i-th non-void range (zero-based)
static constexpr value_type value_zero
a representation of 0
size_type end_index() const
Returns the first absolute index not included in the range.
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
range_list_t::const_iterator range_const_iterator
type of constant iterator over ranges
template<typename T >
lar::sparse_vector< T >::reference lar::sparse_vector< T >::operator[] ( size_type  index)

Access to an element (read/write for non-void elements only!)

Definition at line 1789 of file sparse_vector.h.

1790 {
1791  // first range not including the index
1793 
1794  // if not even the first range includes the index, we are in the void
1795  // (or in some negative index space, if index signedness allowed);
1796  if (iNextRange == ranges.begin()) return reference();
1797 
1798  // otherwise, let's take the previous range;
1799  // if it includes the index, we return its value;
1800  // or it precedes it, and our index is in the void: return zero
1801  datarange_t& range(*--iNextRange);
1802  return (index < range.end_index())? reference(range[index]): reference();
1803 } // lar::sparse_vector<T>::operator[]
const datarange_t & range(size_t i) const
Returns the i-th non-void range (zero-based)
size_type end_index() const
Returns the first absolute index not included in the range.
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
range_list_t::iterator range_iterator
type of iterator over ranges
template<typename T>
bool lar::sparse_vector< T >::optimize ( )
inline

Performs internal optimization, returns whether the object was changed.

Definition at line 1000 of file sparse_vector.h.

1000 { return optimize(min_gap()); }
static size_t min_gap()
Minimum optimal gap between ranges (a guess)
bool optimize()
Performs internal optimization, returns whether the object was changed.
template<typename T>
bool lar::sparse_vector< T >::optimize ( size_t  )
inline

Definition at line 1001 of file sparse_vector.h.

1001 { return false; /* no optimization implemented yet */ }
template<typename T>
void lar::sparse_vector< T >::push_back ( value_type  value)
inline

Adds one element to the end of the vector (zero values too)

Parameters
valuevalue to be added

Definition at line 642 of file sparse_vector.h.

642 { resize(size() + 1, value); }
void resize(size_type new_size)
Resizes the vector to the specified size, adding void.
size_type size() const
Returns the size of the vector.
template<typename T>
void lar::sparse_vector< T >::push_back ( value_type  value,
value_type  thr 
)
inline

Adds one element to the end of the vector (if zero, just adds void)

Parameters
valuevalue to be added
thrthreshold below which the value is considered zero

If the threshold is strictly negative, all values are pushed back

Definition at line 651 of file sparse_vector.h.

652  {
653  if (is_zero(value, thr)) resize(size() + 1);
654  else push_back(value);
655  } // push_back()
void resize(size_type new_size)
Resizes the vector to the specified size, adding void.
G4double thr[100]
Definition: G4S2Light.cc:59
size_type size() const
Returns the size of the vector.
static value_type is_zero(value_type v)
Returns whether the value is exactly zero.
void push_back(value_type value)
template<typename T>
const datarange_t& lar::sparse_vector< T >::range ( size_t  i) const
inline

Returns the i-th non-void range (zero-based)

Definition at line 724 of file sparse_vector.h.

724 { return ranges[i]; }
template<typename T >
auto lar::sparse_vector< T >::range_const_data ( std::size_t  i) const

Like range_data() but with explicitly read-only access to data.

Definition at line 1891 of file sparse_vector.h.

1892  { auto& r = ranges[i]; return details::iteratorRange(r.cbegin(), r.cend()); }
template<typename T >
auto lar::sparse_vector< T >::range_data ( std::size_t  i)

Provides direct access to data of i-th non-void range (zero-based)

Parameters
iindex of the range
Returns
an object suitable for ranged-for iteration

No information about the positioning of the range itself is provided, which can be obtained with other means (e.g. range(i).begin_index()). The returned object can be used in a ranged-for loop:

for (std::size_t iRange = 0; iRange < sv.n_ranges(); ++iRange) {
for (auto& value: sv.range_data(iRange)) {
v *= 2.0;
}
}

(with sv a lar::sparse_vector instance).

While this is a somehow clumsier interface than get_ranges(), it allows, using the non-const version, write access to the data elements. It intentionally provides no write access to the location of each range, though.

Definition at line 1887 of file sparse_vector.h.

1888  { auto& r = ranges[i]; return details::iteratorRange(r.begin(), r.end()); }
template<typename T>
auto lar::sparse_vector< T >::range_data ( std::size_t const  i) const
inline

Definition at line 750 of file sparse_vector.h.

750 { return range_const_data(i); }
auto range_const_data(std::size_t i) const
Like range_data() but with explicitly read-only access to data.
template<typename T >
void lar::sparse_vector< T >::resize ( size_type  new_size)

Resizes the vector to the specified size, adding void.

Definition at line 1710 of file sparse_vector.h.

1710  {
1711  if (new_size >= size()) {
1712  nominal_size = new_size;
1713  return;
1714  }
1715 
1716  // truncating...
1717  range_iterator iLastRange = find_next_range_iter(new_size);
1718  ranges.erase(iLastRange, ranges.end());
1719  if (!ranges.empty()) {
1720  range_iterator iLastRange = ranges.end() - 1;
1721  if (new_size == iLastRange->begin_index())
1722  ranges.erase(iLastRange);
1723  else if (new_size < iLastRange->end_index())
1724  iLastRange->resize(new_size - iLastRange->begin_index());
1725  } // if we have ranges
1726 
1727  // formally resize
1728  nominal_size = new_size;
1729 } // lar::sparse_vector<T>::resize()
size_type size() const
Returns the size of the vector.
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
size_type nominal_size
current size
range_list_t::iterator range_iterator
type of iterator over ranges
template<typename T >
void lar::sparse_vector< T >::resize ( size_type  new_size,
value_type  def_value 
)

Resizes the vector to the specified size, adding def_value.

Definition at line 1733 of file sparse_vector.h.

1733  {
1734  if (new_size == size()) return;
1735  if (new_size > size()) {
1736 
1737  if (back_is_void()) // add a new range
1738  append(vector_t(new_size - size(), def_value));
1739  else // extend the last range
1740  ranges.back().resize(new_size - ranges.back().begin_index(), def_value);
1741 
1742  nominal_size = new_size;
1743  return;
1744  }
1745  // truncating is the same whether there is a default value or not
1746  resize(new_size);
1747 } // lar::sparse_vector<T>::resize()
std::vector< value_type > vector_t
type of STL vector holding this data
void resize(size_type new_size)
Resizes the vector to the specified size, adding void.
size_type size() const
Returns the size of the vector.
bool back_is_void() const
Returns whether the sparse vector ends with void.
const datarange_t & append(ITER first, ITER last)
Adds a sequence of elements as a range at the end of the vector.
size_type nominal_size
current size
template<typename T >
lar::sparse_vector< T >::value_type & lar::sparse_vector< T >::set_at ( size_type  index,
value_type  value 
)

Writes into an element (creating or expanding a range if needed)

Parameters
indexthe index of the element to set
valuethe value to be set
Returns
a reference to the changed value
See also
unset_at()

Note that setting the value to zero will not cast the element into void. Use unset_at for that.

Definition at line 1829 of file sparse_vector.h.

1830 {
1831  // first range not including the index
1833 
1834  // if not even the first range includes the index, we are in the void
1835  // (or in some negative index space, if index signedness allowed);
1836  if (iNextRange != ranges.begin()) {
1837  // otherwise, let's take the previous range;
1838  // if it includes the index, we set the existing value;
1839  // or it precedes it, and our index is in the void, add the value as a
1840  // range
1841  datarange_t& range(*std::prev(iNextRange));
1842  if (index < range.end_index()) return range[index] = value;
1843  }
1844  // so we are in the void; add the value as a new range
1845  return const_cast<datarange_t&>(add_range(index, { value }))[index];
1846 } // lar::sparse_vector<T>::set_at()
const datarange_t & range(size_t i) const
Returns the i-th non-void range (zero-based)
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
size_type end_index() const
Returns the first absolute index not included in the range.
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
range_list_t::iterator range_iterator
type of iterator over ranges
template<typename T >
bool lar::sparse_vector< T >::should_merge ( const typename datarange_t::base_t a,
const typename datarange_t::base_t b 
)
inlinestatic

Returns if merging the two specified ranges would save memory.

Definition at line 2308 of file sparse_vector.h.

2312 {
2313  size_type gap_size = (a < b)?
2314  b.begin_index() - a.begin_index() - a.size():
2315  a.begin_index() - b.begin_index() - b.size();
2316  return expected_vector_size(a.size() + b.size() + gap_size)
2317  <= expected_vector_size(a.size()) + expected_vector_size(b.size());
2318 } // lar::sparse_vector<T>::should_merge()
static size_t expected_vector_size(size_t size)
Returns the expected size taken by a vector of specified size.
vector_t::size_type size_type
size type
const double a
static bool * b
Definition: config.cpp:1043
template<typename T>
size_type lar::sparse_vector< T >::size ( void  ) const
inline

Returns the size of the vector.

Definition at line 562 of file sparse_vector.h.

562 { return nominal_size; }
size_type nominal_size
current size
template<typename T >
void lar::sparse_vector< T >::unset_at ( size_type  index)

Casts the element with the specified index into the void.

Definition at line 1850 of file sparse_vector.h.

1850  {
1851  // first range not including the index
1853 
1854  // if not even the first range includes the index, we are in the void
1855  // (or in some negative index space, if index signedness allowed);
1856  if (iNextRange == ranges.begin()) return;
1857 
1858  // otherwise, let's take the previous range;
1859  // or it precedes the index, and our index is in the void
1860  datarange_t& range(*--iNextRange);
1861  if (index >= range.end_index()) return; // void already
1862 
1863  // it includes the index:
1864  // - if it's a one-element range, remove the range
1865  if (range.size() == 1) ranges.erase(iNextRange);
1866  // - if it's on a border, resize the range
1867  else if (index == range.begin_index())
1868  range.move_head(index + 1);
1869  else if (index == range.end_index() - 1)
1871  // - if it's inside, break the range in two
1872  else if (index < range.end_index()) {
1873  // we are going to put a hole in a range;
1874  // this effectively creates two ranges;
1875  // first create the rightmost range, and add it to the list
1876  ranges.emplace(++iNextRange, index + 1,
1878  range.end()
1879  );
1880  // then cut the existing one
1882  }
1883 } // lar::sparse_vector<T>::unset_at()
const datarange_t & range(size_t i) const
Returns the i-th non-void range (zero-based)
size_type begin_index() const
Returns the first absolute index included in the range.
void move_tail(size_type to_index, value_type def_value=value_zero)
Moves the end of this range.
size_type end_index() const
Returns the first absolute index not included in the range.
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index.
void move_head(size_type to_index, value_type def_value=value_zero)
Moves the begin of this range.
size_type size() const
Returns the size of the range.
range_list_t::iterator range_iterator
type of iterator over ranges
iterator begin()
begin and end iterators
size_type relative_index(size_type index) const
Returns the position within the range of the absolute index specified.
template<typename T >
auto lar::sparse_vector< T >::void_range ( range_iterator const  iRange)

Turns the specified range into void.

Parameters
iRangeiterator or index of range to be deleted
Returns
the range just voided
See also
make_void(), unset_at()

The range is effectively removed from the sparse vector, rendering void the interval it previously covered. The range object itself is returned (no copy is performed).

The specified range must be valid. Trying to void an invalid range (including end_range()) yields undefined behavior.

Definition at line 2118 of file sparse_vector.h.

2118  {
2119  auto r { std::move(*iRange) }; // triggering move constructor
2120  ranges.erase(iRange); // the emptied range is removed from vector
2121  return r; // returning it as a temporary avoids copies
2122 } // lar::sparse_vector<T>::void_range()
def move(depos, offset)
Definition: depos.py:107
template<typename T>
datarange_t lar::sparse_vector< T >::void_range ( std::size_t const  iRange)
inline

Definition at line 973 of file sparse_vector.h.

974  { return void_range(ranges.begin() + iRange); }
datarange_t void_range(range_iterator const iRange)
Turns the specified range into void.

Member Data Documentation

template<typename T>
size_type lar::sparse_vector< T >::nominal_size
protected

current size

Definition at line 1046 of file sparse_vector.h.

template<typename T>
range_list_t lar::sparse_vector< T >::ranges
protected

list of ranges

Definition at line 1047 of file sparse_vector.h.

template<typename T>
constexpr lar::sparse_vector< T >::value_type lar::sparse_vector< T >::value_zero {0}
static

a representation of 0

Definition at line 1007 of file sparse_vector.h.


The documentation for this class was generated from the following file: