STIR 6.4.0
MatrixFunction.inl
Go to the documentation of this file.
1//
2//
3/*
4 Copyright (C) 2004- 2007, Hammersmith Imanet Ltd
5 This file is part of STIR.
6
7 SPDX-License-Identifier: Apache-2.0
8
9 See STIR/LICENSE.txt for details
10*/
21#include "stir/IndexRange2D.h"
22#include <complex>
23#include <cmath>
24#ifdef BOOST_NO_STDC_NAMESPACE
25namespace std
26{
27using ::acos;
28}
29#endif
30
31START_NAMESPACE_STIR
32
33//----------------------------------------------------------------------
34// some functions specific for 1D Arrays
35//----------------------------------------------------------------------
36
37template <class elemT>
38inline elemT
40{
41 assert(v1.get_index_range() == v2.get_index_range());
42 elemT tmp = 0;
43 typename Array<1, elemT>::const_iterator i1 = v1.begin();
44 typename Array<1, elemT>::const_iterator i2 = v2.begin();
45 for (; i1 != v1.end(); ++i1, ++i2)
46 tmp += ((*i1) * (*i2));
47 return tmp;
48}
49
50template <class elemT>
51inline std::complex<elemT>
52inner_product(const Array<1, std::complex<elemT>>& v1, const Array<1, std::complex<elemT>>& v2)
53{
54 assert(v1.get_index_range() == v2.get_index_range());
55 std::complex<elemT> tmp = 0;
56 typename Array<1, std::complex<elemT>>::const_iterator i1 = v1.begin();
57 typename Array<1, std::complex<elemT>>::const_iterator i2 = v2.begin();
58 for (; i1 != v1.end(); ++i1, ++i2)
59 tmp += (std::conj(*i1) * (*i2));
60 return tmp;
61}
62
63template <class elemT>
64inline double
66{
67 return std::acos(inner_product(v1, v2) / norm(v1) / norm(v2));
68}
69
70//----------------------------------------------------------------------
71// functions for matrices
72
73// matrix with vector multiplication
74// first define a help function that works with both types of vectors)
75namespace detail
76{
77template <class elemT, class vecT>
78inline void
79matrix_multiply_help(vecT& retval, const Array<2, elemT>& m, const vecT& vec)
80{
81 assert(m.is_regular());
82 if (m.size() == 0)
83 {
84 return;
85 }
86
87 const int m_min_row = m.get_min_index();
88 const int m_max_row = m.get_max_index();
89 const int m_min_col = m[m_min_row].get_min_index();
90 const int m_max_col = m[m_min_row].get_max_index();
91 // make sure matrices are conformable for multiplication
92 assert(vec.get_min_index() == m_min_col);
93 assert(vec.get_max_index() == m_max_col);
94 for (int i = m_min_row; i <= m_max_row; ++i)
95 {
96 int j = m_min_col;
97 retval[i] = m[i][j] * vec[j];
98 for (++j; j <= m_max_col; ++j)
99 retval[i] += m[i][j] * vec[j];
100 }
101}
102} // namespace detail
103
104template <class elemT>
105inline Array<1, elemT>
107{
109 detail::matrix_multiply_help(ret, m, vec);
110 return ret;
111}
112
113template <int num_dimensions, class elemT>
114inline BasicCoordinate<num_dimensions, elemT>
115matrix_multiply(const Array<2, elemT>& m, const BasicCoordinate<num_dimensions, elemT>& vec)
116{
117 BasicCoordinate<num_dimensions, elemT> ret;
118 detail::matrix_multiply_help(ret, m, vec);
119 return ret;
120}
121
122// matrix multiplication
123template <class elemT>
124inline Array<2, elemT>
126{
127 assert(m1.is_regular());
128 assert(m2.is_regular());
129 if (m1.size() == 0 || m2.size() == 0)
130 {
131 Array<2, elemT> retval;
132 return retval;
133 }
134
135 const int m1_min_row = m1.get_min_index();
136 const int m1_max_row = m1.get_max_index();
137 const int m2_min_row = m2.get_min_index();
138 const int m2_max_row = m2.get_max_index();
139 const int m2_min_col = m2[m2_min_row].get_min_index();
140 const int m2_max_col = m2[m2_min_row].get_max_index();
141 // make sure matrices are conformable for multiplication
142 assert(m1[m1_min_row].get_min_index() == m2_min_row);
143 assert(m1[m1_min_row].get_max_index() == m2_max_row);
144
145 Array<2, elemT> retval(IndexRange2D(m1_min_row, m1_max_row, m2_min_col, m2_max_col));
146
147 for (int i = m1_min_row; i <= m1_max_row; ++i)
148 {
149 for (int j = m2_min_col; j <= m2_max_col; ++j)
150 {
151 for (int k = m2_min_row; k <= m2_max_row; ++k)
152 retval[i][j] += m1[i][k] * m2[k][j];
153 }
154 }
155 return retval;
156}
157
158template <class elemT>
159inline Array<2, elemT>
161{
162 assert(m.is_regular());
163 if (m.size() == 0)
164 {
165 Array<2, elemT> retval;
166 return retval;
167 }
168
169 const int m_min_row = m.get_min_index();
170 const int m_max_row = m.get_max_index();
171 const int m_min_col = m[m_min_row].get_min_index();
172 const int m_max_col = m[m_min_row].get_max_index();
173 Array<2, elemT> new_m(IndexRange2D(m_min_col, m_max_col, m_min_row, m_max_row));
174 for (int j = m_min_row; j <= m_max_row; ++j)
175 for (int i = m_min_col; i <= m_max_col; ++i)
176 new_m[i][j] = m[j][i];
177 return new_m;
178}
179
180template <class elemT>
181inline Array<2, elemT>
182diagonal_matrix(const unsigned dimension, const elemT value)
183{
184 Array<2, elemT> m(IndexRange2D(dimension, dimension));
185 for (unsigned int i = 0; i < dimension; ++i)
186 m[i][i] = value;
187 return m;
188}
189
190template <int dimension, class elemT>
191inline Array<2, elemT>
193{
194 Array<2, elemT> m(IndexRange2D(dimension, dimension));
195 for (unsigned int i = 0; i < dimension; ++i)
196 m[i][i] = values[i + 1];
197 return m;
198}
199
200END_NAMESPACE_STIR
This file declares the class stir::IndexRange2D.
This class defines multi-dimensional (numeric) arrays.
Definition Array.h:78
bool is_regular() const
checks if the index range is 'regular'
Definition Array.inl:469
class BasicCoordinate<int num_dimensions, typename coordT> defines num_dimensions -dimensional coordi...
Definition BasicCoordinate.h:57
a 'convenience' class for 2D index ranges.
Definition IndexRange2D.h:38
iterator begin()
use to initialise an iterator to the first element of the vector
Definition VectorWithOffset.inl:190
int get_max_index() const
get value of last valid index
Definition VectorWithOffset.inl:131
int get_min_index() const
get value of first valid index
Definition VectorWithOffset.inl:124
iterator end()
iterator 'past' the last element of the vector
Definition VectorWithOffset.inl:206
size_t size() const
return number of elements in this vector
Definition VectorWithOffset.inl:546
coordT inner_product(const BasicCoordinate< num_dimensions, coordT > &p1, const BasicCoordinate< num_dimensions, coordT > &p2)
compute sum_i p1[i] * p2[i]
Definition BasicCoordinate.inl:408
double norm(const BasicCoordinate< num_dimensions, coordT > &p1)
compute sqrt(inner_product(p1,p1))
Definition BasicCoordinate.inl:426
double angle(const BasicCoordinate< num_dimensions, coordT > &p1, const BasicCoordinate< num_dimensions, coordT > &p2)
compute angle between 2 directions
Definition BasicCoordinate.inl:440
Array< 2, elemT > diagonal_matrix(const unsigned dimension, const elemT value)
construct a diagonal matrix with all elements on the diagonal equal
Definition MatrixFunction.inl:182
Array< 2, elemT > matrix_transpose(const Array< 2, elemT > &m)
matrix transposition
Definition MatrixFunction.inl:160
Array< 1, elemT > matrix_multiply(const Array< 2, elemT > &m, const Array< 1, elemT > &vec)
matrix with vector multiplication
Definition MatrixFunction.inl:106