// Copyright (C) 2003-2009 Marc Duruflé
// Copyright (C) 2001-2009 Vivien Mallet
//
// This file is part of the linear-algebra library Seldon,
// http://seldon.sourceforge.net/.
//
// Seldon is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your option)
// any later version.
//
// Seldon 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 Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Seldon. If not, see http://www.gnu.org/licenses/.
#ifndef SELDON_FILE_FUNCTIONS_VECTOR_CXX
/*
Functions defined in this file:
alpha.X -> X
Mlt(alpha, X)
alpha.X + Y -> Y
Add(alpha, X, Y)
X -> Y
Copy(X, Y)
X <-> Y
Swap(X, Y)
X.Y
DotProd(X, Y)
DotProdConj(X, Y)
||X||
Norm1(X)
Norm2(X)
GetMaxAbsIndex(X)
Omega*X
GenRot(x, y, cos, sin)
ApplyRot(x, y, cos, sin)
*/
namespace Seldon
{
/////////
// MLT //
template <class T0,
class T1, class Storage1, class Allocator1>
void Mlt(const T0 alpha,
Vector<T1, Storage1, Allocator1>& X) throw()
{
X *= alpha;
}
// MLT //
/////////
/////////
// ADD //
template <class T0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2>
void Add(const T0 alpha,
const Vector<T1, Storage1, Allocator1>& X,
Vector<T2, Storage2, Allocator2>& Y) throw(WrongDim, NoMemory)
{
if (alpha != T0(0))
{
T1 alpha_ = alpha;
int ma = X.GetM();
#ifdef SELDON_CHECK_BOUNDS
CheckDim(X, Y, "Add(alpha, X, Y)");
#endif
for (int i = 0; i < ma; i++)
Y(i) += alpha_ * X(i);
}
}
template <class T0,
class T1, class Allocator1,
class T2, class Allocator2>
void Add(const T0 alpha,
const Vector<T1, VectSparse, Allocator1>& X,
Vector<T2, VectSparse, Allocator2>& Y) throw(WrongDim, NoMemory)
{
if (alpha != T0(0))
{
Vector<T1, VectSparse, Allocator1> Xalpha = X;
Xalpha *= alpha;
Y.AddInteractionRow(Xalpha.GetSize(),
Xalpha.GetIndex(), Xalpha.GetData(), true);
}
}
// ADD //
/////////
//////////
// COPY //
template <class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2>
void Copy(const Vector<T1, Storage1, Allocator1>& X,
Vector<T2, Storage2, Allocator2>& Y)
{
Y.Copy(X);
}
// COPY //
//////////
//////////
// SWAP //
template <class T1, class Storage1, class Allocator1,
class Storage2, class Allocator2>
void Swap(Vector<T1, Storage1, Allocator1>& X,
Vector<T1, Storage2, Allocator2>& Y)
{
int nx = X.GetM();
T1* data = X.GetData();
X.Nullify();
X.SetData(Y.GetM(), Y.GetData());
Y.Nullify();
Y.SetData(nx, data);
}
template <class T1, class Allocator1, class Allocator2>
void Swap(Vector<T1, VectSparse, Allocator1>& X,
Vector<T1, VectSparse, Allocator2>& Y)
{
int nx = X.GetM();
T1* data = X.GetData();
int* index = X.GetIndex();
X.Nullify();
X.SetData(Y.GetM(), Y.GetData(), Y.GetIndex());
Y.Nullify();
Y.SetData(nx, data, index);
}
// SWAP //
//////////
/////////////
// DOTPROD //
//! Scalar product between two vectors.
template<class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2>
T1 DotProd(const Vector<T1, Storage1, Allocator1>& X,
const Vector<T2, Storage2, Allocator2>& Y)
{
T1 value(0);
#ifdef SELDON_CHECK_BOUNDS
CheckDim(X, Y, "DotProd(X, Y)");
#endif
for (int i = 0; i < X.GetM(); i++)
value += X(i) * Y(i);
return value;
}
//! Scalar product between two vectors.
template<class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2>
T1 DotProdConj(const Vector<T1, Storage1, Allocator1>& X,
const Vector<T2, Storage2, Allocator2>& Y)
{
return DotProd(X, Y);
}
//! Scalar product between two vectors.
template<class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2>
complex<T1> DotProdConj(const Vector<complex<T1>, Storage1, Allocator1>& X,
const Vector<T2, Storage2, Allocator2>& Y)
{
complex<T1> value(0);
#ifdef SELDON_CHECK_BOUNDS
CheckDim(X, Y, "DotProdConj(X, Y)");
#endif
for (int i = 0; i < X.GetM(); i++)
value += conj(X(i)) * Y(i);
return value;
}
//! Scalar product between two sparse vectors.
template<class T1, class Allocator1,
class T2, class Allocator2>
T1 DotProd(const Vector<T1, VectSparse, Allocator1>& X,
const Vector<T2, VectSparse, Allocator2>& Y)
{
T1 value(0);
int size_x = X.GetSize();
int size_y = Y.GetSize();
int kx = 0, ky = 0, pos_x;
while (kx < size_x)
{
pos_x = X.Index(kx);
while (ky < size_y && Y.Index(ky) < pos_x)
ky++;
if (ky < size_y && Y.Index(ky) == pos_x)
value += X.Value(kx) * Y.Value(ky);
kx++;
}
return value;
}
//! Scalar product between two sparse vectors.
template<class T1, class Allocator1,
class T2, class Allocator2>
complex<T1>
DotProdConj(const Vector<complex<T1>, VectSparse, Allocator1>& X,
const Vector<T2, VectSparse, Allocator2>& Y)
{
complex<T1> value(0);
int size_x = X.GetSize();
int size_y = Y.GetSize();
int kx = 0, ky = 0, pos_x;
while (kx < size_x)
{
pos_x = X.Index(kx);
while (ky < size_y && Y.Index(ky) < pos_x)
ky++;
if (ky < size_y && Y.Index(ky) == pos_x)
value += conj(X.Value(kx)) * Y.Value(ky);
kx++;
}
return value;
}
// DOTPROD //
/////////////
///////////
// NORM1 //
template<class T1, class Storage1, class Allocator1>
T1 Norm1(const Vector<T1, Storage1, Allocator1>& X)
{
T1 value(0);
for (int i = 0; i < X.GetM(); i++)
value += abs(X(i));
return value;
}
template<class T1, class Storage1, class Allocator1>
T1 Norm1(const Vector<complex<T1>, Storage1, Allocator1>& X)
{
T1 value(0);
for (int i = 0; i < X.GetM(); i++)
value += abs(X(i));
return value;
}
template<class T1, class Allocator1>
T1 Norm1(const Vector<T1, VectSparse, Allocator1>& X)
{
T1 value(0);
for (int i = 0; i < X.GetSize(); i++)
value += abs(X.Value(i));
return value;
}
template<class T1, class Allocator1>
T1 Norm1(const Vector<complex<T1>, VectSparse, Allocator1>& X)
{
T1 value(0);
for (int i = 0; i < X.GetSize(); i++)
value += abs(X.Value(i));
return value;
}
// NORM1 //
///////////
///////////
// NORM2 //
template<class T1, class Storage1, class Allocator1>
T1 Norm2(const Vector<T1, Storage1, Allocator1>& X)
{
T1 value(0);
for (int i = 0; i < X.GetM(); i++)
value += X(i) * X(i);
return sqrt(value);
}
template<class T1, class Storage1, class Allocator1>
T1 Norm2(const Vector<complex<T1>, Storage1, Allocator1>& X)
{
T1 value(0);
for (int i = 0; i < X.GetM(); i++)
value += real(X(i) * conj(X(i)));
return sqrt(value);
}
template<class T1, class Allocator1>
T1 Norm2(const Vector<T1, VectSparse, Allocator1>& X)
{
T1 value(0);
for (int i = 0; i < X.GetSize(); i++)
value += X.Value(i) * X.Value(i);
return sqrt(value);
}
template<class T1, class Allocator1>
T1 Norm2(const Vector<complex<T1>, VectSparse, Allocator1>& X)
{
T1 value(0);
for (int i = 0; i < X.GetSize(); i++)
value += real(X.Value(i) * conj(X.Value(i)));
return sqrt(value);
}
// NORM2 //
///////////
////////////////////
// GETMAXABSINDEX //
template<class T, class Storage, class Allocator>
int GetMaxAbsIndex(const Vector<T, Storage, Allocator>& X)
{
return X.GetNormInfIndex();
}
// GETMAXABSINDEX //
////////////////////
//////////////
// APPLYROT //
//! Computation of rotation between two points.
template<class T>
void GenRot(T& a_in, T& b_in, T& c_, T& s_)
{
// Old BLAS version.
T roe;
if (abs(a_in) > abs(b_in))
roe = a_in;
else
roe = b_in;
T scal = abs(a_in) + abs(b_in);
T r, z;
if (scal != T(0))
{
T a_scl = a_in / scal;
T b_scl = b_in / scal;
r = scal * sqrt(a_scl * a_scl + b_scl * b_scl);
if (roe < T(0))
r *= T(-1);
c_ = a_in / r;
s_ = b_in / r;
z = T(1);
if (abs(a_in) > abs(b_in))
z = s_;
else if (abs(b_in) >= abs(a_in) && c_ != T(0))
z = T(1) / c_;
}
else
{
c_ = T(1);
s_ = T(0);
r = T(0);
z = T(0);
}
a_in = r;
b_in = z;
}
//! Computation of rotation between two points.
template<class T>
void GenRot(complex<T>& a_in, complex<T>& b_in, T& c_, complex<T>& s_)
{
T a = abs(a_in), b = abs(b_in);
if (a == T(0))
{
c_ = T(0);
s_ = complex<T>(1, 0);
a_in = b_in;
}
else
{
T scale = a + b;
T a_scal = abs(a_in / scale);
T b_scal = abs(b_in / scale);
T norm = sqrt(a_scal * a_scal + b_scal * b_scal) * scale;
c_ = a / norm;
complex<T> alpha = a_in / a;
s_ = alpha * conj(b_in) / norm;
a_in = alpha * norm;
}
b_in = complex<T>(0, 0);
}
//! Rotation of a point in 2-D.
template<class T>
void ApplyRot(T& x, T& y, const T c_, const T s_)
{
T temp = c_ * x + s_ * y;
y = c_ * y - s_ * x;
x = temp;
}
//! Rotation of a complex point in 2-D.
template<class T>
void ApplyRot(complex<T>& x, complex<T>& y,
const T& c_, const complex<T>& s_)
{
complex<T> temp = s_ * y + c_ * x;
y = -conj(s_) * x + c_ * y;
x = temp;
}
// APPLYROT //
//////////////
//////////////
// CHECKDIM //
//! Checks the compatibility of the dimensions.
/*! Checks that X + Y is possible according to the dimensions of
the vectors X and Y. If the dimensions are incompatible,
an exception is raised (a WrongDim object is thrown).
\param X vector.
\param Y vector.
\param function (optional) function in which the compatibility is checked.
Default: "".
\param op (optional) operation to be performed on the vectors.
Default: "X + Y".
*/
template <class T0, class Storage0, class Allocator0,
class T1, class Storage1, class Allocator1>
void CheckDim(const Vector<T0, Storage0, Allocator0>& X,
const Vector<T1, Storage1, Allocator1>& Y,
string function = "", string op = "X + Y")
{
if (X.GetLength() != Y.GetLength())
throw WrongDim(function, string("Operation ") + op
+ string(" not permitted:")
+ string("\n X (") + to_str(&X) + string(") is a ")
+ string("vector of length ") + to_str(X.GetLength())
+ string(";\n Y (") + to_str(&Y) + string(") is a ")
+ string("vector of length ") + to_str(Y.GetLength())
+ string("."));
}
// CHECKDIM //
//////////////
///////////////
// CONJUGATE //
//! Sets a vector to its conjugate.
template<class T, class Prop, class Allocator>
void Conjugate(Vector<T, Prop, Allocator>& X)
{
for (int i = 0; i < X.GetM(); i++)
X(i) = conj(X(i));
}
//! Sets a vector to its conjugate.
template<class T, class Allocator>
void Conjugate(Vector<T, VectSparse, Allocator>& X)
{
for (int i = 0; i < X.GetSize(); i++)
X.Value(i) = conj(X.Value(i));
}
// CONJUGATE //
///////////////
} // namespace Seldon.
#define SELDON_FILE_FUNCTIONS_VECTOR_CXX
#endif