Obligement - L'Amiga au maximum

Mercredi 24 avril 2024 - 08:56  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in english


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : C - Une bibliothèque partagée pour les manipulations de matrices (aspects pratiques)
(Article écrit par Randy Finch et extrait du Randy Finch's Web Site - juin 1991)


Depuis un certain temps, je voulais apprendre à créer une bibliothèque partagée pour mon Amiga. J'avais parcouru le ROM Kernel Manual (Cf. référence 1 en fin d'article) et regardé les bibliothèques du domaine public mais cela était trop dense pour comprendre. Il est apparu que le problème était double : pas assez d'informations et mon manque de connaissance de l'assembleur sur Amiga. Dans le passé, j'avais programmé mon Commodore-64 en assembleur. Cependant, l'assembleur 68000 semblait être beaucoup plus complexe que celui pour 6502. J'étais encore en train d'apprendre le C et je n'étais pas enclin à apprendre l'assembleur 68000. Au fond de moi, cependant, je continuais à penser qu'il devait y avoir un moyen simple de créer une bibliothèque partagée, un moyen que même moi je pourrais comprendre.

Puis c'est arrivé ! J'ai reçu le numéro d'avril 1989 d'Amazing Computing. Il contenait un article de John Baez intitulé "Créer une bibliothèque partagée" (Cf. référence 2). L'article était merveilleux ; je le recommande vivement. J'ai parcouru l'article et les listings de programmes plusieurs fois et j'ai commencé à me rendre compte que mes soupçons étaient fondés. Créer une bibliothèque partagée peut être facile ! Comme le temps le permettait, j'ai expérimenté avec le code de l'article de John Naez. Une fois que j'ai réussi à le faire fonctionner, j'étais prêt à commencer à créer ma propre bibliothèque.

La première bibliothèque que j'ai décidé de créer est Matrix.library qui contient des routines pour manipuler les matrices. Les raisons de ce choix sont multiples. Mon travail habituel m'oblige à résoudre des équations simultanées et à calculer des coefficients de régression multiple par la méthode des moindres carrés. Bien que j'utilise généralement des logiciels commerciaux pour ces tâches, je savais que les calculs étaient basés sur des matrices et je voulais en savoir plus sur les mathématiques qui sous-tendent ces calculs. En outre, je travaillais personnellement sur un programme de traçage de fonctions tridimensionnelles. La translation, la rotation et la mise à l'échelle de vecteurs en deux et trois dimensions sont également basées sur la manipulation de matrices. Une bibliothèque partagée ne devrait être créée que si une variété de programmes peuvent l'utiliser. Matrix.library répond à ce critère.

Lorsque j'ai commencé à créer Matrix.library, je me suis rendu compte que certaines améliorations pouvaient être apportées au code de John Baez, car j'utilisais la version 5.04 de Lattice, qui est bien meilleure que la version 4 dont disposait John Baez au moment de son article. Par conséquent, cet article a un triple objectif :
  1. Présenter le code source de Matrix.library ainsi qu'un programme de test exhaustif.
  2. Indiquer certaines améliorations par rapport au code de John Baez en raison des améliorations apportées au système de développement de Lattice.
  3. Présenter plusieurs programmes qui illustrent comment la bibliothèque peut être utilisée de manière pratique.
Dévoiler mon code source

Contrairement à la plupart des journalistes, de nombreux développeurs de logiciels aiment dévoiler leurs (codes) source. C'est exactement ce que je suis prêt à faire. Matrix.library se compose de quatre fichiers. Ils sont présentés dans les listings 1 à 4. Le listing 1 est MatrixLib.a, le seul fichier en assembleur. Il se compose des données d'en-tête de la bibliothèque partagée standard et des routines d'interface pour les fonctions de la bibliothèque standard et utilisateur qui sont écrites en C. Le listing 2 est Matrix.c. Il contient tout le code pour les fonctions standard et utilisateur. Le listing 3 est Matrix.fd. Il s'agit du texte de description du fichier standard qui fournit des informations sur les registres du microprocesseur à utiliser pour passer les paramètres aux fonctions utilisateur de la bibliothèque. Le listing 4 est MatrixProto.h. Il s'agit d'un fichier d'en-tête C contenant les prototypes de fonctions utilisateur.

Le listing 5 est Test.h, un fichier d'en-tête qui inclut plusieurs autres fichiers d'en-tête et contient des fonctions d'affichage vectoriel et matriciel. Il est utilisé par plusieurs des programmes présentés dans cet article. Le listing 6 montre un makefile qui peut être utilisé avec LMK (Lattice Make Utility) pour créer Matrix.library et d'autres programmes présentés plus tard.

Une comparaison

Je n'ai pas l'intention de détailler le fonctionnement interne de MatrixLib.a. A part les instructions XREF et les vecteurs de saut vers le début du fichier et les routines de stub ("bouchon") d'interface à la fin du fichier, il est essentiellement le même que slibh.a dans l'article de John Baez. Je tiens à signaler certaines modifications que j'ai apportées au code de John Baez. Alors sortez votre numéro d'avril 1989 d'Amazing Computing, posez-le à côté de cet article, et suivez la discussion qui va suivre. J'ai numéroté les lignes dans MatrixLib.a pour rendre la discussion plus facile à suivre.

Les lignes 27-53 sont les déclarations XREF des fonctions utilisateur qui permettent aux fonctions C de Matrix.c d'être visibles pendant la liaison. Il y a 25 fonctions utilisateur dans Matrix.library. Elles seront discutées plus en détail plus tard. Au fur et à mesure que de nouvelles fonctions sont ajoutées à la bibliothèque, de nouvelles instructions XREF doivent être ajoutées à cette liste. De même, de nouvelles instructions jmp devront être ajoutées à la liste des vecteurs de saut des lignes 94 à 120. Il est important de se rappeler que les vecteurs de saut doivent être dans l'ordre inverse de la liste des fonctions dans Matrix.fd. La table de saut dans MatrixLib.a utilise l'instruction jmp alors que John Baez utilisait un $4EF9 codé en dur (saut long) à cause d'un bogue dans l'assembleur qu'il utilisait.

Aux lignes 151 et 157, j'ai décrit la taille de la table de vecteurs de saut et de la section de données en termes de différence de deux étiquettes plutôt que de coder en dur les tailles. Cela permet d'ajouter des fonctions supplémentaires (et donc plus d'instructions jmp) et de nouvelles données sans avoir à se soucier de changer ces chiffres.

Les lignes 237-408 contiennent les routines de stub d'interface pour toutes les fonctions utilisateur de Matrix.library. Ces routines déplacent simplement les registres appropriés sur la pile et appellent les fonctions C dans Matrix.c. Une chose à garder à l'esprit est que l'instruction "addq.l" ne peut être utilisée que pour une valeur de huit ou moins. Étant donné que chaque paramètre nécessite que la pile soit ajustée de quatre, "addq.l" ne peut être utilisée que lorsque deux paramètres ou moins sont passés. Pour plus de paramètres, "add.l" doit être utilisée. Il est très important que les registres placés sur la pile correspondent aux registres déclarés dans Matrix.fd car le compilateur placera les paramètres dans les registres en fonction du fichier ".fd". Lattice 4 ne gère que quatre paramètres dans les déclarations #pragma (produites à partir du fichier ".fd" à l'aide de fd2pragma). Cependant, Lattice 5 gère six paramètres. Cette gestion supplémentaire est arrivée à point nommé, car Matrix.library possède deux fonctions qui passent autant de paramètres.

Les commentaires de John Baez vers la fin de slibh.a indiquent que Lattice n'est pas clair (pourrait-il vouloir dire pointilleux) sur le fait qu'il n'a pas son propre code de démarrage pendant la liaison et donne un morceau de code commençant par "SECTION __MERGED" qui contient quelques XREF et des étiquettes de données. Rien de tout cela n'est nécessaire pour Lattice 5.04 ; blink se comporte maintenant très bien.

Regarder à travers la bibliothèque

Jetons un coup d'oeil aux fonctions qui font partie de Matrix.c. Les fonctions de la bibliothèque standard CInit(), LibOpen(), LibClose() et LibExpunge() sont les mêmes que celles de John Baez, sauf CInit(). Certaines des fonctions utilisateur de Matrix.c utilisent des calculs en virgule flottante. La bibliothèque mathieeedoubbas.library est utilisée pour ces calculs. Par conséquent, cette bibliothèque doit être ouverte dans CInit(). Si elle ne s'ouvre pas, un NULL est renvoyé pour informer Exec que l'initialisation de la bibliothèque Matrix.library a échoué.

Les fonctions utilisateur de la bibliothèque Matrix.library sont divisées en deux catégories : les fonctions de calcul des nombres entiers longs et les fonctions de calcul en virgule flottante à double précision. Les premières s'occupent de la manipulation des matrices contenant des nombres entiers et les secondes de la manipulation des matrices contenant des nombres à virgule flottante. Il existe un total de 25 fonctions utilisateur dans Matrix.library ; 12 pour les matrices en nombres entiers et 13 pour les matrices en virgule flottante. Une matrice ne comportant qu'une seule ligne ou colonne est également connue sous le nom de vecteur. Certaines fonctions sont écrites spécifiquement pour les vecteurs, tandis que d'autres fonctions sont écrites pour les matrices en général. Le tableau 1 présente une liste des fonctions utilisateur et décrit les tâches effectuées par chacune d'elles. La lettre "L" dans le nom d'une fonction indique qu'il s'agit d'une fonction d'entier long ; la lettre "D" indique une fonction de double précision en virgule flottante.

Tableau 1 - Résumé des fonctions utilisateur dans Matrix.library
  • AllocLVector/AllocDVector (numels) : alloue de la mémoire pour un vecteur contenant "numels" éléments et retourne un pointeur vers l'espace mémoire.
  • AllocLMatrix/AllocDMatrix (numrows,numcols) : alloue de la mémoire pour une matrice avec "numrows" lignes et "numcols" colonnes et retourne un pointeur vers un vecteur de pointeurs de lignes.
  • FreeLVector/FreeDVector (v,numels) : libère la mémoire allouée par AllocLVector ou AllocDVector où "v" est le pointeur retourné par ces fonctions et "numels" est le nombre d'éléments dans le vecteur. Retourne soit "TRUE" (VRAI), soit "FALSE" (FAUX).
  • FreeLMatrix/FreeDMatrix (m,numrows,numcols) : libère la mémoire allouée par AllocLMatrix ou AllocDMatrix où "m" est le pointeur retourné par ces fonctions, "numrows" est le nombre de lignes dans la matrice, et "numcols" est le nombre de colonnes dans le vecteur. Elle retourne soit "TRUE" (VRAI), soit "FALSE" (FAUX).
  • AddLVectors/AddDVectors (v1,v2,vr,numels) : additionne les éléments "numels" des vecteurs v1 et v2 et place le résultat dans le vecteur "vr". Si "vr" est NULL, il est alloué. Retourne vr.
  • SubLVectors/SubDVectors (v1,v2,vr,numels) : soustrait les éléments "numels" du vecteur v2 de v1 et place les résultats dans le vecteur "vr". Si "vr" est NULL, il est alloué. Retourne vr.
  • AddLMatrix/AddDVectors (m1,m2,mr,numrows,numcols) : additionne les éléments "numrows*numcols" des matrices m1 et m2 et place les résultats dans la matrice "mr". Si "mr" est NULL, elle est allouée. Retourne mr.
  • SubLMatrix/SubDMatrix (m1,m2,mr,numrows,numcols) : soustrait les éléments "numrows*numcols" de la matrice m2 de m1 et place les résultats dans la matrice "mr". Si "mr" est NULL, elle est allouée. Retourne mr.
  • MultLMatrix/MultDMatrix (m1,m2,mr,numrows1,numcols1,numcols2) : multiplie la matrice m1 avec "numrows1" lignes et "numcols1" colonnes et la matrice m2 avec "numcols1" lignes et "numcols2" colonnes (par exemple, -m1*m2). Le résultat est placé dans la matrice mr avec "numrows1" lignes et "numcols2" colonnes. Si "mr" est NULL, elle est allouée. Retourne mr.
  • MultLVectorMatrix/MultDVectorMatrix (v,m,vr,numels,numcols) : multiplie le vecteur "v" avec "numels" éléments et la matrice "m" avec "numels" lignes et "numcols" colonnes (par exemple - v*m). Le résultat est placé dans le vecteur "vr" avec "numcols" éléments. L'ordre de la multiplication implique que "v" et "vr" sont tous deux des vecteurs de lignes. Si "vr" est NULL, il est alloué. Retourne vr.
  • MultLMatrixVector/MultDMatrixVector (m,v,vr,numrows,numels) : multiplie la matrice "m" avec "numrows" lignes et "numels" colonnes et le vecteur "v" avec "numels" éléments (par exemple - m*v). Le résultat est placé dans le vecteur "vr" avec "numrows" éléments. L'ordre de la multiplication implique que "v" et "vr" sont tous deux des vecteurs colonnes. Si "vr" est NULL, il est alloué. Retourne vr.
  • TransposeLMatrix/ TransposeDMatrix (m,mt,numrows,numcols) : transpose la matrice "m" avec "numrows" lignes et "numcols" colonnes. Le résultat est placé dans "mt" avec "numcols" lignes et "numrows" colonnes. Si "mt" est NULL, elle est allouée. Retourne mt.
  • InvertDMatrix (m,mcopy,mi,numrows) : inverse une matrice carrée "m" avec "numrows" lignes et colonnes et place le résultat dans la matrice "mi" avec "numrows" lignes et colonnes. "mcopy" est un double de "m". Si elle est passée à la fonction sous la forme NULL, InvertDMatrix l'allouera, y copiera "m", l'utilisera pour les calculs inverses (elle sera détruite dans le processus), puis le désallouera. De même, si "mi" est passé à la fonction en tant que NULL, InvertDMatrix l'allouera. Cette fonction n'est pas implémentée pour les entiers longs car il est très peu probable qu'une matrice d'entiers longs ait un inverse composé de tous les entiers.
Le code des fonctions d'allocation et de désallocation de la mémoire et de la fonction d'inversion de matrice était basé sur des fonctions similaires dans le livre "Numerical Recipes In C" (Cf. référence 3). Ce livre contient un monde d'algorithmes pour les problèmes mathématiques. Je le recommande vivement à tous ceux qui écrivent des logiciels mathématiques.

La plupart du code de Matrix.c est simple et ne nécessite aucune explication. Cependant, il y a quelques éléments qui doivent être mentionnés. Lorsqu'un vecteur est alloué, un pointeur vers l'espace mémoire alloué est renvoyé au programme appelant. Ce pointeur peut être utilisé comme un pointeur de tableau C standard. Cependant, lorsqu'une matrice est allouée, le pointeur qui est renvoyé au programme appelant pointe vers un tableau de pointeurs, chacun d'entre eux pointant vers un tableau de nombres qui représentent les lignes de la matrice. Ainsi, pour faire référence à un élément individuel de la matrice, la notation C standard pour un tableau à deux dimensions, m[ligne][colonne], ne peut pas être utilisée. L'élément doit plutôt être désigné par (m[ligne])[colonne]. Les auteurs de Numerical Recipes In C que la notation standard peut être utilisée, mais qu'elle ne fonctionne pas avec le compilateur Lattice.

La méthode utilisée pour inverser une matrice dans InvertDMatrix() est appelée décomposition LU. L'explication de son fonctionnement est assez longue, je vous renvoie donc à Numerical Recipes In C si vous êtes intéressé par cette méthode.

Test de la bibliothèque

Le listing 7 montre le source C d'un programme intitulé TestMatLib.c. Ce programme ouvre la bibliothèque Matrix.library, alloue plusieurs vecteurs et matrices, et attribue des nombres aléatoires aux éléments. Il appelle ensuite toutes les fonctions de la bibliothèque Matrix. Les vecteurs et matrices d'entrée ainsi que les vecteurs et matrices de résultat sont imprimés sur la sortie standard à chaque étape du processus. Lorsque le test est terminé, tous les vecteurs et matrices sont désalloués et Matrix.library est fermé. Un exemple de sortie du programme est présenté dans le listing 8.

Utilisation réelle de Matrix.library

Le programme de test est bien pour tester les bogues de Matrix.library mais le vrai but de la bibliothèque partagée est de l'utiliser réellement. J'ai mentionné au début de cet article qu'il y avait plusieurs raisons d'écrire Matrix.library. Il s'agit notamment de la résolution d'équations simultanées, de la détermination de coefficients de régression par la méthode des moindres carrés et de la manipulation de vecteurs bidimensionnels et tridimensionnels. Le reste de cet article se concentrera sur des exemples de ces problèmes. Sachez que, par souci de concision, les programmes qui seront présentés n'effectuent pas beaucoup de contrôles d'erreurs.

Équations simultanées

Supposons que nous ayons l'ensemble d'équations suivant :
  • 1.3x1 + 342.7x2 - 17.7x3 = 1003.88(1)
  • -222,17x1 + 3,0x2 + 23,6x3 = -667,05(2)
  • 1,0x1 - 17,4x2 - 15,6x3 = 3,0(3)
Nous devons savoir quelles valeurs des xi sont valables pour les trois équations. En d'autres termes, nous devons résoudre les équations simultanément. Les équations ci-dessus peuvent être écrites en notation matricielle sous la forme AX=B, où A est une matrice 3 par 3 contenant les trois coefficients de chaque équation dans ses lignes, X est un vecteur colonne contenant les xi et B est un vecteur colonne contenant les constantes du côté droit (RHS). Cette équation matricielle peut être écrite comme suit :

 ___                  ___   _  _     __     __
|                        | |    |   |         |
|    1,3   342,7   -17,7 | | x1 |   | 1003,88 |
|                        | |    |   |         |
| -222,17    3,0    23,6 | | x2 | = | -667,05 |
|                        | |    |   |         |
|    1,0   -17,4   -15,6 | | x3 |   |    3,0  |
|___                  ___| |_  _|   |__     __|

Lorsque chaque côté de l'équation est multiplié par l'inverse de la matrice A, A-1, le côté gauche (LHS) de l'équation sera réduit au vecteur X tandis que le RHS sera le vecteur solution. En d'autres termes, A-1AX=A-1B se réduit à X=A-1B. Cela est dû au fait que A-1A est égal à la matrice unité (des uns dans la diagonale de haut en bas à gauche et des zéros ailleurs). Ainsi, le vecteur RHS après la multiplication contiendra les valeurs des xi. Le listing 9 est un programme permettant d'accomplir l'opération ci-dessus. Le listing 10 montre la sortie du programme. La solution pour le vecteur X est x1=2.71, x2=2.76, et x3=-3.10. Remarquez que le programme multiplie A et X pour vérifier que le résultat est bien égal à B (le vecteur RHS).

Régression par la méthode des moindres carrés

Supposons que nous établissions un plan d'expérience factoriel complet à deux niveaux (Cf. référence 4) pour une réaction chimique qui, selon nous, dépend de la température et du pH. La variable dépendante qui nous intéresse est le rendement en pourcentage d'un certain composé. Le tableau 2 montre le plan d'expérience, qui consiste en quatre essais, et les résultats du rendement.

Tableau 2 Conception expérimentale et résultats

                 Variables codées        Variables réelles
   Test No.       x1       x2       Temp,°C      pH     Rendement, %

      1            -        -         50          5       40.5
      2            +        -         70          5       49.9
      3            -        +         50          9       61.8
      4            +        +         70          9       78.2

Nous voulons modéliser les résultats avec l'équation linéaire suivante :

rendement = b0 + b1(temp) + b2(pH)

Les données du tableau 2 peuvent être combinées avec l'équation ci-dessus et mises en notation matricielle.

 ___        ___   _  _     __  __
|              | |    |   |      |
|  1   50   5  | | b0 |   | 40,5 |
|              | |    |   |      |
|  1   70   5  | | b1 | = | 49,9 |
|              | |    |   |      |
|  1   50   9  | | b2 |   | 61,8 |
|              | |_  _|   |      |
|  1   70   9  |          | 78,2 |
|___        ___|          |__  __|

ou "DB=Y". Comme il y a quatre équations et seulement trois inconnues, le modèle est trop spécifié et il n'y a pas de solution exacte pour les bi. Cependant, il est possible de calculer quelles valeurs de bi donneront des valeurs de rendement prédites qui sont les plus proches des valeurs de rendement réelles. Pour ce faire, il faut choisir les bi de telle sorte que la somme des carrés des différences entre les quatre rendements réels et prédits soit minimisée. C'est ce qu'on appelle l'analyse de régression des moindres carrés. Il s'avère que les bi appropriés peuvent être calculés assez simplement à l'aide de matrices en résolvant un ensemble d'équations simultanées connues sous le nom d'équations normales. Ces équations, en notation matricielle, sont DTDB=DTY, où DT est la transposition de la matrice D. DTD sera une matrice carrée à trois lignes et colonnes et DTY sera un vecteur colonne à trois éléments. Ainsi, les équations normales consistent en trois équations avec trois inconnues. Elles peuvent être résolues de la même manière que les équations simultanées ont été résolues dans la section précédente, comme suit :

       (DTD)B = DTY
(DTD)-1(DTD)B = (DTD)-1DTY
            B = (DTD)-1DTY

Le programme du listing 11 effectue ces calculs. La sortie du programme est présentée dans le listing 12. Les coefficients de régression des moindres carrés sont b0=-24,5, b1=0,645 et b2=6,20, ce qui donne l'équation de régression suivante :

rendement = -24,5 + 0,645(temp) + 6,20(pH)

Notez le vecteur "PREDYIELD" à la fin du listing 12. Il s'agit des quatre valeurs de rendement prédites dans les conditions d'essai du plan d'expérience. Elles sont différentes des valeurs de rendement réelles ; cependant, en raison de la nature de l'analyse de régression des moindres carrés, il n'y a pas d'autres valeurs bi qui donneront une plus faible somme des carrés des différences entre les rendements réels et prédits.

Transformation vectorielle

Les matrices peuvent être utilisées pour transformer des objets à N dimensions. Par souci de concision, l'exemple suivant est une transformation à deux dimensions, mais le même principe peut être appliqué pour des dimensions supérieures (Cf. référence 5).

Un rectangle d'une largeur de quatre et d'une hauteur de trois se trouve dans le plan X-Y et les coordonnées de ses quatre coins sont (5,6), (5,9), (9,9) et (9,6). Nous aimerions mettre ce rectangle à l'échelle par un facteur de 1,5 dans la dimension X et de 2,0 dans la dimension Y, puis le faire pivoter de 45 degrés autour de son point central (7,0,7,5). Les facteurs d'échelle et la rotation ne peuvent pas être appliqués directement aux coordonnées, car le rectangle serait alors mis à l'échelle et pivoté par rapport à l'origine plutôt qu'au centre du rectangle. Par conséquent, il faut d'abord traduire le rectangle de façon à ce que son centre coïncide avec l'origine, le mettre à l'échelle, le faire pivoter, puis le traduire à nouveau de façon à ce que le centre du rectangle retrouve sa position initiale. Ce processus est illustré graphiquement à la figure 1.

figure 1

Il s'avère que les coordonnées cartésiennes ne conviennent pas à la transformation, mais les coordonnées homogènes le font. Les coordonnées homogènes ajoutent un facteur supplémentaire w tel que (w*x,w*y,w) est équivalent à (x,y,1) qui représente les coordonnées cartésiennes (x,y). Pour plus de détails, voir la référence 5.

Les coordonnées cartésiennes des quatre coins du rectangle peuvent être représentées en coordonnées homogènes par (5,6,1), (5,9,1), (9,9,1) et (9,6,1), qui sont des vecteurs de ligne. Pour traduire, mettre à l'échelle ou faire pivoter ces coins, les vecteurs sont multipliés par la matrice de transformation appropriée. Ainsi, pour effectuer l'ensemble de la transformation illustrée à la figure 1, les calculs suivants sont nécessaires :

Ni = (Ci)(T-c)SR(Tc) = (Ci)F

où...
  • Ci = un vecteur d'angle, i=1-4.
  • T-c = la matrice de translation qui déplace le centre du rectangle vers l'origine.
  • S = la matrice de mise à l'échelle.
  • R = la matrice de rotation.
  • Tc = la matrice de translation qui ramène le centre du rectangle vers son emplacement d'origine.
  • F = la matrice de transformation complète = (T-c)SR(Tc).
  • Ni = un vecteur d'angle transformé, i=1-4.
Le tableau 3 montre à quoi ressemblent les matrices de translation, de mise à l'échelle et de rotation en deux dimensions. Une fois que toutes les matrices de transformation individuelles sont multipliées ensemble pour obtenir une matrice de transformation complète, les vecteurs d'angle homogènes peuvent chacun être multipliés par cette matrice pour obtenir les quatre coordonnées d'angle transformées. Le listing 13 montre un programme qui effectue tous ces calculs. Le résultat du programme est présenté dans le listing 14. Les coordonnées cartésiennes des coins transformés sont (7.00,3.26), (2.76,7.50), (7.00,11.74) et (11.24,7.50). Comme vous pouvez le constater, ces coordonnées correspondent à celles de la figure 1e.

Conclusion

Voilà : une bibliothèque partagée pour effectuer des calculs matriciels et les prémices d'une vraie utilisation de cette bibliothèque. Bien sûr, il existe de nombreuses autres tâches qui peuvent faire bon usage de Matrix.library. De même, il existe de nombreuses autres fonctions qui peuvent être ajoutées à la bibliothèque elle-même.

Références
  1. Commodore-Amiga, Inc.; Amiga ROM Kernel Reference Manual: Includes and Autodocs; Addison-Wesley Publishing 1989.
  2. Baez, J. ; "Creating Shared Libraries" ; Amazing Computing for the Commodore Amiga ; PiM Publications, Avril 1989 (v4.4).
  3. Press, W. H., Flannery, B. P., Teukolsky, S. A., et Vetterling, W. T. ; Numerical Recipes In C: The Art Of Scientific Computing ; Cambridge University Press 1988.
  4. Box, G.E.P., Hunter, W.G., et Hunter, J.S. ; Statistics for Experimenters: An Introduction to Design, Data Analysis, and Model Building; John Wiley & Sons 1978.
  5. Pokorny, C. K. et Gerald, C. F. ; Computer Graphics: The Principles Behind The Art And Science; Franklin, Beedle, and Associates 1989.


[Retour en haut] / [Retour aux articles]