/* ================================================================================ RPL/2 (R) version 4.1.1 Copyright (C) 1989-2011 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl-conv.h" /* ================================================================================ Fonction réalisation la factorisation de Schur d'une matrice carrée ================================================================================ Entrées : struct_matrice -------------------------------------------------------------------------------- Sorties : décomposition de Schur de la matrice d'entrée et drapeau d'erreur. La matrice en entrée est écrasée. La matrice de sortie est la forme de Schur. La routine renvoie aussi une matrice de complexes correspondant aux vecteurs de Schur. Cette matrice est allouée par la routine et vaut NULL sinon. -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void factorisation_schur(struct_processus *s_etat_processus, struct_matrice *s_matrice, struct_matrice **s_schur) { complex16 *w; integer4 info; integer4 lwork; integer4 nombre_colonnes_a; integer4 nombre_lignes_a; integer4 sdim; real8 *rwork; real8 *wi; real8 *wr; unsigned char calcul_vecteurs_schur; unsigned char tri_vecteurs_schur; unsigned long i; unsigned long j; unsigned long k; unsigned long taille_matrice_f77; void *matrice_a_f77; void *matrice_vs_f77; void *tampon; void *work; nombre_lignes_a = (integer4) (*s_matrice).nombre_lignes; nombre_colonnes_a = (integer4) (*s_matrice).nombre_colonnes; taille_matrice_f77 = nombre_lignes_a * nombre_colonnes_a; calcul_vecteurs_schur = 'V'; tri_vecteurs_schur = 'N'; switch((*s_matrice).type) { case 'I' : { /* Conversion de la matrice en matrice réelle */ for(i = 0; i < (unsigned long) nombre_lignes_a; i++) { tampon = (*s_matrice).tableau[i]; if ((((real8 **) (*s_matrice).tableau)[i] = (real8 *) malloc(nombre_colonnes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(j = 0; j < (unsigned long) nombre_colonnes_a; j++) { ((real8 **) (*s_matrice).tableau)[i][j] = ((integer8 *) tampon)[j]; } free(tampon); } (*s_matrice).type = 'R'; } case 'R' : { if ((matrice_a_f77 = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((matrice_vs_f77 = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((real8 *) matrice_a_f77)[k++] = ((real8 **) (*s_matrice).tableau)[j][i]; } } if ((wr = (real8 *) malloc(nombre_lignes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((wi = (real8 *) malloc(nombre_lignes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } lwork = -1; if ((work = (real8 *) malloc(sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } dgees_(&calcul_vecteurs_schur, &tri_vecteurs_schur, NULL, &nombre_lignes_a, matrice_a_f77, &nombre_colonnes_a, &sdim, wr, wi, matrice_vs_f77, &nombre_colonnes_a, work, &lwork, NULL, &info, 1, 1); lwork = ((real8 *) work)[0]; free(work); if ((work = (real8 *) malloc(lwork * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } dgees_(&calcul_vecteurs_schur, &tri_vecteurs_schur, NULL, &nombre_lignes_a, matrice_a_f77, &nombre_colonnes_a, &sdim, wr, wi, matrice_vs_f77, &nombre_colonnes_a, work, &lwork, NULL, &info, 1, 1); free(work); free(wr); free(wi); if (info != 0) { if (info > 0) { (*s_etat_processus).exception = d_ep_decomposition_QR; } else { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; } free(matrice_a_f77); free(matrice_vs_f77); return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((real8 **) (*s_matrice).tableau)[j][i] = ((real8 *) matrice_a_f77)[k++]; } } (**s_schur).nombre_colonnes = (*s_matrice).nombre_colonnes; (**s_schur).nombre_lignes = (*s_matrice).nombre_lignes; (**s_schur).type = 'R'; if (((**s_schur).tableau = malloc((**s_schur) .nombre_lignes * sizeof(real8 *))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(i = 0; i < (**s_schur).nombre_lignes; i++) { if ((((real8 **) (**s_schur).tableau)[i] = (real8 *) malloc((**s_schur).nombre_colonnes * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } } for(k = 0, i = 0; i < (**s_schur).nombre_colonnes; i++) { for(j = 0; j < (**s_schur).nombre_lignes; j++) { ((real8 **) (**s_schur).tableau)[j][i] = ((real8 *) matrice_vs_f77)[k++]; } } free(matrice_a_f77); free(matrice_vs_f77); break; } case 'C' : { if ((matrice_a_f77 = (void *) malloc(taille_matrice_f77 * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((matrice_vs_f77 = (void *) malloc(taille_matrice_f77 * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((complex16 *) matrice_a_f77)[k].partie_reelle = ((complex16 **) (*s_matrice).tableau)[j][i] .partie_reelle; ((complex16 *) matrice_a_f77)[k++].partie_imaginaire = ((complex16 **) (*s_matrice).tableau)[j][i] .partie_imaginaire; } } if ((w = (complex16 *) malloc(nombre_lignes_a * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } lwork = -1; if ((work = (complex16 *) malloc(sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((rwork = (real8 *) malloc(nombre_lignes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } zgees_(&calcul_vecteurs_schur, &tri_vecteurs_schur, NULL, &nombre_lignes_a, matrice_a_f77, &nombre_colonnes_a, &sdim, w, matrice_vs_f77, &nombre_colonnes_a, work, &lwork, rwork, NULL, &info, 1, 1); lwork = ((complex16 *) work)[0].partie_reelle; free(work); if ((work = (complex16 *) malloc(lwork * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } zgees_(&calcul_vecteurs_schur, &tri_vecteurs_schur, NULL, &nombre_lignes_a, matrice_a_f77, &nombre_colonnes_a, &sdim, w, matrice_vs_f77, &nombre_colonnes_a, work, &lwork, rwork, NULL, &info, 1, 1); free(work); free(rwork); free(w); if (info != 0) { if (info > 0) { (*s_etat_processus).exception = d_ep_decomposition_QR; } else { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; } free(matrice_a_f77); free(matrice_vs_f77); return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((complex16 **) (*s_matrice).tableau)[j][i] .partie_reelle = ((complex16 *) matrice_a_f77)[k] .partie_reelle; ((complex16 **) (*s_matrice).tableau)[j][i] .partie_imaginaire = ((complex16 *) matrice_a_f77) [k++].partie_imaginaire; } } (**s_schur).nombre_colonnes = (*s_matrice).nombre_colonnes; (**s_schur).nombre_lignes = (*s_matrice).nombre_lignes; (**s_schur).type = 'C'; if (((**s_schur).tableau = malloc((**s_schur) .nombre_lignes * sizeof(complex16 *))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(i = 0; i < (**s_schur).nombre_lignes; i++) { if ((((complex16 **) (**s_schur).tableau)[i] = (complex16 *) malloc((**s_schur).nombre_colonnes * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } } for(k = 0, i = 0; i < (**s_schur).nombre_colonnes; i++) { for(j = 0; j < (**s_schur).nombre_lignes; j++) { ((complex16 **) (**s_schur).tableau)[j][i].partie_reelle = ((complex16 *) matrice_vs_f77)[k].partie_reelle; ((complex16 **) (**s_schur).tableau)[j][i] .partie_imaginaire = ((complex16 *) matrice_vs_f77) [k++].partie_imaginaire; } } free(matrice_a_f77); free(matrice_vs_f77); break; } } return; } /* ================================================================================ Fonction réalisation la factorisation LQ d'une matrice quelconque ================================================================================ Entrées : struct_matrice -------------------------------------------------------------------------------- Sorties : décomposition de LQ de la matrice d'entrée. Le tableau tau est initialisé par la fonction -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void factorisation_lq(struct_processus *s_etat_processus, struct_matrice *s_matrice, void **tau) { integer4 nombre_colonnes_a; integer4 nombre_lignes_a; integer4 erreur; unsigned long i; unsigned long j; unsigned long k; unsigned long taille_matrice_f77; void *matrice_a_f77; void *tampon; void *work; nombre_lignes_a = (integer4) (*s_matrice).nombre_lignes; nombre_colonnes_a = (integer4) (*s_matrice).nombre_colonnes; taille_matrice_f77 = nombre_lignes_a * nombre_colonnes_a; switch((*s_matrice).type) { case 'I' : { /* Conversion de la matrice en matrice réelle */ for(i = 0; i < (unsigned long) nombre_lignes_a; i++) { tampon = (*s_matrice).tableau[i]; if ((((real8 **) (*s_matrice).tableau)[i] = (real8 *) malloc(nombre_colonnes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(j = 0; j < (unsigned long) nombre_colonnes_a; j++) { ((real8 **) (*s_matrice).tableau)[i][j] = ((integer8 *) tampon)[j]; } free(tampon); } (*s_matrice).type = 'R'; } case 'R' : { if ((matrice_a_f77 = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (((*tau) = malloc(((nombre_colonnes_a < nombre_lignes_a) ? nombre_colonnes_a : nombre_lignes_a) * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((work = malloc(nombre_lignes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((real8 *) matrice_a_f77)[k++] = ((real8 **) (*s_matrice).tableau)[j][i]; } } dgelq2_(&nombre_lignes_a, &nombre_colonnes_a, matrice_a_f77, &nombre_lignes_a, (*((real8 **) tau)), work, &erreur); if (erreur != 0) { // L'erreur ne peut être que négative. (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(work); free(matrice_a_f77); return; } for(k = 0, i = 0; i < (unsigned long) nombre_colonnes_a; i++) { for(j = 0; j < (unsigned long) nombre_lignes_a; j++) { ((real8 **) (*s_matrice).tableau)[j][i] = ((real8 *) matrice_a_f77)[k++]; } } free(work); free(matrice_a_f77); break; } case 'C' : { if ((matrice_a_f77 = (void *) malloc(taille_matrice_f77 * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (((*tau) = malloc(((nombre_colonnes_a < nombre_lignes_a) ? nombre_colonnes_a : nombre_lignes_a) * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((work = malloc(nombre_lignes_a * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((complex16 *) matrice_a_f77)[k].partie_reelle = ((complex16 **) (*s_matrice).tableau)[j][i] .partie_reelle; ((complex16 *) matrice_a_f77)[k++].partie_imaginaire = ((complex16 **) (*s_matrice).tableau)[j][i] .partie_imaginaire; } } zgelq2_(&nombre_lignes_a, &nombre_colonnes_a, matrice_a_f77, &nombre_lignes_a, (*((complex16 **) tau)), work, &erreur); if (erreur != 0) { // L'erreur ne peut être que négative. (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(work); free(matrice_a_f77); return; } for(k = 0, i = 0; i < (unsigned long) nombre_colonnes_a; i++) { for(j = 0; j < (unsigned long) nombre_lignes_a; j++) { ((complex16 **) (*s_matrice).tableau)[j][i].partie_reelle = ((complex16 *) matrice_a_f77)[k].partie_reelle; ((complex16 **) (*s_matrice).tableau)[j][i] .partie_imaginaire = ((complex16 *) matrice_a_f77) [k++].partie_imaginaire; } } free(work); free(matrice_a_f77); break; } } return; } /* ================================================================================ Fonction réalisation la factorisation QR d'une matrice quelconque ================================================================================ Entrées : struct_matrice -------------------------------------------------------------------------------- Sorties : décomposition de QR de la matrice d'entrée. Le tableau tau est initialisé par la fonction -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void factorisation_qr(struct_processus *s_etat_processus, struct_matrice *s_matrice, void **tau) { integer4 lwork; integer4 nombre_colonnes_a; integer4 nombre_lignes_a; integer4 erreur; integer4 *pivot; real8 *rwork; unsigned long i; unsigned long j; unsigned long k; unsigned long taille_matrice_f77; void *matrice_a_f77; void *registre; void *tampon; void *work; nombre_lignes_a = (integer4) (*s_matrice).nombre_lignes; nombre_colonnes_a = (integer4) (*s_matrice).nombre_colonnes; taille_matrice_f77 = nombre_lignes_a * nombre_colonnes_a; switch((*s_matrice).type) { case 'I' : { /* Conversion de la matrice en matrice réelle */ for(i = 0; i < (unsigned long) nombre_lignes_a; i++) { tampon = (*s_matrice).tableau[i]; if ((((real8 **) (*s_matrice).tableau)[i] = (real8 *) malloc(nombre_colonnes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(j = 0; j < (unsigned long) nombre_colonnes_a; j++) { ((real8 **) (*s_matrice).tableau)[i][j] = ((integer8 *) tampon)[j]; } free(tampon); } (*s_matrice).type = 'R'; } case 'R' : { if ((matrice_a_f77 = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (((*tau) = malloc(((nombre_colonnes_a < nombre_lignes_a) ? nombre_colonnes_a : nombre_lignes_a) * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((real8 *) matrice_a_f77)[k++] = ((real8 **) (*s_matrice).tableau)[j][i]; } } if ((pivot = malloc(nombre_colonnes_a * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(i = 0; i < (unsigned long) nombre_colonnes_a; pivot[i++] = 0); lwork = -1; if ((work = malloc(sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } // Calcul de la taille de l'espace dgeqp3_(&nombre_lignes_a, &nombre_colonnes_a, matrice_a_f77, &nombre_lignes_a, pivot, (*((real8 **) tau)), work, &lwork, &erreur); lwork = ((real8 *) work)[0]; free(work); if ((work = malloc(lwork * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } // Calcul de la permutation if ((registre = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } memcpy(registre, matrice_a_f77, taille_matrice_f77 * sizeof(real8)); dgeqp3_(&nombre_lignes_a, &nombre_colonnes_a, registre, &nombre_lignes_a, pivot, (*((real8 **) tau)), work, &lwork, &erreur); free(registre); if (erreur != 0) { // L'erreur ne peut être que négative. (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(work); free(matrice_a_f77); free(tau); return; } // La permutation doit maintenant être unitaire dgeqp3_(&nombre_lignes_a, &nombre_colonnes_a, matrice_a_f77, &nombre_lignes_a, pivot, (*((real8 **) tau)), work, &lwork, &erreur); if (erreur != 0) { // L'erreur ne peut être que négative. (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(work); free(matrice_a_f77); free(tau); return; } for(i = 0; i < (unsigned long) nombre_colonnes_a; i++) { if ((i + 1) != (unsigned long) pivot[i]) { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(pivot); free(work); free(matrice_a_f77); free(tau); return; } } free(pivot); for(k = 0, i = 0; i < (unsigned long) nombre_colonnes_a; i++) { for(j = 0; j < (unsigned long) nombre_lignes_a; j++) { ((real8 **) (*s_matrice).tableau)[j][i] = ((real8 *) matrice_a_f77)[k++]; } } free(work); free(matrice_a_f77); break; } case 'C' : { if ((matrice_a_f77 = (void *) malloc(taille_matrice_f77 * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (((*tau) = malloc(((nombre_colonnes_a < nombre_lignes_a) ? nombre_colonnes_a : nombre_lignes_a) * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((complex16 *) matrice_a_f77)[k].partie_reelle = ((complex16 **) (*s_matrice).tableau)[j][i] .partie_reelle; ((complex16 *) matrice_a_f77)[k++].partie_imaginaire = ((complex16 **) (*s_matrice).tableau)[j][i] .partie_imaginaire; } } if ((pivot = malloc(nombre_colonnes_a * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((rwork = malloc(2 * nombre_colonnes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(i = 0; i < (unsigned long) nombre_colonnes_a; pivot[i++] = 0); lwork = -1; if ((work = malloc(sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } // Calcul de la taille de l'espace zgeqp3_(&nombre_lignes_a, &nombre_colonnes_a, matrice_a_f77, &nombre_lignes_a, pivot, (*((complex16 **) tau)), work, &lwork, rwork, &erreur); if (erreur != 0) { // L'erreur ne peut être que négative. (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(work); free(rwork); free(pivot); free(matrice_a_f77); free(tau); return; } lwork = ((complex16 *) work)[0].partie_reelle; free(work); if ((work = malloc(lwork * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } // Calcul de la permutation if ((registre = (void *) malloc(taille_matrice_f77 * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } memcpy(registre, matrice_a_f77, taille_matrice_f77 * sizeof(complex16)); zgeqp3_(&nombre_lignes_a, &nombre_colonnes_a, registre, &nombre_lignes_a, pivot, (*((complex16 **) tau)), work, &lwork, rwork, &erreur); free(registre); if (erreur != 0) { // L'erreur ne peut être que négative. (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(work); free(rwork); free(pivot); free(matrice_a_f77); free(tau); return; } // La permutation doit maintenant être unitaire zgeqp3_(&nombre_lignes_a, &nombre_colonnes_a, matrice_a_f77, &nombre_lignes_a, pivot, (*((complex16 **) tau)), work, &lwork, rwork, &erreur); if (erreur != 0) { // L'erreur ne peut être que négative. (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(work); free(rwork); free(pivot); free(matrice_a_f77); free(tau); return; } free(rwork); for(i = 0; i < (unsigned long) nombre_colonnes_a; i++) { if ((i + 1) != (unsigned long) pivot[i]) { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(pivot); free(work); free(matrice_a_f77); free(tau); return; } } free(pivot); for(k = 0, i = 0; i < (unsigned long) nombre_colonnes_a; i++) { for(j = 0; j < (unsigned long) nombre_lignes_a; j++) { ((complex16 **) (*s_matrice).tableau)[j][i].partie_reelle = ((complex16 *) matrice_a_f77)[k].partie_reelle; ((complex16 **) (*s_matrice).tableau)[j][i] .partie_imaginaire = ((complex16 *) matrice_a_f77)[k++].partie_imaginaire; } } free(work); free(matrice_a_f77); break; } } return; } /* ================================================================================ Fonctions calculant le déterminant ou le rang d'une matrice quelconque ================================================================================ Entrées : struct_matrice -------------------------------------------------------------------------------- Sorties : déterminant -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ static integer4 calcul_rang(struct_processus *s_etat_processus, void *matrice_f77, integer4 nombre_lignes_a, integer4 nombre_colonnes_a, integer4 *pivot, integer4 dimension_vecteur_pivot, unsigned char type) { integer4 erreur; integer4 *iwork; integer4 *jpvt; integer4 lwork; integer4 longueur; integer4 nombre_colonnes_b; integer4 nombre_lignes_b; integer4 ordre; integer4 rang; real8 anorme; real8 rcond; real8 *rwork; unsigned char norme; unsigned long i; void *matrice_b; void *matrice_c; void *work; #undef NORME_I #ifdef NORME_I norme = 'I'; if ((work = malloc(nombre_lignes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } #else norme = '1'; work = NULL; #endif longueur = 1; if (type == 'R') { anorme = dlange_(&norme, &nombre_lignes_a, &nombre_colonnes_a, matrice_f77, &nombre_lignes_a, work, longueur); #ifndef NORME_I free(work); #endif if ((matrice_c = malloc(nombre_lignes_a * nombre_colonnes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } memcpy(matrice_c, matrice_f77, nombre_lignes_a * nombre_colonnes_a * sizeof(real8)); dgetrf_(&nombre_lignes_a, &nombre_colonnes_a, matrice_f77, &nombre_lignes_a, pivot, &erreur); if (erreur < 0) { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(matrice_f77); return(-1); } if ((iwork = malloc(nombre_colonnes_a * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } if ((work = malloc(4 * nombre_colonnes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } ordre = (nombre_lignes_a > nombre_colonnes_a) ? nombre_colonnes_a : nombre_lignes_a; dgecon_(&norme, &ordre, matrice_f77, &nombre_lignes_a, &anorme, &rcond, work, iwork, &erreur, longueur); free(work); free(iwork); if (erreur < 0) { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(matrice_f77); return(-1); } if ((jpvt = malloc(nombre_colonnes_a * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } for(i = 0; i < (unsigned long) nombre_colonnes_a; i++) { ((integer4 *) jpvt)[i] = 0; } lwork = -1; if ((work = malloc(sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } nombre_colonnes_b = 1; nombre_lignes_b = (nombre_lignes_a > nombre_colonnes_a) ? nombre_lignes_a : nombre_colonnes_a; if ((matrice_b = malloc(nombre_lignes_b * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } for(i = 0; i < (unsigned long) nombre_lignes_b; i++) { ((real8 *) matrice_b)[i] = 0; } dgelsy_(&nombre_lignes_a, &nombre_colonnes_a, &nombre_colonnes_b, matrice_c, &nombre_lignes_a, matrice_b, &nombre_lignes_b, jpvt, &rcond, &rang, work, &lwork, &erreur); lwork = ((real8 *) work)[0]; free(work); if ((work = malloc(lwork * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } dgelsy_(&nombre_lignes_a, &nombre_colonnes_a, &nombre_colonnes_b, matrice_c, &nombre_lignes_a, matrice_b, &nombre_lignes_b, jpvt, &rcond, &rang, work, &lwork, &erreur); free(matrice_b); free(matrice_c); free(work); free(jpvt); if (erreur < 0) { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(matrice_f77); return(-1); } } else { anorme = zlange_(&norme, &nombre_lignes_a, &nombre_colonnes_a, matrice_f77, &nombre_lignes_a, work, longueur); #ifndef NORME_I free(work); #endif if ((matrice_c = malloc(nombre_lignes_a * nombre_colonnes_a * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } memcpy(matrice_c, matrice_f77, nombre_lignes_a * nombre_colonnes_a * sizeof(complex16)); zgetrf_(&nombre_lignes_a, &nombre_colonnes_a, matrice_f77, &nombre_lignes_a, pivot, &erreur); if (erreur < 0) { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(matrice_f77); return(-1); } if ((rwork = malloc(2 * nombre_colonnes_a * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } if ((work = malloc(2 * nombre_colonnes_a * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } ordre = (nombre_lignes_a > nombre_colonnes_a) ? nombre_colonnes_a : nombre_lignes_a; zgecon_(&norme, &ordre, matrice_f77, &nombre_lignes_a, &anorme, &rcond, work, rwork, &erreur, longueur); free(work); if (erreur < 0) { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(matrice_f77); return(-1); } if ((jpvt = malloc(nombre_colonnes_a * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } for(i = 0; i < (unsigned long) nombre_colonnes_a; i++) { ((integer4 *) jpvt)[i] = 0; } lwork = -1; if ((work = malloc(sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } nombre_colonnes_b = 1; nombre_lignes_b = (nombre_lignes_a > nombre_colonnes_a) ? nombre_lignes_a : nombre_colonnes_a; if ((matrice_b = malloc(nombre_lignes_b * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } for(i = 0; i < (unsigned long) nombre_lignes_b; i++) { ((complex16 *) matrice_b)[i].partie_reelle = 0; ((complex16 *) matrice_b)[i].partie_imaginaire = 0; } zgelsy_(&nombre_lignes_a, &nombre_colonnes_a, &nombre_colonnes_b, matrice_c, &nombre_lignes_a, matrice_b, &nombre_lignes_b, jpvt, &rcond, &rang, work, &lwork, rwork, &erreur); lwork = ((complex16 *) work)[0].partie_reelle; free(work); if ((work = malloc(lwork * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } zgelsy_(&nombre_lignes_a, &nombre_colonnes_a, &nombre_colonnes_b, matrice_c, &nombre_lignes_a, matrice_b, &nombre_lignes_b, jpvt, &rcond, &rang, work, &lwork, rwork, &erreur); free(rwork); free(matrice_b); free(matrice_c); free(work); free(jpvt); if (erreur < 0) { (*s_etat_processus).erreur_execution = d_ex_routines_mathematiques; free(matrice_f77); return(-1); } } return(rang); } void determinant(struct_processus *s_etat_processus, struct_matrice *s_matrice, void *valeur) { complex16 *vecteur_complexe; integer4 dimension_vecteur_pivot; integer4 nombre_colonnes_a; integer4 nombre_lignes_a; integer4 *pivot; integer4 rang; integer8 signe; real8 *vecteur_reel; unsigned long i; unsigned long j; unsigned long k; unsigned long taille_matrice_f77; void *matrice_f77; nombre_lignes_a = (integer4) (*s_matrice).nombre_lignes; nombre_colonnes_a = (integer4) (*s_matrice).nombre_colonnes; dimension_vecteur_pivot = (nombre_lignes_a < nombre_colonnes_a) ? nombre_lignes_a : nombre_colonnes_a; taille_matrice_f77 = nombre_lignes_a * nombre_colonnes_a; switch((*s_matrice).type) { case 'I' : { if ((matrice_f77 = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((real8 *) matrice_f77)[k++] = ((integer8 **) (*s_matrice).tableau)[j][i]; } } if ((pivot = (integer4 *) malloc(dimension_vecteur_pivot * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((rang = calcul_rang(s_etat_processus, matrice_f77, nombre_lignes_a, nombre_colonnes_a, pivot, dimension_vecteur_pivot, 'R')) < 0) { return; } if (rang < nombre_lignes_a) { (*((real8 *) valeur)) = 0; } else { if ((vecteur_reel = malloc((*s_matrice).nombre_colonnes * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } signe = 1; for(i = 0; i < (*s_matrice).nombre_colonnes; i++) { if ((unsigned long) pivot[i] != (i + 1)) { signe = (signe == 1) ? -1 : 1; } vecteur_reel[i] = ((real8 *) matrice_f77) [(i * nombre_colonnes_a) + i]; } for(i = 1; i < (*s_matrice).nombre_colonnes; i++) { vecteur_reel[0] *= vecteur_reel[i]; } (*((real8 *) valeur)) = vecteur_reel[0] * signe; free(vecteur_reel); } free(matrice_f77); free(pivot); break; } case 'R' : { if ((matrice_f77 = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((real8 *) matrice_f77)[k++] = ((real8 **) (*s_matrice).tableau)[j][i]; } } if ((pivot = (integer4 *) malloc(dimension_vecteur_pivot * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((rang = calcul_rang(s_etat_processus, matrice_f77, nombre_lignes_a, nombre_colonnes_a, pivot, dimension_vecteur_pivot, 'R')) < 0) { return; } if (rang < nombre_lignes_a) { (*((real8 *) valeur)) = 0; } else { if ((vecteur_reel = malloc((*s_matrice).nombre_colonnes * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } signe = 1; for(i = 0; i < (*s_matrice).nombre_colonnes; i++) { if ((unsigned long) pivot[i] != (i + 1)) { signe = (signe == 1) ? -1 : 1; } vecteur_reel[i] = ((real8 *) matrice_f77) [(i * nombre_colonnes_a) + i]; } for(i = 1; i < (*s_matrice).nombre_colonnes; i++) { vecteur_reel[0] *= vecteur_reel[i]; } (*((real8 *) valeur)) = vecteur_reel[0] * signe; free(vecteur_reel); } free(matrice_f77); free(pivot); break; } case 'C' : { if ((matrice_f77 = (void *) malloc(taille_matrice_f77 * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((complex16 *) matrice_f77)[k++] = ((complex16 **) (*s_matrice).tableau)[j][i]; } } if ((pivot = (integer4 *) malloc(dimension_vecteur_pivot * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((rang = calcul_rang(s_etat_processus, matrice_f77, nombre_lignes_a, nombre_colonnes_a, pivot, dimension_vecteur_pivot, 'C')) < 0) { return; } if (rang < nombre_lignes_a) { (*((complex16 *) valeur)).partie_reelle = 0; (*((complex16 *) valeur)).partie_imaginaire = 0; } else { if ((vecteur_complexe = malloc((*s_matrice).nombre_colonnes * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } signe = 1; for(i = 0; i < (*s_matrice).nombre_colonnes; i++) { if ((unsigned long) pivot[i] != (i + 1)) { signe = (signe == 1) ? -1 : 1; } vecteur_complexe[i] = ((complex16 *) matrice_f77) [(i * nombre_colonnes_a) + i]; } for(i = 1; i < (*s_matrice).nombre_colonnes; i++) { f77multiplicationcc_(&(vecteur_complexe[0]), &(vecteur_complexe[i]), &(vecteur_complexe[0])); } f77multiplicationci_(&(vecteur_complexe[0]), &signe, ((complex16 *) valeur)); free(vecteur_complexe); } free(matrice_f77); free(pivot); break; } } return; } void rang(struct_processus *s_etat_processus, struct_matrice *s_matrice, integer8 *valeur) { integer4 dimension_vecteur_pivot; integer4 nombre_lignes_a; integer4 nombre_colonnes_a; integer4 *pivot; integer4 rang; integer4 taille_matrice_f77; unsigned long i; unsigned long j; unsigned long k; void *matrice_f77; nombre_lignes_a = (integer4) (*s_matrice).nombre_lignes; nombre_colonnes_a = (integer4) (*s_matrice).nombre_colonnes; dimension_vecteur_pivot = (nombre_lignes_a < nombre_colonnes_a) ? nombre_lignes_a : nombre_colonnes_a; taille_matrice_f77 = nombre_lignes_a * nombre_colonnes_a; if ((pivot = (integer4 *) malloc(dimension_vecteur_pivot * sizeof(integer4))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } switch((*s_matrice).type) { case 'I' : { if ((matrice_f77 = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((real8 *) matrice_f77)[k++] = ((integer8 **) (*s_matrice).tableau)[j][i]; } } if ((rang = calcul_rang(s_etat_processus, matrice_f77, nombre_lignes_a, nombre_colonnes_a, pivot, dimension_vecteur_pivot, 'R')) < 0) { free(pivot); free(matrice_f77); return; } free(matrice_f77); (*valeur) = rang; break; } case 'R' : { if ((matrice_f77 = (void *) malloc(taille_matrice_f77 * sizeof(real8))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((real8 *) matrice_f77)[k++] = ((real8 **) (*s_matrice).tableau)[j][i]; } } if ((rang = calcul_rang(s_etat_processus, matrice_f77, nombre_lignes_a, nombre_colonnes_a, pivot, dimension_vecteur_pivot, 'R')) < 0) { free(pivot); free(matrice_f77); return; } free(matrice_f77); (*valeur) = rang; break; } case 'C' : { if ((matrice_f77 = (void *) malloc(taille_matrice_f77 * sizeof(complex16))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(k = 0, i = 0; i < (*s_matrice).nombre_colonnes; i++) { for(j = 0; j < (*s_matrice).nombre_lignes; j++) { ((complex16 *) matrice_f77)[k++] = ((complex16 **) (*s_matrice).tableau)[j][i]; } } if ((rang = calcul_rang(s_etat_processus, matrice_f77, nombre_lignes_a, nombre_colonnes_a, pivot, dimension_vecteur_pivot, 'C')) < 0) { free(pivot); free(matrice_f77); return; } free(matrice_f77); (*valeur) = rang; break; } } free(pivot); return; } // vim: ts=4