Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 41 additions & 23 deletions src/core/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,38 +39,55 @@ template <class T> class Array {
int m_offset;
std::vector<T> m_data;

bool is_in_range(const int p_index) const
{
return p_index >= m_offset && p_index <= back_index();
}

public:
using iterator = typename std::vector<T>::iterator;
using const_iterator = typename std::vector<T>::const_iterator;
using value_type = typename std::vector<T>::value_type;
using reference = typename std::vector<T>::reference;
using const_reference = typename std::vector<T>::const_reference;

explicit Array(size_t len = 0) : m_offset(1), m_data(len) {}
Array(int lo, int hi) : m_offset(lo), m_data(hi - lo + 1) {}
Array(const Array<T> &) = default;
explicit Array(size_t p_length = 0) : m_offset(1), m_data(p_length) {}
/// Construct an array with the given index bounds.
/// If p_high is less than p_low, the resulting array will have
/// front_index equal to p_low, and size 0.
explicit Array(const int p_low, const int p_high) : m_offset(p_low)
{
if (p_high >= p_low) {
m_data.resize(p_high - p_low + 1);
}
}
Array(const Array &) = default;
Array(Array &&) noexcept = default;
~Array() = default;

Array<T> &operator=(const Array<T> &) = default;

bool operator==(const Array<T> &a) const { return m_offset == a.m_offset && m_data == a.m_data; }
Array &operator=(const Array &) = default;
Array &operator=(Array &&) noexcept = default;

bool operator!=(const Array<T> &a) const { return m_offset != a.m_offset || m_data != a.m_data; }
bool operator==(const Array &p_other) const
{
return m_offset == p_other.m_offset && m_data == p_other.m_data;
}
bool operator!=(const Array &p_other) const { return !(*this == p_other); }

const_reference operator[](int index) const
const_reference operator[](const int p_index) const
{
if (index < m_offset || index > back_index()) {
if (!is_in_range(p_index)) {
throw std::out_of_range("Index out of range in Array");
}
return m_data.at(index - m_offset);
return m_data.at(p_index - m_offset);
}

reference operator[](int index)
reference operator[](const int p_index)
{
if (index < m_offset || index > back_index()) {
if (!is_in_range(p_index)) {
throw std::out_of_range("Index out of range in Array");
}
return m_data[index - m_offset];
return m_data.at(p_index - m_offset);
}
const T &front() const { return m_data.front(); }
T &front() { return m_data.front(); }
Expand All @@ -84,25 +101,26 @@ template <class T> class Array {
const_iterator cbegin() const { return m_data.cbegin(); }
const_iterator cend() const { return m_data.cend(); }

bool empty() const { return m_data.empty(); }
size_t size() const { return m_data.size(); }
int front_index() const { return m_offset; }
int back_index() const { return m_offset + m_data.size() - 1; }
[[nodiscard]] bool empty() const noexcept { return m_data.empty(); }
[[nodiscard]] size_t size() const noexcept { return m_data.size(); }
[[nodiscard]] int front_index() const noexcept { return m_offset; }
[[nodiscard]] int back_index() const { return m_offset + m_data.size() - 1; }

void clear() { m_data.clear(); }
void insert(const_iterator pos, const T &value) { m_data.insert(pos, value); }
void erase(iterator pos) { m_data.erase(pos); }
void erase_at(const int p_index)
{
if (!is_in_range(p_index)) {
throw std::out_of_range("Index out of range in Array");
}
erase(std::next(begin(), p_index - front_index()));
}
void push_back(const T &value) { m_data.push_back(value); }
void pop_back() { m_data.pop_back(); }
void reserve(size_t len) { m_data.reserve(len); }
};

/// Convenience function to erase the element at `p_index`
template <class T> void erase_atindex(Array<T> &p_array, int p_index)
{
p_array.erase(std::next(p_array.begin(), p_index - p_array.front_index()));
}

} // end namespace Gambit

#endif // GAMBIT_CORE_ARRAY_H
11 changes: 6 additions & 5 deletions src/core/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ namespace Gambit {
/// Note importantly that the index operator [] is **1-based** - that is, the first
/// element of the list is 1, not 0.
template <class T> class List {
private:
std::list<T> m_list;

public:
Expand All @@ -53,10 +52,12 @@ template <class T> class List {
using size_type = typename std::list<T>::size_type;

List() = default;
List(const List<T> &) = default;
List(const List &) = default;
List(List &&) noexcept = default;
List &operator=(List &&) noexcept = default;
~List() = default;

List<T> &operator=(const List<T> &) = default;
List &operator=(const List &) = default;

const T &operator[](size_type p_index) const
{
Expand Down Expand Up @@ -109,8 +110,8 @@ template <class T> class List {
/// Returns a reference to the last element in the list container.
const T &back() const { return m_list.back(); }

bool operator==(const List<T> &b) const { return m_list == b.m_list; }
bool operator!=(const List<T> &b) const { return m_list != b.m_list; }
bool operator==(const List &b) const { return m_list == b.m_list; }
bool operator!=(const List &b) const { return m_list != b.m_list; }

/// Return a forward iterator starting at the beginning of the list
iterator begin() { return m_list.begin(); }
Expand Down
100 changes: 51 additions & 49 deletions src/core/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,44 +35,39 @@ template <class T> class Matrix;
template <class T> class Vector {
Array<T> m_data;

// check vector for identical boundaries
bool Check(const Vector<T> &v) const
bool is_conformable(const Vector &p_other) const
{
return v.front_index() == front_index() && v.size() == size();
return p_other.front_index() == front_index() && p_other.size() == size();
}

public:
using iterator = typename std::vector<T>::iterator;
using const_iterator = typename std::vector<T>::const_iterator;
using iterator = typename Array<T>::iterator;
using const_iterator = typename Array<T>::const_iterator;

/// Create a vector of length len, starting at 1
explicit Vector(size_t len = 0) : m_data(len) {}
/// Create a vector indexed from low to high
Vector(int low, int high) : m_data(low, high) {}
/// Copy constructor
Vector(const Vector<T> &) = default;
/// Destructor
Vector(Vector &&) noexcept = default;
Vector(const Vector &) = default;
~Vector() = default;

/// Assignment operator: requires vectors to have same index range
Vector<T> &operator=(const Vector<T> &v)
Vector &operator=(Vector &&v) noexcept = default;
Vector &operator=(const Vector &v)
{
if (!Check(v)) {
if (!is_conformable(v)) {
throw DimensionException();
}
m_data = v.m_data;
return *this;
}
/// Assigns the value c to all components of the vector
Vector<T> &operator=(const T &c)
Vector &operator=(const T &c)
{
std::fill(m_data.begin(), m_data.end(), c);
return *this;
}

int front_index() const { return m_data.front_index(); }
int back_index() const { return m_data.back_index(); }
size_t size() const { return m_data.size(); }
int front_index() const noexcept { return m_data.front_index(); }
int back_index() const noexcept { return m_data.back_index(); }
size_t size() const noexcept { return m_data.size(); }

const T &front() const { return m_data.front(); }
T &front() { return m_data.front(); }
Expand All @@ -89,106 +84,113 @@ template <class T> class Vector {
const_iterator cbegin() const { return m_data.cbegin(); }
const_iterator cend() const { return m_data.cend(); }

Vector<T> operator+(const Vector<T> &v) const
Vector operator+(const Vector &v) const
{
if (!Check(v)) {
if (!is_conformable(v)) {
throw DimensionException();
}
Vector<T> tmp(front_index(), back_index());
Vector tmp(front_index(), back_index());
std::transform(m_data.cbegin(), m_data.cend(), v.m_data.cbegin(), tmp.m_data.begin(),
std::plus<>());
return tmp;
}

Vector<T> &operator+=(const Vector<T> &v)
Vector &operator+=(const Vector &v)
{
if (!Check(v)) {
if (!is_conformable(v)) {
throw DimensionException();
}
std::transform(m_data.cbegin(), m_data.cend(), v.m_data.cbegin(), m_data.begin(),
std::plus<>());
return *this;
}

Vector<T> operator-(const Vector<T> &v) const
Vector operator-(const Vector &v) const
{
if (!Check(v)) {
if (!is_conformable(v)) {
throw DimensionException();
}
Vector<T> tmp(front_index(), back_index());
Vector tmp(front_index(), back_index());
std::transform(m_data.cbegin(), m_data.cend(), v.m_data.cbegin(), tmp.m_data.begin(),
std::minus<>());
return tmp;
}

Vector<T> &operator-=(const Vector<T> &v)
Vector &operator-=(const Vector &v)
{
if (!Check(v)) {
if (!is_conformable(v)) {
throw DimensionException();
}
std::transform(m_data.cbegin(), m_data.cend(), v.m_data.cbegin(), m_data.begin(),
std::minus<>());
return *this;
}

Vector<T> operator*(const T &c) const
Vector operator*(const T &c) const
{
Vector<T> tmp(front_index(), back_index());
Vector tmp(front_index(), back_index());
std::transform(m_data.cbegin(), m_data.cend(), tmp.m_data.begin(),
[&](const T &v) { return v * c; });
[&c](const T &v) { return v * c; });
return tmp;
}

Vector<T> &operator*=(const T &c)
Vector &operator*=(const T &c)
{
std::transform(m_data.cbegin(), m_data.cend(), m_data.begin(),
[&](const T &v) { return v * c; });
std::transform(m_data.begin(), m_data.end(), m_data.begin(),
[&c](const T &v) { return v * c; });
return *this;
}

T operator*(const Vector<T> &v) const
T operator*(const Vector &v) const
{
if (!Check(v)) {
if (!is_conformable(v)) {
throw DimensionException();
}
return std::inner_product(m_data.begin(), m_data.end(), v.m_data.begin(), static_cast<T>(0));
return std::inner_product(m_data.cbegin(), m_data.cend(), v.m_data.cbegin(),
static_cast<T>(0));
}

Vector<T> operator/(const T &c) const
Vector operator/(const T &c) const
{
Vector<T> tmp(front_index(), back_index());
Vector tmp(front_index(), back_index());
std::transform(m_data.cbegin(), m_data.cend(), tmp.m_data.begin(),
[&](const T &v) { return v / c; });
[&c](const T &v) { return v / c; });
return tmp;
}

Vector<T> &operator/=(const T &c)
Vector &operator/=(const T &c)
{
std::transform(m_data.cbegin(), m_data.cend(), m_data.begin(),
[&](const T &v) { return v / c; });
[&c](const T &v) { return v / c; });
return *this;
}

bool operator==(const Vector<T> &v) const { return m_data == v.m_data; }
bool operator!=(const Vector<T> &v) const { return m_data != v.m_data; }
bool operator==(const Vector &v) const { return m_data == v.m_data; }
bool operator!=(const Vector &v) const { return m_data != v.m_data; }

/// Tests if all components of the vector are equal to a constant c
bool operator==(const T &c) const
{
return std::all_of(m_data.begin(), m_data.end(), [&](const T &v) { return v == c; });
return std::all_of(m_data.begin(), m_data.end(), [&c](const T &v) { return v == c; });
}
bool operator!=(const T &c) const
{
return std::any_of(m_data.begin(), m_data.end(), [&](const T &v) { return v != c; });
return std::any_of(m_data.begin(), m_data.end(), [&c](const T &v) { return v != c; });
}

/// The square of the Euclidaen norm of the vector
T NormSquared() const
/// The square of the Euclidean norm of the vector
T NormSquared() const noexcept(noexcept(std::declval<T>() * std::declval<T>()))
{
return std::inner_product(m_data.begin(), m_data.end(), m_data.begin(), static_cast<T>(0));
return std::transform_reduce(m_data.cbegin(), m_data.cend(), T{0}, std::plus<>{},
[](const T &v) -> T { return v * v; });
}
};

template <class T> Vector<T> operator*(const T &p_c, const Vector<T> &p_vector)
{
return p_vector * p_c;
}

} // end namespace Gambit

#endif // GAMBIT_CORE_VECTOR_H
4 changes: 2 additions & 2 deletions src/gui/nfgtable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1021,13 +1021,13 @@ void TableWidget::OnUpdate()
else if (m_doc->NumPlayers() < m_rowPlayers.size() + m_colPlayers.size()) {
for (size_t i = 1; i <= m_rowPlayers.size(); i++) {
if (m_rowPlayers[i] > static_cast<int>(m_doc->NumPlayers())) {
erase_atindex(m_rowPlayers, i--);
m_rowPlayers.erase_at(i--);
}
}

for (size_t i = 1; i <= m_colPlayers.size(); i++) {
if (m_colPlayers[i] > static_cast<int>(m_doc->NumPlayers())) {
erase_atindex(m_colPlayers, i--);
m_colPlayers.erase_at(i--);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/solvers/linalg/lemketab.imp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ template <class T> int LemkeTableau<T>::SF_ExitIndex(int inlabel)
for (size_t i = BestSet.size(); i >= 1; i--) {
ratio = col[BestSet[i]] / incol[BestSet[i]];
if (ratio > tempmax + this->eps2) {
erase_atindex(BestSet, i);
BestSet.erase_at(i);
}
}
c++;
Expand Down Expand Up @@ -159,7 +159,7 @@ template <class T> int LemkeTableau<T>::ExitIndex(int inlabel)
for (size_t j = BestSet.size(); j >= 1; j--) {
ratio = col[BestSet[j]] / incol[BestSet[j]];
if (ratio < tempmax - this->eps1) {
erase_atindex(BestSet, j);
BestSet.erase_at(j);
}
}
c++;
Expand Down
Loading