Commit 19cc08b7 authored by Sébastien Villemot's avatar Sébastien Villemot

Dynare++: modernization and simplification of the IntSequence class

Similarly to Vector, it now uses a std::shared_ptr for managing the underlying
data.
parent 099a1de6
Pipeline #766 passed with stages
in 67 minutes and 27 seconds
......@@ -9,6 +9,7 @@
#include <sys/time.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
......
......@@ -4,15 +4,16 @@
#include "symmetry.hh"
#include "tl_exception.hh"
#include <cstdio>
#include <climits>
#include <iostream>
#include <limits>
#include <numeric>
/* This unfolds a given integer sequence with respect to the given
symmetry. If for example the symmetry is $(2,3)$, and the sequence is
$(a,b)$, then the result is $(a,a,b,b,b)$. */
IntSequence::IntSequence(const Symmetry &sy, const IntSequence &se)
: data(new int[sy.dimen()]), length(sy.dimen()), destroy(true)
: data{new int[sy.dimen()], [](int *arr) { delete[] arr; }}, length{sy.dimen()}
{
int k = 0;
for (int i = 0; i < sy.num(); i++)
......@@ -30,7 +31,7 @@ IntSequence::IntSequence(const Symmetry &sy, const IntSequence &se)
and one $u$. */
IntSequence::IntSequence(const Symmetry &sy, const std::vector<int> &se)
: data(new int[sy.num()]), length(sy.num()), destroy(true)
: data{new int[sy.num()], [](int *arr) { delete[] arr; }}, length{sy.num()}
{
TL_RAISE_IF(sy.dimen() <= se[se.size()-1],
"Sequence is not reachable by symmetry in IntSequence()");
......@@ -45,7 +46,7 @@ IntSequence::IntSequence(const Symmetry &sy, const std::vector<int> &se)
sequence inserting the given number to the sequence. */
IntSequence::IntSequence(int i, const IntSequence &s)
: data(new int[s.size()+1]), length(s.size()+1), destroy(true)
: data{new int[s.size()+1], [](int *arr) { delete[] arr; }}, length{s.size()+1}
{
int j = 0;
while (j < s.size() && s[j] < i)
......@@ -58,7 +59,7 @@ IntSequence::IntSequence(int i, const IntSequence &s)
}
IntSequence::IntSequence(int i, const IntSequence &s, int pos)
: data(new int[s.size()+1]), length(s.size()+1), destroy(true)
: data{new int[s.size()+1], [](int *arr) { delete[] arr; }}, length{s.size()+1}
{
TL_RAISE_IF(pos < 0 || pos > s.size(),
"Wrong position for insertion IntSequence constructor");
......@@ -72,42 +73,31 @@ IntSequence::IntSequence(int i, const IntSequence &s, int pos)
const IntSequence &
IntSequence::operator=(const IntSequence &s)
{
TL_RAISE_IF(!destroy && length != s.length,
"Wrong length for in-place IntSequence::operator=");
if (destroy && length != s.length)
{
delete [] data;
data = new int[s.length];
destroy = true;
length = s.length;
}
memcpy(data, s.data, sizeof(int)*length);
TL_RAISE_IF(length != s.length, "Wrong length for in-place IntSequence::operator=");
std::copy_n(s.data.get()+s.offset, length, data.get()+offset);
return *this;
}
const IntSequence &
IntSequence::operator=(IntSequence &&s)
{
TL_RAISE_IF(length != s.length, "Wrong length for in-place IntSequence::operator=");
std::copy_n(s.data.get()+s.offset, length, data.get()+offset);
return *this;
}
bool
IntSequence::operator==(const IntSequence &s) const
{
if (size() != s.size())
return false;
int i = 0;
while (i < size() && operator[](i) == s[i])
i++;
return i == size();
return std::equal(data.get()+offset, data.get()+offset+length,
s.data.get()+s.offset, s.data.get()+s.offset+s.length);
}
/* We need some linear irreflexive ordering, we implement it as
lexicographic ordering without identity. */
bool
IntSequence::operator<(const IntSequence &s) const
{
int len = std::min(size(), s.size());
int i = 0;
while (i < len && operator[](i) == s[i])
i++;
return (i < s.size() && (i == size() || operator[](i) < s[i]));
return std::lexicographical_compare(data.get()+offset, data.get()+offset+length,
s.data.get()+s.offset, s.data.get()+s.offset+s.length);
}
bool
......@@ -134,28 +124,10 @@ IntSequence::less(const IntSequence &s) const
return (i == size());
}
/* This is a bubble sort, all sequences are usually very short, so this
sin might be forgiven. */
void
IntSequence::sort()
{
for (int i = 0; i < length; i++)
{
int swaps = 0;
for (int j = 0; j < length-1; j++)
{
if (data[j] > data[j+1])
{
int s = data[j+1];
data[j+1] = data[j];
data[j] = s;
swaps++;
}
}
if (swaps == 0)
return;
}
std::sort(data.get()+offset, data.get()+offset+length);
}
/* Here we monotonize the sequence. If an item is less then its
......@@ -165,8 +137,8 @@ void
IntSequence::monotone()
{
for (int i = 1; i < length; i++)
if (data[i-1] > data[i])
data[i] = data[i-1];
if (operator[](i-1) > operator[](i))
operator[](i) = operator[](i-1);
}
/* This partially monotones the sequence. The partitioning is done by a
......@@ -181,8 +153,8 @@ IntSequence::pmonotone(const Symmetry &s)
for (int i = 0; i < s.num(); i++)
{
for (int j = cum + 1; j < cum + s[i]; j++)
if (data[j-1] > data[j])
data[j] = data[j-1];
if (operator[](j-1) > operator[](j))
operator[](j) = operator[](j-1);
cum += s[i];
}
}
......@@ -192,10 +164,7 @@ IntSequence::pmonotone(const Symmetry &s)
int
IntSequence::sum() const
{
int res = 0;
for (int i = 0; i < length; i++)
res += operator[](i);
return res;
return std::accumulate(data.get()+offset, data.get()+offset+length, 0);
}
/* This returns product of subsequent items. Useful for Kronecker product
......@@ -204,10 +173,8 @@ IntSequence::sum() const
int
IntSequence::mult(int i1, int i2) const
{
int res = 1;
for (int i = i1; i < i2; i++)
res *= operator[](i);
return res;
return std::accumulate(data.get()+offset+i1, data.get()+offset+i2,
1, std::multiplies<int>());
}
/* Return a number of the same items in the beginning of the sequence. */
......@@ -228,9 +195,9 @@ int
IntSequence::getNumDistinct() const
{
int res = 0;
if (size() > 0)
if (length > 0)
res++;
for (int i = 1; i < size(); i++)
for (int i = 1; i < length; i++)
if (operator[](i) != operator[](i-1))
res++;
return res;
......@@ -242,11 +209,9 @@ IntSequence::getNumDistinct() const
int
IntSequence::getMax() const
{
int res = INT_MIN;
for (int i = 0; i < size(); i++)
if (operator[](i) > res)
res = operator[](i);
return res;
if (length == 0)
return std::numeric_limits<int>::min();
return *std::max_element(data.get()+offset, data.get()+offset+length);
}
void
......@@ -268,36 +233,23 @@ IntSequence::add(int f, const IntSequence &s)
bool
IntSequence::isPositive() const
{
int i = 0;
while (i < size() && operator[](i) >= 0)
i++;
return (i == size());
return std::all_of(data.get()+offset, data.get()+offset+length,
[](int x) { return x >= 0; });
}
bool
IntSequence::isConstant() const
{
bool res = true;
int i = 1;
while (res && i < size())
{
res = res && operator[](0) == operator[](i);
i++;
}
return res;
if (length < 2)
return true;
return std::all_of(data.get()+offset+1, data.get()+offset+length,
[this](int x) { return x == operator[](0); });
}
bool
IntSequence::isSorted() const
{
bool res = true;
int i = 1;
while (res && i < size())
{
res = res && operator[](i-1) <= operator[](i);
i++;
}
return res;
return std::is_sorted(data.get()+offset, data.get()+offset+length);
}
/* Debug print. */
......@@ -305,8 +257,8 @@ IntSequence::isSorted() const
void
IntSequence::print() const
{
printf("[");
std::cout << '[';
for (int i = 0; i < size(); i++)
printf("%2d ", operator[](i));
printf("]\n");
std::cout << operator[](i) << ' ';
std::cout << ']' << std::endl;
}
......@@ -19,26 +19,25 @@
items in the front (|getPrefixLength|), and also to add some integer
number to all items.
Also, we need to construct a subsequence of a sequence, so
some instances do destroy the underlying data, and some not. */
Also, we need to construct a subsequence of a sequence. */
#ifndef INT_SEQUENCE_H
#define INT_SEQUENCE_H
#include <cstring>
#include <vector>
#include <memory>
#include <algorithm>
/* The implementation of |IntSequence| is straightforward. It has a
pointer |data|, a |length| of the data, and a flag |destroy|, whether
the instance must destroy the underlying data. */
/* The implementation of |IntSequence| is straightforward. It has a pointer
|data|, an |offset| integer indicating the beginning of the data relatively
to the pointer and a |length| of the sequence. */
class Symmetry;
class IntSequence
{
int *data;
std::shared_ptr<int> data;
int length;
bool destroy;
int offset{0};
public:
/* We have a constructor allocating a given length of data, constructor
allocating and then initializing all members to a given number, a copy
......@@ -49,46 +48,38 @@ public:
respect to a given symmetry and constructor which inserts a given
number to the ordered sequence or given number to a given position. */
IntSequence(int l)
: data(new int[l]), length(l), destroy(true)
explicit IntSequence(int l)
: data{new int[l], [](int *arr) { delete[] arr; }}, length{l}
{
}
IntSequence(int l, int n)
: data(new int[l]), length(l), destroy(true)
: data{new int[l], [](int *arr) { delete[] arr; }}, length{l}
{
for (int i = 0; i < length; i++)
data[i] = n;
std::fill_n(data.get(), length, n);
}
IntSequence(const IntSequence &s)
: data(new int[s.length]), length(s.length), destroy(true)
: data{new int[s.length], [](int *arr) { delete[] arr; }}, length{s.length}
{
memcpy(data, s.data, length*sizeof(int));
std::copy_n(s.data.get()+s.offset, length, data.get());
}
IntSequence(IntSequence &&s) = default;
IntSequence(IntSequence &s, int i1, int i2)
: data(s.data+i1), length(i2-i1), destroy(false)
: data{s.data}, length{i2-i1}, offset{s.offset+i1}
{
}
IntSequence(const IntSequence &s, int i1, int i2)
: data(new int[i2-i1]), length(i2-i1), destroy(true)
: data{new int[i2-i1], [](int *arr) { delete[] arr; }}, length{i2-i1}
{
memcpy(data, s.data+i1, sizeof(int)*length);
std::copy_n(s.data.get()+s.offset+i1, length, data.get());
}
IntSequence(const Symmetry &sy, const std::vector<int> &se);
IntSequence(const Symmetry &sy, const IntSequence &se);
IntSequence(int i, const IntSequence &s);
IntSequence(int i, const IntSequence &s, int pos);
IntSequence(int l, const int *d)
: data(new int[l]), length(l), destroy(true)
{
memcpy(data, d, sizeof(int)*length);
}
const IntSequence &operator=(const IntSequence &s);
virtual ~IntSequence()
{
if (destroy)
delete [] data;
}
const IntSequence &operator=(IntSequence &&s);
virtual ~IntSequence() = default;
bool operator==(const IntSequence &s) const;
bool
operator!=(const IntSequence &s) const
......@@ -98,12 +89,12 @@ public:
int &
operator[](int i)
{
return data[i];
return data.get()[offset+i];
}
int
operator[](int i) const
{
return data[i];
return data.get()[offset+i];
}
int
size() const
......
......@@ -75,7 +75,8 @@ public:
Symmetry(int i1, int i2)
: IntSequence(2)
{
operator[](0) = i1; operator[](1) = i2;
operator[](0) = i1;
operator[](1) = i2;
}
Symmetry(int i1, int i2, int i3)
: IntSequence(3)
......@@ -92,9 +93,8 @@ public:
operator[](2) = i3;
operator[](3) = i4;
}
Symmetry(const Symmetry &s)
= default;
Symmetry(const Symmetry &s) = default;
Symmetry(Symmetry &&s) = default;
Symmetry(const Symmetry &s, const OrdSequence &cl)
: IntSequence(s, cl.getData())
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment