233 lines
7.4 KiB
C++
233 lines
7.4 KiB
C++
/*
|
|
* Copyright (C) 2010 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef _VECTOR_HH
|
|
#define _VECTOR_HH
|
|
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
|
|
#include <cstdlib>
|
|
#include <cassert>
|
|
#include <cmath>
|
|
|
|
/*
|
|
This header defines three vector classes, which implement a "vector concept"
|
|
(much like the concepts of the Standard Template Library or of Boost
|
|
Library). The first class is a vector owning the data space for its elements,
|
|
and the other two are vector "views" of something else (either a subvector of
|
|
another vector, or a row or column of a matrix). This design philosophy is
|
|
close to the design of the GNU Scientific Library, but here using the
|
|
syntactic power of C++ class and templates, while achieving very high
|
|
efficiency.
|
|
|
|
These classes can be used with various templated functions, including
|
|
wrappers around the BLAS primitives.
|
|
|
|
The expressions required to be valid for a class V implementing the "vector concept" are:
|
|
- V.getSize(): return number of elements
|
|
- V.getStride(): return the stride, i.e. the offset between two elements in the data space
|
|
- V.getData(): return the pointer to the data space
|
|
- V(i): get an element of the vector
|
|
|
|
The expressions required to be valid for a class V implementing the "mutable vector concept" are (in addition to those of "vector concept"):
|
|
- V = X: assignment operator
|
|
- V(i) = d: assign an element of the vector
|
|
- V.setAll(d): set all the elements of the vector
|
|
|
|
*/
|
|
|
|
//! A full vector, implements the "mutable vector concept"
|
|
/*! Owns the data space for the elements */
|
|
class Vector
|
|
{
|
|
private:
|
|
double *data;
|
|
const size_t size;
|
|
public:
|
|
Vector(size_t size_arg);
|
|
Vector(const Vector &arg);
|
|
virtual ~Vector();
|
|
inline size_t getSize() const { return size; }
|
|
inline size_t getStride() const { return 1; }
|
|
inline double *getData() { return data; }
|
|
inline const double *getData() const { return data; }
|
|
inline void setAll(double val) { std::fill_n(data, size, val); }
|
|
inline double &operator() (size_t i) { return data[i]; }
|
|
inline const double &operator() (size_t i) const { return data[i]; }
|
|
//! Assignment operator, only works for vectors of same size
|
|
template<class Vec>
|
|
Vector &operator= (const Vec &arg)
|
|
{
|
|
assert(size == arg.getSize());
|
|
const double *p2 = arg.getData();
|
|
for(double *p1 = data; p1 < data + size; p1++)
|
|
{
|
|
*p1 = *p2;
|
|
p2 += arg.getStride();
|
|
}
|
|
return *this;
|
|
}
|
|
//! The copy assignment operator, which is not generated by the template assignment operator
|
|
/*! See C++ standard, §12.8.9, in the footnote */
|
|
Vector &operator= (const Vector &arg);
|
|
};
|
|
|
|
//! A vector view (i.e. a subvector of another vector, or a row or column of a matrix), implements the "mutable vector concept"
|
|
/*! Does not own the data space for the elements, so depends on another vector or matrix */
|
|
class VectorView
|
|
{
|
|
private:
|
|
double *const data;
|
|
const size_t size, stride;
|
|
public:
|
|
VectorView(double *data_arg, size_t size_arg, size_t stride_arg);
|
|
/* Can't use a template for the 2 constructors below: this would override the
|
|
constructor which uses a pointer, because the argument list is the same */
|
|
VectorView(Vector &arg, size_t offset, size_t size_arg);
|
|
VectorView(VectorView &arg, size_t offset, size_t size_arg);
|
|
virtual ~VectorView(){};
|
|
inline size_t getSize() const { return size; }
|
|
inline size_t getStride() const { return stride; }
|
|
inline double *getData() { return data; }
|
|
inline const double *getData() const { return data; }
|
|
inline void setAll(double val)
|
|
{
|
|
for (double *p = data; p < data + size*stride; p += stride)
|
|
*p = val;
|
|
}
|
|
inline double &operator() (size_t i) { return data[i*stride]; }
|
|
inline const double &operator() (size_t i) const { return data[i*stride]; }
|
|
//! Assignment operator, only works for vectors of same size
|
|
template<class Vec>
|
|
VectorView &
|
|
operator= (const Vec &arg)
|
|
{
|
|
assert(size == arg.getSize());
|
|
double *p1;
|
|
const double *p2;
|
|
for (p1 = data, p2 = arg.getData(); p1 < data + size*stride; p1 += stride, p2 += arg.getStride())
|
|
*p1 = *p2;
|
|
return *this;
|
|
}
|
|
//! The copy assignment operator, which is not generated by the template assignment operator
|
|
/*! See C++ standard, §12.8.9, in the footnote */
|
|
VectorView &operator= (const VectorView &arg);
|
|
};
|
|
|
|
//! Like a VectorView, but the data cannot be modified (implements the "vector concept")
|
|
class VectorConstView
|
|
{
|
|
private:
|
|
const double *const data;
|
|
const size_t size, stride;
|
|
public:
|
|
VectorConstView(const double *data_arg, size_t size_arg, size_t stride_arg);
|
|
/* Can't use a template for the 3 constructors below: this would override the
|
|
constructor which uses a pointer, because the argument list is the same */
|
|
VectorConstView(const Vector &arg, size_t offset, size_t size_arg);
|
|
VectorConstView(const VectorView &arg, size_t offset, size_t size_arg);
|
|
VectorConstView(const VectorConstView &arg, size_t offset, size_t size_arg);
|
|
|
|
virtual ~VectorConstView(){};
|
|
inline size_t getSize() const { return size; }
|
|
inline size_t getStride() const { return stride; }
|
|
inline const double *getData() const { return data; }
|
|
inline const double &operator() (size_t i) const { return data[i*stride]; }
|
|
};
|
|
|
|
std::ostream &operator<<(std::ostream &out, const Vector &V);
|
|
std::ostream &operator<<(std::ostream &out, const VectorView &V);
|
|
std::ostream &operator<<(std::ostream &out, const VectorConstView &V);
|
|
|
|
namespace vec
|
|
{
|
|
template<class Vec>
|
|
void
|
|
print(std::ostream &out, const Vec &V)
|
|
{
|
|
for (size_t i = 0; i < V.getSize(); i++)
|
|
out << V(i) << " ";
|
|
out << std::endl;
|
|
}
|
|
|
|
//! Computes v1 = v1 + v2
|
|
template<class Vec1, class Vec2>
|
|
void
|
|
add(Vec1 &v1, const Vec2 &v2)
|
|
{
|
|
assert(v1.getSize() == v2.getSize());
|
|
double *p1 = v1.getData();
|
|
const double *p2 = v2.getData();
|
|
while (p1 < v1.getData() + v1.getSize() * v1.getStride())
|
|
{
|
|
*p1 += *p2;
|
|
p1 += v1.getStride();
|
|
p2 += v2.getStride();
|
|
}
|
|
}
|
|
|
|
//! Computes v1 = v1 - v2
|
|
template<class Vec1, class Vec2>
|
|
void
|
|
sub(Vec1 &v1, const Vec2 &v2)
|
|
{
|
|
assert(v1.getSize() == v2.getSize());
|
|
double *p1 = v1.getData();
|
|
const double *p2 = v2.getData();
|
|
while (p1 < v1.getData() + v1.getSize() * v1.getStride())
|
|
{
|
|
*p1 -= *p2;
|
|
p1 += v1.getStride();
|
|
p2 += v2.getStride();
|
|
}
|
|
}
|
|
|
|
//! Does v = -v
|
|
template<class Vec>
|
|
void
|
|
negate(Vec &v)
|
|
{
|
|
double *p = v.getData();
|
|
while (p < v.getData() + v.getSize() * v.getStride())
|
|
{
|
|
*p = -*p;
|
|
p += v.getStride();
|
|
}
|
|
}
|
|
|
|
// Computes the infinite norm of a vector
|
|
template<class Vec>
|
|
double
|
|
nrminf(const Vec &v)
|
|
{
|
|
double nrm = 0;
|
|
const double *p = v.getData();
|
|
while (p < v.getData() + v.getSize() * v.getStride())
|
|
{
|
|
if (fabs(*p) > nrm)
|
|
nrm = fabs(*p);
|
|
p += v.getStride();
|
|
}
|
|
return nrm;
|
|
}
|
|
} // End of namespace
|
|
|
|
#endif
|