Skip to content

Latest commit

 

History

History
250 lines (213 loc) · 17.6 KB

tensorOps.rst

File metadata and controls

250 lines (213 loc) · 17.6 KB

LvArray::tensorOps

LvArray::tensorOps is a collection of free template functions which perform common linear algebra operations on compile time sized matrices and vectors. All of the functions work on device.

Object Representation

The LvArray::tensorOps methods currently operate on four different types of object; scalars, vectors, matrices, and symmetric matrices.

Vectors are represented by either a one dimensional c-array or a one dimensional LvArray::Array object. Examples of acceptable vector types are

  • double[ 4 ]
  • int[ 55 ]
  • LvArray::Array< float, 1, camp::idx_seq< 0 >, std::ptrdiff_t, LvArray::MallocBuffer >
  • LvArray::ArrayView< long, 1, 0, std::ptrdiff_t, LvArray::MallocBuffer >
  • LvArray::ArraySlice< double, 1, 0, std::ptrdiff_t >
  • LvArray::ArraySlice< double, 1, -1, std::ptrdiff_t >

Matrices are represented by either a two dimensional c-array or a two dimensional LvArray::Array object. Examples of acceptable matrix types

  • double[ 3 ][ 3 ]
  • int[ 5 ][ 2 ]
  • LvArray::Array< float, 2, camp::idx_seq< 0, 1 >, std::ptrdiff_t, LvArray::MallocBuffer >
  • LvArray::ArrayView< long, 2, 0, std::ptrdiff_t, LvArray::MallocBuffer >:
  • LvArray::ArraySlice< double, 2, 1, std::ptrdiff_t >
  • LvArray::ArraySlice< double, 2, 0, std::ptrdiff_t >
  • LvArray::ArraySlice< double, 2, -1, std::ptrdiff_t >

Symmetric matrices are represented in Voigt notation as a vector. This means that a 2 × 2 symmetric matrix is represented as vector of length three as [a00, a11, a01] and that a 3 × 3 symmetric matrix is represented as vector of length six as [a00, a11, a22, a12, a02, a01]. One consequence of this is that you can use the vector methods to for example add one symmetric matrix to another.

Common operations

Variables
α: A scalar.
---------------------------------------------------------------------------------------------------------------
x: A vector in m × ℝ1.
---------------------------------------------------------------------------------------------------------------
y: A vector in m × ℝ1.
---------------------------------------------------------------------------------------------------------------
z: A vector in m × ℝ1.
---------------------------------------------------------------------------------------------------------------
A: A matrix in m × ℝn.
---------------------------------------------------------------------------------------------------------------
B: A matrix in m × ℝn.
---------------------------------------------------------------------------------------------------------------
Operation Function
====================================================== ========================================================
x ← y tensorOps::copy< m >( x, y )
A ← B tensorOps::copy< m, n >( A, B )
x ← αx tensorOps::scale< m >( x, alpha )
A ← αA tensorOps::scale< m, n >( A, alpha )
x ← αy tensorOps::scaledCopy< m >( x, y, alpha )
A ← αB tensorOps::scaledCopy< m, n >( A, B, alpha )
x ← x + y tensorOps::add< m >( x, y )
A ← A + B tensorOps::add< m, n >( A, B, alpha )
x ← x − y tensorOps::subtract< m >( x, y )
x ← x + αy tensorOps::scaledAdd< m >( x, y, alpha )
x ← y ∘ z tensorOps::hadamardProduct< m >( x, y, z )

There is also a function fill that will set all the entries of the object to a specific value. For a vector it is called as tensorOps::fill< n >( x ) and for a matrix as tensorOps::fill< m, n >( A ).

Vector operations

Variables
α: A scalar.
------------------------------------------------------------------------------
x: A vector in m × ℝ1.
------------------------------------------------------------------------------
y: A vector in m × ℝ1.
------------------------------------------------------------------------------
z: A vector in m × ℝ1.
------------------------------------------------------------------------------
Operation Function
==================================== =========================================
|x| tensorOps::maxAbsoluteEntry< m >( x )
|x|22 tensorOps::l2NormSquared< m >( x )
|x|2 tensorOps::l2Norm< m >( x )
x ←  tensorOps::normalize< m >( x )
xTy tensorOps::AiBi( x, y )

If x, y and z are all in 3 × ℝ1 then you can perform the operation x ← y × z as tensorOps::crossProduct( x, y, z ).

Matrix vector operations

Variables
x: A vector in m × ℝ1.
--------------------------------------------------------------------------------------------------
y: A vector in n × ℝ1.
--------------------------------------------------------------------------------------------------
A: A matrix in m × ℝn.
--------------------------------------------------------------------------------------------------
Operation Function
====================================================== ===========================================
A ← xyT tensorOps::Rij_eq_AiBj< m, n >( A, x, y )
A ← A + xyT tensorOps::Rij_add_AiBj< m, n >( A, x, y )
x ← Ay tensorOps::Ri_eq_AijBj< m, n >( x, A, y )
x ← x + Ay tensorOps::Ri_add_AijBj< m, n >( x, A, y )
y ← ATx tensorOps::Ri_eq_AjiBj< n, m >( y, A, x )
y ← y + ATx tensorOps::Ri_add_AjiBj< n, m >( y, A, x )

Matrix operations

Variables
A: A matrix in m × ℝn.
-------------------------------------------------------------------------------------------------------------------
B: A matrix in m × ℝp.
-------------------------------------------------------------------------------------------------------------------
C: A matrix in p × ℝn.
-------------------------------------------------------------------------------------------------------------------
D: A matrix in n × ℝm.
-------------------------------------------------------------------------------------------------------------------
E: A matrix in m × ℝm.
-------------------------------------------------------------------------------------------------------------------
Operation Function
=================================================================== ===============================================
A ← DT tensorOps::transpose< m, n >( A, D )
A ← BC tensorOps::Rij_eq_AikBkj< m, n, p >( A, B, C )
A ← A + BC tensorOps::Rij_add_AikBkj< m, n, p >( A, B, C )
B ← ACT tensorOps::Rij_eq_AikBjk< m, p, n >( B, A, C )
B ← B + ACT tensorOps::Rij_add_AikBjk< m, p, n >( B, A, C )
E ← E + AAT tensorOps::Rij_add_AikAjk< m, n >( E, A )
C ← BTA tensorOps::Rij_eq_AkiBkj< p, n, m >( C, B, A )
C ← C + BTA tensorOps::Rij_add_AkiBkj< p, n, m >( C, B, A )

Square matrix operations

Variables
α: A scalar.
-----------------------------------------------------------------------------------------------------------------------
A: A matrix in m × ℝm.
-----------------------------------------------------------------------------------------------------------------------
B: A matrix in m × ℝm.
-----------------------------------------------------------------------------------------------------------------------
Operation Function
=============================================================== =======================================================
A ← AT tensorOps::transpose< m >( A )
A ← A + αI tensorOps::tensorOps::addIdentity< m >( A, alpha )
tr(A) tensorOps::trace< m >( A )
|A| tensorOps::determinant< m >( A )
A ← B1 tensorOps::invert< m >( A, B )
A ← A1 tensorOps::invert< m >( A )

Note

Apart from tensorOps::determinant and tensorOps::invert are only implemented for matrices of size 2 × 2 and 3 × 3.

Symmetric matrix operations

Variables
α: A scalar.
-------------------------------------------------------------------------------------------------------------------------------
x: A vector in m × ℝ1.
-------------------------------------------------------------------------------------------------------------------------------
y: A vector in m × ℝ1.
-------------------------------------------------------------------------------------------------------------------------------
A: A matrix in m × ℝm.
-------------------------------------------------------------------------------------------------------------------------------
B: A matrix in m × ℝm.
-------------------------------------------------------------------------------------------------------------------------------
S: A symmetric matrix in m × ℝm.
-------------------------------------------------------------------------------------------------------------------------------
Q: A symmetric matrix in m × ℝm.
-------------------------------------------------------------------------------------------------------------------------------
Operation Function
================================================================================ ==============================================
S ← S + αI tensorOps::symAddIdentity< m >( S, alpha )
tr(S) tensorOps::symTrace< m >( S )
x ← Sy tensorOps::Ri_eq_symAijBj< m >( x, S ,y )
x ← x + Sy tensorOps::Ri_add_symAijBj< m >( x, S ,y )
A ← SBT tensorOps::Rij_eq_symAikBjk< m >( A, S, B )
S ← AQAT tensorOps::Rij_eq_AikSymBklAjl< m >( S, A, Q )
|S| tensorOps::symDeterminant< m >( S )
S ← Q1 tensorOps::symInvert< m >( S, Q )
S ← S1 tensorOps::symInvert< m >( S )
x ← SAT = diag(x)AT tensorOps::symEigenvalues< M >( x, S )
x, A ← SAT = diag(x)AT tensorOps::symEigenvectors< M >( x, S )

There are also two function tensorOps::denseToSymmetric and tensorOps::symmetricToDense which convert between dense and symmetric matrix representation.

Note

Apart from tensorOps::symAddIdentity and tensorOps::symTrace the symmetric matrix operations are only implemented for matrices of size 2 × 2 and 3 × 3.

Examples

../../examples/exampleTensorOps.cpp

[Source: examples/exampleTensorOps.cpp]

You can mix and match the data types of the objects and also call the tensorOps methods on device.

../../examples/exampleTensorOps.cpp

[Source: examples/exampleTensorOps.cpp]

Bounds checking

Whatever the argument type the number of dimensions is checked at compile time. For example if you pass a double[ 3 ][ 3 ] or a three dimensional LvArray::ArraySlice to LvArray::tensorOps::crossProduct you will get a compilation error since that function is only implemented for vectors. When passing a c-array as an argument the size of the array is checked at compile time. For example if you pass int[ 2 ][ 3 ] to LvArray::tensorOps::addIdentity you will get a compilation error because that function only operates on square matrices. However when passing an LvArray::Array* object the size is only checked at runtime if LVARRAY_BOUNDS_CHECK is defined.

../../examples/exampleTensorOps.cpp

[Source: examples/exampleTensorOps.cpp]

Doxygen