os/ossrv/ossrv_pub/boost_apis/boost/numeric/ublas/lu.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
//
sl@0
     2
//  Copyright (c) 2000-2002
sl@0
     3
//  Joerg Walter, Mathias Koch
sl@0
     4
//
sl@0
     5
//  Permission to use, copy, modify, distribute and sell this software
sl@0
     6
//  and its documentation for any purpose is hereby granted without fee,
sl@0
     7
//  provided that the above copyright notice appear in all copies and
sl@0
     8
//  that both that copyright notice and this permission notice appear
sl@0
     9
//  in supporting documentation.  The authors make no representations
sl@0
    10
//  about the suitability of this software for any purpose.
sl@0
    11
//  It is provided "as is" without express or implied warranty.
sl@0
    12
//
sl@0
    13
//  The authors gratefully acknowledge the support of
sl@0
    14
//  GeNeSys mbH & Co. KG in producing this work.
sl@0
    15
//
sl@0
    16
sl@0
    17
#ifndef _BOOST_UBLAS_LU_
sl@0
    18
#define _BOOST_UBLAS_LU_
sl@0
    19
sl@0
    20
#include <boost/numeric/ublas/operation.hpp>
sl@0
    21
#include <boost/numeric/ublas/vector_proxy.hpp>
sl@0
    22
#include <boost/numeric/ublas/matrix_proxy.hpp>
sl@0
    23
#include <boost/numeric/ublas/vector.hpp>
sl@0
    24
#include <boost/numeric/ublas/triangular.hpp>
sl@0
    25
sl@0
    26
// LU factorizations in the spirit of LAPACK and Golub & van Loan
sl@0
    27
sl@0
    28
namespace boost { namespace numeric { namespace ublas {
sl@0
    29
sl@0
    30
    template<class T = std::size_t, class A = unbounded_array<T> >
sl@0
    31
    class permutation_matrix:
sl@0
    32
        public vector<T, A> {
sl@0
    33
    public:
sl@0
    34
        typedef vector<T, A> vector_type;
sl@0
    35
        typedef typename vector_type::size_type size_type;
sl@0
    36
sl@0
    37
        // Construction and destruction
sl@0
    38
        BOOST_UBLAS_INLINE
sl@0
    39
        permutation_matrix (size_type size):
sl@0
    40
            vector<T, A> (size) {
sl@0
    41
            for (size_type i = 0; i < size; ++ i)
sl@0
    42
                (*this) (i) = i;
sl@0
    43
        }
sl@0
    44
        BOOST_UBLAS_INLINE
sl@0
    45
        ~permutation_matrix () {}
sl@0
    46
sl@0
    47
        // Assignment
sl@0
    48
        BOOST_UBLAS_INLINE
sl@0
    49
        permutation_matrix &operator = (const permutation_matrix &m) {
sl@0
    50
            vector_type::operator = (m);
sl@0
    51
            return *this;
sl@0
    52
        }
sl@0
    53
    };
sl@0
    54
sl@0
    55
    template<class PM, class MV>
sl@0
    56
    BOOST_UBLAS_INLINE
sl@0
    57
    void swap_rows (const PM &pm, MV &mv, vector_tag) {
sl@0
    58
        typedef typename PM::size_type size_type;
sl@0
    59
        typedef typename MV::value_type value_type;
sl@0
    60
sl@0
    61
        size_type size = pm.size ();
sl@0
    62
        for (size_type i = 0; i < size; ++ i) {
sl@0
    63
            if (i != pm (i))
sl@0
    64
                std::swap (mv (i), mv (pm (i)));
sl@0
    65
        }
sl@0
    66
    }
sl@0
    67
    template<class PM, class MV>
sl@0
    68
    BOOST_UBLAS_INLINE
sl@0
    69
    void swap_rows (const PM &pm, MV &mv, matrix_tag) {
sl@0
    70
        typedef typename PM::size_type size_type;
sl@0
    71
        typedef typename MV::value_type value_type;
sl@0
    72
sl@0
    73
        size_type size = pm.size ();
sl@0
    74
        for (size_type i = 0; i < size; ++ i) {
sl@0
    75
            if (i != pm (i))
sl@0
    76
                row (mv, i).swap (row (mv, pm (i)));
sl@0
    77
        }
sl@0
    78
    }
sl@0
    79
    // Dispatcher
sl@0
    80
    template<class PM, class MV>
sl@0
    81
    BOOST_UBLAS_INLINE
sl@0
    82
    void swap_rows (const PM &pm, MV &mv) {
sl@0
    83
        swap_rows (pm, mv, typename MV::type_category ());
sl@0
    84
    }
sl@0
    85
sl@0
    86
    // LU factorization without pivoting
sl@0
    87
    template<class M>
sl@0
    88
    typename M::size_type lu_factorize (M &m) {
sl@0
    89
        typedef M matrix_type;
sl@0
    90
        typedef typename M::size_type size_type;
sl@0
    91
        typedef typename M::value_type value_type;
sl@0
    92
sl@0
    93
#if BOOST_UBLAS_TYPE_CHECK
sl@0
    94
        matrix_type cm (m);
sl@0
    95
#endif
sl@0
    96
        int singular = 0;
sl@0
    97
        size_type size1 = m.size1 ();
sl@0
    98
        size_type size2 = m.size2 ();
sl@0
    99
        size_type size = (std::min) (size1, size2);
sl@0
   100
        for (size_type i = 0; i < size; ++ i) {
sl@0
   101
            matrix_column<M> mci (column (m, i));
sl@0
   102
            matrix_row<M> mri (row (m, i));
sl@0
   103
            if (m (i, i) != value_type/*zero*/()) {
sl@0
   104
                project (mci, range (i + 1, size1)) *= value_type (1) / m (i, i);
sl@0
   105
            } else if (singular == 0) {
sl@0
   106
                singular = i + 1;
sl@0
   107
            }
sl@0
   108
            project (m, range (i + 1, size1), range (i + 1, size2)).minus_assign (
sl@0
   109
                outer_prod (project (mci, range (i + 1, size1)),
sl@0
   110
                            project (mri, range (i + 1, size2))));
sl@0
   111
        }
sl@0
   112
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   113
        BOOST_UBLAS_CHECK (singular != 0 ||
sl@0
   114
                           detail::expression_type_check (prod (triangular_adaptor<matrix_type, unit_lower> (m),
sl@0
   115
                                                                triangular_adaptor<matrix_type, upper> (m)), 
sl@0
   116
                                                          cm), internal_logic ());
sl@0
   117
#endif
sl@0
   118
        return singular;
sl@0
   119
    }
sl@0
   120
sl@0
   121
    // LU factorization with partial pivoting
sl@0
   122
    template<class M, class PM>
sl@0
   123
    typename M::size_type lu_factorize (M &m, PM &pm) {
sl@0
   124
        typedef M matrix_type;
sl@0
   125
        typedef typename M::size_type size_type;
sl@0
   126
        typedef typename M::value_type value_type;
sl@0
   127
sl@0
   128
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   129
        matrix_type cm (m);
sl@0
   130
#endif
sl@0
   131
        int singular = 0;
sl@0
   132
        size_type size1 = m.size1 ();
sl@0
   133
        size_type size2 = m.size2 ();
sl@0
   134
        size_type size = (std::min) (size1, size2);
sl@0
   135
        for (size_type i = 0; i < size; ++ i) {
sl@0
   136
            matrix_column<M> mci (column (m, i));
sl@0
   137
            matrix_row<M> mri (row (m, i));
sl@0
   138
            size_type i_norm_inf = i + index_norm_inf (project (mci, range (i, size1)));
sl@0
   139
            BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ());
sl@0
   140
            if (m (i_norm_inf, i) != value_type/*zero*/()) {
sl@0
   141
                if (i_norm_inf != i) {
sl@0
   142
                    pm (i) = i_norm_inf;
sl@0
   143
                    row (m, i_norm_inf).swap (mri);
sl@0
   144
                } else {
sl@0
   145
                    BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ());
sl@0
   146
                }
sl@0
   147
                project (mci, range (i + 1, size1)) *= value_type (1) / m (i, i);
sl@0
   148
            } else if (singular == 0) {
sl@0
   149
                singular = i + 1;
sl@0
   150
            }
sl@0
   151
            project (m, range (i + 1, size1), range (i + 1, size2)).minus_assign (
sl@0
   152
                outer_prod (project (mci, range (i + 1, size1)),
sl@0
   153
                            project (mri, range (i + 1, size2))));
sl@0
   154
        }
sl@0
   155
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   156
        swap_rows (pm, cm);
sl@0
   157
        BOOST_UBLAS_CHECK (singular != 0 ||
sl@0
   158
                           detail::expression_type_check (prod (triangular_adaptor<matrix_type, unit_lower> (m),
sl@0
   159
                                                                triangular_adaptor<matrix_type, upper> (m)), cm), internal_logic ());
sl@0
   160
#endif
sl@0
   161
        return singular;
sl@0
   162
    }
sl@0
   163
sl@0
   164
    template<class M, class PM>
sl@0
   165
    typename M::size_type axpy_lu_factorize (M &m, PM &pm) {
sl@0
   166
        typedef M matrix_type;
sl@0
   167
        typedef typename M::size_type size_type;
sl@0
   168
        typedef typename M::value_type value_type;
sl@0
   169
        typedef vector<value_type> vector_type;
sl@0
   170
sl@0
   171
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   172
        matrix_type cm (m);
sl@0
   173
#endif
sl@0
   174
        int singular = 0;
sl@0
   175
        size_type size1 = m.size1 ();
sl@0
   176
        size_type size2 = m.size2 ();
sl@0
   177
        size_type size = (std::min) (size1, size2);
sl@0
   178
#ifndef BOOST_UBLAS_LU_WITH_INPLACE_SOLVE
sl@0
   179
        matrix_type mr (m);
sl@0
   180
        mr.assign (zero_matrix<value_type> (size1, size2));
sl@0
   181
        vector_type v (size1);
sl@0
   182
        for (size_type i = 0; i < size; ++ i) {
sl@0
   183
            matrix_range<matrix_type> lrr (project (mr, range (0, i), range (0, i)));
sl@0
   184
            vector_range<matrix_column<matrix_type> > urr (project (column (mr, i), range (0, i)));
sl@0
   185
            urr.assign (solve (lrr, project (column (m, i), range (0, i)), unit_lower_tag ()));
sl@0
   186
            project (v, range (i, size1)).assign (
sl@0
   187
                project (column (m, i), range (i, size1)) -
sl@0
   188
                axpy_prod<vector_type> (project (mr, range (i, size1), range (0, i)), urr));
sl@0
   189
            size_type i_norm_inf = i + index_norm_inf (project (v, range (i, size1)));
sl@0
   190
            BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ());
sl@0
   191
            if (v (i_norm_inf) != value_type/*zero*/()) {
sl@0
   192
                if (i_norm_inf != i) {
sl@0
   193
                    pm (i) = i_norm_inf;
sl@0
   194
                    std::swap (v (i_norm_inf), v (i));
sl@0
   195
                    project (row (m, i_norm_inf), range (i + 1, size2)).swap (project (row (m, i), range (i + 1, size2)));
sl@0
   196
                } else {
sl@0
   197
                    BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ());
sl@0
   198
                }
sl@0
   199
                project (column (mr, i), range (i + 1, size1)).assign (
sl@0
   200
                    project (v, range (i + 1, size1)) / v (i));
sl@0
   201
                if (i_norm_inf != i) {
sl@0
   202
                    project (row (mr, i_norm_inf), range (0, i)).swap (project (row (mr, i), range (0, i)));
sl@0
   203
                }
sl@0
   204
            } else if (singular == 0) {
sl@0
   205
                singular = i + 1;
sl@0
   206
            }
sl@0
   207
            mr (i, i) = v (i);
sl@0
   208
        }
sl@0
   209
        m.assign (mr);
sl@0
   210
#else
sl@0
   211
        matrix_type lr (m);
sl@0
   212
        matrix_type ur (m);
sl@0
   213
        lr.assign (identity_matrix<value_type> (size1, size2));
sl@0
   214
        ur.assign (zero_matrix<value_type> (size1, size2));
sl@0
   215
        vector_type v (size1);
sl@0
   216
        for (size_type i = 0; i < size; ++ i) {
sl@0
   217
            matrix_range<matrix_type> lrr (project (lr, range (0, i), range (0, i)));
sl@0
   218
            vector_range<matrix_column<matrix_type> > urr (project (column (ur, i), range (0, i)));
sl@0
   219
            urr.assign (project (column (m, i), range (0, i)));
sl@0
   220
            inplace_solve (lrr, urr, unit_lower_tag ());
sl@0
   221
            project (v, range (i, size1)).assign (
sl@0
   222
                project (column (m, i), range (i, size1)) -
sl@0
   223
                axpy_prod<vector_type> (project (lr, range (i, size1), range (0, i)), urr));
sl@0
   224
            size_type i_norm_inf = i + index_norm_inf (project (v, range (i, size1)));
sl@0
   225
            BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ());
sl@0
   226
            if (v (i_norm_inf) != value_type/*zero*/()) {
sl@0
   227
                if (i_norm_inf != i) {
sl@0
   228
                    pm (i) = i_norm_inf;
sl@0
   229
                    std::swap (v (i_norm_inf), v (i));
sl@0
   230
                    project (row (m, i_norm_inf), range (i + 1, size2)).swap (project (row (m, i), range (i + 1, size2)));
sl@0
   231
                } else {
sl@0
   232
                    BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ());
sl@0
   233
                }
sl@0
   234
                project (column (lr, i), range (i + 1, size1)).assign (
sl@0
   235
                    project (v, range (i + 1, size1)) / v (i));
sl@0
   236
                if (i_norm_inf != i) {
sl@0
   237
                    project (row (lr, i_norm_inf), range (0, i)).swap (project (row (lr, i), range (0, i)));
sl@0
   238
                }
sl@0
   239
            } else if (singular == 0) {
sl@0
   240
                singular = i + 1;
sl@0
   241
            }
sl@0
   242
            ur (i, i) = v (i);
sl@0
   243
        }
sl@0
   244
        m.assign (triangular_adaptor<matrix_type, strict_lower> (lr) +
sl@0
   245
                  triangular_adaptor<matrix_type, upper> (ur));
sl@0
   246
#endif
sl@0
   247
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   248
        swap_rows (pm, cm);
sl@0
   249
        BOOST_UBLAS_CHECK (singular != 0 ||
sl@0
   250
                           detail::expression_type_check (prod (triangular_adaptor<matrix_type, unit_lower> (m),
sl@0
   251
                                                                triangular_adaptor<matrix_type, upper> (m)), cm), internal_logic ());
sl@0
   252
#endif
sl@0
   253
        return singular;
sl@0
   254
    }
sl@0
   255
sl@0
   256
    // LU substitution
sl@0
   257
    template<class M, class E>
sl@0
   258
    void lu_substitute (const M &m, vector_expression<E> &e) {
sl@0
   259
        typedef const M const_matrix_type;
sl@0
   260
        typedef vector<typename E::value_type> vector_type;
sl@0
   261
sl@0
   262
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   263
        vector_type cv1 (e);
sl@0
   264
#endif
sl@0
   265
        inplace_solve (m, e, unit_lower_tag ());
sl@0
   266
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   267
        BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor<const_matrix_type, unit_lower> (m), e), cv1), internal_logic ());
sl@0
   268
        vector_type cv2 (e);
sl@0
   269
#endif
sl@0
   270
        inplace_solve (m, e, upper_tag ());
sl@0
   271
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   272
        BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor<const_matrix_type, upper> (m), e), cv2), internal_logic ());
sl@0
   273
#endif
sl@0
   274
    }
sl@0
   275
    template<class M, class E>
sl@0
   276
    void lu_substitute (const M &m, matrix_expression<E> &e) {
sl@0
   277
        typedef const M const_matrix_type;
sl@0
   278
        typedef matrix<typename E::value_type> matrix_type;
sl@0
   279
sl@0
   280
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   281
        matrix_type cm1 (e);
sl@0
   282
#endif
sl@0
   283
        inplace_solve (m, e, unit_lower_tag ());
sl@0
   284
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   285
        BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor<const_matrix_type, unit_lower> (m), e), cm1), internal_logic ());
sl@0
   286
        matrix_type cm2 (e);
sl@0
   287
#endif
sl@0
   288
        inplace_solve (m, e, upper_tag ());
sl@0
   289
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   290
        BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor<const_matrix_type, upper> (m), e), cm2), internal_logic ());
sl@0
   291
#endif
sl@0
   292
    }
sl@0
   293
    template<class M, class PMT, class PMA, class MV>
sl@0
   294
    void lu_substitute (const M &m, const permutation_matrix<PMT, PMA> &pm, MV &mv) {
sl@0
   295
        swap_rows (pm, mv);
sl@0
   296
        lu_substitute (m, mv);
sl@0
   297
    }
sl@0
   298
    template<class E, class M>
sl@0
   299
    void lu_substitute (vector_expression<E> &e, const M &m) {
sl@0
   300
        typedef const M const_matrix_type;
sl@0
   301
        typedef vector<typename E::value_type> vector_type;
sl@0
   302
sl@0
   303
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   304
        vector_type cv1 (e);
sl@0
   305
#endif
sl@0
   306
        inplace_solve (e, m, upper_tag ());
sl@0
   307
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   308
        BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor<const_matrix_type, upper> (m)), cv1), internal_logic ());
sl@0
   309
        vector_type cv2 (e);
sl@0
   310
#endif
sl@0
   311
        inplace_solve (e, m, unit_lower_tag ());
sl@0
   312
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   313
        BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor<const_matrix_type, unit_lower> (m)), cv2), internal_logic ());
sl@0
   314
#endif
sl@0
   315
    }
sl@0
   316
    template<class E, class M>
sl@0
   317
    void lu_substitute (matrix_expression<E> &e, const M &m) {
sl@0
   318
        typedef const M const_matrix_type;
sl@0
   319
        typedef matrix<typename E::value_type> matrix_type;
sl@0
   320
sl@0
   321
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   322
        matrix_type cm1 (e);
sl@0
   323
#endif
sl@0
   324
        inplace_solve (e, m, upper_tag ());
sl@0
   325
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   326
        BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor<const_matrix_type, upper> (m)), cm1), internal_logic ());
sl@0
   327
        matrix_type cm2 (e);
sl@0
   328
#endif
sl@0
   329
        inplace_solve (e, m, unit_lower_tag ());
sl@0
   330
#if BOOST_UBLAS_TYPE_CHECK
sl@0
   331
        BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor<const_matrix_type, unit_lower> (m)), cm2), internal_logic ());
sl@0
   332
#endif
sl@0
   333
    }
sl@0
   334
    template<class MV, class M, class PMT, class PMA>
sl@0
   335
    void lu_substitute (MV &mv, const M &m, const permutation_matrix<PMT, PMA> &pm) {
sl@0
   336
        swap_rows (pm, mv);
sl@0
   337
        lu_substitute (mv, m);
sl@0
   338
    }
sl@0
   339
sl@0
   340
}}}
sl@0
   341
sl@0
   342
#endif