source: trunk/etc/src/Ydf1.cc

Last change on this file was 610, checked in by grlod, 12 years ago

header replacements
uml diagrams updated
should have been committed 3 months ago ...

File size: 47.0 KB
Line 
1/*
2Copyright or © or Copr. MMSA team, LOCEAN Paris (2011)
3
4This software is a framework for variational data assimilation in
5numerical models.
6
7This software is governed by the CeCILL license under French law and
8abiding by the rules of distribution of free software.  You can  use,
9modify and/ or redistribute the software under the terms of the CeCILL
10license as circulated by CEA, CNRS and INRIA at the following URL
11"http://www.cecill.info".
12
13As a counterpart to the access to the source code and  rights to copy,
14modify and redistribute granted by the license, users are provided only
15with a limited warranty  and the software's author,  the holder of the
16economic rights,  and the successive licensors  have only  limited
17liability.
18
19In this respect, the user's attention is drawn to the risks associated
20with loading,  using,  modifying and/or developing or reproducing the
21software by the user in light of its specific status of free software,
22that may mean  that it is complicated to manipulate,  and  that  also
23therefore means  that it is reserved for developers  and  experienced
24professionals having in-depth computer knowledge. Users are therefore
25encouraged to load and test the software's suitability as regards their
26requirements in conditions enabling the security of their systems and/or
27data to be ensured and,  more generally, to use and operate it in the
28same conditions as regards security.
29
30The fact that you are presently reading this means that you have had
31knowledge of the CeCILL license and that you accept its terms.
32
33YAO website : http://www.locean-ipsl.upmc.fr/~yao/
34Contact : yao@locean-ipsl.upmc.fr
35*/
36// Contributor : Charles Sorror
37//g++ Ydf1.cc -Wall -o Ydf1
38
39#include <stdio.h>
40#include <string.h>
41#include <stdlib.h>
42#include <ctype.h>
43
44#define BUFSIZE           2048
45#define LG_MAX_NAME         24
46#define NB_MAX_VARIAB    10000
47#define LG_MAX_BIGVAR      128
48#define NB_MAX_EXPRESYM  10000
49#define NB_MAX_DIFFVAR   10000
50//#define NB_MAX_CPLX     1000
51
52/*=============================================================================*/
53struct st_diff {
54        char            vardiff[LG_MAX_NAME*2 + 1];
55        int             deblockportee;
56};
57
58/*=============================================================================*/
59short   trace=0;
60FILE    *fpmodul, *fpginac;
61//char    modul_file_name[LG_MAX_NAME+1];
62int     i, j=0, k;
63char      buffer[BUFSIZE+1];
64char    delim[] =" \t(),\n";
65//char    *pstr1, *pstr3, *pstrw;
66//char    *pstr2=NULL;
67short   Phase=0;
68int     NbIn, NbOut;
69int     indicYS=0;
70int     indic=0;
71char      instruct[BUFSIZE+1];
72short   indicBLOCK=0;
73short   indicCROUV=0;
74short   indicTAB=0;
75char    TabVar[NB_MAX_VARIAB][LG_MAX_BIGVAR+1];
76int     NbVar=0;
77short   indicDECLAR=0;
78short   indicAFFECT=0;
79short   prodlevel=0;
80char    Ysubstit[LG_MAX_NAME+1];
81int     iexp;
82
83char    TabExpreSym[NB_MAX_EXPRESYM][LG_MAX_NAME + 1];
84short   TabFlagIn[NB_MAX_EXPRESYM];
85int     NbExpreSym = 0;
86//char    affectsv[BUFSIZE+1];
87struct  st_diff TabDiff[NB_MAX_DIFFVAR];
88int     NbDiff = 0;
89
90int     CurBlockLev = 0; //semaphore de decompte des accolades pour gerer le niveau d'imbrication des block
91
92char    ModulName[LG_MAX_NAME+1];
93//int     lenModulName;
94
95char    TabDejaDiff[NB_MAX_DIFFVAR][LG_MAX_NAME+1]; //!!! tableau en global a usage local : initialement, et
96int     NbDejaDiff;                                 //    localement, mettre NbDejaDiff a ZERO !
97
98short   flagCPLX=0;
99int     NbInCplx=0;
100//char    TabCplx[NB_MAX_CPLX][LG_MAX_NAME + 1];
101//int     NbCplx=0;
102
103//principaux mots du langage C/C++ (liste non exhaustive ... )
104#define NB_CWORD  109
105char    TabCword [NB_CWORD][LG_MAX_NAME] =
106{       "abs",      "acos",     "asin",     "atan",    "atan2",    "atoi",
107        "atof",     "atol",     "break",    "case",    "char",     "close",  "complex",
108        "const",    "continue", "cos",      "cosh",    "default",  "delete",
109        "div",      "do",       "double",   "enum",    "else",     "exp",
110        "exit",     "extern",   "fabs",     "float",   "fclose"    "feof",
111        "fgetc",    "fgets",    "fopen",    "for",     "fprintf",  "fputc",
112        "fputs",    "free",     "getc",     "getchar", "getenv",   "gets",
113        "goto",     "if",       "int",      "isalnum", "isdigit",  "islower",
114        "isupper",  "log",      "log10",    "long",    "memchr",   "memcmp",
115        "memcpy",   "memove",   "new",      "NULL",    "open",     "pow",
116        "putenv",   "puts",     "rand",     "read",    "return",   "scanf",
117        "setenv",   "sprintf",  "short",    "sin",     "sinh",     "sizeof",
118        "sqrt",     "srand",    "sscanf",   "static",  "stdin",    "stdout",
119        "strcat",   "strchr",   "strcmp",   "strcpy",  "strlen",   "strncat",
120        "strncmp",  "strncpy",  "strpbrk",  "strrchr", "strspn",   "strstr",
121        "strtok",   "strtol",   "struct",   "switch",  "tan",      "tanh",
122        "tolower",  "toupper",  "typedef",  "union",   "unsigned", "void",
123        "volatile", "vfprintf", "vsprintf", "while",   "write",    "YREAL",
124};
125
126/*=============================================================================*/
127
128//*---------------------------------------------------------------------------*/
129int c_word(char *word)
130{   int wi;
131    for (wi=0; wi<NB_CWORD; ++wi)
132    {     if (!strcmp(word, TabCword[wi]))
133                 return (1);
134    }
135    return(0);
136}
137//*---------------------------------------------------------------------------*/
138char *str_affect(char *str)
139{    char *pstr;
140
141     pstr = strstr(str, "+=");  if (pstr != NULL) return pstr;
142     pstr = strstr(str, "-=");  if (pstr != NULL) return pstr;
143     pstr = strstr(str, "*=");  if (pstr != NULL) return pstr;
144     pstr = strstr(str, "/=");  if (pstr != NULL) return pstr;
145
146     pstr = strstr(str, "==");
147     if (pstr != NULL)  return (str_affect(pstr+2));
148     pstr = strstr(str, ">=");
149     if (pstr != NULL)  return (str_affect(pstr+2));
150     pstr = strstr(str, "<=");
151     if (pstr != NULL)  return (str_affect(pstr+2));
152     pstr = strstr(str, "!=");
153     if (pstr != NULL)  return (str_affect(pstr+2));
154     //autres cas non traited plm : <<=, >>=, &=, ^=, |=
155
156     //et enfin le cas d'une simple affectation
157     pstr = strstr(str, "=");  if (pstr != NULL) return pstr;
158
159     return(NULL);
160}
161/*---------------------------------------------------------------------------*/
162void str_lesschr(char *str, char car)
163{ int lg, i,j;
164  lg = strlen(str);
165  i=j=0;
166  for (i=0; i<lg; ++i)
167  {   if (str[i]==car) continue;
168      str[j]=str[i];
169      ++j;
170  }
171  str[j]='\0';
172}
173/*---------------------------------------------------------------------------*/
174int str_qalphanum(char *str)
175{   int lgstr = strlen(str);
176    int i=0;
177    short alphok=0;
178    while (i<lgstr)
179    {  if ( !isalnum(str[i]) && str[i]!='_') return(0);
180       if ( isalpha(str[i]) || str[i]=='_') alphok = 1;
181       ++i;
182    }
183    if (alphok) return(1);
184    return(0);
185}
186/*---------------------------------------------------------------------------*/
187int str_qdigit(char *str)
188{   int lgstr = strlen(str);
189    int i;
190    for (i=0; i<lgstr; ++i)
191    {  if (!isdigit(str[i])) return(0);
192    }
193    return(1);
194}
195/*---------------------------------------------------------------------------*/
196char *str_tok(char *str, char *delim, char *svdelim, char *pmax)
197{    char *p1, *p2;
198
199     if (str>=pmax) return (NULL);
200
201     p1 = str;
202     //se positionner sur le 1er caratere non delimiteur
203     while (p1[0]!='\0' && strchr(delim, p1[0])!=NULL) ++p1;
204     //avancer tant qu'on ne retombe pas sur un caratere delimiteur
205     p2=p1;
206     while (p2[0]!='\0' && strchr(delim, p2[0])==NULL) ++p2;
207     //on informe du delimiteur trouved avant de l'ecraser par '\0'
208     *svdelim=p2[0];
209     p2[0]='\0';
210     return(p1);
211}
212
213/*---------------------------------------------------------------------------*/
214void BackwardOut(char *instruct)
215{    char   *pstr1, *pstr2;
216     char    bufwrk[BUFSIZE+1];
217
218     if (trace) printf("\n/*BO:%s:*/\n", instruct);
219
220     strcpy(bufwrk, instruct);
221     pstr1 = bufwrk;
222                 fprintf(fpginac, "  cout ");
223     while (1)
224     {  pstr2 = strpbrk(pstr1, "\n\"");
225        if (pstr2!=NULL)
226        {
227           if (pstr2[0]=='\n')
228           {  pstr2[0]='\0';
229              fprintf(fpginac," <<\"%s\" <<endl ",pstr1);
230              pstr1=pstr2+1;
231           }
232           else
233           {  pstr2[0]='\0';
234              fprintf(fpginac,"<<\"%s\\\"\" ", pstr1);
235              pstr1=pstr2+1;
236           }
237        }
238        else
239        { fprintf(fpginac," <<\"%s\"",pstr1);
240          break;
241        }
242     }
243     fprintf(fpginac, " ;\n");
244}
245
246/*---------------------------------------------------------------------------*/
247int add_var(char *strvar)
248{
249    if (NbVar>=NB_MAX_VARIAB)
250    {  printf("Ydf1: too much variables in that modul (%s)\n", ModulName);
251       exit(-9);
252    }
253    strcpy(TabVar[NbVar], strvar);
254    ++NbVar;
255    return(NbVar-1);
256}
257
258/*---------------------------------------------------------------------------*/
259short is_yadvar(char *str)
260{   char bufstr[7];
261    strncpy(bufstr, str, 6);  //strcpy(bufstr, str);
262    bufstr[6]='\0';
263    return (!strcmp(bufstr, "Yadvar"));
264}
265
266/*---------------------------------------------------------------------------*/
267int exist_expresym(char *expresym)
268{
269    int wi;
270    for (wi=0; wi<NbExpreSym; ++wi)
271    {   if (!strcmp(expresym, TabExpreSym[wi]))
272           return (1);
273    }
274    return(0);
275}
276
277/*---------------------------------------------------------------------------*/
278int id_diff(char *diff)
279{
280    int wi;
281    for (wi=0; wi<NbDiff; ++wi)
282    {   if (!strcmp(diff, TabDiff[wi].vardiff))
283               return (wi);
284    }
285    return(-1);
286}
287/*---------------------------------------------------------------------------*/
288void decrem_diff_blocklev()
289{
290    int wi;
291    for (wi=0; wi<NbDiff; ++wi)
292    {     if (TabDiff[wi].deblockportee  == CurBlockLev)
293           TabDiff[wi].deblockportee = 0;
294    }
295    --CurBlockLev;
296}
297
298/*---------------------------------------------------------------------------*/
299/*int is_input(char *str)
300{
301    int wi;
302    for (wi=0; wi<NbIn; ++wi)
303    {     if (!strcmp(str, TabExpreSym[wi]))
304                 return (1);
305    }
306    return(0);
307}
308int is_input(char *str)
309{
310    int wi, nballin;
311                nballin = NbIn+NbInCplx;
312    for (wi=0; wi<nballin; ++wi)
313    {     if (!strcmp(str, TabExpreSym[wi]))
314                 return (1);
315    }
316    return(0);
317}
318*/
319int id_input(char *input)
320{
321    int wi, nballin;
322                nballin = NbIn+NbInCplx;
323    for (wi=0; wi<nballin; ++wi)
324    {   if (!strcmp(input, TabExpreSym[wi]))
325               return (wi);
326    }
327    return(-1);
328}
329
330/*---------------------------------------------------------------------------*/
331int id_YSi(char *tok)
332{   int num;
333    if (tok[0]!='Y' || tok[1]!='S') return(0);
334                if (tok[2]=='0') return(0);
335                if (!str_qdigit(&tok[2])) return (0);
336                num = atoi(&tok[2]);
337                if (num<=NbOut) return(num);
338    return(0);
339}
340
341/*---------------------------------------------------------------------------*/
342void transfo_affect(char *instruct, char *pstr2)
343{//   ...VAR {+,-,*,/}= EXPR ;   a tranformer en :--->    VAR = VAR {+,-,*,/} ( EXPR ) ;
344 //   ( avec pstr2 qui pointera sur le = et non plus le {+,-,*,/}= )
345
346     char    bufwrk[BUFSIZE+1];
347     char    *p3;
348
349     //printf("befor|%s|%c|\n", instruct, pstr2[0]);
350
351                 memset(bufwrk, '\0', BUFSIZE+1);
352                 bufwrk[0]=pstr2[-1];
353                 pstr2[-1] = '\0'; //on termine la variable affectee par un '\0'
354
355                 //il faut retrouver la variable affectee (ie se positionner dessus)
356                 p3 = pstr2-2;
357     while ((p3[0]==' ' || p3[0]=='\t') && p3>instruct) --p3; //on remonte les espaces et \t
358     while (p3[0]!=' ' && p3[0]!='\t' && p3>instruct) --p3; //on remonte les autres caractères
359                 if (p3<instruct) p3=instruct; //en faisant attention de rester sur l'instruction
360
361                 //
362                 strcat(bufwrk, "= ");                                                                  //'= '
363                 strcat(bufwrk, p3);                                                                            //VAR
364                 strcat(bufwrk, " ");                                                                           //' '
365                 bufwrk[strlen(bufwrk)] = pstr2[0];               //{'+','-','*','/'}
366                 strcat(bufwrk, " (");                                                                  //' ('
367                 strcat(bufwrk, pstr2+2);                                                               //EXPR ;
368                 bufwrk[strlen(bufwrk)-1] = '\0';               //pour enlever le ';' de fin
369                 strcat(bufwrk, " ) ;");                                                                //et le remplacer par ' ) ;"
370
371                 //
372                 strcat(instruct, bufwrk);
373
374     //printf("after|%s|%c|\n", instruct, pstr2[0]);
375}
376
377/*---------------------------------------------------------------------------*/
378void substitut_by_symbol(char *str)
379{    char    *pstr1, *pmax;
380     char    bufwrk[BUFSIZE+1];
381     char    delim;
382     char    *p1;
383     strcpy(bufwrk, str);
384     memset(str, '\0', strlen(str)); //raz de la string qu'on va
385     //reconstruire en substituant les QAN par leur equivalent symbol
386     pstr1 = bufwrk;
387     pmax = pstr1+strlen(pstr1);
388     while ((p1=str_tok(pstr1, " \n\t", &delim, pmax))!=NULL)
389     {
390               if (str_qalphanum (p1))
391            if (!c_word(p1) && !is_yadvar(p1))
392               if (exist_expresym(p1))
393         {
394                  strcat(str, "Ygs_");
395         }
396         strcat(str, p1);
397         sprintf(str, "%s%c", str, delim);
398               pstr1 = pstr1+strlen(pstr1)+1;
399     }
400}
401
402/*---------------------------------------------------------------------------*/
403void substitut_produce_tab(char *instruct)
404{    //on a detected qu'il y avait 1 (ou plusieurs) tableau dans instruct
405     //on va les substituer, ..., mais avant, il faut les trouver ...
406     char   *pstr1, *pstr2, *pstr3;
407     char    bufwrk[BUFSIZE+1];
408     char    strtab[LG_MAX_BIGVAR+1];
409     int     idvar;
410     int     semcro;
411     char    yadvari[LG_MAX_NAME+1];
412                 //printf("TAB(S) FOUND IN |%s|\n", instruct);
413
414     strcpy(bufwrk, instruct);
415     memset(instruct, '\0', strlen(instruct)); //raz d'instruct qu'on va
416     //reconstruire en substituant les tableaux s'il y en a (risqued!?)
417
418     fprintf(fpginac,"  cout<<endl;\n");
419
420     pstr1 = bufwrk;
421     while (1)
422     {
423        pstr2 = strchr(pstr1, '[');
424        semcro=1;
425        if (pstr2!=NULL)
426        {  //pstr2 pointe sur le debut de tableau, il faut en trouver la fin
427           pstr3=pstr2+1;
428           while (1)
429           {   pstr3=strpbrk(pstr3, "][");
430               if (pstr3!=NULL)
431               {
432                              if (pstr3[0]=='[') ++semcro; else --semcro; //
433                              ++pstr3;
434                  if (pstr3[0]!='['  && semcro==0) break;
435               }
436               else break; //?
437           }
438           //rendu ici, pstr3 est sensed pointer sur l'octet qui suit le
439           //crochet de fin du tableau
440
441           //maintenant, on remonte pstr2 en arriere pour se mettre au debut
442           //de la variable tableau
443           while (pstr2[0]!=' ' && pstr2[0]!='\t' && pstr2[0]!='\n') --pstr2;
444
445           //on met des /0 pour delimiter et creer la string tableau
446           pstr2[0]='\0'; ++pstr2; //debut de la string tableau
447           pstr3[0]='\0';          //fin de la string tableau
448                                         //printf ("->|%s|%s|%s|<-\n", pstr1, pstr2, pstr3+1); //pour verif du decoupage
449
450                 strcpy(strtab, pstr2);
451           str_lesschr(strtab, ' ');
452                                         //printf ("->|%s|<-\n", strtab);
453
454           //ajout de ce tableau comme variable dans un tableaux de variable
455           idvar = add_var(strtab);
456           sprintf (yadvari, "Yadvar%i", idvar); //
457           //creation du symbol pour le tableau
458           fprintf(fpginac,"  symbol %s(\"%s\");\n", yadvari, yadvari);
459
460           //declaration de la variable intermediaire pour backward
461           fprintf(fpginac,"  cout<<\"double %s = %s;\"<<endl;\n", yadvari, strtab);
462
463           //substitution : on reconstruit instruct (qu'on a razeder au debut)
464           strcat(instruct, pstr1);
465           strcat(instruct, " ");
466           strcat(instruct, yadvari);
467
468           //on repositionne pstr1 pour la suite, y'a peut etre encore d'autres tableaux?
469           pstr1 = pstr3+1;
470        }
471        else
472        {  strcat(instruct, pstr1);   //fin de reconstruction de instruct
473           break;
474        }
475     }
476}
477
478/*---------------------------------------------------------------------------*/
479void BackProduce_DAdx(char *instruct)
480{    char   *pstr, *pmax;
481     char   bufwrk[BUFSIZE+1];
482     char   delim;
483     char   *p1;
484     char   DA_dx[LG_MAX_NAME*2+1];
485     int    wi, idiff;
486int nballin, startin;
487nballin = NbIn+NbInCplx;
488if (flagCPLX) startin=NbIn; else startin=0;
489
490     strcpy(bufwrk, instruct);
491     pstr = bufwrk;
492     pmax = pstr+strlen(pstr);
493     while ((p1=str_tok(pstr, " \n\t", &delim, pmax))!=NULL)
494     {
495               if (str_qalphanum(p1))
496            if (!c_word(p1) && !is_yadvar(p1))
497                                 {
498//            for (wi=0; wi<NbIn; ++wi)
499for (wi=startin; wi<nballin; ++wi)
500            {
501                sprintf(DA_dx, "YD%s_d%s", p1, TabExpreSym[wi]);
502                      idiff = id_diff(DA_dx);
503                      if (idiff<0) //ce qui veut dire qu'on rencontre DA_dx pour la 1ere fois
504                {
505                   if (NbDiff>=NB_MAX_DIFFVAR)
506                   {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
507                      printf("       because :=> too much derivative in that modul\n");
508                      exit(-9);
509                   }
510                               strcpy(TabDiff[NbDiff].vardiff, DA_dx);
511                               TabDiff[NbDiff].deblockportee = CurBlockLev;
512                   ++NbDiff;
513                   fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", DA_dx);
514                }
515                else //DA_dx existe deja, mais pour backward il faut eventuellement
516                {    //produire de nouveau la declaration en tenant compte de l'imbrication des blocks !
517                   if (TabDiff[idiff].deblockportee == 0)
518                   {  TabDiff[idiff].deblockportee = CurBlockLev;
519                                  fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", DA_dx);
520                   }
521                }
522            }
523                                 }
524         pstr = pstr+strlen(pstr)+1;
525     }
526}
527
528/*---------------------------------------------------------------------------*/
529void Sto_GinProduce_ExpreSym(char *str)
530{    char    *pstr, *pmax;
531     char    bufwrk[BUFSIZE+1];
532     char    delim;
533     char    *p1;
534     strcpy(bufwrk, str);
535     pstr = bufwrk;
536     pmax = pstr+strlen(pstr);
537/*
538short  vuegal=0;
539printf("SGPESI: |%s|\n", instruct);
540*/
541     while ((p1=str_tok(pstr, " \n\t", &delim, pmax))!=NULL)
542     {
543/*
544if (p1[0]=='=') vuegal=1;
545*/
546               if (str_qalphanum(p1))
547            if (!c_word(p1) && !is_yadvar(p1))
548               if (!exist_expresym(p1))
549               {
550                  if (NbExpreSym>=NB_MAX_EXPRESYM)
551                  {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
552                     printf("       because :=> too much token in that modul\n");
553                     exit(-9);
554                  }
555/*nb: on est dans cette fct que si queaffect,
556CELA N'EST SANS DOUTE PLUS VRAI
557donc la variable n'a pas du faire l'objet
558//    d'une declaration ce qui laisse penser qu'il s'agit d'une variable externe.
559//    Si on est sur le token qui precede le '=', alors cela voudrait dire qu'on est en
560//    train de de modifier cette variable externe, ce qui du coup modifie la fonction
561//    elle meme, ce qui not fair et rend les testdf KO, --> WARNING
562if (!vuegal)
563{  printf("WARNING: you may be are modifying a extenal variable (%s) ...\n", p1);
564   printf("         this is not fair and may make failed the validation functions test\n");
565}
566*/
567                  strcpy(TabExpreSym[NbExpreSym], p1);
568                  ++NbExpreSym;
569                              fprintf(fpginac,"  ex %s;\n", p1);
570                              fprintf(fpginac,"  symbol Ygs_%s(\"Ygs_%s\");\n", p1, p1);
571               }
572               pstr = pstr+strlen(pstr)+1;
573     }
574}
575
576/*---------------------------------------------------------------------------*/
577short dejadiff(char *var2diff)
578{   //char   TabDejaDiff[NB_MAX_DIFFVAR][LG_MAX_NAME+1];
579    //!!! tableau en global a usage local : initialement, et
580                //    localement, mettre NbDejaDiff a ZERO !
581    int wi;
582    for (wi=0; wi<NbDejaDiff; ++wi)
583    {   if (!strcmp(var2diff, TabDejaDiff[wi]))
584               return (1);
585    }
586    return(0);
587}
588
589/*---------------------------------------------------------------------------*/
590void GinBackProduce_dfDf(char *A, char *straffect) //A = straffect
591{                //maintenant, il faut produire les derivees.
592     //1) il faut  produire dans ginac les derivee de tous les QAN de droite pour celui de gauche :
593     //   ex avec : A = f(sB, sB, sC, ...)
594     //   on doit obtenir : da_DB = A.diff(sB,1);  UNE SEULE FOIS
595     //                                                                                 da_DC = A.diff(sC,1);    ...
596     //algo:
597     // pour chaque variable (V) de straffect (en considerant qu'un token QAN !c_word et !yadvare est une variable (quid des constantes?)
598     // construire da_DV
599     // si dA_DV n'existe pas dans Tabdiff alors l'y ajouter et creer "ex da_DV;" pour ginac
600     // produire pour ginac : "da_DV = A.diff(Ygs_V, 1);" une seule fois pour chaque variable
601     char   *pstr, *pmax;
602     char    bufwrk[BUFSIZE+1];
603     char    delim;
604     char    dA_DV[LG_MAX_NAME*2+1];
605     int     idiff;
606     char    *p1;
607
608                 NbDejaDiff=0; //usage du tableau TabDejaDiff pour s'assurer qu'on ne derive qu'une seule fois une variable
609                               //et meme si, lorsqu'en particulier elle apparait plusieurs fois en partie droite
610
611     strcpy(bufwrk, straffect);
612                 pstr = bufwrk;
613     pmax = pstr+strlen(pstr);
614     while ((p1=str_tok(pstr, " \n\t", &delim, pmax))!=NULL)
615     {
616               if (str_qalphanum(p1))
617            if (!c_word(p1) && !is_yadvar(p1))
618         {
619               sprintf(dA_DV, "Yd%s_D%s", A, p1);
620                     idiff = id_diff(dA_DV);
621                     if (idiff<0) //ce qui veut dire qu'on rencontre dA_DV pour la 1ere fois
622               {
623                  if (NbDiff>=NB_MAX_DIFFVAR)
624                  {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
625                     printf("       because :=> too much derivative in that modul\n");
626                     exit(-9);
627                  }
628                              strcpy(TabDiff[NbDiff].vardiff, dA_DV);
629                              TabDiff[NbDiff].deblockportee = CurBlockLev;
630                  ++NbDiff;
631                              fprintf(fpginac,"  ex %s;\n", dA_DV);
632                  fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", dA_DV);
633               }
634               else //dA_DV existe deja, mais pour backward il faut eventuellement
635               {    //produire de nouveau la declaration en tenant compte de l'imbrication des blocks !
636                  if (TabDiff[idiff].deblockportee == 0)
637                  {  TabDiff[idiff].deblockportee = CurBlockLev;
638                                 fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", dA_DV);
639                  }
640               }
641
642                                                         //pour ne produire la derivee qu'une seule fois
643                                                         if (!dejadiff(dA_DV))
644               {  if (NbDejaDiff>=NB_MAX_DIFFVAR)
645                  {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
646                     printf("       because :=> too much derivative in that modul\n");
647                     exit(-9);
648                  }
649                                                                  strcpy(TabDejaDiff[NbDejaDiff], dA_DV);
650                                                                        ++NbDejaDiff;
651                                                            fprintf(fpginac,"  %s = %s.diff(Ygs_%s, 1);\n", dA_DV, A, p1);
652                  fprintf(fpginac,"  cout<<\"%s = \" <<csrc<< %s <<\";\"<<endl;\n", dA_DV, dA_DV);
653               }
654         }
655               pstr = pstr+strlen(pstr)+1;
656     }
657}
658
659/*---------------------------------------------------------------------------*/
660void BackProduce_Dfdx(char *A, char *straffect)
661{    //2) puis il faut produire la derivee du terme de gauche par rapport aux entrees.
662     //   il s'agit de faire, directement dans le backward, la somme pour chaque entree xi :
663     //             DA_dxi = dA_DV1.DV1_dxi + ... + dA_DVn.DVn_dxi
664     char   *pstr, *pmax;
665     char    bufwrk[BUFSIZE+1];
666     char    delim;
667     char    DA_dx[LG_MAX_NAME*2+1];
668     int     wi;
669     char    dA_DV[LG_MAX_NAME*2+1];
670     int     idiff;
671     char    *p1;
672     char    DV_dx[LG_MAX_NAME*2+1];
673int nballin, startin;
674nballin = NbIn+NbInCplx;
675if (flagCPLX) startin=NbIn; else startin=0;
676     //pmax = straffect+strlen(straffect);
677//---
678//     for (wi=0; wi<NbIn; ++wi)
679//for (wi=startin; wi<nballin; ++wi)
680for (wi=0; wi<nballin; ++wi)
681     {
682if (TabFlagIn[wi]==-1) continue; //entree reelle comprise dans une entree complexe
683
684         if (indicYS<=0) //(!isYSi)
685         {
686            sprintf(DA_dx, "YD%s_d%s", A, TabExpreSym[wi]);
687                  idiff = id_diff(DA_dx);
688                  if (idiff<0) //ce qui veut dire qu'on rencontre DA_dx pour la 1ere fois
689            {
690               if (NbDiff>=NB_MAX_DIFFVAR)
691               {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
692                  printf("       because :=> too much derivative in that modul\n");
693                  exit(-9);
694               }
695                           strcpy(TabDiff[NbDiff].vardiff, DA_dx);
696                           TabDiff[NbDiff].deblockportee = CurBlockLev;
697               ++NbDiff;
698               fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", DA_dx); //+pB
699            }
700            else //DA_dx existe deja, mais pour backward il faut eventuellement
701            {    //produire de nouveau la declaration en tenant compte de l'imbrication des blocks !
702               if (TabDiff[idiff].deblockportee == 0)
703               {  TabDiff[idiff].deblockportee = CurBlockLev;
704                              fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", DA_dx);
705               }
706            }
707         }
708         else
709            sprintf(DA_dx, "YJ%iI%i", indicYS, wi+1);
710//---
711         fprintf(fpginac,"  cout<<\"%s = \";", DA_dx);
712
713                                 NbDejaDiff=0;
714
715             strcpy(bufwrk, straffect);
716         pmax = bufwrk+strlen(bufwrk);
717         pstr = bufwrk;
718               while ((p1=str_tok(pstr, " \n\t", &delim, pmax))!=NULL)
719           {
720                   if (str_qalphanum(p1))
721                 if (!c_word(p1) && !is_yadvar(p1))
722             {
723                                                                  sprintf(dA_DV, "Yd%s_D%s", A, p1);
724                                                                  sprintf(DV_dx, "YD%s_d%s", p1, TabExpreSym[wi]); //.
725
726                                                            //pour ne produire la derivee qu'une seule fois
727                                                                        if (!dejadiff(dA_DV))
728                                                                        {  if (NbDejaDiff>=NB_MAX_DIFFVAR)
729                                                                                 {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
730                                                                                          printf("       because :=> too much derivative in that modul\n");
731                                                                                                 exit(-9);
732                                                                                        }
733                                                                                        strcpy(TabDejaDiff[NbDejaDiff], dA_DV);
734                                                                                        ++NbDejaDiff;
735                      if (!strcmp(p1, TabExpreSym[wi]))
736                      {  //fprintf(fpginac,"  cout<<\"Yd%s_D%s + \";", A, p1);
737                                                                               fprintf(fpginac,"  cout<<\"%s + \";", dA_DV);
738                      }
739                      else if (id_input(p1)==-1) //(!is_input(p1))
740                      {  //fprintf(fpginac,"  cout<<\"Yd%s_D%s*YD%s_d%s + \";", A, p1, p1, TabExpreSym[wi]);
741                         if (id_diff(DV_dx)>=0) //on s'assure que DV_dx existe bien ...
742                                                                                            fprintf(fpginac,"  cout<<\"%s*%s + \";", dA_DV, DV_dx);
743                      }
744                                                                        }
745             }
746                   pstr = pstr+strlen(pstr)+1;
747         }
748               fprintf(fpginac,"  cout <<\"0;\"<<endl;\n");
749     }
750}
751
752/*----------------------------------------------------------------------------*/
753/*============================================================================*/
754void quedeclar (char *instruct, char *pstr2)
755{  if (trace) printf("\n/*indicDECLAR & !indicAFFECT:|%s|%s|*/\n", instruct, pstr2);
756   //un token de Type (double, float, ...) a ete rencontred et pstr2 pointe dessus
757   //exemple soil_CG:         "} else { double ZFROZEN2;"
758   //on va decouper l'instruction en 2 morceaux : Debut (instruct), et la declaration proprement dite (pstr2)
759   pstr2[-1]='\0'; //nb: le token est en principe preceded d'au moins un ' ' ou '\t'
760   //on produit le debut
761   if (instruct<pstr2)
762      BackwardOut(instruct); //d'abord le debut de l'instruction
763
764   //on produit DAdx pour backward
765   BackProduce_DAdx(pstr2);
766         //on stocke et produit pour ginac les QAN d'instruct dans TabExp si ils n'existe pas deja (ni en symbol)
767   Sto_GinProduce_ExpreSym(pstr2);
768
769   //on reconduit la suite (declaration proprement dite) tel quel pour backward
770   BackwardOut(pstr2);
771}
772
773/*---------------------------------------------------------------------------*/
774void quedeclar_cplx(char *instruct, char *pstr2)
775{    char    *pstr, *pmax;
776     char    bufwrk[BUFSIZE+1];
777     char    delim;
778     char    *p1;
779     char    varcplx[LG_MAX_NAME+1];
780                 short   flagvarcplx=0;
781                 //short flagisinput=0;
782                 short   idin1=-1,idin2=-1;
783
784//exemple1:         "} else { complex < double > beta ( betr , beti ) ;"
785//                            ^
786//exemple2:         "} else { complex < double > beta ( betr , beti ), alpha ( ar , ai ), gamma;"
787//                            ^
788     pstr2[-1]='\0'; //nb: le token est en principe preceded d'au moins un ' ' ou '\t'
789     //on produit le debut
790     if (instruct<pstr2)
791        BackwardOut(instruct); //d'abord le debut de l'instruction
792
793     strcpy(bufwrk, pstr2);
794     pstr = bufwrk;
795     pmax = pstr+strlen(pstr);
796     while ((p1=str_tok(pstr, " \t", &delim, pmax))!=NULL)
797     {
798                     if ((p1[0]==')' || p1[0]==';') && flagvarcplx==1)          // fin de la variable complexe precedente
799                                 {
800                                                //a la fin, si flagisinput vaut 2 alors il s'agit une variable complexe d'entree
801                                                //if (flagisinput==2)
802                                                //Si idin1 et idin2 on une valeur d'indice alors (...) : variable complexe (d'entree?)
803                                                if (idin1>=0 && idin2>=0)
804                                                {  TabFlagIn[idin1] = TabFlagIn[idin2] = -1; //on neutralise ces entrees car c'est le complexe
805                                                                ++NbInCplx;                               //associed qui devient la variable d'entree
806                                                                //idin1 = idin2 = -1;
807                                                                //flagvarcplx=0;
808                                                }
809                                                else    //sinon, il s'agit d'une variable intermediaire, on produit DAdx pour backward
810                                                {  BackProduce_DAdx(varcplx);
811                                                }
812
813                                    //re-init et passage a l'eventuelle variable suivante
814                                    flagvarcplx=0;
815                                                idin1 = idin2 = -1;
816            pstr = pstr+strlen(pstr)+1; //pour avancer sur la chaine de carateres
817                                    continue;
818                                 }
819
820               if (str_qalphanum(p1))
821            if (!c_word(p1) && !is_yadvar(p1))
822                                 {
823            if (!flagvarcplx)
824                                                {  //on est sur le 1er token apres "double",  donc c'est sense etre le
825                                                   //nom de la variable complexe beta
826
827/*xxxxxxxxx
828                                                         if (!exist_expresym(p1))
829                                                         {  if (NbExpreSym>=NB_MAX_EXPRESYM)
830                                                                        {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
831                                                                                        printf("       because :=> too much token in that modul\n");
832                                                                                        exit(-9);
833                                                            }
834                                                            strcpy(TabExpreSym[NbExpreSym], p1);
835                                                            ++NbExpreSym;
836                                                            fprintf(fpginac,"  ex %s;\n", p1);
837                                                            fprintf(fpginac,"  symbol Ygs_%s(\"Ygs_%s\");\n", p1, p1);
838                                                         }
839*/
840                                                         Sto_GinProduce_ExpreSym(p1);
841/*xxxxxxxxx
842//             if (!exist_cplx(p1))
843                                                   {  if (NbCplx>=NB_MAX_CPLX)
844                  {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
845                     printf("       because :=> too much complex token in that modul\n");
846                     exit(-9);
847                  }
848                  strcpy(TabCplx[NbCplx], p1);
849                  ++NbCplx;
850                                                         }
851*/
852                                                         strcpy(varcplx, p1); //="beta"
853                                                   flagvarcplx=1;
854                                                }
855                                                else
856                                                {  //on est sur une des variables d'entree (betr ou beti) qui forme le complexe
857                                                   //if (is_input(p1)) ++flagisinput;
858                                                         if (idin1==-1) idin1=id_input(p1);
859                                                         else idin2=id_input(p1);
860                                                }
861
862                                 }
863         pstr = pstr+strlen(pstr)+1;
864     }
865
866                 //on reconduit la suite (declaration proprement dite) tel quel pour backward
867     BackwardOut(pstr2);
868}
869
870
871/*---------------------------------------------------------------------------*/
872/*=============================================================================*/
873void queaffect(char *instruct, char *pstr2)
874{  char   *pstr3;
875   char   affectsv[BUFSIZE+1];
876
877         if (trace) printf("\n/*indicAFFECT:|%s|%s|*/\n", instruct, pstr2);
878   //des tokens d'affectation ('=', '+=', '-=', '*=', '/=')
879   //on ete detected ... et pstr2 pointe dessus printf ("|%s|\n|%s|\n", instruct, pstr2);
880         //exemple:  "} else { double ZFROZEN2 = x1 ;"
881
882   //si on a VAR {+,-,*,/}= EXPR; on va transformer en VAR = VAR {+,-,*,/} ( EXPR );
883         if (pstr2[0]=='+' || pstr2[0]=='-' || pstr2[0]=='*' || pstr2[0]=='/')
884         {  //printf("avant:|%s|%p|%c|\n", instruct, pstr2, pstr2[0]);
885            transfo_affect(instruct, pstr2); //(! modifie la chaine passed mais pstr2 doit pointer sur '=')
886      //printf("apres:|%s|%p|%c|\n", instruct, pstr2, pstr2[0]);
887         }
888
889         //si les variables sont externes au module (une variable globale par exemple)
890         //il faut quand meme la declarer pour ginac
891         Sto_GinProduce_ExpreSym(instruct);
892
893         //ensuite, on va decouper l'instruction en 3 morceaux : Debut (instruct)  Variable(pstr3) Suite(pstr2)
894   --pstr2;
895   while ((pstr2[0]==' ' || pstr2[0]=='\t') && pstr2>instruct) --pstr2; //on remonte les espaces et \t
896   pstr3=pstr2; //pstr3 va servire a pointer sur le debut de la variable affectee
897   while (pstr3[0]!=' ' && pstr3[0]!='\t' && pstr3>instruct) --pstr3; //on remonte les autres caractères
898         if (pstr3>=instruct)  //si on est pas au debut de instruct
899   {  pstr3[0]='\0'; //on met un '\0' avant la variable affected
900      ++pstr3;
901   }
902   ++pstr2; pstr2[0]='\0'; //on met un '\0' apres la variable
903   ++pstr2; //pour ne pas perdre la partie affectation de la suite de 'instruction
904   //on devrait etre dans la situation suivante: ex:  "   if ( C1 ) " "A"    " = pow ( x , 2 ) , B ; "
905         //                                                  ^instruct       ^pstr3 ^pstr2
906
907   //au passage, on interdit l'affectation des variables d'input ...!
908   if (id_input(pstr3)!=-1) //(is_input(pstr3))
909   {  printf (" Ydf1: Automatic derivative failed for modul %s\n", ModulName);
910      printf ("       because :=> input values must not be changed !\n");
911                        exit (-9);
912   }
913
914   //positionnenemt d'un flag pour savoir s'il s'agit d'un YSi
915   indicYS = id_YSi(pstr3);
916
917   //puis on produit pour backward
918         if (instruct<pstr3) BackwardOut(instruct); //d'abord le debut de l'instruction (si different de pstr3)
919   if ((indicBLOCK-indicCROUV)>0) //if (indicBLOCK && !indicCROUV)
920   {  fprintf(fpginac,"  cout << \"{\"<<endl;\n"); //et eventuellement, on rajoute un crochet ouvrant ('{')
921      ++CurBlockLev; //printf("+CurBlockLev=%i\n", CurBlockLev);
922   }
923
924   //si on a detecter un tableau on passe et on le remplace par une variable intermediaire
925         if (indicTAB) substitut_produce_tab(pstr2); // puis les tableaux s'il y a lieu (! modifie la chaine passed)
926
927         //pour ginac il faut reconduire l'affectation en remplacant les variables de la partie droite par des symbols
928   //on sauvegarde donc cette partie droite car on devra la reproduire pour backward mais seulement apres les derivee
929   strcpy(affectsv, pstr2);    //sauvegarde pour backward
930         substitut_by_symbol(pstr2); //on remplace les QAN par leur equivalent symbol(! modifie la chaine passed)
931   fprintf(fpginac,"  %s %s\n", pstr3, pstr2); //et on produit pour ginac
932
933         //maintenant, il faut calculer les derivees.
934   //1) il faut  produire dans ginac les derivee de tous les QAN de droite pour celui de gauche :
935   //   ex avec : A = f(sB, sB, sC, ...)
936   //   on doit obtenir :  da_DB = A.diff(sB,1);  UNE SEULE FOIS
937   //                                                                            da_DC = A.diff(sC,1);                  ...
938         GinBackProduce_dfDf(pstr3, affectsv);
939
940   //2) puis il faut produire dans le backward directement, la derivee du terme de gauche par rapport aux entrees.
941   //   il s'agit de faire, la somme pour chaque entree xi :
942   //             DA_dxi = dA_DV1.DV1_dxi + ... + dA_DVn.DVn_dxi
943         BackProduce_Dfdx(pstr3, affectsv);
944
945   //on termine par l'affectation pour backward (sauf pour YSi a moins que level>=9 !?)
946   if (indicYS<=0 || (indicYS>0 && prodlevel>=9))
947   {
948                        BackwardOut(pstr3);          //la variable
949      fprintf(fpginac,"  cout <<\" \";\n"); //(un espace separateur?)
950                        BackwardOut(affectsv);       //puis la suite (partie affectation prealablement sauvegarded)
951   }
952
953         //eventuellement, il faut terminer par une accolade fermante ('}')
954   if ((indicBLOCK-indicCROUV)>0) //if (indicBLOCK && !indicCROUV)
955   {  fprintf(fpginac,"  cout <<endl<< \"}\"<<endl;\n");
956      decrem_diff_blocklev(); //--CurBlockLev; //printf("+CurBlockLev=%i\n", CurBlockLev);
957   }
958}
959/*----------------------------------------------------------------------------*/
960/*============================================================================*/
961void declaretaffect (char *instruct, char *pstr2)
962{  //declaration et affectation: ex : if (... double A=vglob1, B=pow(A,2), C, D=A*vglob2;
963   //pstr2 pointe sur le type
964         char   *p3;
965         char   *paffect;
966         char   winst[BUFSIZE +1];
967         int    entre;
968         int    wi, last;
969         int    blockindic=0;
970
971   if (trace) printf("\n/*indicDECLAR & indicAFFECT:|%s|%s|*/\n", instruct, pstr2);
972
973   //on produit le debut
974         pstr2[-1]='\0'; //nb: le token est en principe preceded d'au moins un ' ' ou '\t'
975   if (instruct<pstr2) BackwardOut(instruct); //d'abord le debut de l'instruction (si different de pstr2)
976
977   //puis ici, y'a peut etre bien des crochet ....
978   if ((indicBLOCK-indicCROUV)>0) //if (indicBLOCK && !indicCROUV)
979   {  fprintf(fpginac,"  cout << \"{\"<<endl;\n"); //et eventuellement, on rajoute une accolade ouvrante ('{')
980      ++CurBlockLev; //printf("+CurBlockLev=%i\n", CurBlockLev);
981                        //et on neutralise le flag indicBLOCK pour pas avoir des accolades en double par la fct queaffect()
982            //blockindic=1; indicBLOCK=0;
983                        blockindic=indicBLOCK;  indicBLOCK=indicCROUV;
984   }
985
986         //on se positionne a la fin du type pour l'isoler
987         p3 = pstr2;
988         while (p3[0]!=' ' && p3[0]!='\t') ++p3;
989         p3[0]='\0';
990         ++p3;
991
992         //puis, on remplace toutes les ',' qui ne sont pas entre ({[]}) par ';'
993         //a partir de p3
994         entre = 0;
995         wi=0; last=0;
996         while (!last)
997         {   if (p3[wi]==';') last=1;
998
999             if (p3[wi]=='(' || p3[wi]=='{' || p3[wi]=='[') ++entre;
1000             if (p3[wi]==')' || p3[wi]=='}' || p3[wi]==']') --entre;
1001                         if (p3[wi]==',' && entre==0) p3[wi]=';';
1002
1003                         if (p3[wi]==';') //il faut traiter le cas   icicicicici
1004                         {  if (!last) p3[wi+1]='\0';
1005                            if ((paffect = str_affect(p3)) != NULL)
1006                                        {  //on traite l'aspect declaration
1007                                           paffect[-1] = '\0'; //ca isole la variable
1008                                                 sprintf(winst, " %s %s ;\n", pstr2, p3); //on formate la declaration
1009                                                 quedeclar(winst, winst);                                                     //et on la traite
1010
1011                                                 //on traite l'aspect affectation
1012                                                 sprintf(winst, " %s %s \n", p3, paffect);
1013                                                 paffect = str_affect(winst);
1014                                                 queaffect(winst, paffect);
1015                                        }
1016          else // il ne s'agit que d'une declarartion
1017                                        {   sprintf(winst, " %s %s \n", pstr2, p3); //on formate la declaration
1018                                                  quedeclar(winst, winst);                                                   //et on la traite
1019                                        }
1020
1021                                        p3 = &p3[wi+2]; //equiv: p3 = p3+wi+2;
1022                                        wi = 0;
1023                         }
1024                         else
1025                            ++wi;
1026         }
1027
1028   //eventuellement, on ajoute une accolade fermante ('}') et on restaure le flag indicBLOCK
1029   if (blockindic) //(blockindic>0)
1030   {  fprintf(fpginac,"  cout <<endl<< \"}\"<<endl;\n");
1031      decrem_diff_blocklev(); //--CurBlockLev; //printf("+CurBlockLev=%i\n", CurBlockLev);
1032      indicBLOCK=blockindic; //indicBLOCK=1;
1033   }
1034
1035         //printf("\n/*indicDECLAR & indicAFFECT:|%s|%s|*/\n", instruct, pstr2);
1036}
1037
1038/*=============================================================================*/
1039/* en entree : un nom de module.h qui est sensee contenir une fonction forward */
1040/* en sortie : un programme qui saura generer une fonction backward            */
1041/*=============================================================================*/
1042/*---------------------------------------------------------------------------*/
1043int main (int argc, char *argv[])
1044{  //syntaxe: Ydf1 wrk_modul_in_file_name  module  nbin  nbout  [prodlevel]
1045        int     nbinfound=0;
1046  char    *paffect;
1047        char      *pstr1;
1048  char    *pstr2=NULL;
1049        char      modul_file_name[LG_MAX_NAME+1];
1050        int     lenmodulname;
1051  printf("Ydf1:id:3\n");
1052
1053   /* debut : verif arg, ouverture fichier ... :::::::::::::::::::::::::::::::*/
1054  if (argc < 5 || argc > 6)
1055        {  printf (" Ydf1: Syntaxe error: Ydf1 modul_file_name module_name nbin nbout [prodlevel]}\n");
1056           exit(-9);
1057        }
1058
1059        strcpy(modul_file_name, argv[1]);
1060        if ((fpmodul = fopen(modul_file_name, "r")) <= 0)
1061        {  printf (" Ydf1: In file (%s) not found \n", argv[1]);
1062           exit(-9);
1063        }
1064
1065  if (argc==6)
1066  {  prodlevel=atoi(argv[5]);
1067  }
1068
1069  NbIn  = atoi(argv[3]);
1070  NbOut = atoi(argv[4]);
1071
1072  /*-----*/
1073        if ((fpginac = fopen("Y37wrk.cc", "w")) <= 0)
1074        {  printf (" Ydf1: Pb when opening out file (Y37wrk.cc)\n");
1075           exit(-9);
1076        }
1077  /*-----*/
1078
1079        //on recupere le nom du module (pour apres)
1080        strcpy(ModulName, argv[2]);                                     //en enlevant
1081        lenmodulname = strlen(ModulName);   //eventuellement .h
1082        if (ModulName[lenmodulname-1]=='h' && ModulName[lenmodulname-2]=='.')
1083           ModulName[lenmodulname-2]='\0';
1084
1085  /* entête */
1086  fprintf (fpginac, "#include <iostream>\n");
1087  fprintf (fpginac, "#include <ginac/ginac.h>\n");
1088  fprintf (fpginac, "using namespace std;\n");
1089  fprintf (fpginac, "using namespace GiNaC;\n");
1090  fprintf (fpginac, "int main()\n");
1091  fprintf (fpginac, "{\n");
1092
1093  memset(instruct, '\0', BUFSIZE+1); //instruct[0]='\0';
1094
1095  /* boucle de lecture du module */
1096  while (  (fgets(buffer, BUFSIZE+1, fpmodul)) != NULL)
1097  {   //printf("lu|%s|\n", buffer);
1098
1099                  pstr1 = strtok(buffer, delim);
1100      while (pstr1!=NULL)
1101      {   //printf("pstr1=|%s|\n", pstr1);
1102
1103          if (!strcmp(pstr1, "{")) ++CurBlockLev;
1104          if (!strcmp(pstr1, "}")) decrem_diff_blocklev(); //--CurBlockLev; //printf("CurBlockLev=%i\n", CurBlockLev);
1105          //----------------------------------------------------------
1106          //traitement ligne forward
1107                                        //----------------------------------------------------------
1108          if (Phase==0 && !strcmp(pstr1, "forward"))
1109          {  Phase=1;
1110          }
1111          else if (Phase==1)
1112          {  if (!strcmp(pstr1, "{")) //if (pstr1[0]=='{')
1113             {
1114                if (nbinfound != NbIn)
1115                {  printf (" Ydf1: Automatic derivative failed for modul %s\n", ModulName);
1116                   printf ("       because :=> Desagree on input: found %i expected %i\n", nbinfound, NbIn);
1117                                                                         exit (-9);
1118                }
1119                fprintf(fpginac, "  cout << \"void %s::backward (", ModulName);
1120                for (k=0; k<NbIn-1; ++k)
1121                    fprintf(fpginac, "YREAL  %s, ", TabExpreSym[k] );
1122                fprintf(fpginac, "YREAL  %s ", TabExpreSym[k] );
1123                fprintf(fpginac, ")\"<<endl<<\"{\";\n");
1124
1125                Phase=2;
1126                                                                strcpy(delim," \t");  //delimiteur pour la PHASE 2
1127             }
1128             else
1129             {  //traitement ligne forward : symbole d'input
1130                if (strcmp(pstr1, "YREAL"))
1131                {  //chouette voici un symbole d'input //printf ("symbol=%s\n", pstr1);
1132                                                                         Sto_GinProduce_ExpreSym(pstr1);
1133                   ++nbinfound;
1134               }
1135             }
1136          }
1137                                        //----------------------------------------------------------
1138          // fin ligne forward, maintenant il s'agit de traiter le corps
1139                                        //----------------------------------------------------------
1140          //algo : on stock les tokens dans une chaine jusqu'a un ';'
1141                                  else if (Phase==2)
1142          {
1143                                                        //stockage (par concatenation) des tokens dans la chaine instruct
1144                                                  sprintf (instruct, "%s %s", instruct, pstr1);
1145
1146              //indicateurs ...
1147              if      (!strcmp(pstr1, "complex"))
1148              {  flagCPLX=1;
1149                                                           //ne pas casser pstr2 si deja positionned
1150                                                                 if (pstr2==NULL) //if (!indicAFFECT) //sinon il doit s'agir d'un cast
1151                                                           {  pstr2=instruct+strlen(instruct)-strlen(pstr1);
1152                                                                    indicDECLAR = 1;
1153                                                                 }
1154              }
1155              else if (!strcmp(pstr1, "if"))      ++indicBLOCK; //indicBLOCK  = 1;
1156              else if (!strcmp(pstr1, "else"))    ++indicBLOCK; //indicBLOCK  = 1;
1157              else if (!strcmp(pstr1, "while"))   ++indicBLOCK; //indicBLOCK  = 1;
1158              else if (!strcmp(pstr1, "for"))     ++indicBLOCK; //indicBLOCK  = 1;
1159              else if (!strcmp(pstr1, "{"))       ++indicCROUV; //indicCROUV  = 1;
1160              else if (strchr(pstr1, '[')!=NULL)  indicTAB    = 1;
1161              else if ( !strcmp(pstr1, "YREAL") || !strcmp(pstr1, "double")  || !strcmp(pstr1, "int")
1162              ||        !strcmp(pstr1, "long")  || !strcmp(pstr1, "float")
1163                      )
1164              {  //ne pas casser pstr2 si deja positionned
1165                                                           if (pstr2==NULL) //if (!indicAFFECT) //sinon il doit s'agir d'un cast
1166                                                           {  pstr2=instruct+strlen(instruct)-strlen(pstr1);
1167                                                                    indicDECLAR = 1;
1168                                                                 }
1169              }
1170
1171                                                        paffect = str_affect(pstr1);
1172                                                        if (paffect != NULL)
1173                                                        {  //if (!indicAFFECT && !indicDECLAR) //... ne pas casser pstr2 si deja positionned
1174                                                           if (pstr2==NULL) //... ne pas casser pstr2 si deja positionned
1175                                                           {  //pstr2 = paffect;
1176                                                                    pstr2 = instruct+strlen(instruct)-strlen(paffect);
1177                                                                 }
1178                                                           indicAFFECT = 1;
1179                                                        }
1180
1181              //au passage, on s'assurer qu'YS* n'apparait pas en partie droite
1182              //because c'est pas pratique a gerer, mais ce peut etre une source d'erreur !!!??? ...
1183              if  (indicAFFECT || indicDECLAR) //on est donc soit deja en partie droite d'une affectation,
1184              {                                //soit sur une declaration et la aussi YSi ne doit pas apparaitre
1185                                  if (id_YSi(pstr1)>0)
1186                  {  printf (" Ydf1: Automatic derivative failed for modul %s\n", ModulName);
1187                     printf ("       because :=> YSi must not appears neither on declaration or on right side of an affectation !\n");
1188                                                                           exit (-9);
1189                  }
1190              }
1191
1192                    //fin de constitution de la chaine; il faut traiter
1193              if  (!strcmp(pstr1, ";"))
1194              {
1195                  if (indicDECLAR && !indicAFFECT)  //=> SI QUE DECLAR
1196                                                                        {        if (flagCPLX)                                                                                   //ex:  " if ( C1 ) complex < double > A ( rA , iA ) ; "
1197                                                                              quedeclar_cplx(instruct, pstr2); //                           ^
1198                                                                           else //cas 'normal'
1199                                                                                    quedeclar(instruct, pstr2);   //ex:  " if ( C1 ) double A ; "
1200                                                                                                                                                                                                                  //      ^instruct  ^pstr2
1201                                                                        }
1202                  else if (indicDECLAR) //=> SI DECLAR ET AFFECT
1203                  {  declaretaffect(instruct, pstr2); //ex:  "if ( C1 )  double A = pow ( x , 2 ) , B ; "
1204                                                                        }                                   //      ^instruct  ^pstr2
1205                                                                        else if (indicAFFECT) //=> SI QUE AFFECT
1206                  {   queaffect(instruct, pstr2);     //ex:  "   if ( C1 )  A = pow ( x , 2 ) , B ; "
1207                                                                        }                                   //      ^instruct       ^pstr2
1208                  else
1209                  {  // ???!!!! reconduit-on ou pas tel quel !!!???
1210                     if (prodlevel==1 || prodlevel>2)
1211                     {  //on reproduite tel quel, QUE pour BACKWARD et donc RIEN pour GINAC.
1212                        //il doit s'agir de ce genre d'instruction dont on ne sait que faire
1213                        //pour la derivation comme *printf*, *str*, *get*, *scan*, io, ...
1214
1215                        //j'ai un pb avec les " exemple :  strcpy ( toto , "toto" ) ; ...
1216                        //ca devrait etre regled
1217                        //printf("  cout << \"%s\";\n", instruct);
1218                                                                                                BackwardOut(instruct); //par contre c'est ok pour par exemple:  strcpy(toto,titi);
1219                     }
1220                  }
1221
1222                  //re-init pour instruction suivante
1223                  indicBLOCK=indicCROUV=indicTAB=indicAFFECT=indicDECLAR=indicYS=0; //re-init des indicateurs
1224                                                                        pstr2=NULL;
1225                  memset(instruct, '\0', BUFSIZE+1); //reinit de instruct
1226              }//fin de if ';'
1227                                        }//fin du if Phase 2
1228                            //passer au token suivant
1229          pstr1 = strtok(NULL, delim);
1230     }
1231  }
1232  BackwardOut(instruct); //pour reconduire la fin du code pour backward qui peut (et
1233                         //devrait) consister des carateres de terminaison de block ('}')
1234
1235        //fprintf(fpginac, "  } \n\n", pstr2); // fin pour ginac
1236        fprintf(fpginac, "  } \n\n"); // fin pour ginac
1237  exit(0);
1238}
Note: See TracBrowser for help on using the repository browser.