/* This file is part of MAUS: http:// micewww.pp.rl.ac.uk:8080/projects/maus * * MAUS 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. * * MAUS 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 MAUS. If not, see . */ /* Author: Peter Lane */ #include "Maths/Vector.hh" #include #include #include #include #include "CLHEP/Matrix/Vector.h" #include "gsl/gsl_complex_math.h" #include "gsl/gsl_vector.h" #include "gsl/gsl_vector_complex_double.h" #include "Maths/Complex.hh" #include "Utils/Exception.hh" namespace MAUS { // ############################ // VectorBase (public) // ############################ // ************************* // Constructors // ************************* template VectorBase::VectorBase() : vector_(NULL) {} template VectorBase::VectorBase(); template VectorBase::VectorBase(); template <> VectorBase::VectorBase( const VectorBase& original_instance) : vector_(NULL) { if (original_instance.vector_ != NULL) { build_vector(original_instance.vector_->size); gsl_vector_memcpy(vector_, original_instance.vector_); } } template <> VectorBase::VectorBase( const VectorBase& original_instance) : vector_(NULL) { if (original_instance.vector_ != NULL) { build_vector(original_instance.vector_->size); gsl_vector_complex_memcpy(vector_, original_instance.vector_); } } template <> VectorBase::VectorBase( const ::CLHEP::HepVector& hep_vector) : vector_(NULL) { size_t size = hep_vector.num_row(); build_vector(size); for (size_t index = 1; index <= size; ++index) { (*this)(index) = hep_vector(index); } } template <> VectorBase::VectorBase( const ::CLHEP::HepVector& hep_vector) : vector_(NULL) { size_t size = hep_vector.num_row(); build_vector(size); for (size_t index = 1; index <= size; ++index) { (*this)(index) = MAUS::Complex::complex(hep_vector(index)); } } template VectorBase::VectorBase(const size_t i) : vector_(NULL) { build_vector(i); } template VectorBase::VectorBase(const size_t i); template VectorBase::VectorBase(const size_t i); template VectorBase::VectorBase( const size_t size, const StdType value) : vector_(NULL) { VectorBase::build_vector(size); for (size_t i = 0; i < size; ++i) { (*this)[i] = value; } } template VectorBase::VectorBase( const size_t size, const double value); template VectorBase::VectorBase( const size_t size, const complex value); template VectorBase::VectorBase( const StdType* data, const size_t size) : vector_(NULL) { build_vector(size, data); } template VectorBase::VectorBase( const double* data, const size_t size); template VectorBase::VectorBase( const complex* data, const size_t size); template VectorBase::VectorBase( const std::vector >& std_vector) : vector_(NULL) { build_vector(std_vector.size()); typename std::vector::const_iterator element; int index = 0; for (element = std_vector.begin(); element < std_vector.end(); ++element) { // TODO(plane1@iit.edu): create a MAUS::Vector iterator (*this)[index++] = *element; } } template VectorBase::VectorBase( const std::vector >& std_vector); template VectorBase::VectorBase( const std::vector >& std_vector); template VectorBase::~VectorBase() { delete_vector(); } template VectorBase::~VectorBase(); template VectorBase::~VectorBase(); // ************************* // Indexing Operators // ************************* template <> const double& VectorBase::operator[](const size_t i) const { if (vector_ == NULL) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to index an empty vector.", "MAUS::VectorBase::operator[]()")); } return *gsl_vector_ptr(vector_, i); } template <> const complex& VectorBase::operator[]( const size_t i) const { if (vector_ == NULL) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to index an empty vector.", "MAUS::VectorBase::operator[]()")); } return *gsl_vector_complex_ptr(vector_, i); } template <> double& VectorBase::operator[](const size_t i) { if (vector_ == NULL) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to index an empty vector.", "MAUS::VectorBase::operator[]()")); } return *gsl_vector_ptr(vector_, i); } template <> complex& VectorBase::operator[](const size_t i) { if (vector_ == NULL) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to index an empty vector.", "MAUS::VectorBase::operator[]()")); } return *gsl_vector_complex_ptr(vector_, i); } template StdType& VectorBase::operator()(const size_t i) { return (*this)[i-1]; } template double& VectorBase::operator()(const size_t i); template complex& VectorBase::operator()( const size_t i); template const StdType& VectorBase::operator()(const size_t i) const { return (*this)[i-1]; } template const double& VectorBase::operator()( const size_t i) const; template const complex& VectorBase::operator()( const size_t i) const; // ************************* // Size Functions // ************************* template const size_t VectorBase::size() const { if (vector_ != NULL) { return vector_->size; } return 0; } template const size_t VectorBase::size() const; template const size_t VectorBase::size() const; // ************************* // Subvector Functions // ************************* template <> VectorBase VectorBase::subvector( size_t begin_index, size_t end_index) const { if (vector_ == NULL) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to create a subvector from an empty vector.", "MAUS::VectorBase::subvector()")); } VectorBase subvector; size_t sub_size = end_index-begin_index; if (sub_size > 0) { subvector = VectorBase(sub_size); for (size_t index = 0; index < sub_size; ++index) { *gsl_vector_ptr(subvector.vector_, index) = *gsl_vector_ptr(vector_, begin_index+index); } } return subvector; } template <> VectorBase VectorBase::subvector( size_t begin_index, size_t end_index) const { if (vector_ == NULL) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to create a subvector from an empty vector.", "MAUS::VectorBase::subvector()")); } VectorBase subvector; size_t sub_size = end_index-begin_index; if (sub_size > 0) { subvector = VectorBase(sub_size); for (size_t index = 0; index < sub_size; ++index) { *gsl_vector_complex_ptr(subvector.vector_, index) = *gsl_vector_complex_ptr(vector_, begin_index+index); } } return subvector; } // ************************* // Assignment Operators // ************************* template <> VectorBase& VectorBase::operator=( const VectorBase& rhs) { if (&rhs != this) { if (vector_ == NULL) { // special case (like for a copy constructor call) where a non-null // vector is assigned to a null vector build_vector(rhs.vector_->size); } else if ((rhs.vector_ == NULL) || (vector_->size != rhs.vector_->size)) { throw(Exceptions::Exception(Exceptions::recoverable, "Attempted to assign a vector of a different size.", "VectorBase::operator=()")); } gsl_vector_memcpy(vector_, rhs.vector_); } return *this; } template <> VectorBase& VectorBase::operator=( const VectorBase& rhs) { if (&rhs != this) { if (vector_ == NULL) { // special case (like for a copy constructor call) where a non-null // vector is assigned to a null vector build_vector(rhs.vector_->size); } else if ((rhs.vector_ == NULL) || (vector_->size != rhs.vector_->size)) { throw(Exceptions::Exception(Exceptions::recoverable, "Attempted to assign a vector of a different size.", "VectorBase::operator=()")); } gsl_vector_complex_memcpy(vector_, rhs.vector_); } return *this; } template<> VectorBase& VectorBase::operator+=( const VectorBase& rhs) { if (rhs.vector_ != NULL) { gsl_vector_add(vector_, rhs.vector_); } return *this; } template<> VectorBase& VectorBase::operator+=( const VectorBase& rhs) { if (rhs.vector_ != NULL) { gsl_vector_complex_add(vector_, rhs.vector_); } return *this; } template<> VectorBase& VectorBase::operator-=( const VectorBase& rhs) { if (rhs.vector_ != NULL) { gsl_vector_sub(vector_, rhs.vector_); } return *this; } template<> VectorBase& VectorBase::operator-=( const VectorBase& rhs) { if (rhs.vector_ != NULL) { gsl_vector_complex_sub(vector_, rhs.vector_); } return *this; } template<> VectorBase& VectorBase::operator*=( const VectorBase& rhs) { if (rhs.vector_ != NULL) { size_t size = this->size(); if (rhs.size() != size) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to perform the product of two vectors of different sizes.", "MAUS::VectorBase::operator*=")); } gsl_vector_mul(vector_, rhs.vector_); } else { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to multiply a vector by an empty vector.", "MAUS::VectorBase::operator*=")); } return *this; } template<> VectorBase& VectorBase::operator*=( const VectorBase& rhs) { if (rhs.vector_ != NULL) { size_t size = this->size(); if (rhs.size() != size) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to perform the product of two vectors of different sizes.", "MAUS::VectorBase::operator*=")); } gsl_vector_complex_mul(vector_, rhs.vector_); } else { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to multiply a vector by an empty vector.", "MAUS::VectorBase::operator*=")); } return *this; } template<> VectorBase& VectorBase::operator/=( const VectorBase& rhs) { if (rhs.vector_ != NULL) { size_t size = this->size(); if (rhs.size() != size) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to perform the product of two vectors of different sizes.", "MAUS::VectorBase::operator/=")); } gsl_vector_div(vector_, rhs.vector_); } else { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to divide a vector by an empty vector.", "MAUS::VectorBase::operator/=")); } return *this; } template<> VectorBase& VectorBase::operator/=( const VectorBase& rhs) { if (rhs.vector_ != NULL) { size_t size = this->size(); if (rhs.size() != size) { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to perform the product of two vectors of different sizes.", "MAUS::VectorBase::operator/=")); } gsl_vector_complex_div(vector_, rhs.vector_); } else { throw(Exceptions::Exception( Exceptions::recoverable, "Attempted to divide a vector by an empty vector.", "MAUS::VectorBase::operator/=")); } return *this; } template<> VectorBase& VectorBase::operator+=( const double& rhs) { if (vector_ != NULL) { gsl_vector_add_constant(vector_, rhs); } return *this; } template<> VectorBase& VectorBase::operator+=( const complex& rhs) { if (vector_ != NULL) { gsl_vector_complex_add_constant(vector_, rhs); } return *this; } template<> VectorBase& VectorBase::operator-=( const double& rhs) { if (vector_ != NULL) { gsl_vector_add_constant(vector_, -rhs); } return *this; } template<> VectorBase& VectorBase::operator-=( const complex& rhs) { if (vector_ != NULL) { gsl_vector_complex_add_constant(vector_, -rhs); } return *this; } template<> VectorBase& VectorBase::operator*=( const double& rhs) { if (vector_ != NULL) { gsl_vector_scale(vector_, rhs); } return *this; } template<> VectorBase& VectorBase::operator*=( const complex& rhs) { if (vector_ != NULL) { gsl_vector_complex_scale(vector_, rhs); } return *this; } template<> VectorBase& VectorBase::operator/=(const double& rhs) { if (vector_ != NULL) { gsl_vector_scale(vector_, 1./rhs); } return *this; } template<> VectorBase& VectorBase::operator/=(const complex& rhs) { if (vector_ != NULL) { gsl_vector_complex_scale(vector_, 1./rhs); } return *this; } // ************************* // Algebraic Operators // ************************* template const VectorBase VectorBase::operator+( const VectorBase& rhs) const { return VectorBase(*this) += rhs; } template const VectorBase VectorBase::operator+( const VectorBase& rhs) const; template const VectorBase VectorBase::operator+( const VectorBase& rhs) const; template const VectorBase VectorBase::operator-( const VectorBase& rhs) const { return VectorBase(*this) -= rhs; } template const VectorBase VectorBase::operator-( const VectorBase& rhs) const; template const VectorBase VectorBase::operator-( const VectorBase& rhs) const; template const VectorBase VectorBase::operator*( const VectorBase& rhs) const { return VectorBase(*this) *= rhs; } template const VectorBase VectorBase::operator*( const VectorBase& rhs) const; template const VectorBase VectorBase::operator*( const VectorBase& rhs) const; template const VectorBase VectorBase::operator/( const VectorBase& rhs) const { return VectorBase(*this) /= rhs; } template const VectorBase VectorBase::operator/( const VectorBase& rhs) const; template const VectorBase VectorBase::operator/( const VectorBase& rhs) const; template const VectorBase VectorBase::operator+( const StdType& rhs) const { return VectorBase(*this) += rhs; } template const VectorBase VectorBase::operator+( const double& rhs) const; template const VectorBase VectorBase::operator+( const complex& rhs) const; template const VectorBase VectorBase::operator-( const StdType& rhs) const { return VectorBase(*this) -= rhs; } template const VectorBase VectorBase::operator-( const double& rhs) const; template const VectorBase VectorBase::operator-( const complex& rhs) const; template const VectorBase VectorBase::operator*( const StdType& rhs) const { return VectorBase(*this) *= rhs; } template const VectorBase VectorBase::operator*( const double& rhs) const; template const VectorBase VectorBase::operator*( const complex& rhs) const; template const VectorBase VectorBase::operator/( const StdType& rhs) const { return VectorBase(*this) /= rhs; } template const VectorBase VectorBase::operator/(const double& rhs) const; template const VectorBase VectorBase::operator/(const complex& rhs) const; // ************************* // Comparison Operators // ************************* template <> const bool VectorBase::operator==( const VectorBase& rhs) const { size_t this_size = size(); if (this_size != rhs.size()) { return false; } if (vector_ != NULL) { for (size_t index = 0; index < this_size; ++index) { if ( *gsl_vector_ptr(vector_, index) != *gsl_vector_ptr(rhs.vector_, index)) { return false; } } } else if (rhs.vector_ != NULL) { return false; } return true; } template <> const bool VectorBase::operator==( const VectorBase& rhs) const { size_t this_size = size(); if (this_size != rhs.size()) { return false; } if (vector_ != NULL) { for (size_t index = 0; index < this_size; ++index) { if ( *gsl_vector_complex_ptr(vector_, index) != *gsl_vector_complex_ptr(rhs.vector_, index)) { return false; } } } else if (rhs.vector_ != NULL) { return false; } return true; } template const bool VectorBase::operator!=( const VectorBase& rhs) const { return !((*this) == rhs); } // ############################ // VectorBase (protected) // ############################ template <> void VectorBase::delete_vector() { if (vector_ != NULL) { gsl_vector_free(vector_); } vector_ = NULL; } template <> void VectorBase::delete_vector() { if (vector_ != NULL) { gsl_vector_complex_free(vector_); } vector_ = NULL; } template <> void VectorBase::build_vector(const size_t size, const bool initialize) { delete_vector(); if (initialize) { vector_ = gsl_vector_calloc(size); } else { vector_ = gsl_vector_alloc(size); } } template <> void VectorBase::build_vector( const size_t size, const bool initialize) { delete_vector(); if (initialize) { vector_ = gsl_vector_complex_calloc(size); } else { vector_ = gsl_vector_complex_alloc(size); } } template void VectorBase::build_vector( const size_t size, const StdType* data) { build_vector(size, false); for (size_t i = 0; i < this->size(); ++i) { (*this)[i] = data[i]; } } template void VectorBase::build_vector( const size_t size, const double* data); template void VectorBase::build_vector( const size_t size, const complex* data); template GslType * VectorBase::vector() { return vector_; } template gsl_vector * VectorBase::vector(); template gsl_vector_complex * VectorBase::vector(); // ############################ // Vector (public) // ############################ const Vector Vector::operator+(const Vector& rhs) const { return VectorBase::operator+(rhs); } const Vector Vector::operator-(const Vector& rhs) const { return VectorBase::operator-(rhs); } const Vector Vector::operator*(const Vector& rhs) const { return VectorBase::operator*(rhs); } const Vector Vector::operator/(const Vector& rhs) const { return VectorBase::operator/(rhs); } const Vector Vector::operator+(const double& rhs) const { return VectorBase::operator+(rhs); } const Vector Vector::operator-(const double& rhs) const { return VectorBase::operator-(rhs); } const Vector Vector::operator*(const double& rhs) const { return VectorBase::operator*(rhs); } const Vector Vector::operator/(const double& rhs) const { return VectorBase::operator/(rhs); } const Vector Vector::operator+(const Vector& rhs) const { return VectorBase::operator+(rhs); } const Vector Vector::operator-(const Vector& rhs) const { return VectorBase::operator-(rhs); } const Vector Vector::operator*(const Vector& rhs) const { return VectorBase::operator*(rhs); } const Vector Vector::operator/(const Vector& rhs) const { return VectorBase::operator/(rhs); } const Vector Vector::operator+(const complex& rhs) const { return VectorBase::operator+(rhs); } const Vector Vector::operator-(const complex& rhs) const { return VectorBase::operator-(rhs); } const Vector Vector::operator*(const complex& rhs) const { return VectorBase::operator*(rhs); } const Vector Vector::operator/(const complex& rhs) const { return VectorBase::operator/(rhs); } // ############################ // Template Declarations // ############################ template class VectorBase; template class VectorBase; template class Vector; template class Vector; // ############################ // Free Functions // ############################ // **************************** // Conversion Functions // **************************** VectorBase real( const VectorBase& complex_vector) { VectorBase double_vector; if (complex_vector.vector_ != NULL) { double_vector = VectorBase(complex_vector.size()); for (size_t i = 1; i <= complex_vector.size(); ++i) { double_vector(i) = real(complex_vector(i)); } } return double_vector; } VectorBase imag( const VectorBase& complex_vector) { VectorBase double_vector; if (complex_vector.vector_ != NULL) { double_vector = VectorBase(complex_vector.size()); for (size_t i = 1; i <= complex_vector.size(); ++i) { double_vector(i) = imag(complex_vector(i)); } } return double_vector; } // ############################ // Global Operators // ############################ // ************************* // Unitary Operators // ************************* template Vector operator-(const Vector& operand) { size_t size = operand.size(); Vector vector(operand); for (size_t index = 0; index < size; ++index) { vector[index] = -vector[index]; } return vector; } template Vector operator-(const Vector& operand); template Vector operator-(const Vector& operand); // ************************* // Scalar Operators // ************************* template Vector operator*(const StdType& scalar, const Vector& vector) { return vector.operator*(scalar); } template Vector operator*( const double& scalar, const Vector& vector); template Vector operator*( const complex& scalar, const Vector& vector); // ************************* // Stream Operators // ************************* template std::ostream& operator<<( std::ostream& out, const VectorBase& vector) { size_t vector_size = vector.size(); out << vector_size << " : "; for (size_t i = 0; i < vector_size; ++i) { out << " " << vector[i]; } return out; } template std::ostream& operator<<( std::ostream& out, const VectorBase& vector); template std::ostream& operator<<( std::ostream& out, const VectorBase& vector); template std::istream& operator>>(std::istream& in, VectorBase& vector) { size_t n; in >> n; vector = VectorBase(n); char dummy; in >> dummy; for (size_t i = 0; i < n; ++i) { in >> vector[i]; } return in; } template std::istream& operator>>( std::istream& in, VectorBase& vector); template std::istream& operator>>( std::istream& in, VectorBase& vector); } // namespace MAUS