svd22.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2016, The Regents of The University of Michigan.
2 All rights reserved.
3 
4 This software was developed in the APRIL Robotics Lab under the
5 direction of Edwin Olson, ebolson@umich.edu. This software may be
6 available under alternative licensing terms; contact the address above.
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 
11 1. Redistributions of source code must retain the above copyright notice, this
12  list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 The views and conclusions contained in the software and documentation are those
29 of the authors and should not be interpreted as representing official policies,
30 either expressed or implied, of the Regents of The University of Michigan.
31 */
32 
33 #include <math.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <stdio.h>
37 
38 #include "common/doubles.h"
39 
98 void svd22(const double A[4], double U[4], double S[2], double V[4])
99 {
100  double A00 = A[0];
101  double A01 = A[1];
102  double A10 = A[2];
103  double A11 = A[3];
104 
105  double B0 = A00 + A11;
106  double B1 = A00 - A11;
107  double B2 = A01 + A10;
108  double B3 = A01 - A10;
109 
110  double PminusT = atan2(B3, B0);
111  double PplusT = atan2(B2, B1);
112 
113  double P = (PminusT + PplusT) / 2;
114  double T = (-PminusT + PplusT) / 2;
115 
116  double CP = cos(P), SP = sin(P);
117  double CT = cos(T), ST = sin(T);
118 
119  U[0] = CT;
120  U[1] = -ST;
121  U[2] = ST;
122  U[3] = CT;
123 
124  V[0] = CP;
125  V[1] = -SP;
126  V[2] = SP;
127  V[3] = CP;
128 
129  // C0 = e+f. There are two ways to compute C0; we pick the one
130  // that is better conditioned.
131  double CPmT = cos(P-T), SPmT = sin(P-T);
132  double C0 = 0;
133  if (fabs(CPmT) > fabs(SPmT))
134  C0 = B0 / CPmT;
135  else
136  C0 = B3 / SPmT;
137 
138  // C1 = e-f. There are two ways to compute C1; we pick the one
139  // that is better conditioned.
140  double CPpT = cos(P+T), SPpT = sin(P+T);
141  double C1 = 0;
142  if (fabs(CPpT) > fabs(SPpT))
143  C1 = B1 / CPpT;
144  else
145  C1 = B2 / SPpT;
146 
147  // e and f are the singular values
148  double e = (C0 + C1) / 2;
149  double f = (C0 - C1) / 2;
150 
151  if (e < 0) {
152  e = -e;
153  U[0] = -U[0];
154  U[2] = -U[2];
155  }
156 
157  if (f < 0) {
158  f = -f;
159  U[1] = -U[1];
160  U[3] = -U[3];
161  }
162 
163  // sort singular values.
164  if (e > f) {
165  // already in big-to-small order.
166  S[0] = e;
167  S[1] = f;
168  } else {
169  // Curiously, this code never seems to get invoked. Why is it
170  // that S[0] always ends up the dominant vector? However,
171  // this code has been tested (flipping the logic forces us to
172  // sort the singular values in ascending order).
173  //
174  // P = [ 0 1 ; 1 0 ]
175  // USV' = (UP)(PSP)(PV')
176  // = (UP)(PSP)(VP)'
177  // = (UP)(PSP)(P'V')'
178  S[0] = f;
179  S[1] = e;
180 
181  // exchange columns of U and V
182  double tmp[2];
183  tmp[0] = U[0];
184  tmp[1] = U[2];
185  U[0] = U[1];
186  U[2] = U[3];
187  U[1] = tmp[0];
188  U[3] = tmp[1];
189 
190  tmp[0] = V[0];
191  tmp[1] = V[2];
192  V[0] = V[1];
193  V[2] = V[3];
194  V[1] = tmp[0];
195  V[3] = tmp[1];
196  }
197 
198  /*
199  double SM[4] = { S[0], 0, 0, S[1] };
200 
201  doubles_print_mat(U, 2, 2, "%20.10g");
202  doubles_print_mat(SM, 2, 2, "%20.10g");
203  doubles_print_mat(V, 2, 2, "%20.10g");
204  printf("A:\n");
205  doubles_print_mat(A, 2, 2, "%20.10g");
206 
207  double SVt[4];
208  doubles_mat_ABt(SM, 2, 2, V, 2, 2, SVt, 2, 2);
209  double USVt[4];
210  doubles_mat_AB(U, 2, 2, SVt, 2, 2, USVt, 2, 2);
211 
212  printf("USVt\n");
213  doubles_print_mat(USVt, 2, 2, "%20.10g");
214 
215  double diff[4];
216  for (int i = 0; i < 4; i++)
217  diff[i] = A[i] - USVt[i];
218 
219  printf("diff\n");
220  doubles_print_mat(diff, 2, 2, "%20.10g");
221 
222  */
223 
224 }
225 
226 
227 // for the matrix [a b; b d]
228 void svd_sym_singular_values(double A00, double A01, double A11,
229  double *Lmin, double *Lmax)
230 {
231  double A10 = A01;
232 
233  double B0 = A00 + A11;
234  double B1 = A00 - A11;
235  double B2 = A01 + A10;
236  double B3 = A01 - A10;
237 
238  double PminusT = atan2(B3, B0);
239  double PplusT = atan2(B2, B1);
240 
241  double P = (PminusT + PplusT) / 2;
242  double T = (-PminusT + PplusT) / 2;
243 
244  // C0 = e+f. There are two ways to compute C0; we pick the one
245  // that is better conditioned.
246  double CPmT = cos(P-T), SPmT = sin(P-T);
247  double C0 = 0;
248  if (fabs(CPmT) > fabs(SPmT))
249  C0 = B0 / CPmT;
250  else
251  C0 = B3 / SPmT;
252 
253  // C1 = e-f. There are two ways to compute C1; we pick the one
254  // that is better conditioned.
255  double CPpT = cos(P+T), SPpT = sin(P+T);
256  double C1 = 0;
257  if (fabs(CPpT) > fabs(SPpT))
258  C1 = B1 / CPpT;
259  else
260  C1 = B2 / SPpT;
261 
262  // e and f are the singular values
263  double e = (C0 + C1) / 2;
264  double f = (C0 - C1) / 2;
265 
266  *Lmin = fmin(e, f);
267  *Lmax = fmax(e, f);
268 }
void svd_sym_singular_values(double A00, double A01, double A11, double *Lmin, double *Lmax)
Definition: svd22.c:228
void svd22(const double A[4], double U[4], double S[2], double V[4])
Definition: svd22.c:98


apriltags2
Author(s): Danylo Malyuta
autogenerated on Fri Oct 19 2018 04:02:32