Rien

Modifs
- MTK: but = comprendre comment ça marche et virer ce qu'on utilise pas.
Faire aussi une batterie de tests.
- Lorsqu'on demande un élément hors d'une matrice, Oofelie renvoie une référence (c'est ça le pbl) vers une variable statique "outOfRange" (c'est la philosophie d'OE: "quelque chose ne va pas mais j'essaye quand même que ça marche"). Pour éviter des problèmes, j'ai préféré faire un FATAL_ERROR dans ce cas: je préfère la philosophie "quelque chose semble incorrect - j'arrête tout"!
- Lorsque C=A+B (A, B et C sont des matrices), il est difficile de savoir quelle sera la taille des matrices qui vont intervenir dans le calcul: en regardant le code de plus près, le résultat de A+B aura la taille de la plus grande matrice. Par contre C gardera sa taille quoiqu'il arrive (et de manière totallement silencieuse). Pour éviter cette source d'erreur, j'ai ajouté un FATAL_ERROR dès que les tailles sont incompatibles(Autrement dit, si A, B et C ont pas la même taille, ça plante et affiche une erreur claire). Il faudra voir si ce serait pas intéressant d'avoir plus tard un comportement a la Matlab, c-à-d que C se redimensionne automatiquement à la taille de A+B.
- Les Matrices/Vecteurs dérivent maintenant de VirtualObject (sauf les petits c à d Vect2, Vect3, etc - autrement dit ceux qui possèdent au moins une fonction virtuelle)
- Impossible de créer un matrice en lui passant une dimension <0
- ILU0Preconditioner : la structure du préconditionneur est calculée en fonction de la valeur absolue des termes de la matrice du système (si le terme est <1e-6, il est considéré nul!)... oui, c'est nul... j'ai fait un test qui me semble plus approprié.
Remarques sur la gestion mémoire des matrices (et objets accociés)
Contexte:
- Lorsqu'on veut utiliser des fonctions qui retournent des références (pour éviter une copie) vers des objets de grosse taille, il se pose inévitablement le problème de la destruction des objets retournés. L'utilisateur doit ainsi toujours supprimer manuellement l'objet qu'il vient de récupérer lorsqu'il n'en a plus besoin.
- Si, maintenant, ces valeurs sont passées à leur tour comme argument à une autre fonction, la situation se complique: la fonction doit pouvoir savoir si cet argument est de type "temporaire" pour pouvoir le supprimer au bon moment et 1 seule fois.
- Dans les matrices d'Oofelie, un flag nommé "status" (classe WithCheckRef) permet de définir l'état d'une matrice.
pour ceux qui comme moi n'y voient pas clair dans le rôle de status (je vous rassure, c'est normal, c'est pas correctement appliqué)
- status est mis à 1 pour une matrice classique définie par l'utilisateur (allouée dynamiquement ou non).
- Par contre, le résultat d'une opération (variable "temporaire" allouée localement et renvoyée en retour de fonction) sera mis à 0. Chaque fonction qui reçoit une matrice en argument (l'argument pouvant être un retour de fonction si on fait un appel d'un appel de fonction) ou par retour de fonction doit donc tenter de virer cette matrice lorsqu'elle n'est plus nécessaire.
- Si cette fonction appelle a son tour une fonction avec, comme argument, la fameuse matrice temporaire, elle doit incrémenter status, appeler la fonction puis décrementer status (et si status vaut 0, détruire l'objet).
Schématiquement:
Idéalement, on devrait avoir ce genre de code :
Matrix & funct1(Matrix &arg)
{
INCREF(arg); // empeche la destruction de arg par "funct2" : arg.status++
// utilisation de arg
Matrix &res = funct2(arg); // res.status = 0
INCREF(res) // je signale que j'utilise res (sinon, n'importe quel appel avec res supprimera res)
// utilise res
// ...
DECREF(res); // j'en ai fini avec res : arg.status-- ; if(arg.status==0) delete &arg
// creation de la valeur retour
Matrix &ret = *new Matrix(); // ret.status = 1
// ...
DECREF(arg); // arg.status-- ; if(arg.status==0) delete &arg
SETRETURN(ret); // ret.status--;
}
C'est loin d'être fait comme ça dans le code actuel. La plupart du temps, le programmeur essaye de se démerder en fin de fonction et, par exemple, le INCREF du début est systématiquement oublié...
Qui sait par exemple que si on fait : Matrix &C = A+B, il faut incrémenter le status de C (INCREF(C)) sinon, tout appel à une fonction utilisant C détruira cette variable et mènera à un beau plantage! bien sur, il est possible d'écrire Matrix C = A+B et, là, ça marche mais au prix d'une copie supplémentaire.
Les dangers viennent du fait qu'on utilise partout des références (les références permettent une écriture simple des appels). idéalement, il faudrait utiliser soit des pointeurs, soit, encore mieux, des smart pointers (auto_ptr<Matrix>):
- DECREF(res) désalloue la mémoire derrière la référence mais n'empêche pas l'utilisation de "res" (bug très difficile à trouver!).
- Il est également possible de se retrouver avec des désallocations de mémoire de pile (en bref: Matrix A(); DECREF(A)) qui fournissent des erreurs très variées et très surprenantes (même purify ne s'y retrouve pas toujours).
Fichiers ajoutés
A oeMTK/oeMTKEnums.cpp
A oeMTK/oeMTKEnums.h
Fichiers ajoutés
A mtPython/testMTK.*