/***************************************************************************
* GVector.cpp - Vector class *
* ----------------------------------------------------------------------- *
* copyright (C) 2006-2013 by Juergen Knoedlseder *
* ----------------------------------------------------------------------- *
* *
* This program 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. *
* *
* This program 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 this program. If not, see . *
* *
***************************************************************************/
/**
* @file GVector.cpp
* @brief Vector class implementation
* @author Juergen Knoedlseder
*/
/* __ Includes ___________________________________________________________ */
#ifdef HAVE_CONFIG_H
#include
#endif
#include "GVector.hpp"
#include "GTools.hpp"
/* __ Method name definitions ____________________________________________ */
#define G_OP_ADD "GVector::operator+=(GVector&)"
#define G_OP_SUB "GVector::operator-=(GVector&)"
#define G_AT "GVector::at(int&)"
#define G_CROSS "cross(GVector&, GVector&)"
#define G_SCALAR "operator*(GVector&, GVector&)"
/*==========================================================================
= =
= Constructors/destructors =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Void vector constructor
***************************************************************************/
GVector::GVector(void)
{
// Initialise class members
init_members();
// Return
return;
}
/***********************************************************************//**
* @brief Vector constructor
*
* @param[in] num Number of elements in vector.
*
* Initialises a vector with @p num elements. All vector elements will be
* set to 0.
***************************************************************************/
GVector::GVector(const int& num)
{
// Initialise class members
init_members();
// Store vector size
m_num = num;
// Allocate vector (filled with 0)
alloc_members();
// Return
return;
}
/***********************************************************************//**
* @brief Single element vector constructor
*
* @param[in] a Vector element.
*
* Initialises a vector with a single element.
***************************************************************************/
GVector::GVector(const double& a)
{
// Initialise class members
init_members();
// Store vector size
m_num = 1;
// Allocate vector
alloc_members();
// Set value
m_data[0] = a;
// Return
return;
}
/***********************************************************************//**
* @brief Two elements vector constructor
*
* @param[in] a First vector element.
* @param[in] b Second vector element.
*
* Initialises a vector with two elements.
***************************************************************************/
GVector::GVector(const double& a, const double& b)
{
// Initialise class members
init_members();
// Store vector size
m_num = 2;
// Allocate vector
alloc_members();
// Set values
m_data[0] = a;
m_data[1] = b;
// Return
return;
}
/***********************************************************************//**
* @brief Three elements vector constructor
*
* @param[in] a First vector element.
* @param[in] b Second vector element.
* @param[in] c Third vector element.
*
* Initialises a vector with three elements.
***************************************************************************/
GVector::GVector(const double& a, const double& b, const double& c)
{
// Initialise class members
init_members();
// Store vector size
m_num = 3;
// Allocate vector
alloc_members();
// Set values
m_data[0] = a;
m_data[1] = b;
m_data[2] = c;
// Return
return;
}
/***********************************************************************//**
* @brief Copy constructor
*
* @param[in] vector Vector.
***************************************************************************/
GVector::GVector(const GVector& vector)
{
// Initialise class members
init_members();
// Copy members
copy_members(vector);
// Return
return;
}
/***********************************************************************//**
* @brief Destructor
***************************************************************************/
GVector::~GVector(void)
{
// Free members
free_members();
// Return
return;
}
/*==========================================================================
= =
= Operators =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Assignment operator
*
* @param[in] vector Vector.
* @return Vector.
***************************************************************************/
GVector& GVector::operator=(const GVector& vector)
{
// Execute only if object is not identical
if (this != &vector) {
// Free members
free_members();
// Initialise private members
init_members();
// Copy members
copy_members(vector);
} // endif: object was not identical
// Return this object
return *this;
}
/***********************************************************************//**
* @brief Equality operator
*
* @param[in] vector Vector.
* @return True if vectors are identical.
*
* Returns true if vectors are identical. Vectors are considered identical
* if they have the same size and if all their elements are identical.
***************************************************************************/
bool GVector::operator==(const GVector& vector) const
{
// Initalise result depending on vector size identity
bool result = (m_num == vector.m_num);
// Test for difference. Break at first difference
if (result) {
for (int i = 0; i < m_num; ++i) {
if (m_data[i] != vector.m_data[i]) {
result = false;
break;
}
}
}
// Return result
return result;
}
/***********************************************************************//**
* @brief Non-equality operator
*
* @param[in] vector Vector.
* @return True if both vectors are different.
***************************************************************************/
bool GVector::operator!=(const GVector& vector) const
{
// Get negated result of equality operation
bool result = !(this->operator==(vector));
// Return result
return result;
}
/***********************************************************************//**
* @brief Unary addition operator
*
* @param[in] vector Vector.
* @return Vector.
*
* @exception GException::vector_mismatch
* Vectors have not the same size.
*
* Adds vector.
***************************************************************************/
GVector& GVector::operator+=(const GVector& vector)
{
// Raise exception if vectors mismatch
if (m_num != vector.m_num) {
throw GException::vector_mismatch(G_OP_ADD, m_num, vector.m_num);
}
// Add elements
for (int i = 0; i < m_num; ++i) {
m_data[i] += vector.m_data[i];
}
// Return vector
return *this;
}
/***********************************************************************//**
* @brief Unary subtraction operator
*
* @param[in] vector Vector.
* @return Vector.
*
* @exception GException::vector_mismatch
* Vectors have not the same size.
*
* Subtracts vector.
***************************************************************************/
GVector& GVector::operator-=(const GVector& vector)
{
// Raise exception if vectors mismatch
if (m_num != vector.m_num) {
throw GException::vector_mismatch(G_OP_SUB, m_num, vector.m_num);
}
// Subtract elements
for (int i = 0; i < m_num; ++i) {
m_data[i] -= vector.m_data[i];
}
// Return vector
return *this;
}
/***********************************************************************//**
* @brief Scalar assignment operator
*
* @param[in] scalar Scalar.
* @return Vector.
*
* Subtracts vector.
***************************************************************************/
GVector& GVector::operator=(const double& scalar)
{
// Set elements
for (int i = 0; i < m_num; ++i) {
m_data[i] = scalar;
}
// Return vector
return *this;
}
/***********************************************************************//**
* @brief Scalar unary addition operator
*
* @param[in] scalar Scalar.
* @return Vector.
*
* Adds scalar to all vector elements.
***************************************************************************/
GVector& GVector::operator+=(const double& scalar)
{
// Add scalar to elements
for (int i = 0; i < m_num; ++i) {
m_data[i] += scalar;
}
// Return vector
return *this;
}
/***********************************************************************//**
* @brief Scalar unary subtraction operator
*
* @param[in] scalar Scalar.
* @return Vector.
*
* Subtract scalar to all vector elements.
***************************************************************************/
GVector& GVector::operator-=(const double& scalar)
{
// Subtract scalar from elements
for (int i = 0; i < m_num; ++i) {
m_data[i] -= scalar;
}
// Return vector
return *this;
}
/***********************************************************************//**
* @brief Scalar unary multiplication operator
*
* @param[in] scalar Scalar.
* @return Vector.
*
* Multiply all vector elements by scalar.
***************************************************************************/
GVector& GVector::operator*=(const double& scalar)
{
// Multiply all elements
for (int i = 0; i < m_num; ++i) {
m_data[i] *= scalar;
}
// Return vector
return *this;
}
/***********************************************************************//**
* @brief Scalar unary division operator
*
* @param[in] scalar Scalar.
* @return Vector.
*
* Divide all vector elements by scalar.
***************************************************************************/
GVector& GVector::operator/=(const double& scalar)
{
// Divide all elements
for (int i = 0; i < m_num; ++i) {
m_data[i] /= scalar;
}
// Return vector
return *this;
}
/***********************************************************************//**
* @brief Unary minus operator
*
* @return Vector.
*
* Negate all vector elements.
***************************************************************************/
GVector GVector::operator-(void) const
{
// Copy vector
GVector result = *this;
// Negate all elements
for (int i = 0; i < m_num; ++i) {
result.m_data[i] = -result.m_data[i];
}
// Return vector
return result;
}
/*==========================================================================
= =
= Public methods =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Clear vector
***************************************************************************/
void GVector::clear(void)
{
// Free members
free_members();
// Initialise private members
init_members();
// Return
return;
}
/***********************************************************************//**
* @brief Clone vector
*
* @return Pointer to deep copy of vector.
***************************************************************************/
GVector* GVector::clone(void) const
{
// Clone vector
return new GVector(*this);
}
/***********************************************************************//**
* @brief Vector element access with range checking
*
* @param[in] index Element index [0,...,size()-1].
*
* @exception GException::out_of_range
* Element index is out of range.
***************************************************************************/
double& GVector::at(const int& index)
{
// Raise an exception if index is out of range
if (index < 0 || index >= size()) {
throw GException::out_of_range(G_AT, index, size()-1);
}
// Return vector element
return m_data[index];
}
/***********************************************************************//**
* @brief Vector element access with range checking (const variant)
*
* @param[in] index Element index [0,...,size()-1].
*
* @exception GException::out_of_range
* Element index is out of range.
***************************************************************************/
const double& GVector::at(const int& index) const
{
// Raise an exception if index is out of range
if (index < 0 || index >= size()) {
throw GException::out_of_range(G_AT, index, size()-1);
}
// Return vector element
return m_data[index];
}
/***********************************************************************//**
* @brief Returns number of non-zero elements in vector
*
* @return Number of non-zero elements in vector.
***************************************************************************/
int GVector::non_zeros(void) const
{
// Initialise number of non-zeros
int non_zeros = 0;
// Gather all non-zero elements
for (int i = 0; i < m_num; ++i) {
if (m_data[i] != 0.0) {
non_zeros++;
}
}
// Return number of non-zero elements
return non_zeros;
}
/***********************************************************************//**
* @brief Print vector information
*
* @param[in] chatter Chattiness (defaults to NORMAL).
* @return String containing vector information.
***************************************************************************/
std::string GVector::print(const GChatter& chatter) const
{
// Initialise result string
std::string result = "(";
// Continue only if chatter is not silent
if (chatter != SILENT) {
// Put all elements in stream
for (int i = 0; i < m_num; ++i) {
result += gammalib::str((*this)[i]);
if (i != m_num-1) {
result += ", ";
}
}
// Append )
result += ")";
} // endif: chatter was not silent
// Return result
return result;
}
/*==========================================================================
= =
= Private methods =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Initialise class members
***************************************************************************/
void GVector::init_members(void)
{
// Initialise members
m_num = 0;
m_data = NULL;
// Return
return;
}
/***********************************************************************//**
* @brief Allocate vector
***************************************************************************/
void GVector::alloc_members(void)
{
// Continue only if vector has non-zero length
if (m_num > 0) {
// Allocate vector and initialize elements to 0
m_data = new double[m_num];
for (int i = 0; i < m_num; ++i) {
m_data[i] = 0.0;
}
} // endif: vector had non-zero length
// Return
return;
}
/***********************************************************************//**
* @brief Copy class members
*
* @param[in] vector Vector from which members should be copied.
***************************************************************************/
void GVector::copy_members(const GVector& vector)
{
// Copy attributes
m_num = vector.m_num;
// Copy elements
if (m_num > 0) {
alloc_members();
for (int i = 0; i < m_num; ++i) {
m_data[i] = vector.m_data[i];
}
}
// Return
return;
}
/***********************************************************************//**
* @brief Delete class members
***************************************************************************/
void GVector::free_members(void)
{
// Free memory
if (m_data != NULL) delete[] m_data;
// Signal free pointers
m_data = NULL;
// Return
return;
}
/*==========================================================================
= =
= Friends =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Vector cross product
*
* @param[in] a Vector.
* @param[in] b Vector.
* @return Vector cross product.
*
* @exception GException::vector_mismatch
* Mismatch between vector size.
*
* Computes the cross product between two 3-element vectors (note that the
* cross product is only defined for 3-element vectors).
***************************************************************************/
GVector cross(const GVector& a, const GVector& b)
{
// Verify that vectors have same dimensions
if (a.m_num != b.m_num) {
throw GException::vector_mismatch(G_CROSS, a.m_num, b.m_num);
}
// Verify that vectors have 3 elements
if (a.m_num != 3) {
throw GException::vector_bad_cross_dim(G_CROSS, a.m_num);
}
// Compute cross product
GVector result(3);
result.m_data[0] = a.m_data[1]*b.m_data[2] - a.m_data[2]*b.m_data[1];
result.m_data[1] = a.m_data[2]*b.m_data[0] - a.m_data[0]*b.m_data[2];
result.m_data[2] = a.m_data[0]*b.m_data[1] - a.m_data[1]*b.m_data[0];
// Return result
return result;
}
/***********************************************************************//**
* @brief Vector scalar product
*
* @param[in] a Vector.
* @param[in] b Vector.
* @return Product between vector @p a and @p b.
*
* @exception GException::vector_mismatch
* Mismatch between vector size.
*
* Returns the scalar product between vector @p a and @p b.
***************************************************************************/
double operator*(const GVector& a, const GVector& b)
{
// Verify that vectors have same dimensions
if (a.m_num != b.m_num) {
throw GException::vector_mismatch(G_SCALAR, a.m_num, b.m_num);
}
// Compute scalar product
double result = 0.0;
for (int i = 0; i < a.m_num; ++i) {
result += (a.m_data[i] * b.m_data[i]);
}
// Return scalar product
return result;
}
/***********************************************************************//**
* @brief Computes vector norm
*
* @param[in] vector Vector.
* @return Vector norm.
***************************************************************************/
double norm(const GVector& vector)
{
// Initialises result
double result = 0.0;
// Computes norm
for (int i = 0; i < vector.m_num; ++i) {
result += (vector.m_data[i] * vector.m_data[i]);
}
result = (result > 0.0) ? std::sqrt(result) : 0.0;
// Returns norm
return result;
}
/***********************************************************************//**
* @brief Computes minimum vector element
*
* @param[in] vector Vector.
* @return Minimum vector element.
***************************************************************************/
double min(const GVector& vector)
{
// Initialises result
double result = 0.0;
// Continue only if we have elements
if (vector.m_num > 0) {
// Search for minimum
result = vector.m_data[0];
for (int i = 1; i < vector.m_num; ++i) {
if (vector.m_data[i] < result) {
result = vector.m_data[i];
}
}
} // endif: there were elements
// Returns minimum
return result;
}
/***********************************************************************//**
* @brief Computes maximum vector element
*
* @param[in] vector Vector.
* @return Maximum vector element.
***************************************************************************/
double max(const GVector& vector)
{
// Initialises result
double result = 0.0;
// Continue only if we have elements
if (vector.m_num > 0) {
// Search for maximum
result = vector.m_data[0];
for (int i = 1; i < vector.m_num; ++i) {
if (vector.m_data[i] > result) {
result = vector.m_data[i];
}
}
} // endif: there were elements
// Returns maximum
return result;
}
/***********************************************************************//**
* @brief Computes vector sum
*
* @param[in] vector Vector.
* @return Sum of vector elements.
***************************************************************************/
double sum(const GVector& vector)
{
// Compute sum
double result = 0.0;
for (int i = 0; i < vector.m_num; ++i) {
result += vector.m_data[i];
}
// Returns sum
return result;
}
/***********************************************************************//**
* @brief Computes vector permutation
*
* @param[in] vector Vector.
* @param[in] p Permutation array.
* @return Permuted vector.
***************************************************************************/
GVector perm(const GVector& vector, const int* p)
{
// Initialise result vector
GVector result(vector.m_num);
// Compute permutations
if (p != NULL) {
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = vector.m_data[p[i]];
}
}
else {
result = vector;
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes vector inverse permutation
*
* @param[in] vector Vector.
* @param[in] p Permutation array.
* @return Inversely permuted vector.
***************************************************************************/
GVector iperm(const GVector& vector, const int* p)
{
// Initialise result vector
GVector result(vector.m_num);
// Compute permutations
if (p != NULL) {
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[p[i]] = vector.m_data[i];
}
}
else {
result = vector;
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes arccos of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the arccos of every element.
***************************************************************************/
GVector acos(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::acos(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes acosh of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the acosh of every element.
***************************************************************************/
GVector acosh(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = acosh(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes arcsin of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the arcsin of every element.
***************************************************************************/
GVector asin(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::asin(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes asinh of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the asinh of every element.
***************************************************************************/
GVector asinh(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = asinh(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes arctan of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the arctan of every element.
***************************************************************************/
GVector atan(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::atan(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes atanh of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the atanh of every element.
***************************************************************************/
GVector atanh(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = atanh(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes cosine of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the cosine of every element.
***************************************************************************/
GVector cos(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::cos(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes cosh of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the cosh of every element.
***************************************************************************/
GVector cosh(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::cosh(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes exponential of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the exponential of every element.
***************************************************************************/
GVector exp(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::exp(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes absolute of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the absolute of every element.
***************************************************************************/
GVector abs(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::abs(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes natural logarithm of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the natural logarithm of every element.
***************************************************************************/
GVector log(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::log(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes base10 logarithm of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the base10 logarithm of every element.
***************************************************************************/
GVector log10(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::log10(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes sine of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the sine of every element.
***************************************************************************/
GVector sin(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::sin(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes sinh of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the sinh of every element.
***************************************************************************/
GVector sinh(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::sinh(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes square root of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the square root of every element.
***************************************************************************/
GVector sqrt(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::sqrt(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes tangens of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the tangens of every element.
***************************************************************************/
GVector tan(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::tan(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes tanh of vector elements
*
* @param[in] vector Vector.
* @return Vector containing the tanh of every element.
***************************************************************************/
GVector tanh(const GVector& vector)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::tanh(vector.m_data[i]);
}
// Return vector
return result;
}
/***********************************************************************//**
* @brief Computes tanh of vector elements
*
* @param[in] vector Vector.
* @param[in] power Power.
* @return Vector containing the power of every element.
***************************************************************************/
GVector pow(const GVector& vector, const double& power)
{
// Initialise result vector
GVector result(vector.m_num);
// Evaluate each vector element
for (int i = 0; i < vector.m_num; ++i) {
result.m_data[i] = std::pow(vector.m_data[i], power);
}
// Return vector
return result;
}