Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F91569398
cached_vector.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Nov 12, 07:21
Size
12 KB
Mime Type
text/x-c++
Expires
Thu, Nov 14, 07:21 (2 d)
Engine
blob
Format
Raw Data
Handle
22284562
Attached To
rSPECMICP SpecMiCP / ReactMiCP
cached_vector.hpp
View Options
/* =============================================================================
Copyright (c) 2014 - 2016
F. Georget <fabieng@princeton.edu> Princeton University
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
============================================================================= */
#ifndef SPECMICP_REACTMICP_CACHEDVECTOR_HPP
#define SPECMICP_REACTMICP_CACHEDVECTOR_HPP
//! \file utils/cached_vector.hpp
//! \brief Vector with cache
#include <vector>
#include <string>
#include <utility>
#include <stdexcept>
#include <algorithm>
#include <type_traits>
namespace
specmicp
{
namespace
utils
{
//! \brief A vector with cache
//!
//! This vector is designed to simulate a large vector with only a few different
//! values of type T, where T is 'big'
//!
//! \tparam T must be copyable, assignable, default constructible
template
<
typename
T
>
class
CachedVector
{
class
CachedIterator
;
public
:
using
value_type
=
T
;
using
reference
=
T
&
;
using
const_reference
=
const
T
&
;
using
size_type
=
std
::
size_t
;
using
iterator
=
CachedIterator
;
using
const_iterator
=
const
CachedIterator
;
using
index_vector
=
std
::
vector
<
size_type
>
;
//! \brief Default constructor, an empty vector
CachedVector
()
{}
//! \brief Initialize a 'size' vector with value T
CachedVector
(
size_type
size
,
T
&&
value
)
:
m_cache
({
std
::
forward
<
T
>
(
value
),}),
m_indexes
(
size
,
0
)
{}
//! \brief Initialize a 'size' vector with default T
CachedVector
(
size_type
size
,
typename
std
::
enable_if
<
std
::
is_default_constructible
<
T
>::
value
>::
type
*
=
nullptr
)
:
m_cache
(),
m_indexes
(
size
,
0
)
{
m_cache
.
emplace_back
();
}
//! \brief Reserve storage
void
reserve
(
size_type
size_cap
)
{
m_indexes
.
reserve
(
size_cap
);
}
//! \brief Reserve cache storage
void
reserve_cache
(
size_type
size_cap
)
{
m_cache
.
reserve
(
size_cap
);
}
//! \brief Access specified element
reference
operator
[]
(
size_type
pos
)
{
return
m_cache
[
m_indexes
[
pos
]];
}
//! \brief Access specified element
const_reference
operator
[]
(
size_type
pos
)
const
{
return
m_cache
[
m_indexes
[
pos
]];
}
//! \brief Access specified element with bounds checking
reference
at
(
size_type
pos
)
{
std
::
size_t
ind
=
m_indexes
.
at
(
pos
);
return
m_cache
.
at
(
ind
);
}
//! \brief Access specified element with bounds checking
const_reference
at
(
size_type
pos
)
const
{
std
::
size_t
ind
=
m_indexes
.
at
(
pos
);
return
m_cache
.
at
(
ind
);
}
//! \brief Return a reference to the position in the cache
size_type
&
operator
()
(
size_type
pos
)
{
return
m_indexes
[
pos
];
}
//! \brief Return a reference to the position in the cache
const
size_type
&
operator
()
(
size_type
pos
)
const
{
return
m_indexes
[
pos
];
}
//! \brief Return the cached value
reference
get
(
size_t
pos_cache
)
{
return
m_cache
[
pos_cache
];
}
//! \brief Return the cached value
const_reference
get
(
size_t
pos_cache
)
const
{
return
m_cache
[
pos_cache
];
}
//! \brief Return the size of the vector
size_type
size
()
const
{
return
m_indexes
.
size
();
}
//! \brief Return the size of the cache
size_type
size_cache
()
const
{
return
m_cache
.
size
();
}
//! \brief Push an element to the cache
//!
//! \param value The element to add
//! \return the position of the element in the cache
size_type
push_back_cache
(
T
&&
value
)
{
m_cache
.
push_back
(
std
::
forward
<
T
>
(
value
));
return
(
m_cache
.
size
()
-
1
);
}
//! \brief Emplace a new element to the cache
template
<
typename
...
Args
>
size_type
emplace_back_cache
(
Args
...
args
)
{
m_cache
.
emplace_back
(
args
...);
return
(
m_cache
.
size
()
-
1
);
}
//! \brief Adds an element to the end
//!
//! \param index_t refers to a position in the cache
void
push_back
(
size_type
index
)
{
m_indexes
.
push_back
(
index
);
}
//! \brief Adds an element to the end and a new value to the cache
//!
//! \param value a new value
void
push_back
(
T
&&
value
)
{
auto
ind
=
push_back_cache
(
std
::
forward
<
T
>
(
value
));
m_indexes
.
push_back
(
ind
);
}
//! \brief Add a new element at the end and build a new element to the cache
template
<
typename
...
Args
>
void
emplace_back
(
Args
...
args
)
{
auto
ind
=
emplace_back_cache
(
args
...);
m_indexes
.
push_back
(
ind
);
}
//! \brief Fork the value at the given position
reference
fork
(
size_type
pos
)
{
m_cache
.
push_back
(
m_cache
[
m_indexes
[
pos
]]);
m_indexes
[
pos
]
=
m_cache
.
size
()
-
1
;
return
m_cache
.
back
();
}
//! \brief Set the value to another
//!
//! Don't check the validity of the value !
void
set
(
size_type
pos
,
size_type
pos_cache
)
{
m_indexes
[
pos
]
=
pos_cache
;
}
// Iterator business
//! \brief Return an iterator to the beginning
iterator
begin
()
{
return
CachedIterator
(
m_indexes
.
begin
(),
m_cache
);
}
//! \brief Return an iterator to the end
iterator
end
()
{
return
CachedIterator
(
m_indexes
.
end
(),
m_cache
);
}
//! \brief Return an iterator to the beginning
const_iterator
cbegin
()
const
{
return
CachedIterator
(
m_indexes
.
begin
(),
m_cache
);
}
//! \brief Return an iterator to the end
const_iterator
cend
()
const
{
return
CachedIterator
(
m_indexes
.
end
(),
m_cache
);
}
//! \brief Return an iterator to the beginning of the indexes
index_vector
::
iterator
begin_index
()
{
return
m_indexes
.
begin
();
}
//! \brief Return an iterator to the end of the indexes
index_vector
::
iterator
end_index
()
{
return
m_indexes
.
end
();
}
//! \brief Return an iterator to the beginning of the indexes
index_vector
::
const_iterator
cbegin_index
()
const
{
return
m_indexes
.
cbegin
();
}
//! \brief Return an iterator to the end of the indexes
index_vector
::
const_iterator
cend_index
()
const
{
return
m_indexes
.
cend
();
}
private
:
//! \brief The iterator
class
CachedIterator
:
public
std
::
vector
<
size_type
>::
iterator
{
using
base
=
std
::
vector
<
size_type
>
;
using
base_iterator
=
base
::
iterator
;
public
:
CachedIterator
(
const
base_iterator
&
base
,
std
::
vector
<
T
>&
cache
)
:
base_iterator
(
base
),
m_cache
(
cache
)
{}
CachedIterator
(
std
::
size_t
pos
,
std
::
vector
<
T
>&
cache
)
:
base_iterator
(),
m_cache
(
cache
)
{
advance
(
static_cast
<
base_iterator
&>
(
*
this
),
pos
-
1
);
}
T
&
operator
*
()
{
return
m_cache
[
base_iterator
::
operator
*
()];
}
const
T
&
operator
*
()
const
{
return
m_cache
[
base_iterator
::
operator
*
()];
}
private
:
std
::
vector
<
T
>&
m_cache
;
};
private
:
std
::
vector
<
T
>
m_cache
;
std
::
vector
<
size_type
>
m_indexes
;
};
//! \brief A name cached vector
//!
//! Every cache value has an associated name
template
<
typename
T
>
class
NameCachedVector
:
public
CachedVector
<
T
>
{
public
:
using
size_type
=
typename
CachedVector
<
T
>::
size_type
;
using
reference
=
typename
CachedVector
<
T
>::
reference
;
using
const_reference
=
typename
CachedVector
<
T
>::
const_reference
;
NameCachedVector
()
:
CachedVector
<
T
>
()
{}
NameCachedVector
(
size_type
size
,
std
::
string
name
,
T
&&
value
)
:
CachedVector
<
T
>
(
size
,
std
::
forward
<
T
>
(
value
)),
m_names
({
name
,
})
{}
NameCachedVector
(
size_type
size
,
std
::
string
name
,
typename
std
::
enable_if
<
std
::
is_default_constructible
<
T
>::
value
>::
type
*
=
nullptr
)
:
CachedVector
<
T
>
(
size
),
m_names
({
name
,
})
{}
//! \brief Reserve cache storage
void
reserve_cache
(
size_type
size_cap
)
{
CachedVector
<
T
>::
reserve_cache
(
size_cap
);
m_names
.
reserve
(
size_cap
);
}
//! \brief Push an element to the cache
//!
//! \param value The element to add
//! \return the position of the element in the cache
size_type
push_back_cache
(
const
std
::
string
&
name
,
T
&&
value
)
{
m_names
.
push_back
(
name
);
return
CachedVector
<
T
>::
push_back_cache
(
std
::
forward
<
T
>
(
value
));
}
//! \brief Emplace a new element to the cache
template
<
typename
...
Args
>
size_type
emplace_back_cache
(
const
std
::
string
&
name
,
Args
...
args
)
{
m_names
.
push_back
(
name
);
return
CachedVector
<
T
>::
emplace_back_cache
(
args
...);
}
//! \brief Adds an element to the end and a new value to the cache
//!
//! \param value a new value
void
push_back
(
const
std
::
string
&
name
,
T
&&
value
)
{
CachedVector
<
T
>::
push_back
(
std
::
forward
<
T
>
(
value
));
m_names
.
push_back
(
name
);
}
//! \brief Add a new element at the end and build a new element to the cache
template
<
typename
...
Args
>
void
emplace_back
(
const
std
::
string
&
name
,
Args
...
args
)
{
CachedVector
<
T
>::
emplace_back
(
args
...);
m_names
.
push_back
(
name
);
}
//! \brief Return the value stored as "name"
reference
get
(
std
::
string
name
)
{
return
CachedVector
<
T
>::
get
(
get_cache_position
(
name
));
}
//! \brief Return the value stored as "name"
const_reference
get
(
std
::
string
name
)
const
{
return
CachedVector
<
T
>::
get
(
get_cache_position
(
name
));
}
bool
has_value
(
std
::
string
name
)
const
{
auto
it
=
std
::
find
(
m_names
.
cbegin
(),
m_names
.
cend
(),
name
);
return
(
it
!=
m_names
.
cend
());
}
//! \brief Fork the value at the given position
reference
fork
(
size_type
pos
,
const
std
::
string
&
name
)
{
m_names
.
push_back
(
name
);
return
CachedVector
<
T
>::
fork
(
pos
);
}
//! \brief Fork the value of a given name
reference
fork
(
const
std
::
string
&
old_name
,
const
std
::
string
&
new_name
)
{
auto
&&
val
=
get
(
old_name
);
auto
pos
=
push_back_cache
(
new_name
,
std
::
forward
<
T
>
(
val
));
return
CachedVector
<
T
>::
get
(
pos
);
}
//! \brief Set the given node to the value 'name'
void
set
(
size_type
pos
,
const
std
::
string
&
name
)
{
CachedVector
<
T
>::
set
(
pos
,
get_cache_position
(
name
));
}
//! \brief Return the position in the cache
size_type
get_cache_position
(
const
std
::
string
&
name
)
const
{
auto
it
=
std
::
find
(
m_names
.
cbegin
(),
m_names
.
cend
(),
name
);
if
(
it
==
m_names
.
cend
())
{
throw
std
::
invalid_argument
(
"Unknow value in NamedCachedVector '"
+
name
+
"'."
);
}
return
(
it
-
m_names
.
cbegin
());
}
private
:
std
::
vector
<
std
::
string
>
m_names
;
};
}
//end namespace utils
}
//end namespace specmicp
#endif
// SPECMICP_REACTMICP_CACHEDVECTOR_HPP
Event Timeline
Log In to Comment