227 lines
6.1 KiB
C++
227 lines
6.1 KiB
C++
/*
|
||
* Copyright © 2004-2011 Ondra Kamenik
|
||
* Copyright © 2019-2024 Dynare Team
|
||
*
|
||
* This file is part of Dynare.
|
||
*
|
||
* Dynare is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* Dynare is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#ifndef VECTOR_HH
|
||
#define VECTOR_HH
|
||
|
||
/* NOTE: Vector and ConstVector have not common super class in order
|
||
to avoid running virtual method invokation mechanism. Some
|
||
members, and methods are thus duplicated */
|
||
|
||
#include <compare>
|
||
#include <complex>
|
||
#include <utility>
|
||
|
||
#include <dynmex.h>
|
||
|
||
class GeneralMatrix;
|
||
class ConstVector;
|
||
|
||
class Vector
|
||
{
|
||
friend class ConstVector;
|
||
|
||
protected:
|
||
int len {0};
|
||
int s {1}; // stride (also called “skip” in some places)
|
||
double* data;
|
||
bool destroy {true};
|
||
|
||
public:
|
||
Vector() : data {nullptr}, destroy {false}
|
||
{
|
||
}
|
||
Vector(int l) : len {l}, data {new double[l]}
|
||
{
|
||
}
|
||
Vector(Vector& v) : len {v.len}, s {v.s}, data {v.data}, destroy {false}
|
||
{
|
||
}
|
||
Vector(const Vector& v);
|
||
Vector(Vector&& v) noexcept :
|
||
len {std::exchange(v.len, 0)},
|
||
s {v.s},
|
||
data {std::exchange(v.data, nullptr)},
|
||
destroy {std::exchange(v.destroy, false)}
|
||
{
|
||
}
|
||
// We don't want implict conversion from ConstVector, since it’s expensive
|
||
explicit Vector(const ConstVector& v);
|
||
Vector(double* d, int l) : len(l), data {d}, destroy {false}
|
||
{
|
||
}
|
||
Vector(Vector& v, int off_arg, int l);
|
||
Vector(const Vector& v, int off_arg, int l);
|
||
Vector(Vector& v, int off_arg, int skip, int l);
|
||
Vector(const Vector& v, int off_arg, int skip, int l);
|
||
explicit Vector(mxArray* p);
|
||
Vector& operator=(const Vector& v);
|
||
/* The move-assignment operator is not implemented, because moving pointers
|
||
across class instances would break the “reference semantics” that the
|
||
Vector class implements. The copy-assignment operator is thus used as a
|
||
fallback. */
|
||
Vector& operator=(const ConstVector& v);
|
||
double&
|
||
operator[](int i)
|
||
{
|
||
return data[s * i];
|
||
}
|
||
const double&
|
||
operator[](int i) const
|
||
{
|
||
return data[s * i];
|
||
}
|
||
[[nodiscard]] const double*
|
||
base() const
|
||
{
|
||
return data;
|
||
}
|
||
double*
|
||
base()
|
||
{
|
||
return data;
|
||
}
|
||
[[nodiscard]] int
|
||
length() const
|
||
{
|
||
return len;
|
||
}
|
||
[[nodiscard]] int
|
||
skip() const
|
||
{
|
||
return s;
|
||
}
|
||
|
||
virtual ~Vector()
|
||
{
|
||
if (destroy)
|
||
delete[] data;
|
||
}
|
||
void zeros();
|
||
void nans();
|
||
void infs();
|
||
void rotatePair(double alpha, double beta1, double beta2, int i);
|
||
// Computes this = this + r·v
|
||
void add(double r, const Vector& v);
|
||
// Computes this = this + r·v
|
||
void add(double r, const ConstVector& v);
|
||
// Computes this = this + z·v (where this and v are intepreted as complex vectors)
|
||
void addComplex(const std::complex<double>& z, const Vector& v);
|
||
// Computes this = this + z·v (where this and v are intepreted as complex vectors)
|
||
void addComplex(const std::complex<double>& z, const ConstVector& v);
|
||
void mult(double r);
|
||
[[nodiscard]] double getNorm() const;
|
||
[[nodiscard]] double getMax() const;
|
||
[[nodiscard]] double getNorm1() const;
|
||
[[nodiscard]] double dot(const Vector& y) const;
|
||
[[nodiscard]] bool isFinite() const;
|
||
void print() const;
|
||
|
||
/* Computes:
|
||
⎛x₁⎞ ⎛ α −β₁⎞ ⎛b₁⎞
|
||
⎢ ⎥=⎢ ⎥⊗I·⎢ ⎥
|
||
⎝x₂⎠ ⎝−β₂ α ⎠ ⎝b₂⎠
|
||
*/
|
||
static void mult2(double alpha, double beta1, double beta2, Vector& x1, Vector& x2,
|
||
const Vector& b1, const Vector& b2);
|
||
/* Computes:
|
||
⎛x₁⎞ ⎛x₁⎞ ⎛ α −β₁⎞ ⎛b₁⎞
|
||
⎢ ⎥=⎢ ⎥+⎢ ⎥⊗I·⎢ ⎥
|
||
⎝x₂⎠ ⎝x₂⎠ ⎝−β₂ α ⎠ ⎝b₂⎠
|
||
*/
|
||
static void mult2a(double alpha, double beta1, double beta2, Vector& x1, Vector& x2,
|
||
const Vector& b1, const Vector& b2);
|
||
/* Computes:
|
||
⎛x₁⎞ ⎛x₁⎞ ⎛ α −β₁⎞ ⎛b₁⎞
|
||
⎢ ⎥=⎢ ⎥−⎢ ⎥⊗I·⎢ ⎥
|
||
⎝x₂⎠ ⎝x₂⎠ ⎝−β₂ α ⎠ ⎝b₂⎠
|
||
*/
|
||
static void
|
||
mult2s(double alpha, double beta1, double beta2, Vector& x1, Vector& x2, const Vector& b1,
|
||
const Vector& b2)
|
||
{
|
||
mult2a(-alpha, -beta1, -beta2, x1, x2, b1, b2);
|
||
}
|
||
|
||
private:
|
||
void copy(const double* d, int inc);
|
||
};
|
||
|
||
class ConstGeneralMatrix;
|
||
|
||
class ConstVector
|
||
{
|
||
friend class Vector;
|
||
|
||
protected:
|
||
int len;
|
||
int s {1}; // stride (also called “skip” in some places)
|
||
const double* data;
|
||
|
||
public:
|
||
// Implicit conversion from Vector is ok, since it’s cheap
|
||
ConstVector(const Vector& v);
|
||
ConstVector(const ConstVector& v) = default;
|
||
ConstVector(ConstVector&& v) = default;
|
||
ConstVector(const double* d, int l) : len {l}, data {d}
|
||
{
|
||
}
|
||
ConstVector(const ConstVector& v, int off_arg, int l);
|
||
ConstVector(const ConstVector& v, int off_arg, int skip, int l);
|
||
ConstVector(const double* d, int skip, int l);
|
||
explicit ConstVector(const mxArray* p);
|
||
virtual ~ConstVector() = default;
|
||
ConstVector& operator=(const ConstVector& v) = delete;
|
||
ConstVector& operator=(ConstVector&& v) = delete;
|
||
const double&
|
||
operator[](int i) const
|
||
{
|
||
return data[s * i];
|
||
}
|
||
[[nodiscard]] const double*
|
||
base() const
|
||
{
|
||
return data;
|
||
}
|
||
[[nodiscard]] int
|
||
length() const
|
||
{
|
||
return len;
|
||
}
|
||
[[nodiscard]] int
|
||
skip() const
|
||
{
|
||
return s;
|
||
}
|
||
// Exact equality
|
||
[[nodiscard]] bool operator==(const ConstVector& y) const;
|
||
// Lexicographic ordering
|
||
[[nodiscard]] std::partial_ordering operator<=>(const ConstVector& y) const;
|
||
|
||
[[nodiscard]] double getNorm() const;
|
||
[[nodiscard]] double getMax() const;
|
||
[[nodiscard]] double getNorm1() const;
|
||
[[nodiscard]] double dot(const ConstVector& y) const;
|
||
[[nodiscard]] bool isFinite() const;
|
||
void print() const;
|
||
};
|
||
|
||
#endif
|