//------------------------------------------------------------------------------ // makeIdent (overloaded version) //------------------------------------------------------------------------------ bool Matrix::makeIdent(const unsigned int k) { if (k < 1) return false; setMatrix(k,k); makeIdent(); return true; }
// Returns a pre-ref'd pointer to the inverse of this matrix, or zero // if the matrix can not be inverted Matrix* Matrix::getInvLU() const { if (!isGoodMatrix() || !isSquare()) return nullptr; const unsigned int N = rows; const auto pL = new Matrix(N,N); const auto pU = new Matrix(N,N); getLU(pL, pU); const auto pB = new Matrix(N,N); pB->makeIdent(); const auto pY = new Matrix(N,N); const auto pX = new Matrix(N,N); //------------------------------------------------------- // find Y from LY = I using forward substitution //------------------------------------------------------- for (unsigned int i = 0; i < N; i++) { for (unsigned int j = 0; j < N; j++) { (*pY)(i,j) = (*pB)(i,j); for (unsigned int k = 0; k < i; k++) { (*pY)(i,j) -= (*pL)(i,k) * (*pY)(k,j); } } } //------------------------------------------------------- // find X from UX = Y using back substitution //------------------------------------------------------- for (int i = (N-1); i >= 0; i--) { for (unsigned int j = 0; j < N; j++) { (*pX)(i,j) = (*pY)(i,j); for (int k = (N-1); k > i; k--) { (*pX)(i,j) -= (*pU)(i,k) * (*pX)(k,j); } (*pX)(i,j) /= (*pU)(i,i); } } pL->unref(); pU->unref(); pB->unref(); pY->unref(); return pX; }
/* Appel: * tp [-option]* programme.txt * Les options doivent apparaitre avant le nom du fichier du programme. * Options: -[vV] -[hH?] */ int main(int argc, char **argv) { idents = NEW(TABSIZE, IdentS); /* liste des identificateurs */ int fi; int token; int i; for(i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'v': case 'V': verbose = TRUE; continue; case '?': case 'h': case 'H': help(); exit(1); default: fprintf(stderr, "Option inconnue: %c\n", argv[i][1]); exit(1); } } else break; } if (i == argc) { fprintf(stderr, "Erreur: Fichier programme manquant\n"); help(); exit(1); } if ((fi = open(argv[i++], O_RDONLY)) == -1) { fprintf(stderr, "Erreur: fichier inaccessible %s\n", argv[i-1]); help(); exit(1); } /* redirige l'entree standard sur le fichier... */ close(0); dup(fi); close(fi); while (1) { token = yylex(); switch (token) { case 0: /* EOF */ printf("Fin de l'analyse lexicale\n"); printf("Liste des identificateurs avec leur premiere occurrence:\n"); for (i = 0; i < nbIdent; i++) printf("ligne %d : %s\n", idents[i].line, idents[i].id); printf("Nombre d'identificateurs: %4d\n", nbIdent); return 0; case CID: makeIdent(yylineno, yylval.S); if (verbose) printf("Nom de classe:\t\t%s\n", yylval.S); break; case ID: makeIdent(yylineno, yylval.S); if (verbose) printf("Identificateur:\t\t%s\n", yylval.S); break; case INT: /* ici on suppose qu'on a recupere la valeur de la constante, pas sa * representation sous forme de chaine de caracteres. */ printf("Constante:\t\t%d\n", yylval.I); break; case STR: printf("Chaine:\t\t\t'%s'\n", yylval.S); break; case ASSIGN: printf("Affectation\t\t:=\n"); break; case CLASS: case EXT: case DEF: case OVERRIDE: case IS: case VAR: case IF: case THEN: case ELSE: case YIELD: case RET: case NEW: if (verbose) printf("Mot-clef:\t\t%s\n", yytext); break; case '(': case ')': case ',': case '.': case ':': if (verbose) printf("Symbole:\t\t%s\n", yytext); break; case'{': case '}': case ';': if (verbose) printf("Symbole:\t\t%s\n\n", yytext); break; case ADD: case SUB: case MUL: case DIV: if (verbose) printf("Oper arithmetique:\t%s\n", yytext); break; case RELOP: /* inutilement complique ici, mais sert a illustrer la difference * entre le token et l'infirmation supplementaire qu'on peut associer * via la valeur. */ if (verbose) { printf("Operateur de comparaison:\t%s\n", yytext); switch(yylval.C) { case EQ: case NE: case LT: case GT: case LTE: case GTE: break; default: printf("operateur inconnu de code: %d\n", yylval.C); } } break; default: printf("Token non reconnu:\t\"%d\"\n", token); } } }
//------------------------------------------------------------------------------ // getTriDiagonal //------------------------------------------------------------------------------ bool Matrix::getTriDiagonal(Matrix* const pA) const { //------------------------------------------------------- // initial compatibility and error checks //------------------------------------------------------- //if (!isSymmetric()) return 0; const int N = getRows(); const auto pAI = new Matrix(*this); for (int k=0; k<N-2; k++) { double gama = (*pAI)(k+1,k); double alfa = (gama * gama); for (int j=k+2; j<N; j++) { double zeta = (*pAI)(j,k); alfa += (zeta * zeta); } alfa = -sign(gama) * std::sqrt(alfa); double beta = std::sqrt(0.5 * alfa * (alfa - gama)); //---------------------------------------------------- // construct column vector X //---------------------------------------------------- const auto pX = new CVector(N); for (int p=0; p<k+1; p++) { (*pX)[p] = 0.0; } (*pX)[k+1] = (gama - alfa) / beta / 2.0; for (int q=k+2; q<N; q++) { (*pX)[q] = (*pAI)(q,k) / beta / 2.0; } //---------------------------------------------------- // construct row vector Y = X' //---------------------------------------------------- RVector* pY = pX->getTranspose(); //---------------------------------------------------- // M = 2*X*Y = 2*X*X' //---------------------------------------------------- Matrix* pM = outerProduct(*pX, *pY); pM->multiply(2.0); //---------------------------------------------------- // H = I - M = I - 2*X*X' //---------------------------------------------------- const auto pH = new Matrix(N,N); pH->makeIdent(); pH->subtract(*pM); //---------------------------------------------------- // A = H*A*H //---------------------------------------------------- Matrix* pAI0 = base::multiply(*pH, *pAI); Matrix* pAI1 = base::multiply(*pAI0, *pH); *pAI = *pAI1; //---------------------------------------------------- // unref intermediate loop pointers //---------------------------------------------------- pX->unref(); pY->unref(); pM->unref(); pH->unref(); pAI0->unref(); pAI1->unref(); } //------------------------------------------------------- // A = H(N-3)*...*H1*H0* A *H0*H1*...*H(N-3) //------------------------------------------------------- *pA = *pAI; //---------------------------------------------------- // unref pointers //---------------------------------------------------- pAI->unref(); return true; }
//------------------------------------------------------------------------------ // getQR // Returns pre-ref'd pointers to the lower QR (pQ) and upper QR (pR) matrices // of 'this' matrix, or zero if the matrix can not be QR-ized //------------------------------------------------------------------------------ bool Matrix::getQR(Matrix* const pQ, Matrix* const pR) const { //------------------------------------------------------- // initial compatibility and error checks //------------------------------------------------------- bool b1 = isGoodMatrix(); bool b2 = isSquare(); if (!b1 || !b2) return false; //------------------------------------------------------- // Initialize intermediate R matrix to 'this' matrix //------------------------------------------------------- const auto pRI = new Matrix(*this); //------------------------------------------------------- // Initialize intermediate Q matrix to 'identity' matrix //------------------------------------------------------- const int N = getRows(); const auto pQI = new Matrix(N,N); pQI->makeIdent(); //------------------------------------------------------- // X and V are intermediate vectors //------------------------------------------------------- const auto pX = new CVector(N); const auto pV = new CVector(N); //------------------------------------------------------- // Begin loop //------------------------------------------------------- for (int k = 0; k < N-1; k++) { pX->fillWith(0.0); for (int i = k; i<N ; i++) { (*pX)[i] = (*pRI)(i,k); } double g = pX->getNorm(); (*pV) = (*pX); (*pV)[k] += g; double s = pV->getNorm(); if (s == 0.0) { pQI->unref(); pRI->unref(); pX->unref(); pV->unref(); return false; } CVector* pW = base::multiply((*pV), 1.0/s); RVector* pWT = pW->getTranspose(); { //---------------------------------------------------- // U' = (2*R'*W)' //---------------------------------------------------- Matrix* pRIT = pRI->getTranspose(); CVector* pU0 = base::multiply((*pRIT), (*pW)); CVector* pU = base::multiply((*pU0), 2.0); RVector* pUT = pU->getTranspose(); pU0->unref(); pU->unref(); pRIT->unref(); //---------------------------------------------------- // R = R - W*U' //---------------------------------------------------- Matrix* pM1 = outerProduct(*pW, *pUT); pRI->subtract(*pM1); pM1->unref(); pUT->unref(); } //---------------------------------------------------- // Q = Q - 2*Q*W*W' //---------------------------------------------------- { Matrix* pM2 = outerProduct(*pW, *pWT); Matrix* pM3 = base::multiply(*pQI, *pM2); Matrix* pM4 = base::multiply(*pM3, 2.0); pQI->subtract(*pM4); pM2->unref(); pM3->unref(); pM4->unref(); } //------------------------------------------------------- // Unref pointers //------------------------------------------------------- pW->unref(); pWT->unref(); } //------------------------------------------------------- // Assign results to argument list variables for output //------------------------------------------------------- *pQ = *pQI; *pR = *pRI; //------------------------------------------------------- // Unref pointers //------------------------------------------------------- pQI->unref(); pRI->unref(); pX->unref(); pV->unref(); return true; }
/* Appel: * tp [-option]* programme.txt * Les options doivent apparaitre avant le nom du fichier du programme. * Options: -[vV] -[hH?] */ int main(int argc, char **argv) { idents = NEW(1000, IdentS); /* liste des identificateurs */ int fi; int token; int i; for(i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'v': case 'V': verbose = TRUE; continue; case '?': case 'h': case 'H': help(); exit(1); default: fprintf(stderr, "Option inconnue: %c\n", argv[i][1]); exit(1); } } else break; } if (i == argc) { fprintf(stderr, "Erreur: Fichier programme manquant\n"); help(); exit(1); } if ((fi = open(argv[i++], O_RDONLY)) == -1) { fprintf(stderr, "Erreur: fichier inaccessible %s\n", argv[i-1]); help(); exit(1); } /* redirige l'entree standard sur le fichier... */ close(0); dup(fi); close(fi); while (1) { token = yylex(); switch (token) { case 0: printf("Fin de l'analyse lexicale\n"); printf("Liste des identificateurs avec leur premiere occurrence:\n"); for (i = 0; i < nbIdent; i++) { printf("ligne %d : %s\n", idents[i].line, idents[i].id); } printf("Nombre d'identificateurs: %4d\n", nbIdent); return 0; case ID: makeIdent(yylineno, yylval.S); if (verbose) printf("Identificateur:\t\t%s\n", yylval.S); break; case STR: if (verbose) printf("String:\t\t\t%s\n", yylval.S); break; case NOM: makeIdent(yylineno, yylval.S); if (verbose) printf("Nom de classe:\t\t%s\n", yylval.S); break; case CST: if (verbose) printf("Constante:\t\t%d\n", yylval.I); break; case '(': case ')': case ';': case ',': case '{': case '}': case '|': case ':': case '.': case '"': if (verbose) printf("Symbole (%d):\t\t%s\n", token, yytext); break; case IF: case THEN: case ELSE: case AFF: case VAR: case IS: case FINAL: case DEF: case CLASS: case STATIC: case RETURNS: case YIELD: case CONCAT : case SUPER : case OVERRIDE : case WHILE : case DO : case NEW : case THIS : case EXTENDS : if (verbose) printf("Mot clé (%d):\t\t%s\n",token, yytext); break; case '!' : if (verbose) printf("Symbole interdit (%d):\t\t%s\n",token, yytext); break; /* remarque : l'analyse lexicale ne peut pas distinguer les + et - binaires * de leurs homologues binaires. Ci-dessous on ne peut recevoir que ADD ou SUB */ case ADD: case SUB: case DIV: case MUL: if (verbose) printf("Oper arithmetique (%d):\t%s\n", token, yytext); break; case RELOP: /* inutilement complique ici, mais sert a illustrer la difference * entre le token et l'information supplementaire qu'on peut associer * via la valeur. */ if (verbose) { printf("Oper de comparaison:\t%s ", yytext); switch(yylval.C) { case EQ: printf("egalite\n"); break; case NE: printf("non egalite\n"); break; case GT: printf("superieur strict\n"); break; case GE: printf("superieur ou egal\n"); break; case LT: printf("inferieur strict\n"); break; case LE: printf("inferieur ou egal\n"); break; default: printf("Unexpected code: %d\n", yylval.C); } } break; default: printf("Token non reconnu:\t %d,%s \n", token, yytext); } } }