trsv.hpp
Go to the documentation of this file.
1/*!
2 *
3 *
4 * \brief -
5 *
6 * \author O. Krause
7 * \date 2011
8 *
9 *
10 * \par Copyright 1995-2015 Shark Development Team
11 *
12 * <BR><HR>
13 * This file is part of Shark.
14 * <http://image.diku.dk/shark/>
15 *
16 * Shark is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU Lesser General Public License as published
18 * by the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * Shark is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public License
27 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
28 *
29 */
30#ifndef REMORA_KERNELS_DEFAULT_TRSV_HPP
31#define REMORA_KERNELS_DEFAULT_TRSV_HPP
32
33#include "../../detail/traits.hpp" //structure tags, expression types etc
34#include "../../assignment.hpp" //plus_assign
35#include "../dot.hpp" //dot kernel
36#include "../../proxy_expressions.hpp" //range, row, transpose
37
38#include <stdexcept> //exception when matrix is singular
39#include <type_traits> //std::false_type marker for unoptimized
40
41namespace remora {namespace bindings {
42
43//Lower triangular(row-major) - vector
44template<bool Unit, class MatA, class V>
45void trsv_impl(
46 matrix_expression<MatA, cpu_tag> const& A,
47 vector_expression<V, cpu_tag> &b,
48 lower, column_major, left
49) {
50 REMORA_SIZE_CHECK(A().size1() == A().size2());
51 REMORA_SIZE_CHECK(A().size2() == b().size());
52
53 typedef typename MatA::value_type value_type;
54 typedef device_traits<cpu_tag>::multiply_and_add<value_type> MultAdd;
55 std::size_t size = b().size();
56 for (std::size_t n = 0; n != size; ++ n) {
57 if(!Unit){
58 if(A()(n, n) == value_type()){//matrix is singular
59 throw std::invalid_argument("[TRSV] Matrix is singular!");
60 }
61 b()(n) /= A()(n, n);
62 }
63 if (b()(n) != value_type/*zero*/()){
64 auto blower = subrange(b,n+1,size);
65 auto colAlower = subrange(column(A,n),n+1,size);
66 kernels::assign(blower, colAlower, MultAdd(-b()(n)));
67 }
68 }
69}
70//Lower triangular(column-major) - vector
71template<bool Unit, class MatA, class V>
72void trsv_impl(
73 matrix_expression<MatA, cpu_tag> const& A,
74 vector_expression<V, cpu_tag> &b,
75 lower, row_major, left
76) {
77 REMORA_SIZE_CHECK(A().size1() == A().size2());
78 REMORA_SIZE_CHECK(A().size2() == b().size());
79
80 typedef typename V::value_type value_type;
81
82 std::size_t size = b().size();
83 for (std::size_t n = 0; n < size; ++ n) {
84 value_type value;
85 kernels::dot(subrange(b,0,n),subrange(row(A,n),0,n),value);
86 b()(n) -= value;
87 if(!Unit){
88 if(A()(n, n) == value_type()){//matrix is singular
89 throw std::invalid_argument("[TRSV] Matrix is singular!");
90 }
91 b()(n) /= A()(n, n);
92 }
93 }
94}
95
96//upper triangular(column-major)-vector
97template<bool Unit, class MatA, class V>
98void trsv_impl(
99 matrix_expression<MatA, cpu_tag> const& A,
100 vector_expression<V, cpu_tag> &b,
101 upper, column_major, left
102) {
103 REMORA_SIZE_CHECK(A().size1() == A().size2());
104 REMORA_SIZE_CHECK(A().size2() == b().size());
105
106 typedef typename MatA::value_type value_type;
107 typedef device_traits<cpu_tag>::multiply_and_add<value_type> MultAdd;
108 std::size_t size = b().size();
109 for (std::size_t i = 0; i < size; ++ i) {
110 std::size_t n = size-i-1;
111 if(!Unit){
112 if(A()(n, n) == value_type()){//matrix is singular
113 throw std::invalid_argument("[TRSV] Matrix is singular!");
114 }
115 b()(n) /= A()(n, n);
116 }
117 if (b()(n) != value_type/*zero*/()) {
118 auto blower = subrange(b(),0,n);
119 auto colAlower = subrange(column(A,n),0,n);
120 kernels::assign(blower, colAlower, MultAdd(-b()(n)));
121 }
122 }
123}
124//upper triangular(row-major)-vector
125template<bool Unit, class MatA, class V>
126void trsv_impl(
127 matrix_expression<MatA, cpu_tag> const& A,
128 vector_expression<V, cpu_tag> &b,
129 upper, row_major, left
130) {
131 REMORA_SIZE_CHECK(A().size1() == A().size2());
132 REMORA_SIZE_CHECK(A().size2() == b().size());
133
134 typedef typename MatA::value_type value_type;
135
136 std::size_t size = A().size1();
137 for (std::size_t i = 0; i < size; ++ i) {
138 std::size_t n = size-i-1;
139 value_type value;
140 kernels::dot(subrange(b(),n+1,size),subrange(row(A,n),n+1,size),value);
141 b()(n) -= value;
142 if(!Unit){
143 if(A()(n, n) == value_type()){//matrix is singular
144 throw std::invalid_argument("[TRSV] Matrix is singular!");
145 }
146 b()(n) /= A()(n, n);
147 }
148 }
149}
150
151
152//right is mapped onto left via transposing A
153template<bool Unit, class Triangular, class Orientation, class MatA, class V>
154void trsv_impl(
155 matrix_expression<MatA, cpu_tag> const& A,
156 vector_expression<V, cpu_tag> &b,
157 Triangular, Orientation, right
158) {
159 trsv_impl<Unit>(
160 trans(A), b,
161 typename Triangular::transposed_orientation(),
162 typename Orientation::transposed_orientation(),
163 left()
164 );
165}
166
167//dispatcher
168template <class Triangular, class Side,typename MatA, typename V>
169void trsv(
170 matrix_expression<MatA, cpu_tag> const& A,
171 vector_expression<V, cpu_tag> & b,
172 std::false_type//unoptimized
173){
174 trsv_impl<Triangular::is_unit>(
175 A, b,
176 triangular_tag<Triangular::is_upper,false>(),
177 typename MatA::orientation(), Side()
178 );
179}
180
181}}
182#endif