2
* SymmetricMatrix trace
5
* Marco Cecchetti <mrcekets at gmail.com>
7
* Copyright 2009 authors
9
* This library is free software; you can redistribute it and/or
10
* modify it either under the terms of the GNU Lesser General Public
11
* License version 2.1 as published by the Free Software Foundation
12
* (the "LGPL") or, at your option, under the terms of the Mozilla
13
* Public License Version 1.1 (the "MPL"). If you do not alter this
14
* notice, a recipient may use your version of this file under either
15
* the MPL or the LGPL.
17
* You should have received a copy of the LGPL along with this library
18
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* You should have received a copy of the MPL along with this library
21
* in the file COPYING-MPL-1.1
23
* The contents of this file are subject to the Mozilla Public License
24
* Version 1.1 (the "License"); you may not use this file except in
25
* compliance with the License. You may obtain a copy of the License at
26
* http://www.mozilla.org/MPL/
28
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
29
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
30
* the specific language governing rights and limitations.
38
#include <2geom/numeric/matrix.h>
39
#include <2geom/numeric/symmetric-matrix-fs.h>
45
namespace Geom { namespace NL {
56
int sgn_prod (int x, int y)
58
if (x == 0 || y == 0) return 0;
64
bool abs_less (double x, double y)
66
return (std::fabs(x) < std::fabs(y));
71
* trace K-th of symmetric matrix S of order N
73
template <size_t K, size_t N>
77
double evaluate (const ConstBaseSymmetricMatrix<N> & S)
79
THROW_NOTIMPLEMENTED();
89
double evaluate (const ConstBaseSymmetricMatrix<N> & S)
92
for (size_t i = 0; i < N; ++i)
104
double evaluate (const ConstBaseSymmetricMatrix<N> & S)
112
* trace for symmetric matrix of order 2
118
double evaluate (const ConstBaseSymmetricMatrix<2> & S)
120
return (S.get<0,0>() + S.get<1,1>());
128
double evaluate (const ConstBaseSymmetricMatrix<2> & S)
130
return (S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>());
136
* trace for symmetric matrix of order 3
142
double evaluate (const ConstBaseSymmetricMatrix<3> & S)
144
return (S.get<0,0>() + S.get<1,1>() + S.get<2,2>());
152
double evaluate (const ConstBaseSymmetricMatrix<3> & S)
154
double a00 = S.get<1,1>() * S.get<2,2>() - S.get<1,2>() * S.get<2,1>();
155
double a11 = S.get<0,0>() * S.get<2,2>() - S.get<0,2>() * S.get<2,0>();
156
double a22 = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>();
157
return (a00 + a11 + a22);
165
double evaluate (const ConstBaseSymmetricMatrix<3> & S)
167
double d = S.get<0,0>() * S.get<1,1>() * S.get<2,2>();
168
d += (2 * S.get<1,0>() * S.get<2,0>() * S.get<2,1>());
169
d -= (S.get<0,0>() * S.get<2,1>() * S.get<2,1>());
170
d -= (S.get<1,1>() * S.get<2,0>() * S.get<2,0>());
171
d -= (S.get<2,2>() * S.get<1,0>() * S.get<1,0>());
180
template <size_t K, size_t N>
184
int evaluate (const ConstBaseSymmetricMatrix<N> & S)
186
double d = trace<K, N>::evaluate(S);
193
* sign of trace for symmetric matrix of order 2
196
struct trace_sgn<2,2>
199
int evaluate (const ConstBaseSymmetricMatrix<2> & S)
201
double m00 = S.get<0,0>();
202
double m10 = S.get<1,0>();
203
double m11 = S.get<1,1>();
205
int sm00 = sgn (m00);
206
int sm10 = sgn (m10);
207
int sm11 = sgn (m11);
211
return sgn_prod (sm00, sm11);
215
int sm00m11 = sgn_prod (sm00, sm11);
219
double f00 = std::frexp (m00, &e00);
220
double f10 = std::frexp (m10, &e10);
221
double f11 = std::frexp (m11, &e11);
223
int e0011 = e00 + e11;
224
int e1010 = e10 << 1;
225
int ed = e0011 - e1010;
237
double d = std::ldexp (f00 * f11, ed) - f10 * f10;
238
//std::cout << "trace_sgn<2,2>: det = " << d << std::endl;
239
double eps = std::ldexp (1, -50);
240
if (std::fabs(d) < eps) return 0;
251
* sign of trace for symmetric matrix of order 3
254
struct trace_sgn<2,3>
257
int evaluate (const ConstBaseSymmetricMatrix<3> & S)
259
double eps = std::ldexp (1, -50);
262
t[0] = S.get<1,1>() * S.get<2,2>();
263
t[1] = - S.get<1,2>() * S.get<2,1>();
264
t[2] = S.get<0,0>() * S.get<2,2>();
265
t[3] = - S.get<0,2>() * S.get<2,0>();
266
t[4] = S.get<0,0>() * S.get<1,1>();
267
t[5] = - S.get<0,1>() * S.get<1,0>();
270
double* maxp = std::max_element (t, t+6, abs_less);
272
std::frexp(*maxp, &em);
274
for (size_t i = 0; i < 6; ++i)
278
double r = std::fabs (std::ldexp (d, -em)); // relative error
279
//std::cout << "trace_sgn<2,3>: d = " << d << std::endl;
280
//std::cout << "trace_sgn<2,3>: r = " << r << std::endl;
281
if (r < eps) return 0;
288
struct trace_sgn<3,3>
291
int evaluate (const ConstBaseSymmetricMatrix<3> & S)
294
double eps = std::ldexp (1, -48);
297
t[0] = S.get<0,0>() * S.get<1,1>() * S.get<2,2>();
298
t[1] = 2 * S.get<1,0>() * S.get<2,0>() * S.get<2,1>();
299
t[2] = -(S.get<0,0>() * S.get<2,1>() * S.get<2,1>());
300
t[3] = -(S.get<1,1>() * S.get<2,0>() * S.get<2,0>());
301
t[4] = -(S.get<2,2>() * S.get<1,0>() * S.get<1,0>());
303
double* maxp = std::max_element (t, t+5, abs_less);
305
std::frexp(*maxp, &em);
307
for (size_t i = 0; i < 5; ++i)
311
//std::cout << "trace_sgn<3,3>: d = " << d << std::endl;
312
double r = std::fabs (std::ldexp (d, -em)); // relative error
313
//std::cout << "trace_sgn<3,3>: r = " << r << std::endl;
315
if (r < eps) return 0;
319
}; // end struct trace_sgn<3,3>
321
} // end namespace detail
324
template <size_t K, size_t N>
326
double trace (const ConstBaseSymmetricMatrix<N> & _matrix)
328
return detail::trace<K, N>::evaluate(_matrix);
333
double trace (const ConstBaseSymmetricMatrix<N> & _matrix)
335
return detail::trace<1, N>::evaluate(_matrix);
340
double det (const ConstBaseSymmetricMatrix<N> & _matrix)
342
return detail::trace<N, N>::evaluate(_matrix);
346
template <size_t K, size_t N>
348
int trace_sgn (const ConstBaseSymmetricMatrix<N> & _matrix)
350
return detail::trace_sgn<K, N>::evaluate(_matrix);
355
int trace_sgn (const ConstBaseSymmetricMatrix<N> & _matrix)
357
return detail::trace_sgn<1, N>::evaluate(_matrix);
362
int det_sgn (const ConstBaseSymmetricMatrix<N> & _matrix)
364
return detail::trace_sgn<N, N>::evaluate(_matrix);
370
size_t rank (const ConstBaseSymmetricMatrix<N> & S)
372
THROW_NOTIMPLEMENTED();
378
size_t rank<2> (const ConstBaseSymmetricMatrix<2> & S)
380
if (S.is_zero()) return 0;
381
double d = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>();
382
if (d != 0) return 2;
388
size_t rank<3> (const ConstBaseSymmetricMatrix<3> & S)
390
if (S.is_zero()) return 0;
392
double a20 = S.get<0,1>() * S.get<1,2>() - S.get<0,2>() * S.get<1,1>();
393
double a21 = S.get<0,2>() * S.get<1,0>() - S.get<0,0>() * S.get<1,2>();
394
double a22 = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>();
395
double d = a20 * S.get<2,0>() + a21 * S.get<2,1>() + a22 * S.get<2,2>();
397
if (d != 0) return 3;
399
if (a20 != 0 || a21 != 0 || a22 != 0) return 2;
401
double a00 = S.get<1,1>() * S.get<2,2>() - S.get<1,2>() * S.get<2,1>();
402
if (a00 != 0) return 2;
404
double a10 = S.get<0,2>() * S.get<2,1>() - S.get<0,1>() * S.get<2,2>();
405
if (a10 != 0) return 2;
407
double a11 = S.get<0,0>() * S.get<2,2>() - S.get<0,2>() * S.get<2,0>();
408
if (a11 != 0) return 2;
414
} /* end namespace NL*/ } /* end namespace Geom*/
419
#endif // _NL_TRACE_H_
427
c-file-style:"stroustrup"
428
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
433
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :