blob: a159ec70696b4fc7e8bb15c1ddeeee645b03527a [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2015 Google Inc. All rights reserved.
3// http://ceres-solver.org/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28//
29// Author: sameeragarwal@google.com (Sameer Agarwal)
30
31#include "ceres/lapack.h"
32
33#include "ceres/internal/port.h"
34#include "ceres/linear_solver.h"
35#include "glog/logging.h"
36
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080037#ifndef CERES_NO_LAPACK
Austin Schuh70cc9552019-01-21 19:46:48 -080038// C interface to the LAPACK Cholesky factorization and triangular solve.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080039extern "C" void dpotrf_(char* uplo, int* n, double* a, int* lda, int* info);
Austin Schuh70cc9552019-01-21 19:46:48 -080040
41extern "C" void dpotrs_(char* uplo,
42 int* n,
43 int* nrhs,
44 double* a,
45 int* lda,
46 double* b,
47 int* ldb,
48 int* info);
49
50extern "C" void dgels_(char* uplo,
51 int* m,
52 int* n,
53 int* nrhs,
54 double* a,
55 int* lda,
56 double* b,
57 int* ldb,
58 double* work,
59 int* lwork,
60 int* info);
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080061#endif
Austin Schuh70cc9552019-01-21 19:46:48 -080062
63namespace ceres {
64namespace internal {
65
66LinearSolverTerminationType LAPACK::SolveInPlaceUsingCholesky(
67 int num_rows,
68 const double* in_lhs,
69 double* rhs_and_solution,
70 std::string* message) {
71#ifdef CERES_NO_LAPACK
72 LOG(FATAL) << "Ceres was built without a BLAS library.";
73 return LINEAR_SOLVER_FATAL_ERROR;
74#else
75 char uplo = 'L';
76 int n = num_rows;
77 int info = 0;
78 int nrhs = 1;
79 double* lhs = const_cast<double*>(in_lhs);
80
81 dpotrf_(&uplo, &n, lhs, &n, &info);
82 if (info < 0) {
83 LOG(FATAL) << "Congratulations, you found a bug in Ceres."
84 << "Please report it."
85 << "LAPACK::dpotrf fatal error."
86 << "Argument: " << -info << " is invalid.";
87 return LINEAR_SOLVER_FATAL_ERROR;
88 }
89
90 if (info > 0) {
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080091 *message = StringPrintf(
92 "LAPACK::dpotrf numerical failure. "
93 "The leading minor of order %d is not positive definite.",
94 info);
Austin Schuh70cc9552019-01-21 19:46:48 -080095 return LINEAR_SOLVER_FAILURE;
96 }
97
98 dpotrs_(&uplo, &n, &nrhs, lhs, &n, rhs_and_solution, &n, &info);
99 if (info < 0) {
100 LOG(FATAL) << "Congratulations, you found a bug in Ceres."
101 << "Please report it."
102 << "LAPACK::dpotrs fatal error."
103 << "Argument: " << -info << " is invalid.";
104 return LINEAR_SOLVER_FATAL_ERROR;
105 }
106
107 *message = "Success";
108 return LINEAR_SOLVER_SUCCESS;
109#endif
110}
111
112int LAPACK::EstimateWorkSizeForQR(int num_rows, int num_cols) {
113#ifdef CERES_NO_LAPACK
114 LOG(FATAL) << "Ceres was built without a LAPACK library.";
115 return -1;
116#else
117 char trans = 'N';
118 int nrhs = 1;
119 int lwork = -1;
120 double work;
121 int info = 0;
122 dgels_(&trans,
123 &num_rows,
124 &num_cols,
125 &nrhs,
126 NULL,
127 &num_rows,
128 NULL,
129 &num_rows,
130 &work,
131 &lwork,
132 &info);
133
134 if (info < 0) {
135 LOG(FATAL) << "Congratulations, you found a bug in Ceres."
136 << "Please report it."
137 << "LAPACK::dgels fatal error."
138 << "Argument: " << -info << " is invalid.";
139 }
140 return static_cast<int>(work);
141#endif
142}
143
144LinearSolverTerminationType LAPACK::SolveInPlaceUsingQR(
145 int num_rows,
146 int num_cols,
147 const double* in_lhs,
148 int work_size,
149 double* work,
150 double* rhs_and_solution,
151 std::string* message) {
152#ifdef CERES_NO_LAPACK
153 LOG(FATAL) << "Ceres was built without a LAPACK library.";
154 return LINEAR_SOLVER_FATAL_ERROR;
155#else
156 char trans = 'N';
157 int m = num_rows;
158 int n = num_cols;
159 int nrhs = 1;
160 int lda = num_rows;
161 int ldb = num_rows;
162 int info = 0;
163 double* lhs = const_cast<double*>(in_lhs);
164
165 dgels_(&trans,
166 &m,
167 &n,
168 &nrhs,
169 lhs,
170 &lda,
171 rhs_and_solution,
172 &ldb,
173 work,
174 &work_size,
175 &info);
176
177 if (info < 0) {
178 LOG(FATAL) << "Congratulations, you found a bug in Ceres."
179 << "Please report it."
180 << "LAPACK::dgels fatal error."
181 << "Argument: " << -info << " is invalid.";
182 }
183
184 *message = "Success.";
185 return LINEAR_SOLVER_SUCCESS;
186#endif
187}
188
189} // namespace internal
190} // namespace ceres