1 #ifndef SimTK_SIMMATRIX_MATRIX_CHARACTERISTICS_H_ 2 #define SimTK_SIMMATRIX_MATRIX_CHARACTERISTICS_H_ 3 4 /* -------------------------------------------------------------------------- * 5 * Simbody(tm): SimTKcommon * 6 * -------------------------------------------------------------------------- * 7 * This is part of the SimTK biosimulation toolkit originating from * 8 * Simbios, the NIH National Center for Physics-Based Simulation of * 9 * Biological Structures at Stanford, funded under the NIH Roadmap for * 10 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 11 * * 12 * Portions copyright (c) 2005-13 Stanford University and the Authors. * 13 * Authors: Michael Sherman * 14 * Contributors: * 15 * * 16 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 17 * not use this file except in compliance with the License. You may obtain a * 18 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 19 * * 20 * Unless required by applicable law or agreed to in writing, software * 21 * distributed under the License is distributed on an "AS IS" BASIS, * 22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 23 * See the License for the specific language governing permissions and * 24 * limitations under the License. * 25 * -------------------------------------------------------------------------- */ 26 27 /** @file 28 * 29 * Here we declare the classes needed for managing the properties of matrices, 30 * which we call Matrix Characteristics. 31 */ 32 33 #include "SimTKcommon/Scalar.h" 34 35 #include <iostream> 36 #include <cassert> 37 #include <complex> 38 #include <cstddef> 39 #include <utility> // for std::pair 40 41 namespace SimTK { 42 43 44 class MatrixStructure; 45 class MatrixStorage; 46 class MatrixOutline; 47 class MatrixCondition; 48 class MatrixCharacter; 49 class MatrixCommitment; 50 51 52 // ------------------------------ MatrixStructure ----------------------------- 53 /// Matrix "structure" refers to an inherent mathematical (or at least 54 /// algorithmic) characteristic of the matrix rather than a storage strategy. 55 /// Symmetry is the clearest example of this; it is far more significant 56 /// mathematically than just a way to save storage and reduce operation count. 57 // ---------------------------------------------------------------------------- 58 class SimTK_SimTKCOMMON_EXPORT MatrixStructure { 59 public: 60 enum Structure { 61 NoStructure = 0x00000000, ///< unspecified structure 62 Matrix1d = 0x00000001, ///< a 1-d matrix (could be row or column) 63 Zero = 0x00000002, ///< a matrix of all zeroes 64 Identity = 0x00000004, ///< diagonal matrix with repeated 1's 65 Permutation = 0x00000008, ///< permutation of an identity matrix 66 RepeatedDiagonal = 0x00000010, ///< diagonal matrix with repeated element 67 Diagonal = 0x00000020, ///< diagonal matrix with arbitrary elements 68 BiDiagonal = 0x00000040, ///< diagonal plus one upper or lower band 69 TriDiagonal = 0x00000080, ///< diagonal plus one upper and one lower band 70 BandedSymmetric = 0x00000100, ///< diagonal plus adjacent symmetric bands 71 BandedHermitian = 0x00000200, ///< diagonal plus adjacent conjugate bands 72 Banded = 0x00000400, ///< diagonal plus upper and lower bands 73 Triangular = 0x00000800, ///< diagonal plus all upper or all lower bands 74 QuasiTriangular = 0x00001000, ///< triangular but with 2x2 blocks on the diagonal 75 Hessenberg = 0x00002000, ///< triangular plus one band above/below diagonal 76 Symmetric = 0x00004000, ///< symmetric: elt(i,j)==elt(j,i) 77 Hermitian = 0x00008000, ///< hermitian: elt(i,j)==conjugate(elt(j,i)) 78 SkewSymmetric = 0x00010000, ///< skew symmetric: elt(i,j) == -elt(j,i) 79 SkewHermitian = 0x00020000, ///< skew hermitian: elt(i,j) == -conjugate(elt(j,i)) 80 Full = 0x00040000 ///< full mxn matrix, all elements distinct 81 }; 82 static const char* name(Structure); 83 84 typedef unsigned int StructureMask; // 32 bits 85 static const StructureMask AnyStructure = 0x0007ffffU; // see above 86 static const StructureMask UncommittedStructure = 0xffffffffU; 87 static StructureMask calcStructureMask(Structure); 88 89 /// For triangular matrices, we have to know which triangle 90 /// we're talking about. Don't confuse this with MatrixStorage::Placement 91 /// which has to do with where we put it in memory, *not* what 92 /// matrix is being represented. 93 enum Position { 94 NoPosition = 0x0000, 95 Lower = 0x0001, // matrix is lower triangular (default) 96 Upper = 0x0002 // matrix is upper triangular 97 }; 98 static const char* name(Position); 99 100 typedef unsigned short PositionMask; // 16 bits 101 static const PositionMask AnyPosition = 0x0003U; // see above 102 static const PositionMask UncommittedPosition = 0xffffU; 103 static PositionMask calcPositionMask(Structure); 104 105 /// For triangular, symmetric, and hermitian matrices the diagonal elements 106 /// may have a single, assumed value rather than being stored in memory. 107 /// This specifies the value. Don't confuse this with the similar 108 /// MatrixStorage type which simply says whether there is a known value 109 /// rather than stored values, *not* what that value is. 110 enum DiagValue { 111 NoDiagValue = 0x0000, 112 StoredDiag = 0x0001, // could be anything (default) 113 ZeroDiag = 0x0002, // zero (e.g. for skew matrices) 114 UnitDiag = 0x0004 // unit (one) diagonal is used frequently by Lapack 115 }; 116 static const char* name(DiagValue); 117 118 typedef unsigned short DiagValueMask; // 16 bits 119 static const DiagValueMask AnyDiagValue = 0x0003U; 120 static const DiagValueMask UncommittedDiagValue = 0xffffU; 121 static DiagValueMask calcDiagValueMask(Structure); 122 setMissingAttributes()123 MatrixStructure& setMissingAttributes() { 124 if (structure == NoStructure) 125 structure = Full; 126 if (position == NoPosition) 127 position = Lower; 128 if (diagValue == NoDiagValue) 129 diagValue = StoredDiag; 130 return *this; 131 } 132 name()133 std::string name() const { 134 return std::string(name(getStructure())) 135 + "|" + std::string(name(getPosition())) 136 + "|" + std::string(name(getDiagValue())); 137 } 138 139 struct Mask { MaskMask140 Mask() {setToUncommitted();} MaskMask141 Mask(StructureMask sm, PositionMask pm, DiagValueMask dm) 142 : structure(sm), position(pm), diagValue(dm) {} setToUncommittedMask143 Mask& setToUncommitted() 144 { structure=UncommittedStructure; position=UncommittedPosition; 145 diagValue=UncommittedDiagValue; return *this; } isUncommittedMask146 bool isUncommitted() const 147 { return structure==UncommittedStructure && position==UncommittedPosition 148 && diagValue==UncommittedDiagValue; } isSatisfiedByMask149 bool isSatisfiedBy(Structure str, Position pos, DiagValue diag) const 150 { return ((StructureMask)str&structure)==(StructureMask)str 151 && ((PositionMask)pos&position)==(PositionMask)pos 152 && ((DiagValueMask)diag&diagValue)==(DiagValueMask)diag; } isSatisfiedByMask153 bool isSatisfiedBy(const MatrixStructure& actual) const 154 { return isSatisfiedBy(actual.getStructure(), actual.getPosition(), 155 actual.getDiagValue()); } 156 157 StructureMask structure; 158 PositionMask position; 159 DiagValueMask diagValue; 160 }; 161 MatrixStructure()162 MatrixStructure() {setToNone();} 163 164 /// This constructor is also an implicit conversion from the Structure enum 165 /// to a MatrixStructure object which does not specify Position or DiagValue. 166 MatrixStructure(Structure s, Position p=NoPosition, DiagValue d=NoDiagValue) structure(s)167 : structure(s), position(p), diagValue(d) {} 168 169 /// Given a Structure commitment, which more-restrictive Structures will 170 /// still satisfy this commitment? Returned value is a mask with a bit 171 /// set for every Structure that is satisfactory. For example, if the 172 /// commitment is "Banded", "Diagonal" is also acceptable. 173 Mask mask() const; 174 getStructure()175 Structure getStructure() const {return structure;} getPosition()176 Position getPosition() const {return position;} getDiagValue()177 DiagValue getDiagValue() const {return diagValue;} 178 setStructure(Structure s)179 MatrixStructure& setStructure(Structure s) {structure=s; return *this;} setPosition(Position p)180 MatrixStructure& setPosition (Position p) {position=p; return *this;} setDiagValue(DiagValue d)181 MatrixStructure& setDiagValue(DiagValue d) {diagValue=d; return *this;} 182 set(Structure s,Position p,DiagValue d)183 MatrixStructure& set(Structure s, Position p, DiagValue d) 184 { structure=s; position=p; diagValue=d; return *this; } 185 setToNone()186 MatrixStructure& setToNone() 187 { structure=NoStructure; position=NoPosition; 188 diagValue=NoDiagValue; return *this; } 189 190 private: 191 Structure structure:32; 192 Position position:16; 193 DiagValue diagValue:16; 194 }; 195 196 197 // ------------------------------ MatrixStorage ------------------------------- 198 /// Matrix "storage" refers to the physical layout of data in the computer's 199 /// memory. Whenever possible we attempt to store data in a format that enables 200 /// use of special high performance methods, such as those available in the 201 /// SimTK LAPACK/BLAS implementation. 202 // ---------------------------------------------------------------------------- 203 class SimTK_SimTKCOMMON_EXPORT MatrixStorage { 204 public: 205 enum Packing { 206 NoPacking = 0x0000, 207 Full = 0x0001, // full storage layout 208 TriInFull = 0x0002, // a triangular piece of a full storage layout 209 TriPacked = 0x0004, // triangle packed into minimal storage, at performance cost 210 Banded = 0x0008, // a packed, banded storage format 211 Vector = 0x0010, // a possibly-strided or scattered vector 212 Scalar = 0x0020, // a single scalar is stored 213 Permutation = 0x0040 // a permuted identity matrix 214 }; 215 static const char* name(Packing); 216 typedef unsigned short PackingMask; 217 static const PackingMask AllPacking = 0x007fU; // see above 218 static const PackingMask UncommittedPacking = 0xffffU; 219 220 enum Placement { 221 NoPlacement = 0x0000, 222 Lower = 0x0001, // stored in lower triangle of full matrix 223 Upper = 0x0002, // stored in upper triangle of full matrix 224 }; 225 static const char* name(Placement); 226 typedef unsigned short PlacementMask; 227 static const PlacementMask AllPlacement = 0x0003U; // see above 228 static const PlacementMask UncommittedPlacement = 0xffffU; 229 230 enum Order { 231 NoOrder = 0x0000, 232 ColumnOrder = 0x0001, // matrix is stored by columns 233 RowOrder = 0x0002, // matrix is stored by rows 234 }; 235 static const char* name(Order); 236 typedef unsigned short OrderMask; 237 static const OrderMask AllOrder = 0x03U; // see above 238 static const OrderMask UncommittedOrder = 0xffU; 239 240 enum Diagonal { 241 NoDiag = 0x0000, 242 StoredDiag = 0x0001, // matrix diagonal is stored 243 AssumedDiag = 0x0002 // matrix diagonal is not stored but has known value 244 }; 245 static const char* name(Diagonal); 246 typedef unsigned short DiagonalMask; 247 static const DiagonalMask AllDiagonal = 0x0003U; // see above 248 static const DiagonalMask UncommittedDiagonal = 0xffffU; 249 250 /// Use this class to represent sets of acceptable values for each of 251 /// the storage attributes (packing, position, order, diagonal). 252 struct Mask { MaskMask253 Mask() 254 : packing(UncommittedPacking), placement(UncommittedPlacement), 255 order(UncommittedOrder), diagonal(UncommittedDiagonal) {} MaskMask256 Mask(PackingMask pkm, PlacementMask plm, OrderMask om, DiagonalMask dm) 257 : packing(pkm), placement(plm), order(om), diagonal(dm) {} setToUncommittedMask258 Mask& setToUncommitted() 259 { packing=UncommittedPacking; placement=UncommittedPlacement; 260 order=UncommittedOrder; diagonal=UncommittedDiagonal; return *this; } isUncommittedMask261 bool isUncommitted() const 262 { return packing==UncommittedPacking && placement==UncommittedPlacement 263 && order==UncommittedOrder && diagonal==UncommittedDiagonal; } isSatisfiedByMask264 bool isSatisfiedBy(Packing pack, Placement place, Order ord, Diagonal diag) const 265 { return ((PackingMask)pack & packing) == (PackingMask) pack 266 && ((PlacementMask)place & placement) == (PlacementMask)place 267 && ((OrderMask)ord & order) == (OrderMask) ord 268 && ((DiagonalMask)diag & diagonal) == (DiagonalMask) diag; } isSatisfiedByMask269 bool isSatisfiedBy(const MatrixStorage& actual) const 270 { return isSatisfiedBy(actual.getPacking(), actual.getPlacement(), 271 actual.getOrder(), actual.getDiagonal());} 272 273 PackingMask packing; 274 PlacementMask placement; 275 OrderMask order; 276 DiagonalMask diagonal; 277 }; 278 279 static MatrixStorage calcDefaultStorage(const MatrixStructure&, 280 const MatrixOutline&); 281 name()282 std::string name() const { 283 return std::string(name(getPacking())) 284 + "|" + std::string(name(getPlacement())) 285 + "|" + std::string(name(getOrder())) 286 + "|" + std::string(name(getDiagonal())); 287 } 288 289 /// Calculate the commitment mask associated with specifying "this" set 290 /// of storage attributes as a commitment. Here the mask will either be 291 /// fully uncommitted or set to a specific value for each attribute; they 292 /// are all mutually exclusive. mask()293 Mask mask() const { 294 Mask ms; // initially uncommitted 295 if (packing) ms.packing = (PackingMask)packing; 296 if (placement) ms.placement = (PlacementMask)placement; 297 if (order) ms.order = (OrderMask)order; 298 if (diagonal) ms.diagonal = (DiagonalMask)diagonal; 299 return ms; 300 } 301 302 /// Default constructor leaves all fields unspecified. MatrixStorage()303 MatrixStorage() 304 : packing(NoPacking), placement(NoPlacement), order(NoOrder), diagonal(NoDiag) {} 305 306 /// This constructor is also an implicit conversion from the Packing enum to a 307 /// MatrixStorage object which does not contain any specification for placement, 308 /// order, or storage of diagonal elements. 309 MatrixStorage(Packing pk, Placement pl=NoPlacement, Order o=NoOrder, Diagonal d=NoDiag) packing(pk)310 : packing(pk), placement(pl), order(o), diagonal(d) {} 311 312 /// This constructor is for the common case of just packing and order, with 313 /// no particular placement and a stored diagonal. MatrixStorage(Packing pk,Order o)314 MatrixStorage(Packing pk, Order o) 315 : packing(pk), placement(NoPlacement), order(o), diagonal(StoredDiag) {} 316 317 /// Assuming this is an actual matrix description, set any unspecified attributes 318 /// to appropriate defaults to match the specified packing. setMissingAttributes()319 MatrixStorage& setMissingAttributes() { 320 if (packing==NoPacking) 321 packing = Full; 322 if (placement==NoPlacement) 323 placement = Lower; 324 if (order==NoOrder) 325 order = ColumnOrder; 326 if (diagonal==NoDiag) 327 diagonal = StoredDiag; 328 return *this; 329 } 330 331 /// Restore this object to its default-constructed state of "none". setToNone()332 MatrixStorage& setToNone() 333 { packing=NoPacking; placement=NoPlacement; 334 order=NoOrder; diagonal=NoDiag; return *this; } 335 setPacking(Packing p)336 MatrixStorage& setPacking(Packing p) {packing = p; return *this;} setPlacement(Placement p)337 MatrixStorage& setPlacement(Placement p) {placement = p; return *this;} setOrder(Order o)338 MatrixStorage& setOrder(Order o) {order = o; return *this;} setDiagonal(Diagonal d)339 MatrixStorage& setDiagonal(Diagonal d) {diagonal = d; return *this;} 340 getPacking()341 Packing getPacking() const {return packing;} getPlacement()342 Placement getPlacement() const {return placement;} getOrder()343 Order getOrder() const {return order;} getDiagonal()344 Diagonal getDiagonal() const {return diagonal;} 345 346 private: 347 Packing packing:16; 348 Placement placement:16; 349 Order order:16; 350 Diagonal diagonal:16; 351 }; 352 353 354 // ------------------------------- MatrixOutline ------------------------------ 355 /// Matrix "outline" refers to the characteristic relationship between the number 356 /// of rows and columns of a matrix, without necessarily specifying the absolute 357 /// dimensions. 358 /// 359 /// There are seven possible outline attributes: 360 /// - Rectangular (any m x n) 361 /// - Tall (m >= n) 362 /// - Wide (m <= n) 363 /// - Square (m == n) 364 /// - Column (m x 1) 365 /// - Row (1 x n) 366 /// - Scalar (1 x 1) 367 /// 368 /// A matrix handle with no outline commitment can hold a general (rectangular) 369 /// matrix, which of course includes all the other outlines as well. Vector 370 /// handles are always committed to column outline, RowVector handles to row 371 /// outline. Scalar matrices are also rows, columns, and square and some 372 /// rows and columns are square (if they are 1x1). 373 /// 374 /// Note that certain outlines imply fixed sizes of one or both dimensions. 375 // ---------------------------------------------------------------------------- 376 class SimTK_SimTKCOMMON_EXPORT MatrixOutline { 377 public: 378 enum Outline { 379 NoOutline = 0x0000, 380 Scalar = 0x0001, // 1x1 381 Column = 0x0002, // mx1, m != 1 382 Row = 0x0004, // 1xn, n != 1 383 Square = 0x0008, // mxn, m == n 384 Wide = 0x0010, // mxn, m < n 385 Tall = 0x0020, // mxn, m > n 386 Rectangular = 0x0040 // mxn 387 }; 388 static const char* name(Outline); 389 390 typedef unsigned short OutlineMask; 391 static const OutlineMask AnyOutline = 0x007fU; // see above 392 static const OutlineMask UncommittedOutline = 0xffffU; 393 394 struct Mask { MaskMask395 Mask() : outline(UncommittedOutline) {} MaskMask396 explicit Mask(OutlineMask mask) : outline(mask) {} setToUncommittedMask397 Mask& setToUncommitted() {outline=UncommittedOutline; return *this;} isUncommittedMask398 bool isUncommitted() const {return outline==UncommittedOutline;} isSatisfiedByMask399 bool isSatisfiedBy(const MatrixOutline& actual) const 400 { return ((OutlineMask)actual.outline & outline) == (OutlineMask)actual.outline; } 401 402 OutlineMask outline; 403 }; 404 name()405 std::string name() const {return std::string(name(getOutline()));} 406 407 /// Default constructor produces an object containing no outline specification. 408 /// If used as a commitment it won't accept \e any outline! MatrixOutline()409 MatrixOutline() : outline(NoOutline) {} 410 411 /// This is an implicit conversion from the Outline enum to a MatrixOutline object. MatrixOutline(Outline outline)412 MatrixOutline(Outline outline) : outline(outline) {} 413 414 /// Set the outline back to its default-constructed value of "none". setToNone()415 MatrixOutline& setToNone() {outline=NoOutline; return *this;} 416 417 /// Compute a mask of acceptable Outline values given a particular 418 /// value specified as a commitment. For example, if the commitment 419 /// is "Wide" then Square, Row, and Scalar outlines are also acceptable. 420 static OutlineMask calcMask(Outline); 421 422 /// When "this" outline is used as a commitment, it represents a mask of 423 /// acceptable outlines. Calculate and return that mask. mask()424 Mask mask() const {return Mask(calcMask(getOutline()));} 425 426 /// Determine if the proposed shape satisfies this outline. 427 bool isSizeOK(int m, int n) const; 428 429 /// Return the minimum shape that will satisfy this outline. 430 void getMinimumSize(int& m, int& n) const; 431 432 /// Determine the outline from given actual dimensions. 433 static MatrixOutline calcFromSize(int m, int n); 434 435 /// Return the outline value stored in this MatrixOutline object. getOutline()436 Outline getOutline() const {return outline;} 437 438 private: 439 Outline outline:16; 440 }; 441 442 443 444 // ---------------------------- MatrixCondition ------------------------------- 445 /// Matrix "condition" is a statement about the numerical characteristics of a 446 /// Matrix. It can be set as a result of an operation, or by a knowledgeable user. 447 /// Simmatrix is entitled to rely on the correctness of these assertions, 448 /// although it will try to check them if requested or when it is possible to do 449 /// so without sacrificing performance. 450 /// In most cases the condition will not be set at all, which we interpret to 451 /// mean "unknown condition" in an actual character, and "uncommitted" in 452 /// a character commitment. 453 // ---------------------------------------------------------------------------- 454 class SimTK_SimTKCOMMON_EXPORT MatrixCondition { 455 public: 456 enum Condition { 457 UnknownCondition = 0x0000, 458 Orthogonal = 0x0001, // implies well conditioned 459 PositiveDefinite = 0x0002, // implies well conditioned 460 WellConditioned = 0x0004, // implies full rank 461 FullRank = 0x0008, // but might have bad conditioning 462 Singular = 0x0010 // implies possible bad conditioning 463 }; 464 static const char* name(Condition); 465 466 typedef unsigned short ConditionMask; // 16 bits in mask 467 static const ConditionMask AnyCondition = 0x001fU; // see above 468 static const ConditionMask UncommittedCondition = 0xffffU; 469 470 enum Diagonal { 471 UnknownDiagonal = 0x0000, ///< we don't know the condition of the diagonal elements 472 ZeroDiagonal = 0x0001, ///< all diagonal elements are zero (also pure real and pure imaginary) 473 OneDiagonal = 0x0002, ///< all diagonal elements are one (and real) 474 RealDiagonal = 0x0004, ///< all diagonal elements are pure real 475 ImaginaryDiagonal = 0x0008 ///< all diagonal elements are pure imaginary 476 }; 477 static const char* name(Diagonal); 478 479 typedef unsigned short DiagonalMask; // 16 bits in mask 480 static const DiagonalMask AnyDiagonal = 0x000fU; // see above 481 static const DiagonalMask UncommittedDiagonal = 0xffffU; 482 483 /// Use this class to represent a set of acceptable Condition values. 484 struct Mask { MaskMask485 Mask() : condition(UncommittedCondition), diagonal(UncommittedDiagonal) {} MaskMask486 Mask(ConditionMask cmask, DiagonalMask dmask) : condition(cmask), diagonal(dmask) {} setToUncommittedMask487 Mask& setToUncommitted() 488 { condition=UncommittedCondition; diagonal=UncommittedDiagonal; return *this;} isUncommittedMask489 bool isUncommitted() const 490 { return condition==UncommittedCondition && diagonal==UncommittedDiagonal;} isSatisfiedByMask491 bool isSatisfiedBy(const MatrixCondition& actual) const 492 { return ((ConditionMask)actual.condition & condition) == (ConditionMask)actual.condition 493 && ((DiagonalMask) actual.diagonal & diagonal) == (DiagonalMask)actual.diagonal; } 494 495 ConditionMask condition; 496 DiagonalMask diagonal; 497 }; 498 name()499 std::string name() const 500 { return std::string(name(getCondition())) + "|" + std::string(name(getDiagonal()));} 501 502 /// The default constructor sets the condition to Unknown, which is typically 503 /// where it remains. MatrixCondition()504 MatrixCondition() : condition(UnknownCondition), diagonal(UnknownDiagonal) {} 505 506 /// This is an implicit conversion from the Condition enum to a 507 /// MatrixCondition object. 508 MatrixCondition(Condition cond, Diagonal diag=UnknownDiagonal) condition(cond)509 : condition(cond), diagonal(diag) {} 510 511 /// Restore to default-constructed state of "none". setToNone()512 MatrixCondition& setToNone() {condition=UnknownCondition; diagonal=UnknownDiagonal; return *this;} 513 514 /// Given a particular Condition provided as a commitment, calculate 515 /// the mask of all Condition values that would satisfy that commitment. 516 /// For example, if the commitment is "WellConditioned" then "Orthogonal" 517 /// and "PositiveDefinite" also qualify since they are automatically 518 /// well conditioned. If the Condition is "Unknown" we'll return an Uncommitted mask. 519 static ConditionMask calcMask(Condition); 520 521 /// Given a particular Diagonal condition provided as a commitment, calculate 522 /// the mask of all Diagonal conditions that would satisfy that commitment. 523 /// For example, if the commitment is "RealDiagonal" then "ZeroDiagonal" 524 /// and "OneDiagonal" would also be acceptable. If the Diagonal condition 525 /// is specified as "UnknownDiagonal" then we'll return an Uncommitted mask. 526 static DiagonalMask calcMask(Diagonal); 527 528 /// Return the commitment mask corresponding to use of "this" condition 529 /// as a commitment. mask()530 Mask mask() const 531 { return Mask(calcMask(getCondition()), calcMask(getDiagonal())); } 532 getCondition()533 Condition getCondition() const {return condition;} getDiagonal()534 Diagonal getDiagonal() const {return diagonal;} 535 setCondition(Condition c)536 MatrixCondition& setCondition(Condition c) {condition=c; return *this;} setDiagonal(Diagonal d)537 MatrixCondition& setDiagonal (Diagonal d) {diagonal=d; return *this;} 538 539 private: 540 Condition condition:16; 541 Diagonal diagonal:16; 542 }; 543 544 545 546 // ------------------------------ MatrixCharacter ----------------------------- 547 /** A MatrixCharacter is a set containing a value for each of the matrix 548 characteristics except element type, which is part of the templatized 549 declaration of a Matrix_, Vector_, or RowVector_ handle. MatrixCharacters are 550 used both as the handle "commitment", setting restrictions on what kinds 551 of matrices a handle can reference, and as the "facts on the ground" current 552 character of the matrix being referenced. The current character must always 553 satisfy the character commitment. 554 555 %Matrix characteristics are specifications of particular aspects of matrices: 556 - Element type 557 - Size 558 - Structure 559 - Storage format 560 - Outline 561 - Conditioning 562 563 Collectively, the set of values for the above properties is called a <i>matrix 564 character</i>. A matrix character can be used to describe an existing matrix, 565 or a character mask can be used to describe the range of characteristics that 566 a matrix handle may support. The character mask describing the acceptable 567 matrices for a matrix handle is called the handle's <i>character commitment</i> 568 or just the <i>handle commitment</i>. The character describing an existing 569 matrix is called the <i>actual character</i> of that matrix. Thus there are 570 always two sets of characteristics associated with a matrix: the handle's 571 commitment, and the actual character of the matrix to which the handle currently 572 refers. The actual character must always \e satisfy the character commitment. 573 574 When a handle presents a view into another handle's data, it is the 575 characteristics of the matrix as seen through the view that must satisfy the 576 handle's character commitment. So for example, a view showing one column of a 577 full matrix satisfies a "column" outline commitment. 578 579 Element type for a matrix handle is always determined at compile time via the 580 template argument used in the declaration. For example, a matrix handle declared 581 \c Matrix_<Vec3> can only hold matrices whose elements are \c Vec3s. Also, 582 recall that \c Matrix is an abbreviation for \c Matrix_<Real> so that 583 declaration commits the matrix handle to Real-element matrices. Element type 584 is the only matrix characteristic for which no matrix handle can remain 585 uncommitted. However, different handles can provide views of the same data 586 through which that data is seen to contain different element types. 587 588 Each matrix characteristic other than sizes is represented by a class 589 defining one or more enumerated types, where individual characteristics are 590 assigned a single bit. Then an appropriate mask type (an unsigned integral 591 type) is defined which can represent a set of allowable characteristics. 592 The actual character of a matrix is represented via enumeration values; the 593 character commitment is represented by the compatible masks. The operation 594 of determining whether a particular actual character satisfies a handle 595 commitment can then be performed very quickly via bitwise logical operations. 596 **/ 597 class SimTK_SimTKCOMMON_EXPORT MatrixCharacter { 598 public: 599 /// Default constructor sets lengths to zero and the other characteristics 600 /// to "none specified". MatrixCharacter()601 MatrixCharacter() : nr(0), nc(0), lband(0), uband(0) {} 602 603 // Some handy predefined MatrixCharacters. 604 class LapackFull; 605 class Vector; 606 class RowVector; 607 608 /// Restore this MatrixCharacter to its default-constructed state of "none". setToNone()609 MatrixCharacter& setToNone() { 610 nr=nc=lband=uband=0; 611 structure.setToNone(); outline.setToNone(); 612 storage.setToNone(); condition.setToNone(); 613 return *this; 614 } 615 616 /// These are dimensions of the logical matrix and have nothing to do with 617 /// how much storage may be used to hold the elements. nrow()618 int nrow() const {return nr;} ncol()619 int ncol() const {return nc;} getSize()620 std::pair<int,int> getSize() const {return std::pair<int,int>(nrow(),ncol());} nelt()621 ptrdiff_t nelt() const {return (ptrdiff_t)nrow() * (ptrdiff_t)ncol();} 622 getLowerBandwidth()623 int getLowerBandwidth() const {return lband;} getUpperBandwidth()624 int getUpperBandwidth() const {return uband;} getBandwidth()625 std::pair<int,int> getBandwidth() const 626 { return std::pair<int,int>(getLowerBandwidth(), getUpperBandwidth()); } 627 getStructure()628 const MatrixStructure& getStructure() const {return structure;} getStorage()629 const MatrixStorage& getStorage() const {return storage;} getOutline()630 const MatrixOutline& getOutline() const {return outline;} getCondition()631 const MatrixCondition& getCondition() const {return condition;} 632 updStructure()633 MatrixStructure& updStructure() {return structure;} updStorage()634 MatrixStorage& updStorage() {return storage;} updOutline()635 MatrixOutline& updOutline() {return outline;} updCondition()636 MatrixCondition& updCondition() {return condition;} 637 setStructure(const MatrixStructure & sa)638 MatrixCharacter& setStructure(const MatrixStructure& sa) {structure = sa; return *this;} setStorage(const MatrixStorage & sa)639 MatrixCharacter& setStorage (const MatrixStorage& sa) {storage = sa; return *this;} setOutline(const MatrixOutline & oa)640 MatrixCharacter& setOutline (const MatrixOutline& oa) {outline = oa; return *this;} setCondition(const MatrixCondition & ca)641 MatrixCharacter& setCondition(const MatrixCondition& ca) {condition = ca; return *this;} 642 643 644 /// Set the actual size and update the outline to match. setActualSize(int m,int n)645 MatrixCharacter& setActualSize(int m, int n) 646 { setSize(m,n); outline = MatrixOutline::calcFromSize(m,n); return *this; } setActualNumRows(int m)647 MatrixCharacter& setActualNumRows(int m) 648 { setNumRows(m); outline = MatrixOutline::calcFromSize(m,ncol()); return *this; } setActualNumCols(int n)649 MatrixCharacter& setActualNumCols(int n) 650 { setNumCols(n); outline = MatrixOutline::calcFromSize(nrow(),n); return *this; } 651 setBandwidth(int lb,int ub)652 MatrixCharacter& setBandwidth(int lb, int ub) { 653 assert(lb>=0 && lb>=0); 654 lband = lb; uband = ub; 655 return *this; 656 } setLowerBandwidth(int lb)657 MatrixCharacter& setLowerBandwidth(int lb) { 658 assert(lb>=0); 659 lband = lb; 660 return *this; 661 } setUpperBandwidth(int ub)662 MatrixCharacter& setUpperBandwidth(int ub) { 663 assert(ub>=0); 664 uband = ub; 665 return *this; 666 } 667 668 class Mask; // defined below 669 670 protected: MatrixCharacter(int m,int n,int lb,int ub,MatrixStructure structure,MatrixStorage storage,MatrixCondition condition)671 MatrixCharacter(int m, int n, 672 int lb, int ub, 673 MatrixStructure structure, 674 MatrixStorage storage, 675 MatrixCondition condition) 676 : nr(m), nc(n), lband(lb), uband(ub), 677 structure(structure), storage(storage), 678 outline(MatrixOutline::calcFromSize(m,n)), 679 condition(condition) {} 680 681 682 int nr, ///< actual number of rows 683 nc; ///< actual number of columns 684 int lband, ///< actual lower bandwidth, if banded 685 uband; ///< actual upper bandwidth, if banded 686 MatrixStructure structure; 687 MatrixStorage storage; 688 MatrixOutline outline; 689 MatrixCondition condition; 690 691 private: 692 // These are private because they don't set the outline as well. setSize(int m,int n)693 MatrixCharacter& setSize(int m, int n) 694 { assert(m>=0 && n>=0); nr = m; nc = n; return *this; } setNumRows(int m)695 MatrixCharacter& setNumRows(int m) 696 { assert(m>=0); nr = m; return *this; } setNumCols(int n)697 MatrixCharacter& setNumCols(int n) 698 { assert(n>=0); nc = n; return *this; } 699 }; 700 701 /// Output a textual description of a MatrixCharacter; handy for debugging. 702 /// @relates SimTK::MatrixCharacter 703 SimTK_SimTKCOMMON_EXPORT std::ostream& 704 operator<<(std::ostream& o, const MatrixCharacter&); 705 706 /// Predefined MatrixCharacter for an ordinary Lapack-style full matrix 707 /// of a particular dimension m x n (nrows X ncols). Note that the storage 708 /// format allows for a "leading dimension" larger than m, but that the 709 /// leading dimension is not considered part of the matrix character. It is 710 /// dealt with separately. 711 class MatrixCharacter::LapackFull : public MatrixCharacter { 712 public: LapackFull(int m,int n)713 LapackFull(int m, int n) 714 : MatrixCharacter(m,n,0,0, 715 MatrixStructure(MatrixStructure::Full), 716 MatrixStorage(MatrixStorage::Full,MatrixStorage::ColumnOrder), 717 MatrixCondition()) {} 718 }; 719 720 /// Predefined MatrixCharacter for an ordinary column vector of a particular 721 /// size. Note that standard vector storage allows for a "stride" greater than 722 /// 1, but that is not considered part of the matrix character. Stride is 723 /// dealt with separately. 724 class MatrixCharacter::Vector : public MatrixCharacter { 725 public: Vector(int m)726 Vector(int m) 727 : MatrixCharacter(m,1,0,0, 728 MatrixStructure(MatrixStructure::Matrix1d), 729 MatrixStorage(MatrixStorage::Vector,MatrixStorage::ColumnOrder), 730 MatrixCondition()) {} 731 }; 732 733 /// Predefined MatrixCharacter for an ordinary row vector of a particular 734 /// size. Note that standard vector storage allows for a "stride" greater than 735 /// 1, but that is not considered part of the matrix character. Stride is 736 /// dealt with separately. 737 class MatrixCharacter::RowVector : public MatrixCharacter { 738 public: RowVector(int n)739 RowVector(int n) 740 : MatrixCharacter(1,n,0,0, 741 MatrixStructure(MatrixStructure::Matrix1d), 742 MatrixStorage(MatrixStorage::Vector,MatrixStorage::RowOrder), 743 MatrixCondition()) {} 744 }; 745 746 // -------------------------- MatrixCharacter::Mask --------------------------- 747 /// This class collects masks of each characteristic type for representing sets 748 /// of accceptable characteristics. 749 // ---------------------------------------------------------------------------- 750 class MatrixCharacter::Mask { 751 public: Mask()752 Mask() {setToUncommitted();} 753 754 typedef unsigned int SizeMask; 755 static const SizeMask SizeUncommitted = 0xffffffffU; 756 isResizeable()757 bool isResizeable() const {return nr==SizeUncommitted || nc==SizeUncommitted;} isFullyResizeable()758 bool isFullyResizeable() const {return nr==SizeUncommitted && nc==SizeUncommitted;} isNumRowsLocked()759 bool isNumRowsLocked() const {return nr!=SizeUncommitted;} isNumColsLocked()760 bool isNumColsLocked() const {return nc!=SizeUncommitted;} 761 getNumRowsMask()762 unsigned int getNumRowsMask() const {return nr;} getNumColsMask()763 unsigned int getNumColsMask() const {return nc;} getLowerBandwidthMask()764 unsigned int getLowerBandwidthMask() const {return lband;} getUpperBandwidthMask()765 unsigned int getUpperBandwidthMask() const {return uband;} 766 getDefaultNumRows()767 int getDefaultNumRows() const {return isNumRowsLocked() ? nr : 0;} getDefaultNumCols()768 int getDefaultNumCols() const {return isNumColsLocked() ? nc : 0;} 769 isLowerBandwidthLocked()770 bool isLowerBandwidthLocked() const {return lband!=SizeUncommitted;} isUpperBandwidthLocked()771 bool isUpperBandwidthLocked() const {return uband!=SizeUncommitted;} getDefaultLowerBandwidth()772 int getDefaultLowerBandwidth() const {return isLowerBandwidthLocked() ? lband : 0;} getDefaultUpperBandwidth()773 int getDefaultUpperBandwidth() const {return isUpperBandwidthLocked() ? uband : 0;} 774 775 /// Set all bits to one ("Uncommitted"). setToUncommitted()776 Mask& setToUncommitted() { 777 nr=nc=lband=uband=SizeUncommitted; 778 structure.setToUncommitted(); storage.setToUncommitted(); 779 outline.setToUncommitted(); condition.setToUncommitted(); 780 return *this; 781 } 782 783 /// Return if all fields are set to "Uncommitted" (all bits are one). isUncommitted()784 bool isUncommitted() const { 785 return nr==SizeUncommitted && nc==SizeUncommitted 786 && lband==SizeUncommitted && uband==SizeUncommitted 787 && structure.isUncommitted() && storage.isUncommitted() 788 && outline.isUncommitted() && condition.isUncommitted(); 789 } 790 791 /// Check whether an actual matrix character satisfies this matrix commitment. isSatisfiedBy(const MatrixCharacter & actual)792 bool isSatisfiedBy(const MatrixCharacter& actual) const { 793 return isSizeOK(actual.nr, actual.nc) 794 && isBandwidthOK(actual.lband, actual.uband) 795 && structure.isSatisfiedBy(actual.getStructure()) 796 && storage.isSatisfiedBy(actual.getStorage()) 797 && outline.isSatisfiedBy(actual.getOutline()) 798 && condition.isSatisfiedBy(actual.getCondition()); 799 } 800 801 /// Check whether an actual size satisfies the size commitment. isSizeOK(int m,int n)802 bool isSizeOK(int m, int n) const 803 { return ((SizeMask)m & nr) == (SizeMask)m 804 && ((SizeMask)n & nc) == (SizeMask)n; } 805 806 /// Check whether an actual bandwidth satisfies the bandwidth commitment. 807 /// (If the matrix isn't banded any bandwidth will be OK.) isBandwidthOK(int lower,int upper)808 bool isBandwidthOK(int lower, int upper) const 809 { return ((SizeMask)lower & lband) == (SizeMask)lower 810 && ((SizeMask)upper & uband) == (SizeMask)upper; } 811 812 SizeMask nr, ///< number of rows 813 nc; ///< number of columns 814 SizeMask lband, ///< lower bandwidth, if banded 815 uband; ///< upper bandwidth, if banded 816 MatrixStructure::Mask structure; 817 MatrixStorage::Mask storage; 818 MatrixOutline::Mask outline; 819 MatrixCondition::Mask condition; 820 821 friend class MatrixCommitment; 822 }; 823 824 // ----------------------------- MatrixCommitment ----------------------------- 825 826 /// A MatrixCommitment provides a set of acceptable matrix characteristics. 827 /// Since we define the characteristics each with its own bit, a commitment 828 /// is implemented as a set of masks with bits set corresponding to the 829 /// acceptable characteristics. 830 831 // ---------------------------------------------------------------------------- 832 class SimTK_SimTKCOMMON_EXPORT MatrixCommitment { 833 public: MatrixCommitment()834 MatrixCommitment() {} // set commitments to "none" and masks to "uncommitted" 835 836 /// This is an implicit conversion from a MatrixStructure specification to 837 /// a MatrixCommitment with storage, outline, and condition uncommitted. MatrixCommitment(const MatrixStructure & str)838 MatrixCommitment(const MatrixStructure& str) 839 { new (this) MatrixCommitment(str, MatrixStorage(), MatrixOutline(), MatrixCondition());} 840 841 class Vector; 842 class RowVector; 843 class Triangular; 844 class Symmetric; 845 class Hermitian; 846 class SkewSymmetric; 847 class SkewHermitian; 848 commitSize(int m,int n)849 MatrixCommitment& commitSize(int m, int n) 850 { commitNumRows(m); commitNumCols(n); return *this; } commitNumRows(int m)851 MatrixCommitment& commitNumRows(int m) 852 { SimTK_SIZECHECK_NONNEG(m, "MatrixCommitment::commitNumRows()"); 853 masks.nr = m; return *this; } commitNumCols(int n)854 MatrixCommitment& commitNumCols(int n) 855 { SimTK_SIZECHECK_NONNEG(n, "MatrixCommitment::commitNumCols()"); 856 masks.nc = n; return *this; } 857 commitBandwidth(int lb,int ub)858 MatrixCommitment& commitBandwidth(int lb, int ub) 859 { commitLowerBandwidth(lb); commitUpperBandwidth(ub); return *this;} commitLowerBandwidth(int lb)860 MatrixCommitment& commitLowerBandwidth(int lb) 861 { SimTK_SIZECHECK_NONNEG(lb, "MatrixCommitment::commitLowerBandwidth()"); 862 masks.lband = lb; return *this; } commitUpperBandwidth(int ub)863 MatrixCommitment& commitUpperBandwidth(int ub) 864 { SimTK_SIZECHECK_NONNEG(ub, "MatrixCommitment::commitUpperBandwidth()"); 865 masks.uband = ub; return *this; } 866 commitStructure(const MatrixStructure & s)867 MatrixCommitment& commitStructure(const MatrixStructure& s) 868 { structure=s; masks.structure=s.mask(); return *this; } commitStorage(const MatrixStorage & s)869 MatrixCommitment& commitStorage (const MatrixStorage& s) 870 { storage=s; masks.storage =s.mask(); return *this; } commitOutline(const MatrixOutline & o)871 MatrixCommitment& commitOutline (const MatrixOutline& o) 872 { outline=o; masks.outline =o.mask(); return *this; } commitCondition(const MatrixCondition & c)873 MatrixCommitment& commitCondition(const MatrixCondition& c) 874 { condition=c; masks.condition=c.mask(); return *this; } 875 876 /// For any handle commitment, we can calculate a "best character" for 877 /// an allocation that satisfies the commitment, optionally with an 878 /// initial allocation size. Typically it is the least-restrictive 879 /// actual character that satisfies the commitment. For 880 /// example, if the commitment is Triangular we'll allocate a full triangular 881 /// matrix, not a banded one, or a symmetric one, or for that matter an 882 /// identity matrix, all of which would satisfy the commitment. 883 /// The supplied sizes are used as minima -- if the commitment requires 884 /// a larger minimum size you'll get that. For example, if you specify 885 /// 0x0 but you're committed to a Column outline, you'll get 0x1. 886 MatrixCharacter calcDefaultCharacter(int minNumRows, int minNumCols) const; 887 888 /// These report the commitment as it was specified. getStructureCommitment()889 const MatrixStructure& getStructureCommitment() const {return structure;} getStorageCommitment()890 const MatrixStorage& getStorageCommitment() const {return storage;} getOutlineCommitment()891 const MatrixOutline& getOutlineCommitment() const {return outline;} getConditionCommitment()892 const MatrixCondition& getConditionCommitment() const {return condition;} 893 894 /// These report the masks of acceptable values generated from the commitment. getStructureMask()895 const MatrixStructure::Mask& getStructureMask() const {return masks.structure;} getStorageMask()896 const MatrixStorage::Mask& getStorageMask() const {return masks.storage;} getOutlineMask()897 const MatrixOutline::Mask& getOutlineMask() const {return masks.outline;} getConditionMask()898 const MatrixCondition::Mask& getConditionMask() const {return masks.condition;} 899 getNumRowsMask()900 MatrixCharacter::Mask::SizeMask getNumRowsMask() const {return masks.nr;} getNumColsMask()901 MatrixCharacter::Mask::SizeMask getNumColsMask() const {return masks.nc;} getLowerBandwidthMask()902 MatrixCharacter::Mask::SizeMask getLowerBandwidthMask() const {return masks.lband;} getUpperBandwidthMask()903 MatrixCharacter::Mask::SizeMask getUpperBandwidthMask() const {return masks.uband;} 904 getDefaultNumRows()905 int getDefaultNumRows() const {return masks.getDefaultNumRows();} getDefaultNumCols()906 int getDefaultNumCols() const {return masks.getDefaultNumCols();} 907 isSizeOK(int m,int n)908 bool isSizeOK(int m, int n) const {return masks.isSizeOK(m,n);} isSizeOK(const std::pair<int,int> & mn)909 bool isSizeOK(const std::pair<int,int>& mn) const 910 { return isSizeOK(mn.first, mn.second); } 911 isBandwidthOK(int lower,int upper)912 bool isBandwidthOK(int lower, int upper) const {return masks.isBandwidthOK(lower,upper);} 913 isSatisfiedBy(const MatrixCharacter & actual)914 bool isSatisfiedBy(const MatrixCharacter& actual) const 915 { return masks.isSatisfiedBy(actual); } isStructureOK(const MatrixStructure & s)916 bool isStructureOK(const MatrixStructure& s) const 917 { return getStructureMask().isSatisfiedBy(s); } isStorageOK(const MatrixStorage & s)918 bool isStorageOK(const MatrixStorage& s) const 919 { return getStorageMask().isSatisfiedBy(s); } isOutlineOK(const MatrixOutline & o)920 bool isOutlineOK(const MatrixOutline& o) const 921 { return getOutlineMask().isSatisfiedBy(o); } isConditionOK(const MatrixCondition & c)922 bool isConditionOK(const MatrixCondition& c) const 923 { return getConditionMask().isSatisfiedBy(c); } 924 isResizeable()925 bool isResizeable() const {return masks.isResizeable();} isFullyResizeable()926 bool isFullyResizeable() const {return masks.isFullyResizeable();;} isNumRowsLocked()927 bool isNumRowsLocked() const {return masks.isNumRowsLocked();} isNumColsLocked()928 bool isNumColsLocked() const {return masks.isNumColsLocked();} 929 isStructureCommitted()930 bool isStructureCommitted() const 931 { return !getStructureMask().isUncommitted(); } isStorageCommitted()932 bool isStorageCommitted() const 933 { return !getStorageMask().isUncommitted();} isOutlineCommitted()934 bool isOutlineCommitted() const 935 { return !getOutlineMask().isUncommitted(); } isConditionCommitted()936 bool isConditionCommitted() const 937 { return !getConditionMask().isUncommitted();} 938 939 /// Set commitment s to "none" and masks to "uncommitted" for all characteristics. clear()940 void clear() { 941 structure.setToNone(); 942 storage.setToNone(); 943 outline.setToNone(); 944 condition.setToNone(); 945 masks.setToUncommitted(); 946 } 947 948 protected: MatrixCommitment(const MatrixStructure & structure,const MatrixStorage & storage,const MatrixOutline & outline,const MatrixCondition & condition)949 MatrixCommitment(const MatrixStructure& structure, 950 const MatrixStorage& storage, 951 const MatrixOutline& outline, 952 const MatrixCondition& condition) 953 : structure(structure), storage(storage), 954 outline(outline), condition(condition), 955 masks() // set to all 1's 956 { 957 if (outline.getOutline()==MatrixOutline::Scalar) commitSize(1,1); 958 else if (outline.getOutline()==MatrixOutline::Column) commitNumCols(1); 959 else if (outline.getOutline()==MatrixOutline::Row) commitNumRows(1); 960 961 masks.structure = structure.mask(); 962 masks.storage = storage.mask(); 963 masks.outline = outline.mask(); 964 masks.condition = condition.mask(); 965 } 966 967 /// These are the commitments as specified. They are used to fill in 968 /// the corresponding bitmasks of acceptable characteristics below. 969 MatrixStructure structure; 970 MatrixStorage storage; 971 MatrixOutline outline; 972 MatrixCondition condition; 973 974 /// These are the bitmasks of acceptable characteristics which 975 /// would satisfy the above-specified commitments. 976 MatrixCharacter::Mask masks; 977 }; 978 979 980 /// This is the default commitment for a column vector. 981 class MatrixCommitment::Vector : public MatrixCommitment { 982 public: 983 /// Commit to a resizeable column vector. Vector()984 Vector() 985 : MatrixCommitment 986 ( MatrixStructure(MatrixStructure::Matrix1d), 987 MatrixStorage(), 988 MatrixOutline(MatrixOutline::Column), 989 MatrixCondition()) 990 { 991 } 992 /// Commit to a column vector of a particular length. Vector(int m)993 explicit Vector(int m) 994 : MatrixCommitment 995 ( MatrixStructure(MatrixStructure::Matrix1d), 996 MatrixStorage(), 997 MatrixOutline(MatrixOutline::Column), 998 MatrixCondition()) 999 { 1000 commitNumRows(m); 1001 } 1002 }; 1003 1004 /// This is the default commitment for a row vector. 1005 class MatrixCommitment::RowVector : public MatrixCommitment { 1006 public: 1007 /// Commit to a resizeable row vector. RowVector()1008 RowVector() 1009 : MatrixCommitment 1010 ( MatrixStructure(MatrixStructure::Matrix1d), 1011 MatrixStorage(), 1012 MatrixOutline(MatrixOutline::Row), 1013 MatrixCondition()) 1014 { 1015 } 1016 /// Commit to a row vector of a particular length. RowVector(int n)1017 explicit RowVector(int n) 1018 : MatrixCommitment 1019 ( MatrixStructure(MatrixStructure::Matrix1d), 1020 MatrixStorage(), 1021 MatrixOutline(MatrixOutline::Row), 1022 MatrixCondition()) 1023 { 1024 commitNumCols(n); 1025 } 1026 }; 1027 1028 /// This is the default commitment for a triangular matrix. 1029 class MatrixCommitment::Triangular : public MatrixCommitment { 1030 public: Triangular()1031 Triangular() 1032 : MatrixCommitment(MatrixStructure::Triangular, MatrixStorage(), 1033 MatrixOutline(), MatrixCondition()) 1034 { 1035 } 1036 }; 1037 1038 /// This is the default commitment for a symmetric (*not* Hermitian) matrix. 1039 /// There are no restrictions on the underlying elements or diagonals. 1040 class MatrixCommitment::Symmetric : public MatrixCommitment { 1041 public: Symmetric()1042 Symmetric() 1043 : MatrixCommitment(MatrixStructure::Symmetric, MatrixStorage(), 1044 MatrixOutline(), MatrixCondition()) 1045 { 1046 } 1047 }; 1048 1049 /// This is the default commitment for a Hermitian (*not* symmetric) matrix. 1050 /// Diagonal elements must be real since they have to serve as their own 1051 /// conjugates. 1052 class MatrixCommitment::Hermitian : public MatrixCommitment { 1053 public: Hermitian()1054 Hermitian() 1055 : MatrixCommitment 1056 ( MatrixStructure::Hermitian, 1057 MatrixStorage(), 1058 MatrixOutline(), 1059 MatrixCondition().setDiagonal(MatrixCondition::RealDiagonal)) 1060 { 1061 } 1062 }; 1063 1064 /// This is the default commitment for skew symmetric (*not* skew Hermitian) 1065 /// matrix. Diagonal elements must be all-zero since they have to be their 1066 /// own negation. Otherwise any elements are acceptable. 1067 class MatrixCommitment::SkewSymmetric : public MatrixCommitment { 1068 public: SkewSymmetric()1069 SkewSymmetric() 1070 : MatrixCommitment 1071 ( MatrixStructure::SkewSymmetric, 1072 MatrixStorage(), 1073 MatrixOutline(), 1074 MatrixCondition().setDiagonal(MatrixCondition::ZeroDiagonal)) 1075 { 1076 } 1077 }; 1078 1079 /// This is the default commitment for a skew Hermitian (*not* skew symmetric) 1080 /// matrix. Diagonal elements must be pure imaginary since when conjugated they 1081 /// must be their own negation for a skew matrix. 1082 class MatrixCommitment::SkewHermitian : public MatrixCommitment { 1083 public: SkewHermitian()1084 SkewHermitian() 1085 : MatrixCommitment 1086 ( MatrixStructure::SkewHermitian, 1087 MatrixStorage(), 1088 MatrixOutline(), 1089 MatrixCondition().setDiagonal(MatrixCondition::ImaginaryDiagonal)) 1090 { 1091 } 1092 }; 1093 1094 /// Output a textual description of a MatrixCommitment; handy for debugging. 1095 /// @relates SimTK::MatrixCommitment 1096 SimTK_SimTKCOMMON_EXPORT std::ostream& 1097 operator<<(std::ostream& o, const MatrixCommitment&); 1098 1099 } //namespace SimTK 1100 1101 #endif // SimTK_SIMMATRIX_MATRIX_CHARACTERISTICS_H_ 1102