/* * Copyright © 2004-2011 Ondra Kamenik * Copyright © 2019 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 . */ #include "Vector.hh" #include "GeneralMatrix.hh" #include "SylvException.hh" #include #include #include #include #include #include Vector::Vector(const Vector &v) : len(v.len), data{new double[len]} { copy(v.data, v.s); } Vector::Vector(const ConstVector &v) : len(v.len), data{new double[len]} { copy(v.data, v.s); } Vector & Vector::operator=(const Vector &v) { if (this == &v) return *this; if (v.len != len) throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths."); if (s == v.s && (data <= v.data && v.data < data+len*s || v.data <= data && data < v.data+v.len*v.s) && (data-v.data) % s == 0) throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors."); copy(v.data, v.s); return *this; } Vector & Vector::operator=(Vector &&v) { if (v.len != len) throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths."); copy(v.data, v.s); return *this; } Vector & Vector::operator=(const ConstVector &v) { if (v.len != len) throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths."); if (s == v.s && (data <= v.data && v.data < data+len*s || v.data <= data && data < v.data+v.len*v.s) && (data-v.data) % s == 0) throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors."); copy(v.data, v.s); return *this; } void Vector::copy(const double *d, int inc) { blas_int n = len; blas_int incy = s; blas_int inc2 = inc; dcopy(&n, d, &inc2, data, &incy); } Vector::Vector(Vector &v, int off_arg, int l) : len(l), s(v.s), data{v.data+off_arg*v.s}, destroy{false} { if (off_arg < 0 || off_arg + len > v.len) throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); } Vector::Vector(const Vector &v, int off_arg, int l) : len(l), data{new double[len]} { if (off_arg < 0 || off_arg + len > v.len) throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); copy(v.data+off_arg*v.s, v.s); } Vector::Vector(Vector &v, int off_arg, int skip, int l) : len(l), s(v.s*skip), data{v.data+off_arg*v.s}, destroy{false} { } Vector::Vector(const Vector &v, int off_arg, int skip, int l) : len(l), data{new double[len]} { copy(v.data+off_arg*v.s, v.s*skip); } #if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) Vector::Vector(mxArray *p) : len{static_cast(mxGetNumberOfElements(p))}, data{mxGetPr(p)}, destroy{false} { if (!mxIsDouble(p)) throw SYLV_MES_EXCEPTION("This is not a MATLAB array of doubles."); } #endif bool Vector::operator==(const Vector &y) const { return ConstVector(*this) == y; } bool Vector::operator!=(const Vector &y) const { return ConstVector(*this) != y; } bool Vector::operator<(const Vector &y) const { return ConstVector(*this) < y; } bool Vector::operator<=(const Vector &y) const { return ConstVector(*this) <= y; } bool Vector::operator>(const Vector &y) const { return ConstVector(*this) > y; } bool Vector::operator>=(const Vector &y) const { return ConstVector(*this) >= y; } void Vector::zeros() { if (s == 1) std::fill_n(data, len, 0.0); else for (int i = 0; i < len; i++) operator[](i) = 0.0; } void Vector::nans() { for (int i = 0; i < len; i++) operator[](i) = std::numeric_limits::quiet_NaN(); } void Vector::infs() { for (int i = 0; i < len; i++) operator[](i) = std::numeric_limits::infinity(); } void Vector::rotatePair(double alpha, double beta1, double beta2, int i) { double tmp = alpha*operator[](i) - beta1*operator[](i+1); operator[](i+1) = alpha*operator[](i+1) - beta2*operator[](i); operator[](i) = tmp; } void Vector::add(double r, const Vector &v) { add(r, ConstVector(v)); } void Vector::add(double r, const ConstVector &v) { blas_int n = len; blas_int incx = v.s; blas_int incy = s; daxpy(&n, &r, v.data, &incx, data, &incy); } void Vector::addComplex(const std::complex &z, const Vector &v) { addComplex(z, ConstVector(v)); } void Vector::addComplex(const std::complex &z, const ConstVector &v) { blas_int n = len/2; blas_int incx = v.s; blas_int incy = s; zaxpy(&n, reinterpret_cast(z), v.data, &incx, data, &incy); } void Vector::mult(double r) { blas_int n = len; blas_int incx = s; dscal(&n, &r, data, &incx); } void Vector::mult2(double alpha, double beta1, double beta2, Vector &x1, Vector &x2, const Vector &b1, const Vector &b2) { x1.zeros(); x2.zeros(); mult2a(alpha, beta1, beta2, x1, x2, b1, b2); } void Vector::mult2a(double alpha, double beta1, double beta2, Vector &x1, Vector &x2, const Vector &b1, const Vector &b2) { x1.add(alpha, b1); x1.add(-beta1, b2); x2.add(alpha, b2); x2.add(-beta2, b1); } double Vector::getNorm() const { ConstVector v(*this); return v.getNorm(); } double Vector::getMax() const { ConstVector v(*this); return v.getMax(); } double Vector::getNorm1() const { ConstVector v(*this); return v.getNorm1(); } double Vector::dot(const Vector &y) const { return ConstVector(*this).dot(ConstVector(y)); } bool Vector::isFinite() const { return (ConstVector(*this)).isFinite(); } void Vector::print() const { auto ff = std::cout.flags(); std::cout << std::setprecision(4); for (int i = 0; i < len; i++) std::cout << i << '\t' << std::setw(8) << operator[](i) << std::endl; std::cout.flags(ff); } ConstVector::ConstVector(const Vector &v) : len{v.len}, s{v.s}, data{v.data} { } ConstVector::ConstVector(const ConstVector &v, int off_arg, int l) : len{l}, s{v.s}, data{v.data+off_arg*v.s} { if (off_arg < 0 || off_arg + len > v.len) throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); } ConstVector::ConstVector(const ConstVector &v, int off_arg, int skip, int l) : len(l), s{v.s*skip}, data{v.data+off_arg*v.s} { } ConstVector::ConstVector(const double *d, int skip, int l) : len{l}, s{skip}, data{d} { } #if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) ConstVector::ConstVector(const mxArray *p) : len{static_cast(mxGetNumberOfElements(p))}, data{mxGetPr(p)} { if (!mxIsDouble(p)) throw SYLV_MES_EXCEPTION("This is not a MATLAB array of doubles."); } #endif bool ConstVector::operator==(const ConstVector &y) const { if (len != y.len) return false; if (len == 0) return true; int i = 0; while (i < len && operator[](i) == y[i]) i++; return i == len; } bool ConstVector::operator<(const ConstVector &y) const { int i = std::min(len, y.len); int ii = 0; while (ii < i && operator[](ii) == y[ii]) ii++; if (ii < i) return operator[](ii) < y[ii]; else return len < y.len; } double ConstVector::getNorm() const { double s = 0; for (int i = 0; i < len; i++) s += operator[](i)*operator[](i); return sqrt(s); } double ConstVector::getMax() const { double r = 0; for (int i = 0; i < len; i++) r = std::max(r, std::abs(operator[](i))); return r; } double ConstVector::getNorm1() const { double norm = 0.0; for (int i = 0; i < len; i++) norm += std::abs(operator[](i)); return norm; } double ConstVector::dot(const ConstVector &y) const { if (len != y.len) throw SYLV_MES_EXCEPTION("Vector has different length in ConstVector::dot."); blas_int n = len; blas_int incx = s; blas_int incy = y.s; return ddot(&n, data, &incx, y.data, &incy); } bool ConstVector::isFinite() const { int i = 0; while (i < len && std::isfinite(operator[](i))) i++; return i == len; } void ConstVector::print() const { auto ff = std::cout.flags(); std::cout << std::setprecision(4); for (int i = 0; i < len; i++) std::cout << i << '\t' << std::setw(8) << operator[](i) << std::endl; std::cout.flags(ff); }