QCAD
Open Source 2D CAD
Loading...
Searching...
No Matches
opennurbs_matrix.h
Go to the documentation of this file.
1/* $NoKeywords: $ */
2/*
3//
4// Copyright (c) 1993-2007 Robert McNeel & Associates. All rights reserved.
5// Rhinoceros is a registered trademark of Robert McNeel & Assoicates.
6//
7// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
8// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
9// MERCHANTABILITY ARE HEREBY DISCLAIMED.
10//
11// For complete openNURBS copyright information see <http://www.opennurbs.org>.
12//
14*/
15
16#if !defined(ON_MATRIX_INC_)
17#define ON_MATRIX_INC_
18
19class ON_Xform;
20
22{
23public:
24 ON_Matrix();
25 ON_Matrix(
26 int row_count,
27 int col_count
28 );
29 ON_Matrix( // see ON_Matrix::Create(int,int,int,int) for details
30 int, // first valid row index
31 int, // last valid row index
32 int, // first valid column index
33 int // last valid column index
34 );
35 ON_Matrix( const ON_Xform& );
36 ON_Matrix( const ON_Matrix& );
37
38 /*
39 Description:
40 This constructor is for experts who have storage for a matrix
41 and need to use it in ON_Matrix form.
42 Parameters:
43 row_count - [in]
44 col_count - [in]
45 M - [in]
46 bDestructorFreeM - [in]
47 If true, ~ON_Matrix will call onfree(M).
48 If false, caller is managing M's memory.
49 Remarks:
50 ON_Matrix functions that increase the value of row_count or col_count
51 will fail on a matrix created with this constructor.
52 */
54 int row_count,
55 int col_count,
56 double** M,
57 bool bDestructorFreeM
58 );
59
60 virtual ~ON_Matrix();
61 void EmergencyDestroy(); // call if memory pool used matrix by becomes invalid
62
63 // ON_Matrix[i][j] = value at row i and column j
64 // 0 <= i < RowCount()
65 // 0 <= j < ColCount()
66 double* operator[](int);
67 const double* operator[](int) const;
68
69 ON_Matrix& operator=(const ON_Matrix&);
70 ON_Matrix& operator=(const ON_Xform&);
71
72 bool IsValid() const;
73 int IsSquare() const; // returns 0 for no and m_row_count (= m_col_count) for yes
74 int RowCount() const;
75 int ColCount() const;
76 int MinCount() const; // smallest of row and column count
77 int MaxCount() const; // largest of row and column count
78
79 void RowScale(int,double);
80 void ColScale(int,double);
81 void RowOp(int,double,int);
82 void ColOp(int,double,int);
83
84 bool Create(
85 int, // number of rows
86 int // number of columns
87 );
88
89 bool Create( // E.g., Create(1,5,1,7) creates a 5x7 sized matrix that with
90 // "top" row = m[1][1],...,m[1][7] and "bottom" row
91 // = m[5][1],...,m[5][7]. The result of Create(0,m,0,n) is
92 // identical to the result of Create(m+1,n+1).
93 int, // first valid row index
94 int, // last valid row index
95 int, // first valid column index
96 int // last valid column index
97 );
98
99 /*
100 Description:
101 This constructor is for experts who have storage for a matrix
102 and need to use it in ON_Matrix form.
103 Parameters:
104 row_count - [in]
105 col_count - [in]
106 M - [in]
107 bDestructorFreeM - [in]
108 If true, ~ON_Matrix will call onfree(M).
109 If false, caller is managing M's memory.
110 Remarks:
111 ON_Matrix functions that increase the value of row_count or col_count
112 will fail on a matrix created with this constructor.
113 */
114 bool Create(
115 int row_count,
116 int col_count,
117 double** M,
118 bool bDestructorFreeM
119 );
120
121
122 void Destroy();
123
124 void Zero();
125
126 void SetDiagonal(double); // sets diagonal value and zeros off diagonal values
127 void SetDiagonal(const double*); // sets diagonal values and zeros off diagonal values
128 void SetDiagonal(int, const double*); // sets size to count x count and diagonal values and zeros off diagonal values
129 void SetDiagonal(const ON_SimpleArray<double>&); // sets size to length X lengthdiagonal values and zeros off diagonal values
130
131 bool Transpose();
132
133 bool SwapRows( int, int ); // ints are row indices to swap
134 bool SwapCols( int, int ); // ints are col indices to swap
135 bool Invert(
136 double // zero tolerance
137 );
138
139 /*
140 Description:
141 Set this = A*B.
142 Parameters:
143 A - [in]
144 (Can be this)
145 B - [in]
146 (Can be this)
147 Returns:
148 True when A is an mXk matrix and B is a k X n matrix; in which case
149 "this" will be an mXn matrix = A*B.
150 False when A.ColCount() != B.RowCount().
151 */
152 bool Multiply( const ON_Matrix& A, const ON_Matrix& B );
153
154 /*
155 Description:
156 Set this = A+B.
157 Parameters:
158 A - [in]
159 (Can be this)
160 B - [in]
161 (Can be this)
162 Returns:
163 True when A and B are mXn matrices; in which case
164 "this" will be an mXn matrix = A+B.
165 False when A and B have different sizes.
166 */
167 bool Add( const ON_Matrix& A, const ON_Matrix& B );
168
169
170 /*
171 Description:
172 Set this = s*this.
173 Parameters:
174 s - [in]
175 Returns:
176 True when A and s are valid.
177 */
178 bool Scale( double s );
179
180
181 // Description:
182 // Row reduce a matrix to calculate rank and determinant.
183 // Parameters:
184 // zero_tolerance - [in] (>=0.0) zero tolerance for pivot test
185 // If a the absolute value of a pivot is <= zero_tolerance,
186 // then the pivoit is assumed to be zero.
187 // determinant - [out] value of determinant is returned here.
188 // pivot - [out] value of the smallest pivot is returned here
189 // Returns:
190 // Rank of the matrix.
191 // Remarks:
192 // The matrix itself is row reduced so that the result is
193 // an upper triangular matrix with 1's on the diagonal.
194 int RowReduce( // returns rank
195 double, // zero_tolerance
196 double&, // determinant
197 double& // pivot
198 );
199
200 // Description:
201 // Row reduce a matrix as the first step in solving M*X=B where
202 // B is a column of values.
203 // Parameters:
204 // zero_tolerance - [in] (>=0.0) zero tolerance for pivot test
205 // If a the absolute value of a pivot is <= zero_tolerance,
206 // then the pivoit is assumed to be zero.
207 // B - [in/out] an array of m_row_count values that is row reduced
208 // with the matrix.
209 // determinant - [out] value of determinant is returned here.
210 // pivot - [out] If not NULL, then the value of the smallest
211 // pivot is returned here
212 // Returns:
213 // Rank of the matrix.
214 // Remarks:
215 // The matrix itself is row reduced so that the result is
216 // an upper triangular matrix with 1's on the diagonal.
217 // Example:
218 // Solve M*X=B;
219 // double B[m] = ...;
220 // double B[n] = ...;
221 // ON_Matrix M(m,n) = ...;
222 // M.RowReduce(ON_ZERO_TOLERANCE,B); // modifies M and B
223 // M.BackSolve(m,B,X); // solution is in X
224 // See Also:
225 // ON_Matrix::BackSolve
226 int RowReduce(
227 double, // zero_tolerance
228 double*, // B
229 double* = NULL // pivot
230 );
231
232 // Description:
233 // Row reduce a matrix as the first step in solving M*X=B where
234 // B is a column of 3d points
235 // Parameters:
236 // zero_tolerance - [in] (>=0.0) zero tolerance for pivot test
237 // If a the absolute value of a pivot is <= zero_tolerance,
238 // then the pivoit is assumed to be zero.
239 // B - [in/out] an array of m_row_count 3d points that is
240 // row reduced with the matrix.
241 // determinant - [out] value of determinant is returned here.
242 // pivot - [out] If not NULL, then the value of the smallest
243 // pivot is returned here
244 // Returns:
245 // Rank of the matrix.
246 // Remarks:
247 // The matrix itself is row reduced so that the result is
248 // an upper triangular matrix with 1's on the diagonal.
249 // See Also:
250 // ON_Matrix::BackSolve
251 int RowReduce(
252 double, // zero_tolerance
253 ON_3dPoint*, // B
254 double* = NULL // pivot
255 );
256
257 // Description:
258 // Row reduce a matrix as the first step in solving M*X=B where
259 // B is a column arbitrary dimension points.
260 // Parameters:
261 // zero_tolerance - [in] (>=0.0) zero tolerance for pivot test
262 // If a the absolute value of a pivot is <= zero_tolerance,
263 // then the pivoit is assumed to be zero.
264 // pt_dim - [in] dimension of points
265 // pt_stride - [in] stride between points (>=pt_dim)
266 // pt - [in/out] array of m_row_count*pt_stride values.
267 // The i-th point is
268 // (pt[i*pt_stride],...,pt[i*pt_stride+pt_dim-1]).
269 // This array of points is row reduced along with the
270 // matrix.
271 // pivot - [out] If not NULL, then the value of the smallest
272 // pivot is returned here
273 // Returns:
274 // Rank of the matrix.
275 // Remarks:
276 // The matrix itself is row reduced so that the result is
277 // an upper triangular matrix with 1's on the diagonal.
278 // See Also:
279 // ON_Matrix::BackSolve
280 int RowReduce( // returns rank
281 double, // zero_tolerance
282 int, // pt_dim
283 int, // pt_stride
284 double*, // pt
285 double* = NULL // pivot
286 );
287
288 // Description:
289 // Solve M*X=B where M is upper triangular with a unit diagonal and
290 // B is a column of values.
291 // Parameters:
292 // zero_tolerance - [in] (>=0.0) used to test for "zero" values in B
293 // in under determined systems of equations.
294 // Bsize - [in] (>=m_row_count) length of B. The values in
295 // B[m_row_count],...,B[Bsize-1] are tested to make sure they are
296 // "zero".
297 // B - [in] array of length Bsize.
298 // X - [out] array of length m_col_count. Solutions returned here.
299 // Remarks:
300 // Actual values M[i][j] with i <= j are ignored.
301 // M[i][i] is assumed to be one and M[i][j] i<j is assumed to be zero.
302 // For square M, B and X can point to the same memory.
303 // See Also:
304 // ON_Matrix::RowReduce
305 bool BackSolve(
306 double, // zero_tolerance
307 int, // Bsize
308 const double*, // B
309 double* // X
310 ) const;
311
312 // Description:
313 // Solve M*X=B where M is upper triangular with a unit diagonal and
314 // B is a column of 3d points.
315 // Parameters:
316 // zero_tolerance - [in] (>=0.0) used to test for "zero" values in B
317 // in under determined systems of equations.
318 // Bsize - [in] (>=m_row_count) length of B. The values in
319 // B[m_row_count],...,B[Bsize-1] are tested to make sure they are
320 // "zero".
321 // B - [in] array of length Bsize.
322 // X - [out] array of length m_col_count. Solutions returned here.
323 // Remarks:
324 // Actual values M[i][j] with i <= j are ignored.
325 // M[i][i] is assumed to be one and M[i][j] i<j is assumed to be zero.
326 // For square M, B and X can point to the same memory.
327 // See Also:
328 // ON_Matrix::RowReduce
329 bool BackSolve(
330 double, // zero_tolerance
331 int, // Bsize
332 const ON_3dPoint*, // B
333 ON_3dPoint* // X
334 ) const;
335
336 // Description:
337 // Solve M*X=B where M is upper triangular with a unit diagonal and
338 // B is a column of points
339 // Parameters:
340 // zero_tolerance - [in] (>=0.0) used to test for "zero" values in B
341 // in under determined systems of equations.
342 // pt_dim - [in] dimension of points
343 // Bsize - [in] (>=m_row_count) number of points in B[]. The points
344 // correspoinding to indices m_row_count, ..., (Bsize-1)
345 // are tested to make sure they are "zero".
346 // Bpt_stride - [in] stride between B points (>=pt_dim)
347 // Bpt - [in/out] array of m_row_count*Bpt_stride values.
348 // The i-th B point is
349 // (Bpt[i*Bpt_stride],...,Bpt[i*Bpt_stride+pt_dim-1]).
350 // Xpt_stride - [in] stride between X points (>=pt_dim)
351 // Xpt - [out] array of m_col_count*Xpt_stride values.
352 // The i-th X point is
353 // (Xpt[i*Xpt_stride],...,Xpt[i*Xpt_stride+pt_dim-1]).
354 // Remarks:
355 // Actual values M[i][j] with i <= j are ignored.
356 // M[i][i] is assumed to be one and M[i][j] i<j is assumed to be zero.
357 // For square M, B and X can point to the same memory.
358 // See Also:
359 // ON_Matrix::RowReduce
360 bool BackSolve(
361 double, // zero_tolerance
362 int, // pt_dim
363 int, // Bsize
364 int, // Bpt_stride
365 const double*,// Bpt
366 int, // Xpt_stride
367 double* // Xpt
368 ) const;
369
370 bool IsRowOrthoganal() const;
371 bool IsRowOrthoNormal() const;
372
373 bool IsColOrthoganal() const;
374 bool IsColOrthoNormal() const;
375
376
377 double** m; // m[i][j] = value at row i and column j
378 // 0 <= i < RowCount()
379 // 0 <= j < ColCount()
380private:
383 // m_rowmem[i][j] = row i+m_row_offset and column j+m_col_offset.
385 double** m_Mmem; // used by Create(row_count,col_count,user_memory,true);
386 int m_row_offset; // = ri0 when sub-matrix constructor is used
387 int m_col_offset; // = ci0 when sub-matrix constructor is used
388 void* m_cmem;
389 // returns 0 based arrays, even in submatrix case.
390 double const * const * ThisM() const;
391 double * * ThisM();
392};
393
394/*
395Description:
396 Calculate the singular value decomposition of a matrix.
397
398Parameters:
399 row_count - [in]
400 number of rows in matrix A
401 col_count - [in]
402 number of columns in matrix A
403 A - [in]
404 Matrix for which you want the singular value decomposition.
405 A[0][0] = coefficeint in the first row and first column.
406 A[row_count-1][col_count-1] = coefficeint in the last row
407 and last column.
408 U - [out]
409 The singular value decomposition of A is U*Diag(W)*Transpose(V),
410 where U has the same size as A, Diag(W) is a col_count X col_count
411 diagonal matrix with (W[0],...,W[col_count-1]) on the diagonal
412 and V is a col_count X col_count matrix.
413 U and A may be the same pointer. If the input value of U is
414 null, heap storage will be allocated using onmalloc()
415 and the calling function must call onfree(U). If the input
416 value of U is not null, U[i] must point to an array of col_count
417 doubles.
418 W - [out]
419 If the input value W is null, then heap storage will be allocated
420 using onmalloc() and the calling function must call onfree(W).
421 If the input value of W is not null, then W must point to
422 an array of col_count doubles.
423 V - [out]
424 If the input value V is null, then heap storage will be allocated
425 using onmalloc() and the calling function must call onfree(V).
426 If the input value of V is not null, then V[i] must point
427 to an array of col_count doubles.
428
429Example:
430
431 int m = row_count;
432 int n = col_count;
433 ON_Matrix A(m,n);
434 for (i = 0; i < m; i++ ) for ( j = 0; j < n; j++ )
435 {
436 A[i][j] = ...;
437 }
438 ON_Matrix U(m,n);
439 double* W = 0; // ON_GetMatrixSVD() will allocate W
440 ON_Matrix V(n,n);
441 bool rc = ON_GetMatrixSVD(m,n,A.m,U.m,W,V.m);
442 ...
443 onfree(W); // W allocated in ON_GetMatrixSVD()
444
445Returns:
446 True if the singular value decomposition was cacluated.
447 False if the algorithm failed to converge.
448*/
451 int row_count,
452 int col_count,
453 double const * const * A,
454 double**& U,
455 double*& W,
456 double**& V
457 );
458
459/*
460Description:
461 Invert the diagonal matrix in a the singular value decomposition.
462Parameters:
463 count - [in] number of elements in W
464 W - [in]
465 diagonal values in the singular value decomposition.
466 invW - [out]
467 The inverted diagonal is returned here. invW may be the same
468 pointer as W. If the input value of invW is not null, it must
469 point to an array of count doubles. If the input value of
470 invW is null, heap storage will be allocated using onmalloc()
471 and the calling function must call onfree(invW).
472Remarks:
473 If the singular value decomposition were mathematically perfect, then
474 this function would be:
475 for (i = 0; i < count; i++)
476 invW[i] = (W[i] != 0.0) ? 1.0/W[i] : 0.0;
477 Because the double precision arithmetic is not mathematically perfect,
478 very small values of W[i] may well be zero and this function makes
479 a reasonable guess as to when W[i] should be treated as zero.
480Returns:
481 Number of non-zero elements in invW, which, in a mathematically perfect
482 situation, is the rank of Diag(W).
483*/
485int ON_InvertSVDW(
486 int count,
487 const double* W,
488 double*& invW
489 );
490
491/*
492Description:
493 Solve a linear system of equations using the singular value decomposition.
494Parameters:
495 row_count - [in]
496 number of rows in matrix U
497 col_count - [in]
498 number of columns in matrix U
499 U - [in]
500 row_count X col_count matix.
501 See the remarks section for the definition of U.
502 invW - [in]
503 inverted DVD diagonal.
504 See the remarks section for the definition of invW.
505 V - [in]
506 col_count X col_count matrix.
507 See the remarks section for the definition of V.
508 B - [in]
509 An array of row_count values.
510 X - [out]
511 The solution array of col_count values is returned here.
512 If the input value of X is not null, it must point to an
513 array of col_count doubles. If the input value of X is
514 null, heap storage will be allocated using onmalloc() and
515 the calling function must call onfree(X).
516Remarks:
517 If A*X = B is an m X n system of equations (m = row_count, n = col_count)
518 and A = U*Diag(W)*Transpose(V) is the singular value decompostion of A,
519 then a solution is X = V*Diag(1/W)*Transpose(U).
520Example:
521
522 int m = row_count;
523 int n = col_count;
524 ON_Matrix A(m,n);
525 for (i = 0; i < m; i++ ) for ( j = 0; j < n; j++ )
526 {
527 A[i][j] = ...;
528 }
529 ON_SimpleArray<double> B(m);
530 for (i = 0; i < m; i++ )
531 {
532 B[i] = ...;
533 }
534
535 ON_SimpleArray<double> X; // solution returned here.
536 {
537 double** U = 0;
538 double* W = 0;
539 double** V = 0;
540 if ( ON_GetMatrixSVD(m,n,A.m,U,W,V) )
541 {
542 double* invW = 0;
543 int rankW = ON_InvertSVDW(n,W,W); // save invW into W
544 X.Reserve(n);
545 if ( ON_SolveSVD(m,n,U,W,V,B,X.Array()) )
546 X.SetCount(n);
547 }
548 onfree(U); // U allocated in ON_GetMatrixSVD()
549 onfree(W); // W allocated in ON_GetMatrixSVD()
550 onfree(V); // V allocated in ON_GetMatrixSVD()
551 }
552
553 if ( n == X.Count() )
554 {
555 ... use solution
556 }
557Returns:
558 True if input is valid and X[] was calculated.
559 False if input is not valid.
560*/
562bool ON_SolveSVD(
563 int row_count,
564 int col_count,
565 double const * const * U,
566 const double* invW,
567 double const * const * V,
568 const double* B,
569 double*& X
570 );
571
572
573/*
574Description:
575 Perform simple row reduction on a matrix. If A is square, positive
576 definite, and really really nice, then the returned B is the inverse
577 of A. If A is not positive definite and really really nice, then it
578 is probably a waste of time to call this function.
579Parameters:
580 row_count - [in]
581 col_count - [in]
582 zero_pivot - [in]
583 absolute values <= zero_pivot are considered to be zero
584 A - [in/out]
585 A row_count X col_count matrix. Input is the matrix to be
586 row reduced. The calculation destroys A, so output A is garbage.
587 B - [out]
588 A a row_count X row_count matrix. That records the row reduction.
589 pivots - [out]
590 minimum and maximum absolute values of pivots.
591Returns:
592 Rank of A. If the returned value < min(row_count,col_count),
593 then a zero pivot was encountered.
594 If C = input value of A, then B*C = (I,*)
595*/
597int ON_RowReduce(
598 int row_count,
599 int col_count,
600 double zero_pivot,
601 double** A,
602 double** B,
603 double pivots[2]
604 );
605
606#endif
Definition opennurbs_point.h:403
Definition opennurbs_matrix.h:22
double ** m_Mmem
Definition opennurbs_matrix.h:385
int m_col_offset
Definition opennurbs_matrix.h:387
double ** m
Definition opennurbs_matrix.h:377
int m_row_offset
Definition opennurbs_matrix.h:386
int m_col_count
Definition opennurbs_matrix.h:382
void * m_cmem
Definition opennurbs_matrix.h:388
int m_row_count
Definition opennurbs_matrix.h:381
ON_SimpleArray< double * > m_rowmem
Definition opennurbs_matrix.h:384
Definition opennurbs_array.h:46
Definition opennurbs_xform.h:28
Scales selected entities.
Definition Scale.js:11
#define ON_DECL
Definition opennurbs_defines.h:92
#define ON_CLASS
Definition opennurbs_defines.h:91
ON_DECL int ON_InvertSVDW(int count, const double *W, double *&invW)
Definition opennurbs_matrix.cpp:1339
ON_DECL bool ON_SolveSVD(int row_count, int col_count, double const *const *U, const double *invW, double const *const *V, const double *B, double *&X)
Definition opennurbs_matrix.cpp:1382
ON_DECL int ON_RowReduce(int row_count, int col_count, double zero_pivot, double **A, double **B, double pivots[2])
Definition opennurbs_matrix.cpp:1199
ON_DECL bool ON_GetMatrixSVD(int row_count, int col_count, double const *const *A, double **&U, double *&W, double **&V)
#define M
Definition opennurbs_rand.cpp:71
char s
Definition opennurbs_string.cpp:32
#define NULL
Definition opennurbs_system.h:256