program STRAS ; (************************************************************************* Auteurs : AKPAMOLI Eudes HANNOYER Philippe ___________________________ Projet nø 1 Li1 Multiplication de deux matrices selon l'algorithme r‚cursif de Strassen (ou diviser pour rŠgner) Programme r‚alis‚ en Loglan 82, sur un PC 486, ‚cran SVGA Couleur (640 x 480) avec h‚ritage des deux unit‚s * unit‚ graphique : IIUWGRAPH * unit‚ de gestion de la souris : MOUSE. Remarque : Ce programme n‚cessite obligatoirement un PC avec ‚cran graphique (640 x 480). Il est pr‚f‚rable d'uiliser une souris. En effet certaines parties de l'interface graphique ne r‚agissent qu'avec la souris (ascenseurs g‚rants les scrollings). **************************************************************************) begin Pref iiuwgraph block (* h‚ritage de l'unt‚ graphique *) begin Pref mouse block (* h‚ritage de l'unit‚ souris *) (* DEBUT PARTIE GRAPHIQUE *) (* Sauve une partie de l'‚cran d‚finie par X, Y, XX, YY *) unit GET_MAP : function (X, Y, XX, YY : integer) : arrayof integer ; begin call move (XX,YY) ; result:=getmap(X, Y) ; end GET_MAP ; (* Restore la partie d'‚cran sauv‚e par GET_MAP *) unit PUT_MAP : procedure (X, Y : integer; Map : arrayof integer) ; begin call move (X, Y) ; call putmap (Map) ; end PUT_MAP ; (********* BOUTON **********) (* Class g‚rant les procedure sur les boutons X,Y,XX,YY : Coordonn‚es du bouton, Epais : Epaisseur du bord du bouton, C1, C2, C3 : Trois couleurs (Fond, Bordure une, Bordure deux). map_bouton : Sauvegarde de la partie d'‚cran avant affichage, Bouton_aff : Bool‚en indiquant si le bouton est affich‚.*) unit BOUTON : class (X, Y, XX, YY, Epais, C1, C2, C3 : Integer) ; var map_Bouton : arrayof integer, Bouton_Aff : boolean ; (* Affichage de la bordure d'un bouton *) unit BORDURE : procedure (couleur1,couleur2 : integer) ; var i : integer ; begin for i:=0 to Epais-1 do call color(couleur1) ; call move (x+1+i,yy-1-i) ; call draw (x+1+i,y+1+i) ; call draw (xx-1-i,y+1+i) ; call color(couleur2) ; call draw (xx-1-i,yy-1-i) ; call draw (x+1+i,yy-1-i) ; od ; end BORDURE ; (* Modifie les coordonn‚es d'un bouton *) unit CHG_BOUTON_XY : procedure (Nv_X,Nv_Y : integer) ; begin XX:=Nv_X+(XX-X) ; YY:=Nv_Y+(YY-Y) ; X:=Nv_X ; Y:=Nv_Y ; end CHG_BOUTON_XY ; (* Affichage d'un bouton *) unit AFF_BOUTON : procedure ; begin Bouton_Aff:=True ; map_Bouton:=GET_MAP(X,Y,XX,YY) ; call patern(x,y,xx,yy,0,1) ; call patern(x+1,y+1,xx-1,yy-1,C1,1) ; call BORDURE (C2, C3) ; end AFF_BOUTON ; (* Effa‡age d'un bouton *) unit EFF_BOUTON : procedure ; begin Bouton_Aff:=False ; call PUT_MAP (X, Y, map_Bouton) ; end EFF_BOUTON ; (* Simulation du clique sur un bouton avec la souris *) unit BOUTON_ENFONCE : function (Num,NumSouris,XSouris,YSouris : Integer) : boolean ; begin result:=(Num=NumSouris) and (Bouton_Aff and (X<=XSouris) and (XX>=XSouris) and (Y<=YSouris) and (YY>=YSouris)) ; if result then (* simulation de l'onfoncement du bouton *) call BORDURE (C3,C2) ; call BORDURE (C2,C3) ; fi end BOUTON_ENFONCE; (* Bouton_Aff := False ;*) end BOUTON ; (******** BOUTON *********) (********** ASCENSEUR *********) (* Class g‚rant les proc‚dures relatives aux Ascenseur Hor : Bool‚en … vrai si l'ascenseur est horizontal, Max : Valeur indiquant le maximum pour le d‚placement de l'ascenseur, X, Y : Coordonn‚es haut gauche de l'ascenseur, Lgr : Longueur (ou hauteur) de l'ascenseur, C1, C2, C3 : Trois couleurs (Fond, Bordure une, Bordure deux). BPlus, BDep, BBar, BMoins : Boutons de l'ascenseur, Map : Sauvegarde l'‚cran avant l'affichage du bouton, Courant : Valeur de d‚placement de l'ascenseur. *) unit ASCENSEUR : class (Hor:Boolean,Max,X,Y,Lgr,c1,c2,c3 : integer) ; Var BPlus, BDep, BBar, BMoins : BOUTON, Map : arrayof integer, Courant : Integer ; (* Bouge le bouton de d‚placement de l'ascenseur. *) unit BOUGE_ASC : procedure (EffAvt : boolean) ; begin if EffAvt then call BDep.EFF_BOUTON ; fi ; if Max > 0 then if (Hor) then BDep.X:=X+20+(Lgr-60)*Courant/Max ; BDep.XX:=BDep.X+20 ; else BDep.Y:=Y+20+(Lgr-60)*Courant/Max ; BDep.YY:=BDep.Y+20 ; fi ; fi ; call BDep.AFF_BOUTON ; end BOUGE_ASC; (* Affiche l'ascenseur *) unit AFF_ASC : procedure ; Var i : Integer ; begin call BPlus.AFF_BOUTON ; call BMoins.AFF_BOUTON ; call BBar.AFF_BOUTON ; call Color(0) ; for i:=1 to 6 do if (Hor) then call move (X+5+i,y+11-i) ; call draw (X+5+i,y+9+i) ; call move (X+Lgr-14+i,y+4+i) ; call draw (X+Lgr-14+i,y+16-i) ; else call move (X+11-i,y+5+i) ; call draw (X+9+i,y+5+i) ; call move (X+4+i,y+Lgr-14+i) ; call draw (X+16-i,y+Lgr-14+i) ; fi ; od ; call BOUGE_ASC (False) ; end AFF_ASC ; begin if (Lgr<70) then Lgr := 70 fi ; BPlus := new BOUTON (X,Y,X+20,Y+20,2,c1,c3,c2) ; if (Hor) then BDep := new BOUTON (X+20,Y,X+40,Y+20,2,c1,c3,c2) ; BBar := new BOUTON (X+20,Y,X+Lgr-20,Y+20,2,c1,c1,c1) ; BMoins := new BOUTON (X+Lgr-20,Y,X+Lgr,Y+20,2,c1,c3,c2) ; else BDep := new BOUTON ( X,Y+20,X+20,Y+40,2,c1,c3,c2) ; BBar := new BOUTON ( X,Y+20,X+20,Y+Lgr-20,2,c1,c1,c1) ; BMoins := new BOUTON ( X,Y+Lgr-20,X+20,Y+Lgr,2,c1,c3,c2) ; fi ; Courant := 0 ; end ASCENSEUR ; (********** ASCENSEUR *********) (********** WINDOWS *********) (* Class g‚rant les proc‚dures relatives aux Fenˆtres (ces fenˆtres sont celles qui permettent d'afficher les trois matrices (A, B, Res ou Tmp) Titre : Nom de la fenˆtre ("A", "B", "Tmp" ou "Res"), Maxi : Valeur indiquant la taille de la matrice, X, Y : Coordonn‚es haut gauche de la fenˆtre, A1, A2 : Deux ascenseur (horizontal, vertical), Map : Sauvegarde l'‚cran avant l'affichage du bouton, Courant : Valeur de d‚placement de l'ascenseur. Taille, Fond_win : Deux bouton (les 1er pour afficher la taille de la matrice, le second qui sert de fond … la fenˆtre *) unit WINDOWS : class (Titre : string ; Maxi, X, Y : Integer); var A1, A2 : ASCENSEUR, i : integer, Taille, Fond_Win : BOUTON ; (* Affiche la matrice : au maximum 4 x 4 *) unit AFF_MATRICE : procedure (M : arrayof arrayof integer) ; var max, i, j : integer ; begin (* max ne peut ˆtre plus grand que 4 *) max:=imin(4,upper(M)) ; for i:=1 to 4 do (* On efface les ‚ventuelles anciennes valeures *) call outstring (X+10+(i*58),Y+7," ",4,12) ; call outstring (X+10,Y+(i*38)," ",4,12) ; for j:=1 to 4 do call outstring (X-21+(i*58),Y+(j*38)," ",4,12) ; od ; od ; for i:=1 to max do (* On ‚crit les nouvelles valeures *) call track (X+10+(i*58),Y+7,A1.Courant+i,12,4) ; call track (X+10,Y+(i*38),A2.Courant+i,12,4) ; for j:=1 to max do if Aff_Num_Grd or M(j+A1.Courant,i+A2.Courant)<=9999999 and M(j+A1.Courant,i+A2.Courant)>=-100000 then call track (X-21+(i*58),Y+(j*38),M(j+A1.Courant,i+A2.Courant),12,4) ; else call outstring (X-21+(i*58),Y+(j*38)," #####",4,12) ; fi ; od ; od ; end AFF_MATRICE ; (* Test si un clique a eu lieu sur un des bouton (+ ou -) de l'ascenseur, enventuellement modifie la valeur de courant de l'ascenseur et bouge l'ascenseur *) unit MOUVE_ASC : procedure (M : arrayof arrayof integer; A : ASCENSEUR;NumSouris, X_S, Y_S : integer) ; begin if (A.BMoins.BOUTON_ENFONCE (1,NumSouris,X_S, Y_S)) then if (A.Courant0) then (* si le bouton + de l'ascenseur est cliquer et que la valeure courant est sup‚rieure … 0, alors on bouge l'ascenseur, on d‚cr‚ment la valeure courant et on r‚affiche la matrice *) A.Courant:=A.Courant-1 ; call A.BOUGE_ASC (True) ; call AFF_MATRICE (M) ; fi ; fi ; end MOUVE_ASC ; (* Efface une fenˆtre *) unit EFF_WINDOWS : procedure ; begin call A1.BPlus.EFF_BOUTON ; call A2.BPlus.EFF_BOUTON ; call A1.BMoins.EFF_BOUTON ; call A2.BMoins.EFF_BOUTON ; call Fond_Win.EFF_BOUTON ; call Fond_Win.EFF_BOUTON ; call Taille.EFF_BOUTON ; end EFF_WINDOWS; begin Fond_Win:=new BOUTON (X,Y,X+270,Y+180,3,12,13,5) ; Taille:= new BOUTON (X+270,Y+180,X+290,Y+200,0,15,15,15) ; call Fond_Win.AFF_BOUTON ; call Color (0) ; (* double cadre dans la fenˆtre *) call Move (X+34,Y+4) ; call Draw (X+34,Y+176) ; call Move (X+36,Y+4) ; call Draw (X+36,Y+176) ; call Move (X+4,Y+27) ; call Draw (X+266,Y+27) ; call Move (X+4,Y+29) ; call Draw (X+266,Y+29) ; for i:=1 to 3 do (* Cadre s‚parant les valeures *) call Move (X+36+(i*58),Y+4) ; call Draw (X+36+(i*58),Y+176) ; call Move (X+4,Y+29+(i*38)) ; call Draw (X+266,Y+29+(i*38)) ; od ; A1 := new ASCENSEUR(True,maxi-4,X,Y+180,270,7,8,15) ; A2 := new ASCENSEUR(False,maxi-4,X+270,Y,180,7,8,15) ; call A1.AFF_ASC ; call A2.AFF_ASC ; call Taille.AFF_BOUTON ; call Outstring (X+7,Y+10,Titre,12,4) ; call track (X+273,Y+184,Maxi,15,0) ; end WINDOWS ; (********** WINDOWS *********) (********** AIDE *********) (* Class g‚rant les diff‚rents ‚cran d'aide B1 .. B6 : Six bouton permettant l'affichage des menu d'aide, FinAide : Bool‚en qui permet de quitter le menu d'aide, Interrupt, x_s, y_s, Key1, Key2, Flags, Num_Mouse : Permet la gestion des ‚vŠnement de la souris *) unit AIDE : procedure ; var B1, B2, B3, B4, B5, B6 : BOUTON, FinAIDE, Interupt : Boolean, x_s,y_s,Key1,Key2,Flags,Num_Mouse : integer ; (* Texte du menu g‚n‚ral *) unit AIDE_GRL : procedure ; begin call outstring (170, 80,"Pour utiliser cette aide cliquez sur le bouton",0,3) ; call outstring (170,100,"de votre choix.",0,3) ; call outstring (170,130,"Vous trouverez une aide sur :",0,3) ; call outstring (170,155," -->",0,3) ; call outstring (219,155,"Menu :",4,3) ; call outstring (170,175," Explication des choix du menu.",0,3) ; call outstring (170,200," -->",0,3) ; call outstring (219,200,"Principe du calcul :",4,3) ; call outstring (170,220," STRASSEN ou diviser pour r‚gner.",0,3) ; call outstring (170,245," -->",0,3) ; call outstring (219,245,"Am‚lioration :",4,3) ; call outstring (170,265," Comment utiliser des matrices de grandeurs",0,3) ; call outstring (170,285," diff‚rentes.",0,3) ; call outstring (170,310,"Remarques Le signe '>' dans les menus signifie",5,3) ; call outstring (170,330," qu'une fenˆtre d‚pend de ce menu.",5,3); call outstring (170,360," Vous pouvez activer un choix du menu",5,3); call outstring (170,380," soit en cliquant dessus, soit en tapant",5,3); call outstring (170,400," la lettre en noire.",5,3); end AIDE_GRL ; (* Texte du menu "Aide" *) unit AIDE_MENU : procedure ; begin call outstring (170,75,"Quitter :",4,3) ; call outstring (170,95," Retourne au systŠme d'exploitation.",0,3) ; call outstring (170,120,"Variables :",4,3) ; call outstring (170,140," Affichage de l'‚tat des 7 variables de travail",0,3) ; call outstring (170,160," ainsi que le nombre de multiplications et",0,3) ; call outstring (170,180," d'additions utilis‚es en r‚cursif normal, ou par",0,3) ; call outstring (170,200," STRASSEN.",0,3) ; call outstring (170,225,"Suite :",4,3) ; call outstring (170,245," Etape suivante du calcul.",0,3) ; call outstring (170,270,"R‚sultat :",4,3) ; call outstring (170,290," Calcul direct (pas d'‚tapes interm‚diaires).",0,3) ; call outstring (170,315,"Affichage :",4,3) ; call outstring (170,335," Permet de changer le format des grands nombres.",0,3) ; call outstring (170,360,"Aide :",4,3) ; call outstring (170,380," Pour que la vie soit plus douce ....",0,3) ; end ; (* Texte du menu "Calcul" *) unit AIDE_CAL : procedure ; begin call outstring (170,100,"Soit … multiplier 2 matrices n x n.",0,3) ; call outstring (170,130,"Principe :",0,3) ; call outstring (170,160,"1. Si n > 2 : Calcul de 7 matrices n/2 x n/2",0,3) ; call outstring (170,180," Remarque : A chaque fois qu'un produit de",0,3) ; call outstring (170,200," sous_matrices sera rencontr‚ dans le calcul,",0,3) ; call outstring (170,220," il faudra refaire de mˆme; d'o— la r‚cursivit‚.",0,3) ; call outstring (170,250,"2. Sinon : Les diff‚rentes composantes de la",0,3) ; call outstring (170,270," matrice_r‚sultat se d‚duisent directement en",0,3) ; call outstring (170,290," rempla‡ant la m‚thode classique du produit ",0,3) ; call outstring (170,310," scalaire par une m‚thode propre … Strassen.",0,3) ; call outstring (170,330,"N.B. : On ‚conomise une multiplication pour",0,3) ; call outstring (170,350," plusieurs additions.",0,3) ; end AIDE_CAL ; (* Texte du menu "Am‚lioration" *) unit AIDE_AMEL : procedure ; begin call outstring (170,100,"L'algorithme de STRASSEN n‚cessite deux matrices",0,3) ; call outstring (170,130,"carr‚es de taille identique et dont l'ordre doit",0,3) ; call outstring (170,160,"ˆtre sous la forme d'une puissance exacte de deux",0,3) ; call outstring (170,190,"(ordre = 2 ).",0,3) ; call outstring (170+80,180,"k",0,3) ; call outstring (170,230,"Le programme accepte des matrices ne satisfaisant",0,3) ; call outstring (170,260,"pas … ces conditions. Il ajuste ensuite celles-ci",0,3) ; call outstring (170,290,"en compl‚tant, ‚ventuellement, avec des 0.",0,3) ; call outstring (170,330,"Le programme laisse donc … l'utilisateur une plus",0,3) ; call outstring (170,360,"grande souplesse d'utilisation.",0,3) ; end AIDE_AMEL ; begin (* Bouton du fond de l'aide *) B1:=new BOUTON (150,31,600,431,2,3,11,1) ; (* Bouton du fond du menu de l'aide *) B2:=new BOUTON (156,37,256,60,2,7,15,8) ; (* Bouton du menu "Menu" *) B3:=new BOUTON (258,37,358,60,2,7,15,8) ; (* Bouton du menu "Calcul" *) B4:=new BOUTON (360,37,490,60,2,7,15,8) ; (* Bouton du menu "Am‚lioration" *) B5:=new BOUTON (492,37,592,60,2,7,15,8) ; (* Bouton du menu "Fermer" *) B6:=new BOUTON (160,70,580,421,0,3,3,3) ; call B1.AFF_BOUTON ; call B2.AFF_BOUTON ; call outstring (162,40,"Menu >",1,7) ; call outstring (162,40,"M",0,7) ; call B3.AFF_BOUTON ; call outstring (264,40,"Calcul >",1,7) ; call outstring (264,40,"C",0,7) ; call B4.AFF_BOUTON ; call outstring (366,40,"Am‚lioration >",1,7) ; call outstring (366,40,"A",0,7) ; call B5.AFF_BOUTON ; call outstring (498,40,"Fermer",1,7) ; call outstring (498,40,"F",0,7) ; call B6.AFF_BOUTON ; call AIDE_GRL ; FinAIDE:=False ; while (not FinAIDE) do Interupt:=getpress(x_s,y_s,Key1,Key2,Flags,Num_Mouse) ; if Interupt and (Num_Mouse=1 or key2=102 or key2=109 or key2=99 or key2=97) then if B5.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=102 then (* On ferme ... *) FinAIDE:=True ; call B6.EFF_BOUTON ; call B5.EFF_BOUTON ; call B3.EFF_BOUTON ; call B2.EFF_BOUTON ; call B1.EFF_BOUTON ; fi ; if B2.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=109 then (* Appel … l'aide sur les menus *) call B6.EFF_BOUTON ; call B6.AFF_BOUTON ; call AIDE_MENU ; fi ; if B3.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=99 then (* Appel … l'aide sur le calcul *) call B6.EFF_BOUTON ; call B6.AFF_BOUTON ; call AIDE_CAL ; fi ; if B4.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=97 then (* Appel … l'aide sur l'am‚lioration *) call B6.EFF_BOUTON ; call B6.AFF_BOUTON ; call AIDE_AMEL ; fi ; fi ; od ; end AIDE; (********** AIDE *********) unit AFF_NUM : procedure (X, Y : integer, M : arrayof arrayof integer) ; var B1, B2, B3 : BOUTON, FinAFF, Interupt : Boolean, x_s,y_s,Key1,Key2,Flags,Num_Mouse : integer ; begin B1:=new BOUTON (X,Y,X+380,Y+300,2,3,11,1) ; B2:=new BOUTON (X+10,Y+270,X+160,Y+290,2,7,8,15) ; B3:=new BOUTON (X+270,Y+270,X+370,Y+290,2,7,8,15) ; call B1.AFF_BOUTON ; call B2.AFF_BOUTON ; call B3.AFF_BOUTON ; call outstring (X+15,Y+50," AFFICHAGE DES GRANDS NOMBRES",4,3) ; call outstring (X+15,Y+90,"Les grands nombres (> 9999999 et <-100000)",0,3) ; call outstring (X+15,Y+120,"risquent de provoquer des affichages",0,3) ; call outstring (X+15,Y+150,"disgracieux. Ces nombres sont donc, par",0,3) ; call outstring (X+15,Y+180,"d‚faut remplac‚s par des #####. Si toutefois",0,3) ; call outstring (X+15,Y+210,"vous souhaitez afficher ces valeurs, cliquez",0,3) ; call outstring (X+15,Y+240,"sur 'Affiche num‚rique'.",0,3) ; call outstring (X+275,Y+273,"Fermer",1,7) ; call outstring (X+275,Y+273,"F",0,7) ; if Aff_Num_Grd then call outstring (X+15,Y+273,"Affiche ##### ",1,7) ; else call outstring (X+15,Y+273,"Affiche num‚rique",1,7) ; fi ; call outstring (X+15,Y+273,"A",0,7) ; FinAFF:=False ; while (not FinAFF) do Interupt:=getpress(x_s,y_s,Key1,Key2,Flags,Num_Mouse) ; if Interupt and (Num_Mouse=1 or key2=102 or key2=97) then if B3.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=102 then FinAFF:=True ; call B3.EFF_BOUTON ; call B2.EFF_BOUTON ; call B1.EFF_BOUTON ; fi ; if B2.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=97 then FinAFF:=True ; call B3.EFF_BOUTON ; call B2.EFF_BOUTON ; call B1.EFF_BOUTON ; if Aff_Num_Grd then Aff_Num_Grd:=False ; else Aff_Num_Grd:=True ; fi ; call W3.AFF_MATRICE (M) ; fi ; fi ; od ; end AFF_NUM; (* Procedure de saisie d'une matrice *) unit SAISIE_MATRICE : procedure (Mat : String ; output M : Arrayof arrayof integer) ; var Bouton_Saisie, Bout_Pourcent : BOUTON, i, j, n1, n2, Nb : integer ; begin Bouton_Saisie := new BOUTON (50,230,400,430,3,7,15,8) ; Bout_Pourcent := new BOUTON (70,390,370,410,3,7,8,15) ; call Bouton_Saisie.AFF_BOUTON ; call outstring (120,240,"SAISIE DE LA MATRICE",4,7) ; call outstring (290,240,Mat,4,7) ; call outstring (60,270,"Nombre de lignes (de 1 … 32) :",0,7) ; (* Nombre de lignes et de colonnes ??? *) n1:=hfont(330,270,4,1,32,1,8,0,15) ; call outstring (60,290,"Nombre de colonnes (de 1 … 32) :",0,7) ; n2:=hfont(330,290,4,1,32,1,8,0,15) ; M:= CREATION (n1,n2) ; call Bouton_Saisie.EFF_BOUTON ; call Bouton_Saisie.AFF_BOUTON ; call outstring (120,240,"SAISIE DE LA MATRICE",4,7) ; call outstring (290,240,Mat,4,7) ; call Bout_Pourcent.AFF_BOUTON ; call outstring (70,270,"Entrez la valeur pour la ligne : ",0,7) ; call outstring (70,290," et de la colonne : ",0,7) ; call outstring (70,310," (valeur entre -999 et 999)",0,7) ; call outstring (70,370,"0 % SAISIE 100 % ",1,7) ; nb:=0 ; for j:=1 to upper(M) do call outstring(355,270," ",7,0) ; call track (355,270,j,0,7) ; for i:=1 to upper(M(j)) do call outstring(355,290," ",7,0) ; call track (355,290,i,0,7) ; (* saisie des matrices *) M(j,i):=hfont(330,310,6,-999,999,0,8,0,15) ; nb:=nb+1 ; (* remplissage de la barre de pourcentage *) call patern(74,394,74+(292*(nb)/(n1*n2)),406,1,1) ; od ; od ; call Bouton_Saisie.EFF_BOUTON ; end SAISIE_MATRICE ; unit HORLOGE : procedure ; begin (* on fait tourner l'aiguille de l'horloge*) call color (7) ; call move (395,245) ; case Num when 2 : call draw(395,245-8) ; when 3 : call draw(395+8,245-8) ; when 4 : call draw(395+8,245) ; when 5 : call draw(395+8,245+8) ; when 6 : call draw(395,245+10) ; when 7 : call draw(395-8,245+8) ; when 8 : call draw(395-8,245) ; when 1 : call draw(395-8,245-8) ; esac ; call color (15) ; call move (395,245) ; case Num when 1 : Num:=2 ; call draw(395,245-8) ; when 2 : Num:=3 ; call draw(395+8,245-8) ; when 3 : Num:=4 ; call draw(395+8,245) ; when 4 : Num:=5 ; call draw(395+8,245+8) ; when 5 : Num:=6 ; call draw(395,245+10) ; when 6 : Num:=7 ; call draw(395-8,245+8) ; when 7 : Num:=8 ; call draw(395-8,245) ; when 8 : Num:=1 ; call draw(395-8,245-8) ; esac ; end ; (* Procedure de d‚roulement pas … pas de l'algo. de Strassen *) unit PASAPAS : procedure (M : arrayof arrayof integer ; VarTmp : arrayof integer ; Nb : integer) ; var Interupt, Reprise : boolean, i, x_s, y_s, Key1, Key2, Flags, Num_Mouse : integer ; begin if (not Menu) then (* La premiŠre fois on fait ... Affichage du curseur, initialisation des boutons, affichage du menu, affichage des trois matrices. *) call showcursor ; (* Bouton1 : Bouton du fond du menu *) Bouton1:=new BOUTON (0,0,639,30,3,9,11,1) ; (* B2 .. B6 : Boutons menu (Quitte, Variables, suite, R‚sultat, Aide). *) Bouton2:=new BOUTON (4,4,100,26,0,9,1,11) ; Bouton3:=new BOUTON (102,4,202,26,0,9,1,11) ; Bouton4:=new BOUTON (204,4,304,26,0,9,1,11) ; Bouton5:=new BOUTON (306,4,406,26,0,9,1,11) ; Bouton12:=new BOUTON (408,4,508,26,0,9,1,11) ; Bouton6:=new BOUTON (510,4,610,26,0,9,1,11) ; (* Boutons contextuelles (7 Variables, 8 fin variables, 10 calcul direct). *) Bouton7:=new BOUTON (102,31,252,371,3,3,11,1) ; Bouton8:=new BOUTON (147,330,207,355,2,7,8,15) ; call Bouton1.AFF_BOUTON ; call Bouton2.AFF_BOUTON ; call Outstring (9,7,"Quitter",10,9) ; call Outstring (9,7,"Q",0,9) ; call Bouton3.AFF_BOUTON ; call Outstring (107,7,"Variables >",10,9) ; call Outstring (107,7,"V",0,9) ; call Bouton4.AFF_BOUTON ; call Outstring (209,7,"Suite",10,9) ; call Outstring (209,7,"S",0,9) ; call Bouton5.AFF_BOUTON ; call Outstring (311,7,"R‚sultat",10,9) ; call Outstring (311,7,"R",0,9) ; call Bouton6.AFF_BOUTON ; call Outstring (515,7,"Aide >",10,9) ; call Outstring (523,7,"i",0,9) ; call Bouton12.AFF_BOUTON ; call Outstring (413,7,"Affichage >",10,9) ; call Outstring (413,7,"A",0,9) ; W1:= new WINDOWS("A",upper(V),15,265) ; W2:= new WINDOWS("B",upper(V),335,50) ; W3:= new WINDOWS("Tmp",0,335,265) ; call W1.AFF_MATRICE (V) ; call W2.AFF_MATRICE (W) ; Menu:=true ; fi ; if (nb=1 and (Bouton4.BOUTON_Aff or Bouton5.BOUTON_Aff)) then (* si les calculs sont finis mais qu'il reste les boutons suite et r‚sultat, alors on les effaces *) call Bouton4.EFF_BOUTON ; call Bouton5.EFF_BOUTON ; W3.Titre:="Res" ; call Outstring (342,275,"Res",12,4) ; fi ; if (B_PasAPAS or nb=1) then (* Si on est toujours en Pas … Pas ou que les calculs sont fini, on attend un clique sur quitter, suite ou r‚sultat. *) if Bouton10.Bouton_Aff then call Bouton10.EFF_BOUTON ; fi ; W3.Maxi:=upper(M) ; W3.A1.Max:=upper(M)-4 ; W3.A2.Max:=upper(M)-4 ; call W3.Taille.EFF_BOUTON ; call W3.Taille.AFF_BOUTON ; call track (W3.X+273,W3.Y+184,W3.Maxi,15,0) ; call W3.AFF_MATRICE (M) ; Reprise:=false ; while (not reprise) do Interupt:= getpress(x_s, y_s, Key1, Key2, Flags, Num_Mouse) ; if Interupt and (Num_Mouse=1 or Key2=97 or Key2=102 or Key2=105 or (Key2>112 and Key2<116) or Key2=118) then (* Si le bouton gauche de la souris est enfonc‚ alors *) if Bouton7.BOUTON_Aff then if Bouton8.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or key2=102 then (* Si le menu Variables est ouvert et que l'on a cliquer sur fermer alors ... *) call Bouton8.EFF_BOUTON ; call Bouton7.EFF_BOUTON ; fi ; else if Bouton2.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or key2=113 then (* Clique sur quitter *) call groff ; call endrun ; fi ; if Bouton3.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=118 then call Bouton7.AFF_BOUTON ; if nb>1 then (* clique variables *) for i:=1 to 7 do call outstring (113,30+(i*20),"x :",10,3) ; call track(123,33+(i*20),i,3,10) ; call track(153,30+(i*20),VarTmp(i),3,10) ; od ; fi ; call outstring (108,200,"M‚thode STRASSEN",4,3) ; call outstring (108,270,"M‚thode normale",4,3) ; call outstring (113,220,"Xø :",1,3) ; call track (153,220,Opp(1),3,10) ; call outstring (113,240,"+ø :",1,3) ; call track (153,240,Opp(2),3,10) ; call outstring (113,290,"Xø :",1,3) ; call track (153,290,Opp(3),3,10) ; call outstring (113,310,"+ø :",1,3) ; call track (153,310,Opp(4),3,10) ; call Bouton8.AFF_BOUTON ; call Outstring (153,335,"Fermer",1,7) ; call Outstring (153,335,"F",0,7) ; fi ; if Bouton4.BOUTON_Aff and (Bouton4.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=115) then (* clique sur suite *) Reprise:=True ; fi ; if Bouton5.BOUTON_Aff and (Bouton5.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=114) then (* clique sur r‚sultat *) call Bouton4.EFF_BOUTON ; call Bouton5.EFF_BOUTON ; W3.Titre:="Res" ; call Outstring (342,275,"Res",12,4) ; Reprise:=True ; B_PasAPAS := False ; call Bouton10.AFF_BOUTON ; call outstring (310,210,"Patience, je calcule.",0,7) ; Num:=1 ; call patern(380,230,410,260,0,0) ; call move (380,230) ; call draw (384,234) ; call move (380,260) ; call draw (384,256) ; call move (410,260) ; call draw (406,256) ; call move (410,230) ; call draw (406,234) ; call move (380,245) ; call draw (384,245) ; call move (410,245) ; call draw (406,245) ; call move (395,230) ; call draw (395,234) ; call move (395,260) ; call draw (395,256) ; fi ; if Bouton6.BOUTON_Aff and Bouton6.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=105 then (* clique sur aide *) call AIDE ; fi ; if Bouton12.BOUTON_ENFONCE(1,Num_Mouse,x_s,y_s) or Key2=97 then (* clique sur afficahge des nombres *) call AFF_NUM (100,100,M) ; fi ; call W1.MOUVE_ASC(V,W1.A1,Num_Mouse,X_S,Y_S) ; call W1.MOUVE_ASC(V,W1.A2,Num_Mouse,X_S,Y_S) ; call W2.MOUVE_ASC(W,W2.A1,Num_Mouse,X_S,Y_S) ; call W2.MOUVE_ASC(W,W2.A2,Num_Mouse,X_S,Y_S) ; call W3.MOUVE_ASC(M,W3.A1,Num_Mouse,X_S,Y_S) ; call W3.MOUVE_ASC(M,W3.A2,Num_Mouse,X_S,Y_S) ; fi ; fi ; od ; else call HORLOGE ; fi ; if (Nb=1) then call groff ; fi ; end PASAPAS ; (* Gestion de l'‚cran de pr‚sentation *) unit PRESENTATION : procedure ; Var Bout_Pres : BOUTON, i, j, touche_pres,x_s, y_s, special, flags, Etat_souris : integer, Map : arrayof integer, Interupt:boolean, Stars : arrayof arrayof integer ; (* Allume des ‚toiles sur le fond *) unit ALLUME : procedure (Num : integer) ; begin Stars(Num,1):=Random*638 ; Stars(Num,2):=Random*478 ; Stars(Num,3):=Random*200 ; Stars(Num,4):=Random*15 ; if ((Stars(Num,1)>174) and (Stars(Num,1)<466) and (Stars(Num,2)>139) and (Stars(Num,2)<341)) then Stars(Num,3):=0 ; fi ; if Stars(Num,3)>0 then call color (Stars(Num,4)) ; call Point (Stars(Num,1),Stars(Num,2)) ; call Point (Stars(Num,1)+1,Stars(Num,2)) ; call Point (Stars(Num,1),Stars(Num,2)+1) ; call Point (Stars(Num,1)+1,Stars(Num,2)+1) ; fi ; end ALLUME ; (* Efface les ‚toiles *) unit ETEIND : procedure (Num : integer) ; begin if not ((Stars(Num,1)>174) and (Stars(Num,1)<466) and (Stars(Num,2)>139) and (Stars(Num,2)<341)) then call color (0) ; call Point(Stars(Num,1),Stars(Num,2)) ; call Point (Stars(Num,1)+1,Stars(Num,2)) ; call Point (Stars(Num,1),Stars(Num,2)+1) ; call Point (Stars(Num,1)+1,Stars(Num,2)+1) ; fi ; end ETEIND ; begin call gron(0) ; call ranset(100) ; array Stars dim (1:50) ; for i:=1 to 50 do array Stars(i) dim (1:4) ; call ALLUME(i) ; od ; Bout_Pres:=new BOUTON (175,140,465,340,4,7,15,8) ; call Bout_Pres.AFF_BOUTON ; call color (1) ; call move (190,155) ; call draw (450,155) ; call draw (450,217) ; call draw (190,217) ; for i:=1 to 30 do call move (190,155+(i*2)) ; call draw (230,155+(i*2)) ; od ; call color (7) ; for i:=0 to 1 do call move (226,159+(i*2)) ; call draw (194+i,159+(i*2)) ; call draw (194+i,187-(i*2)) ; call draw (225+i,187-(i*2)) ; call draw (225+i,211+(i*2)) ; call draw (194,211+(i*2)) ; od ; call outstring (236,200,"trassen",1,7) ; call outstring (188,230,"Multiplication de deux matrices",4,7) ; call outstring (188,250,"selon l'algorithme de STRASSEN.",4,7) ; call outstring (188,275,"Auteurs : AKPAMOLI E. HANNOYER P.",0,7) ; call outstring (188,295,"R‚alis‚ en Loglan [Janvier 1995]",0,7) ; call color (5) ; call patern(184,273,450,310,5,0) ; for i:=1 to 2 do call move (450+(i*2),273+(7*i)) ; call draw (450+(i*2),310+(2*i)) ; call draw (184+(i*7),310+(2*i)) ; od ; Map:=GET_MAP (Bout_Pres.X,Bout_Pres.Y,Bout_Pres.XX,Bout_Pres.YY) ; call outstring (188,315," pour continuer ...",15,7) ; touche_pres:=0 ; while (not touche_pres=13) do for i:=1 to 50 do if Stars(i,3)=0 then call ETEIND (i) ; call ALLUME (i) ; else Stars(i,3):=Stars(i,3)-1 ; fi ; od ; Interupt:=getpress(x_s,y_s,special,touche_pres,flags,Etat_souris) ; od ; for i:=1 to 50 do call ETEIND (i) ; od ; call Bout_Pres.EFF_BOUTON ; call Bout_Pres.CHG_BOUTON_XY(15,50) ; call Bout_Pres.AFF_BOUTON ; call PUT_MAP (Bout_Pres.X,Bout_Pres.Y,Map) ; call init (1,0) ; end PRESENTATION; (* FIN PARTIE GRAPHIQUE *) (* DEBUT PARTIE CALCUL *) (* Retourne deux matrice selon la norme pour le calcul avec l'algo. de Strassen (les deux matrices sont de tailles identiques, et leur ordre est une puissance entiŠre de deux). *) unit AJUSTE_MATRICE : procedure (inout M1, M2 : arrayof arrayof integer) ; var i, j : integer, Tmp1, Tmp2 : arrayof arrayof integer, Calcul, Max : integer ; begin (* Mais quel est la valeure la plus grande entre les lignes et les colonnes des deux tableaux ???? (attention si 1 alors 2). *) Max:=imax(2,(imax(imax(upper(M1),upper(M1(1))),imax(upper(M2),upper(M2(1)))))) ; Calcul := LN(Max)/LN(2) ; if (Calcul<>LN(Max)/LN(2)) then (* Max n'est pas une puissance entiŠre de deux alors normalisons : *) Max:=EXPO(2,(Calcul+1)) ; fi ; if upper(M1)2 then (* si l'ordre est plus grand que deux en d‚coupe les matrices en rappelant r‚cursivement STRASSEN*) m:=ordre div 2; call STRASSEN(nb,m,SOMME_PORTION(A,1,4),SOMME_PORTION(B,1,4),P1); call STRASSEN(nb,m,SOMME_PORTION(A,3,4),PORTION(B,1),P2); call STRASSEN(nb,m,PORTION(A,1),SOUST_PORTION(B,2,4),P3); call STRASSEN(nb,m,PORTION(A,4),SOUST_PORTION(B,3,1),P4); call STRASSEN(nb,m,SOMME_PORTION(A,1,2),PORTION(B,4),P5); call STRASSEN(nb,m,SOUST_PORTION(A,3,1),SOMME_PORTION(B,1,2),P6); call STRASSEN(nb,m,SOUST_PORTION(A,2,4),SOMME_PORTION(B,3,4),P7); for i:=1 to m do for j:=1 to m do C(i,j):=SOUST_MATRICE(SOMME_MATRICE(P1,P4),SOUST_MATRICE(P5,P7))(i,j); od; od; for i:=m+1 to ordre do for j:=1 to m do C(i,j):=SOMME_MATRICE(P2,P4)(i-m,j); od; od; for i:=1 to m do for j:=m+1 to ordre do C(i,j):=SOMME_MATRICE(P3,P5)(i,j-m); od; od; for i:=m+1 to ordre do for j:=m+1 to ordre do C(i,j):=SOMME_MATRICE(SOUST_MATRICE(P1,P2),SOMME_MATRICE(P3,P6))(i-m,j-m); od; od; else (* calcul des 7 variables de travail *) x(1):=(A(1,1)+A(2,2))*(B(1,1)+B(2,2)); x(2):=(A(2,1)+A(2,2))*B(1,1); x(3):=A(1,1)*(B(1,2)-B(2,2)); x(4):=A(2,2)*(B(2,1)-B(1,1)); x(5):=(A(1,1)+A(1,2))*B(2,2); x(6):=(A(2,1)-A(1,1))*(B(1,1)+B(1,2)); x(7):=(A(1,2)-A(2,2))*(B(2,1)+B(2,2)); (* Calcul du nombre d'opp‚ration : 1, 2 : xø, +ø pour la m‚thode r‚cursive de Strassen, 3, 4 : xø, +ø pour la m‚thode r‚cursive traditionnelle. *) Opp(1):=Opp(1)+7 ; Opp(2):= Opp(2) + 18 ; Opp(3):=Opp(3)+8 ; Opp(4):= Opp(4) + 4 ; (* Calcul de la matrice r‚sultat avec les variables de travail *) C(1,1):=x(1)+x(4)-x(5)+x(7); C(2,1):=x(2)+x(4); C(1,2):=x(3)+x(5); C(2,2):=x(1)-x(2)+x(3)+x(6); fi ; call PASAPAS (C,x,nb) ; end STRASSEN; (* Function calculant A**B *) unit EXPO : function (A, B : integer):Integer ; begin if (B=0) then result:=1 ; else result:=EXPO(A,B-1)*A ; fi ; end EXPO ; var Prof,Num : integer, W1, W2, W3, W4 : WINDOWS , Menu, Aff_Num_Grd, B_PasAPAS : boolean, Opp : arrayof integer, Bouton1, Bouton2, Bouton3, Bouton4, Bouton5, Bouton6, bouton12, Bouton7, Bouton8, Bouton10 : Bouton, V, W, Z : arrayof arrayof integer ; begin array Opp dim (1:4) ; call PRESENTATION ; call SAISIE_MATRICE("A",V); call SAISIE_MATRICE("B",W); call AJUSTE_MATRICE(V,W) ; call init (1,1) ; B_PasAPAS:=True ; Bouton10:=new BOUTON (300,200,490,270,2,7,15,8) ; call STRASSEN (Prof,upper(V),V,W,Z) ; end ; end ; end STRAS;