| 1 | //$$ newmat1.cpp   Matrix type functions | 
|---|
| 2 |  | 
|---|
| 3 | // Copyright (C) 1991,2,3,4: R B Davies | 
|---|
| 4 |  | 
|---|
| 5 | //#define WANT_STREAM | 
|---|
| 6 |  | 
|---|
| 7 | #include "newmat.h" | 
|---|
| 8 |  | 
|---|
| 9 | #ifdef use_namespace | 
|---|
| 10 | namespace NEWMAT { | 
|---|
| 11 | #endif | 
|---|
| 12 |  | 
|---|
| 13 | #ifdef DO_REPORT | 
|---|
| 14 | #define REPORT { static ExeCounter ExeCount(__LINE__,1); ++ExeCount; } | 
|---|
| 15 | #else | 
|---|
| 16 | #define REPORT {} | 
|---|
| 17 | #endif | 
|---|
| 18 |  | 
|---|
| 19 |  | 
|---|
| 20 | /************************* MatrixType functions *****************************/ | 
|---|
| 21 |  | 
|---|
| 22 |  | 
|---|
| 23 | // all operations to return MatrixTypes which correspond to valid types | 
|---|
| 24 | // of matrices. | 
|---|
| 25 | // Eg: if it has the Diagonal attribute, then it must also have | 
|---|
| 26 | // Upper, Lower, Band and Symmetric. | 
|---|
| 27 |  | 
|---|
| 28 |  | 
|---|
| 29 | MatrixType MatrixType::operator*(const MatrixType& mt) const | 
|---|
| 30 | { | 
|---|
| 31 |    REPORT | 
|---|
| 32 |    int a = attribute & mt.attribute & ~Symmetric; | 
|---|
| 33 |    a |= (a & Diagonal) * 31;                   // recognise diagonal | 
|---|
| 34 |    return MatrixType(a); | 
|---|
| 35 | } | 
|---|
| 36 |  | 
|---|
| 37 | MatrixType MatrixType::SP(const MatrixType& mt) const | 
|---|
| 38 | // elementwise product | 
|---|
| 39 | // Lower, Upper, Diag, Band if only one is | 
|---|
| 40 | // Symmetric, Ones, Valid (and Real) if both are | 
|---|
| 41 | // Need to include Lower & Upper => Diagonal | 
|---|
| 42 | // Will need to include both Skew => Symmetric | 
|---|
| 43 | { | 
|---|
| 44 |    REPORT | 
|---|
| 45 |    int a = ((attribute | mt.attribute) & ~(Symmetric + Valid + Ones)) | 
|---|
| 46 |       | (attribute & mt.attribute); | 
|---|
| 47 |    if ((a & Lower) != 0  &&  (a & Upper) != 0) a |= Diagonal; | 
|---|
| 48 |    a |= (a & Diagonal) * 31;                   // recognise diagonal | 
|---|
| 49 |    return MatrixType(a); | 
|---|
| 50 | } | 
|---|
| 51 |  | 
|---|
| 52 | MatrixType MatrixType::KP(const MatrixType& mt) const | 
|---|
| 53 | // Kronecker product | 
|---|
| 54 | // Lower, Upper, Diag, Symmetric, Band, Valid if both are | 
|---|
| 55 | // Do not treat Band separately | 
|---|
| 56 | // Ones is complicated so leave this out | 
|---|
| 57 | { | 
|---|
| 58 |    REPORT | 
|---|
| 59 |    int a = (attribute & mt.attribute) & ~Ones; | 
|---|
| 60 |    return MatrixType(a); | 
|---|
| 61 | } | 
|---|
| 62 |  | 
|---|
| 63 | MatrixType MatrixType::i() const               // type of inverse | 
|---|
| 64 | { | 
|---|
| 65 |    REPORT | 
|---|
| 66 |    int a = attribute & ~(Band+LUDeco); | 
|---|
| 67 |    a |= (a & Diagonal) * 31;                   // recognise diagonal | 
|---|
| 68 |    return MatrixType(a); | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | MatrixType MatrixType::t() const | 
|---|
| 72 | // swap lower and upper attributes | 
|---|
| 73 | // assume Upper is in bit above Lower | 
|---|
| 74 | { | 
|---|
| 75 |    REPORT | 
|---|
| 76 |    int a = attribute; | 
|---|
| 77 |    a ^= (((a >> 1) ^ a) & Lower) * 3; | 
|---|
| 78 |    return MatrixType(a); | 
|---|
| 79 | } | 
|---|
| 80 |  | 
|---|
| 81 | MatrixType MatrixType::MultRHS() const | 
|---|
| 82 | { | 
|---|
| 83 |    REPORT | 
|---|
| 84 |    // remove symmetric attribute unless diagonal | 
|---|
| 85 |    return (attribute >= Dg) ? attribute : (attribute & ~Symmetric); | 
|---|
| 86 | } | 
|---|
| 87 |  | 
|---|
| 88 | bool Rectangular(MatrixType a, MatrixType b, MatrixType c) | 
|---|
| 89 | { | 
|---|
| 90 |    REPORT | 
|---|
| 91 |    return | 
|---|
| 92 |       ((a.attribute | b.attribute | c.attribute) & ~MatrixType::Valid) == 0; | 
|---|
| 93 | } | 
|---|
| 94 |  | 
|---|
| 95 | const char* MatrixType::Value() const | 
|---|
| 96 | { | 
|---|
| 97 | // make a string with the name of matrix with the given attributes | 
|---|
| 98 |    switch (attribute) | 
|---|
| 99 |    { | 
|---|
| 100 |    case Valid:                              REPORT return "Rect "; | 
|---|
| 101 |    case Valid+Symmetric:                    REPORT return "Sym  "; | 
|---|
| 102 |    case Valid+Band:                         REPORT return "Band "; | 
|---|
| 103 |    case Valid+Symmetric+Band:               REPORT return "SmBnd"; | 
|---|
| 104 |    case Valid+Upper:                        REPORT return "UT   "; | 
|---|
| 105 |    case Valid+Diagonal+Symmetric+Band+Upper+Lower: | 
|---|
| 106 |                                             REPORT return "Diag "; | 
|---|
| 107 |    case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones: | 
|---|
| 108 |                                             REPORT return "Ident"; | 
|---|
| 109 |    case Valid+Band+Upper:                   REPORT return "UpBnd"; | 
|---|
| 110 |    case Valid+Lower:                        REPORT return "LT   "; | 
|---|
| 111 |    case Valid+Band+Lower:                   REPORT return "LwBnd"; | 
|---|
| 112 |    default: | 
|---|
| 113 |       REPORT | 
|---|
| 114 |       if (!(attribute & Valid))             return "UnSp "; | 
|---|
| 115 |       if (attribute & LUDeco) | 
|---|
| 116 |          return (attribute & Band) ?     "BndLU" : "Crout"; | 
|---|
| 117 |                                             return "?????"; | 
|---|
| 118 |    } | 
|---|
| 119 | } | 
|---|
| 120 |  | 
|---|
| 121 |  | 
|---|
| 122 | GeneralMatrix* MatrixType::New(int nr, int nc, BaseMatrix* bm) const | 
|---|
| 123 | { | 
|---|
| 124 | // make a new matrix with the given attributes | 
|---|
| 125 |  | 
|---|
| 126 |    Tracer tr("New"); GeneralMatrix* gm=0;   // initialised to keep gnu happy | 
|---|
| 127 |    switch (attribute) | 
|---|
| 128 |    { | 
|---|
| 129 |    case Valid: | 
|---|
| 130 |       REPORT | 
|---|
| 131 |       if (nc==1) { gm = new ColumnVector(nr); break; } | 
|---|
| 132 |       if (nr==1) { gm = new RowVector(nc); break; } | 
|---|
| 133 |       gm = new Matrix(nr, nc); break; | 
|---|
| 134 |  | 
|---|
| 135 |    case Valid+Symmetric: | 
|---|
| 136 |       REPORT gm = new SymmetricMatrix(nr); break; | 
|---|
| 137 |  | 
|---|
| 138 |    case Valid+Band: | 
|---|
| 139 |       { | 
|---|
| 140 |          REPORT | 
|---|
| 141 |          MatrixBandWidth bw = bm->BandWidth(); | 
|---|
| 142 |          gm = new BandMatrix(nr,bw.lower,bw.upper); break; | 
|---|
| 143 |       } | 
|---|
| 144 |  | 
|---|
| 145 |    case Valid+Symmetric+Band: | 
|---|
| 146 |       REPORT gm = new SymmetricBandMatrix(nr,bm->BandWidth().lower); break; | 
|---|
| 147 |  | 
|---|
| 148 |    case Valid+Upper: | 
|---|
| 149 |       REPORT gm = new UpperTriangularMatrix(nr); break; | 
|---|
| 150 |  | 
|---|
| 151 |    case Valid+Diagonal+Symmetric+Band+Upper+Lower: | 
|---|
| 152 |       REPORT gm = new DiagonalMatrix(nr); break; | 
|---|
| 153 |  | 
|---|
| 154 |    case Valid+Band+Upper: | 
|---|
| 155 |       REPORT gm = new UpperBandMatrix(nr,bm->BandWidth().upper); break; | 
|---|
| 156 |  | 
|---|
| 157 |    case Valid+Lower: | 
|---|
| 158 |       REPORT gm = new LowerTriangularMatrix(nr); break; | 
|---|
| 159 |  | 
|---|
| 160 |    case Valid+Band+Lower: | 
|---|
| 161 |       REPORT gm = new LowerBandMatrix(nr,bm->BandWidth().lower); break; | 
|---|
| 162 |  | 
|---|
| 163 |    case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones: | 
|---|
| 164 |       REPORT gm = new IdentityMatrix(nr); break; | 
|---|
| 165 |  | 
|---|
| 166 |    default: | 
|---|
| 167 |       Throw(ProgramException("Invalid matrix type")); | 
|---|
| 168 |    } | 
|---|
| 169 |     | 
|---|
| 170 |    MatrixErrorNoSpace(gm); gm->Protect(); return gm; | 
|---|
| 171 | } | 
|---|
| 172 |  | 
|---|
| 173 |  | 
|---|
| 174 | #ifdef use_namespace | 
|---|
| 175 | } | 
|---|
| 176 | #endif | 
|---|
| 177 |  | 
|---|