1// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
3// http://code.google.com/p/ceres-solver/
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 <algorithm>
32#include <cctype>
33#include <string>
34#include "ceres/types.h"
35#include "glog/logging.h"
36
37namespace ceres {
38
39#define CASESTR(x) case x: return #x
40#define STRENUM(x) if (value == #x) { *type = x; return true;}
41
42static void UpperCase(string* input) {
43  std::transform(input->begin(), input->end(), input->begin(), ::toupper);
44}
45
46const char* LinearSolverTypeToString(LinearSolverType type) {
47  switch (type) {
48    CASESTR(DENSE_NORMAL_CHOLESKY);
49    CASESTR(DENSE_QR);
50    CASESTR(SPARSE_NORMAL_CHOLESKY);
51    CASESTR(DENSE_SCHUR);
52    CASESTR(SPARSE_SCHUR);
53    CASESTR(ITERATIVE_SCHUR);
54    CASESTR(CGNR);
55    default:
56      return "UNKNOWN";
57  }
58}
59
60bool StringToLinearSolverType(string value, LinearSolverType* type) {
61  UpperCase(&value);
62  STRENUM(DENSE_NORMAL_CHOLESKY);
63  STRENUM(DENSE_QR);
64  STRENUM(SPARSE_NORMAL_CHOLESKY);
65  STRENUM(DENSE_SCHUR);
66  STRENUM(SPARSE_SCHUR);
67  STRENUM(ITERATIVE_SCHUR);
68  STRENUM(CGNR);
69  return false;
70}
71
72const char* PreconditionerTypeToString(PreconditionerType type) {
73  switch (type) {
74    CASESTR(IDENTITY);
75    CASESTR(JACOBI);
76    CASESTR(SCHUR_JACOBI);
77    CASESTR(CLUSTER_JACOBI);
78    CASESTR(CLUSTER_TRIDIAGONAL);
79    default:
80      return "UNKNOWN";
81  }
82}
83
84bool StringToPreconditionerType(string value, PreconditionerType* type) {
85  UpperCase(&value);
86  STRENUM(IDENTITY);
87  STRENUM(JACOBI);
88  STRENUM(SCHUR_JACOBI);
89  STRENUM(CLUSTER_JACOBI);
90  STRENUM(CLUSTER_TRIDIAGONAL);
91  return false;
92}
93
94const char* SparseLinearAlgebraLibraryTypeToString(
95    SparseLinearAlgebraLibraryType type) {
96  switch (type) {
97    CASESTR(SUITE_SPARSE);
98    CASESTR(CX_SPARSE);
99    CASESTR(EIGEN_SPARSE);
100    default:
101      return "UNKNOWN";
102  }
103}
104
105bool StringToSparseLinearAlgebraLibraryType(
106    string value,
107    SparseLinearAlgebraLibraryType* type) {
108  UpperCase(&value);
109  STRENUM(SUITE_SPARSE);
110  STRENUM(CX_SPARSE);
111  STRENUM(EIGEN_SPARSE);
112  return false;
113}
114
115const char* DenseLinearAlgebraLibraryTypeToString(
116    DenseLinearAlgebraLibraryType type) {
117  switch (type) {
118    CASESTR(EIGEN);
119    CASESTR(LAPACK);
120    default:
121      return "UNKNOWN";
122  }
123}
124
125bool StringToDenseLinearAlgebraLibraryType(
126    string value,
127    DenseLinearAlgebraLibraryType* type) {
128  UpperCase(&value);
129  STRENUM(EIGEN);
130  STRENUM(LAPACK);
131  return false;
132}
133
134const char* TrustRegionStrategyTypeToString(TrustRegionStrategyType type) {
135  switch (type) {
136    CASESTR(LEVENBERG_MARQUARDT);
137    CASESTR(DOGLEG);
138    default:
139      return "UNKNOWN";
140  }
141}
142
143bool StringToTrustRegionStrategyType(string value,
144                                     TrustRegionStrategyType* type) {
145  UpperCase(&value);
146  STRENUM(LEVENBERG_MARQUARDT);
147  STRENUM(DOGLEG);
148  return false;
149}
150
151const char* DoglegTypeToString(DoglegType type) {
152  switch (type) {
153    CASESTR(TRADITIONAL_DOGLEG);
154    CASESTR(SUBSPACE_DOGLEG);
155    default:
156      return "UNKNOWN";
157  }
158}
159
160bool StringToDoglegType(string value, DoglegType* type) {
161  UpperCase(&value);
162  STRENUM(TRADITIONAL_DOGLEG);
163  STRENUM(SUBSPACE_DOGLEG);
164  return false;
165}
166
167const char* MinimizerTypeToString(MinimizerType type) {
168  switch (type) {
169    CASESTR(TRUST_REGION);
170    CASESTR(LINE_SEARCH);
171    default:
172      return "UNKNOWN";
173  }
174}
175
176bool StringToMinimizerType(string value, MinimizerType* type) {
177  UpperCase(&value);
178  STRENUM(TRUST_REGION);
179  STRENUM(LINE_SEARCH);
180  return false;
181}
182
183const char* LineSearchDirectionTypeToString(LineSearchDirectionType type) {
184  switch (type) {
185    CASESTR(STEEPEST_DESCENT);
186    CASESTR(NONLINEAR_CONJUGATE_GRADIENT);
187    CASESTR(LBFGS);
188    CASESTR(BFGS);
189    default:
190      return "UNKNOWN";
191  }
192}
193
194bool StringToLineSearchDirectionType(string value,
195                                     LineSearchDirectionType* type) {
196  UpperCase(&value);
197  STRENUM(STEEPEST_DESCENT);
198  STRENUM(NONLINEAR_CONJUGATE_GRADIENT);
199  STRENUM(LBFGS);
200  STRENUM(BFGS);
201  return false;
202}
203
204const char* LineSearchTypeToString(LineSearchType type) {
205  switch (type) {
206    CASESTR(ARMIJO);
207    CASESTR(WOLFE);
208    default:
209      return "UNKNOWN";
210  }
211}
212
213bool StringToLineSearchType(string value, LineSearchType* type) {
214  UpperCase(&value);
215  STRENUM(ARMIJO);
216  STRENUM(WOLFE);
217  return false;
218}
219
220const char* LineSearchInterpolationTypeToString(
221    LineSearchInterpolationType type) {
222  switch (type) {
223    CASESTR(BISECTION);
224    CASESTR(QUADRATIC);
225    CASESTR(CUBIC);
226    default:
227      return "UNKNOWN";
228  }
229}
230
231bool StringToLineSearchInterpolationType(
232    string value,
233    LineSearchInterpolationType* type) {
234  UpperCase(&value);
235  STRENUM(BISECTION);
236  STRENUM(QUADRATIC);
237  STRENUM(CUBIC);
238  return false;
239}
240
241const char* NonlinearConjugateGradientTypeToString(
242    NonlinearConjugateGradientType type) {
243  switch (type) {
244    CASESTR(FLETCHER_REEVES);
245    CASESTR(POLAK_RIBIERE);
246    CASESTR(HESTENES_STIEFEL);
247    default:
248      return "UNKNOWN";
249  }
250}
251
252bool StringToNonlinearConjugateGradientType(
253    string value,
254    NonlinearConjugateGradientType* type) {
255  UpperCase(&value);
256  STRENUM(FLETCHER_REEVES);
257  STRENUM(POLAK_RIBIERE);
258  STRENUM(HESTENES_STIEFEL);
259  return false;
260}
261
262const char* CovarianceAlgorithmTypeToString(
263    CovarianceAlgorithmType type) {
264  switch (type) {
265    CASESTR(DENSE_SVD);
266    CASESTR(EIGEN_SPARSE_QR);
267    CASESTR(SUITE_SPARSE_QR);
268    default:
269      return "UNKNOWN";
270  }
271}
272
273bool StringToCovarianceAlgorithmType(
274    string value,
275    CovarianceAlgorithmType* type) {
276  UpperCase(&value);
277  STRENUM(DENSE_SVD);
278  STRENUM(EIGEN_SPARSE_QR);
279  STRENUM(SUITE_SPARSE_QR);
280  return false;
281}
282
283const char* VisibilityClusteringTypeToString(
284    VisibilityClusteringType type) {
285  switch (type) {
286    CASESTR(CANONICAL_VIEWS);
287    CASESTR(SINGLE_LINKAGE);
288    default:
289      return "UNKNOWN";
290  }
291}
292
293bool StringToVisibilityClusteringType(
294    string value,
295    VisibilityClusteringType* type) {
296  UpperCase(&value);
297  STRENUM(CANONICAL_VIEWS);
298  STRENUM(SINGLE_LINKAGE);
299  return false;
300}
301
302const char* TerminationTypeToString(TerminationType type) {
303  switch (type) {
304    CASESTR(CONVERGENCE);
305    CASESTR(NO_CONVERGENCE);
306    CASESTR(FAILURE);
307    CASESTR(USER_SUCCESS);
308    CASESTR(USER_FAILURE);
309    default:
310      return "UNKNOWN";
311  }
312}
313
314#undef CASESTR
315#undef STRENUM
316
317bool IsSchurType(LinearSolverType type) {
318  return ((type == SPARSE_SCHUR) ||
319          (type == DENSE_SCHUR)  ||
320          (type == ITERATIVE_SCHUR));
321}
322
323bool IsSparseLinearAlgebraLibraryTypeAvailable(
324    SparseLinearAlgebraLibraryType type) {
325  if (type == SUITE_SPARSE) {
326#ifdef CERES_NO_SUITESPARSE
327    return false;
328#else
329    return true;
330#endif
331  }
332
333  if (type == CX_SPARSE) {
334#ifdef CERES_NO_CXSPARSE
335    return false;
336#else
337    return true;
338#endif
339  }
340
341  LOG(WARNING) << "Unknown sparse linear algebra library " << type;
342  return false;
343}
344
345bool IsDenseLinearAlgebraLibraryTypeAvailable(
346    DenseLinearAlgebraLibraryType type) {
347  if (type == EIGEN) {
348    return true;
349  }
350  if (type == LAPACK) {
351#ifdef CERES_NO_LAPACK
352    return false;
353#else
354    return true;
355#endif
356  }
357
358  LOG(WARNING) << "Unknown dense linear algebra library " << type;
359  return false;
360}
361
362}  // namespace ceres
363