/* This file is part of the OpenLB library
*
* Copyright (C) 2015 Asher Zarth, Mathias J. Krause, Albert Mink
* E-mail contact: info@openlb.net
* The most recent release of OpenLB can be downloaded at
*
*
* 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 2
* 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, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/** \file
* efficient implementation of a vector class
*/
#ifndef VECTOR_H
#define VECTOR_H
#include
#include
#include
#include "util.h"
#include "math.h"
#include "olbDebug.h"
typedef double S;
// Use BaseType double as the default BaseType.
#ifndef BaseType
///TODO
//check OLD_PRECONDITION
//change this typedef, double for testing only
//#define BaseType S
#define BaseType S
#endif
namespace olb {
/** Efficient implementation of a vector class.
* Static size.
* Default value of vector element is T(0)
*/
template
class Vector {
public:
/// number of dimensions
T data[Size];
public:
/// Constructor from array
Vector(const T ar[Size]);
/// Constructor from std::vector
Vector(const std::vector& v);
/// Construct with all entries as explicit scalar
explicit Vector(const T& s = T());
/// Construct 2D, 2 explicit arguments
Vector(const T& a, const T& b);
/// Construct 3D, 3 explicit arguments
Vector(const T& a, const T& b, const T& c);
/// copy constructor
Vector(const Vector& v);
/// copy assignment operator
Vector& operator = (const Vector& v);
/// destructor
~Vector() = default;
/// element access
T& operator[](unsigned n);
/// element access (read only)
const T& operator[](const unsigned n) const;
/// cumulative add vector
Vector& operator += (const Vector& v);
/// cumulatively subtract vector
Vector& operator -= (const Vector& v);
/// add scalar to each entry
Vector& operator += (const T& s);
/// subtract scalar from each entry
Vector& operator -= (const T& s);
/// multiply by scalar
Vector& operator *= (const T& s);
/// divide by scalar
Vector& operator /= (const T& s);
/// equal operator returns true if all components match
bool operator == (const Vector& v);
/// unequal operator returns true if at least one components differs
bool operator != (const Vector& v);
/// get l2 norm of vector
T norm();
/// get normalized vector
void normalize(const T& scale = T(1));
/// check if vector has zero length
bool closeToZero();
//operator BaseType();
/// convert to std::vector
std::vector toStdVector() const;
};
template
inline Vector::Vector(const T ar[Size])
{
//static_assert(std::is_trivially_copyable::value, "Only trivially copyable objects can safely be copied by memcpy");
std::memcpy( data, ar, Size*sizeof(T));
}
template
inline Vector::Vector(const std::vector& v)
{
OLB_PRECONDITION(v.size() == Size);
//static_assert(std::is_trivially_copyable::value, "Only trivially copyable objects can safely be copied by memcpy");
std::memcpy( data, v.data(), Size*sizeof(T));
}
template
inline Vector::Vector(const T& s)
{
for (unsigned i = 0; i < Size; ++i) {
data[i] = s;
}
}
template
inline Vector::Vector(const T& a, const T& b)
{
OLB_PRECONDITION(Size == 2);
data[0] = a;
data[1] = b;
}
template
inline Vector::Vector(const T& a, const T& b, const T& c)
{
OLB_PRECONDITION(Size == 3);
data[0] = a;
data[1] = b;
data[2] = c;
}
template
inline Vector::Vector(const Vector& v)
{
//static_assert(std::is_trivially_copyable::value, "Only trivially copyable objects can safely be copied by memcpy");
std::memcpy( data, v.data, Size*sizeof(T));
}
template
inline Vector& Vector::operator= (const Vector& v)
{
//static_assert(std::is_trivially_copyable::value, "Only trivially copyable objects can safely be copied by memcpy");
std::memcpy( data, v.data, Size*sizeof(T));
return *this;
}
template
inline Vector& Vector::operator+= (const Vector& v)
{
for (unsigned i = 0; i < Size; ++i) {
data[i] += v[i];
}
return *this;
}
template
inline Vector& Vector::operator+= (const T& s)
{
for (unsigned i = 0; i < Size; ++i) {
data[i] += s;
}
return *this;
}
template
inline Vector& Vector::operator-= (const Vector& v)
{
for (unsigned i = 0; i < Size; ++i) {
data[i] -= v[i];
}
return *this;
}
template
inline Vector& Vector::operator*= (const T& s)
{
for (unsigned i = 0; i < Size; ++i) {
data[i] *= s;
}
return *this;
}
template
inline Vector& Vector::operator/= (const T& s)
{
for (unsigned i = 0; i < Size; ++i) {
data[i] /= s;
}
return *this;
}
template
inline Vector& Vector::operator-= (const T& s)
{
for (unsigned i = 0; i < Size; ++i) {
data[i] -= s;
}
return *this;
}
template
inline bool Vector::operator== (const Vector& v)
{
bool theSame = true;
for (unsigned i = 0; i < Size; ++i) {
theSame &= data[i] == v.data[i];
}
return theSame;
}
template
inline bool Vector::operator!= (const Vector& v)
{
return !(*this == v);
}
template
inline T& Vector::operator[](unsigned n)
{
OLB_PRECONDITION(n < Size);
return data[n];
}
template
inline const T& Vector::operator[](const unsigned n) const
{
OLB_PRECONDITION(n < Size);
return data[n];
}
template
inline bool Vector::closeToZero()
{
bool zero = true;
T EPSILON = std::numeric_limits::epsilon();
for (unsigned i = 0; i < Size; ++i) {
if (fabs(data[i]) > EPSILON) {
zero = false;
}
}
return zero;
}
template
inline T Vector::norm()
{
T v(0);
for (unsigned iD = 0; iD < Size; ++iD) {
v += data[iD]*data[iD];
}
v = sqrt(v);
return v;
}
template
inline void Vector::normalize(const T& scale)
{
T invScale = scale/this->norm();
//assert(scale > 0);
for (unsigned int iDim = 0; iDim < Size; ++iDim) {
data[iDim] *= invScale;
}
}
template
inline std::vector Vector::toStdVector() const
{
return std::vector (data, data+Size);
}
template
inline std::ostream& operator << (std::ostream& os, const Vector& o)
{
if (Size != 0) {
os << "[";
for (unsigned i = 0; i < Size-1; ++i) {
os << o[i] << " ";
}
os << o[Size-1]<<"]";
}
else {
os << "[empty]";
}
return os;
}
template
inline Vector crossProduct3D(const Vector& a, const Vector& b)
{
Vector v(a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0]);
return v;
}
template
inline T norm(const Vector& a)
{
T v(0);
for (unsigned iD = 0; iD < Size; ++iD) {
v += a[iD]*a[iD];
}
v = sqrt(v);
return v;
}
template
inline void normalize(Vector& a)
{
T scale = norm(a);
//assert(scale > 0);
for (unsigned iDim = 0; iDim < Size; ++iDim) {
a[iDim] /= scale;
}
}
// indirect helper functions, providing general arithmetic
// overloading of operators for interaction with BaseType and itself
// addition, subtraction, multiplication and division
// PLUS
template
inline Vector operator+ (const BaseType& a, const Vector& b)
{
return Vector(b)+=a;
}
template
inline Vector operator+ (const Vector& a, const BaseType& b)
{
return Vector(a)+=b;
}
template
inline Vector operator+ (const Vector& a, const Vector& b)
{
return Vector(a)+=b;
}
template
inline Vector operator+ (const Vector& a, const Vector& b)
{
Vector result;
for (unsigned i = 0; i < Size; ++i) {
result[i] = a[i] + b[i];
}
return result;
}
// MINUS
template
inline Vector operator- (const BaseType& a, const Vector& b)
{
return Vector(a)-=b;
}
template
inline Vector operator- (const Vector& a, const BaseType& b)
{
return Vector(a)-=b;
}
template
inline Vector operator- (const Vector& a, const Vector& b)
{
return Vector(a)-=b;
}
template
inline Vector operator- (const Vector& a, const Vector& b)
{
Vector result;
for (unsigned i = 0; i < Size; ++i) {
result[i] = a[i] - b[i];
}
return result;
}
// MULTIPLY
template
inline Vector operator* (const BaseType& a, const Vector& b)
{
return Vector(b)*=a;
}
template
inline Vector operator* (const Vector& a, const BaseType& b)
{
return Vector(a)*=b;
}
template
inline T operator* (const Vector& a, const Vector& b)
{
T scalarProduct = T();
for (unsigned iD = 0; iD < Size; ++iD) {
scalarProduct += a[iD]*b[iD];
}
return scalarProduct;
}
// DIVIDE
template
inline Vector operator/ (const Vector& a, const BaseType& b)
{
return Vector(a)/=b;
}
/// < Operator returns true if all components are smaller
template
inline bool operator< (const Vector& lhs, const Vector& rhs)
{
bool smaller = true;
for (unsigned i = 0; i < Size; ++i) {
smaller &= (lhs[i] < rhs[i]);
}
return smaller;
}
/// > Operator returns true if all components are greater
template
inline bool operator> (const Vector& lhs, const Vector& rhs)
{
return rhs < lhs;
}
/// <= Operator returns true if all components are smaller or equal
template
inline bool operator<=(const Vector& lhs, const Vector& rhs)
{
bool smallerEq = true;
for (unsigned i = 0; i < Size; ++i) {
smallerEq &= (lhs[i] <= rhs[i]);
}
return smallerEq;
}
/// >= Operator returns true if all components are smaller or equal
template
inline bool operator>=(const Vector& lhs, const Vector& rhs)
{
return rhs <= lhs;
}
template
using Scalar = Vector;
template
using Vector2D = Vector;
template
using Vector3D = Vector;
template
using Vector4D = Vector;
} // end namespace olb
#endif