/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E T U D E   D E S   V A R I A T I O N S   D ' U N E   F O N C T I O N  :                                                   */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xtc/var_fonc.01$c' :                                                                                           */
/*                                                                                                                                   */
/*                    Jean-Francois Colonna (LACTAMME, AAAAMMJJhhmmss).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

#include  "INCLUDES.01.I"
                                        /* Introduit le 20051116103102...                                                            */

extern    double    sqrt();
extern    double    log();

extern    double    drand48();
extern    double    sin();

#define   NOMBRE                                                                                                                        \
                    1000                                                                                                                \
                                        /* Nombre de points sur l'axe 'OX'.                                                          */

#define   PREMIER                                                                                                                       \
                    0
#define   DERNIER                                                                                                                       \
                    (NOMBRE-1)

#define   DELTAX                                                                                                                        \
                    1.0/FLOT(DERNIER-PREMIER)

#define   FLOT(x)                                                                                                                       \
                    ((double)(x))

#define   INITIALISATION_DE_LA_FONCTION(Xmin,Yformule,titre)                                                                            \
                    {                                                                                                                   \
                    int       n;                                                                                                        \
                                                                                                                                        \
                    Xfonction_minimum=+1.0e300;                                                                                         \
                    Xfonction_maximum=-1.0e300;                                                                                         \
                    Yfonction_minimum=+1.0e300;                                                                                         \
                    Yfonction_maximum=-1.0e300;                                                                                         \
                                                                                                                                        \
                    Xcommun[0] = Xmin;                                                                                                  \
                                                                                                                                        \
                    for       (n=(PREMIER+1) ; n <= DERNIER ; n++)                                                                      \
                              {                                                                                                         \
                              Xcommun[n] = Xcommun[n-1] + DELTAX;                                                                       \
                                        /* Definition de la coordonnee 'X' commune a la fonction et a sa "diagonale".                */ \
                              }                                                                                                         \
                                                                                                                                        \
                    for       (n=PREMIER ; n <= DERNIER ; n++)                                                                          \
                              {                                                                                                         \
                              double    fn=n*DELTAX;                                                                                    \
                                                                                                                                        \
                              Yfonction[n] = Yformule;                                                                                  \
                                        /* Definition de la coordonnee 'Y' de la fonction.                                           */ \
                              }                                                                                                         \
                                                                                                                                        \
                    for       (n=PREMIER ; n <= DERNIER ; n++)                                                                          \
                              {                                                                                                         \
                              double    fn=n*DELTAX;                                                                                    \
                                                                                                                                        \
                              Ydiagonale[n] = BARY(Yfonction[0],Yfonction[DERNIER],fn);                                                 \
                                        /* Definition de la coordonnee 'Y' de la "diagonale" de la fonction.                         */ \
                              }                                                                                                         \
                                                                                                                                        \
                    for       (n=PREMIER ; n <= DERNIER ; n++)                                                                          \
                              {                                                                                                         \
                              Xfonction_minimum = MIN2(Xcommun[n],Xfonction_minimum);                                                   \
                              Xfonction_maximum = MAX2(Xcommun[n],Xfonction_maximum);                                                   \
                                                                                                                                        \
                              Yfonction_minimum = MIN2(Yfonction[n],Yfonction_minimum);                                                 \
                              Yfonction_maximum = MAX2(Yfonction[n],Yfonction_maximum);                                                 \
                                        /* Recherche des extrema en {X,Y} de la fonction.                                            */ \
                              }                                                                                                         \
                                                                                                                                        \
                    Yderivee_premiere[PREMIER] = 0;                                                                                     \
                    for       (n=(PREMIER+1) ; n <= DERNIER ; n++)                                                                      \
                              {                                                                                                         \
                              Yderivee_premiere[n] = (Yfonction[n] - Yfonction[n-1]) / (Xcommun[n] - Xcommun[n-1]);                     \
                              }                                                                                                         \
                                                                                                                                        \
                    Yderivee_seconde[PREMIER] = 0;                                                                                      \
                    Yderivee_seconde[PREMIER+1] = 0;                                                                                    \
                    for       (n=(PREMIER+2) ; n <= DERNIER ; n++)                                                                      \
                              {                                                                                                         \
                              Yderivee_seconde[n] = (Yderivee_premiere[n] - Yderivee_premiere[n-1]) / (Xcommun[n] - Xcommun[n-1]);      \
                              }                                                                                                         \
                                                                                                                                        \
                    printf("\n %s",titre);                                                                                              \
                    printf("     DY=[%+5.2f,%+5.2f]",Yfonction_minimum,Yfonction_maximum);                                              \
                    }                                                                                                                   \
                                        /* Initialisation de la fonction.                                                            */

#define   EPSILON_DERIVEE_PREMIERE                                                                                                      \
                    1.0e-1

#define   MOYENNE_DE_LA_DERIVEE_PREMIERE_DE_LA_FONCTION                                                                                 \
                    {                                                                                                                   \
                    int       n;                                                                                                        \
                                                                                                                                        \
                    derivee_premiere_moyenne=0;                                                                                         \
                                                                                                                                        \
                    for       (n=PREMIER ; n <= DERNIER ; n++)                                                                          \
                              {                                                                                                         \
                              derivee_premiere_moyenne = derivee_premiere_moyenne + Yderivee_premiere[n];                               \
                              }                                                                                                         \
                                                                                                                                        \
                    derivee_premiere_moyenne = derivee_premiere_moyenne / NOMBRE;                                                       \
                                        /* Evidemment cette valeur est aussi egale a :                                               */ \
                                        /*                                                                                           */ \
                                        /*                   f(b) - f(a)                                                             */ \
                                        /*                  -------------                                                            */ \
                                        /*                      b - a                                                                */ \
                                        /*                                                                                           */ \
                                        /* ou [a,b] est le segment de definition, mais faire le calcul ainsi ouvre la porte a des    */ \
                                        /* extensions futures...                                                                     */ \
                                                                                                                                        \
                    printf("     M(d)=%+9.4f",derivee_premiere_moyenne);                                                                \
                    }                                                                                                                   \
                                        /* Calcul de la moyenne de la derivee premiere de la fonction.                               */

#define   MOYENNE_DE_LA_DERIVEE_SECONDE_DE_LA_FONCTION                                                                                  \
                    {                                                                                                                   \
                    int       n;                                                                                                        \
                                                                                                                                        \
                    derivee_seconde_moyenne=0;                                                                                          \
                                                                                                                                        \
                    for       (n=PREMIER ; n <= DERNIER ; n++)                                                                          \
                              {                                                                                                         \
                              derivee_seconde_moyenne = derivee_seconde_moyenne + Yderivee_seconde[n];                                  \
                              }                                                                                                         \
                                                                                                                                        \
                    derivee_seconde_moyenne = derivee_seconde_moyenne / NOMBRE;                                                         \
                                        /* Evidemment cette valeur est aussi egale a :                                               */ \
                                        /*                                                                                           */ \
                                        /*                   f'(b) - f'(a)                                                           */ \
                                        /*                  -------------                                                            */ \
                                        /*                       b - a                                                               */ \
                                        /*                                                                                           */ \
                                        /* ou [a,b] est le segment de definition, mais faire le calcul ainsi ouvre la porte a des    */ \
                                        /* extensions futures...                                                                     */ \
                                                                                                                                        \
                    printf("     M(dd)=%+9.4f",derivee_seconde_moyenne);                                                                \
                    }                                                                                                                   \
                                        /* Calcul de la moyenne de la derivee seconde de la fonction.                                */

#define   TEMPERATURE(l,h)                                                                                                              \
                    (1.0/log((2*l) / ((2*l) - h)))
#define   TEMPERATURE_BASSE                                                                                                             \
                    0.01
#define   TEMPERATURE_ELEVEE                                                                                                            \
                    20

#define   TEMPERATURE_DE_LA_FONCTION                                                                                                    \
                    {                                                                                                                   \
                    int       n;                                                                                                        \
                                                                                                                                        \
                    longueur_de_la_fonction=0;                                                                                          \
                                                                                                                                        \
                    for       (n=(PREMIER+1) ; n <= DERNIER ; n++)                                                                      \
                              {                                                                                                         \
                              longueur_de_la_fonction = longueur_de_la_fonction                                                         \
                                                      + sqrt((EXP2(Xcommun[n] - Xcommun[n-1])) + EXP2(Yfonction[n] - Yfonction[n-1]));  \
                              }                                                                                                         \
                                                                                                                                        \
                    longueur_de_la_diagonale = sqrt(EXP2(Xcommun[DERNIER] - Xcommun[0]) + EXP2(Ydiagonale[DERNIER] - Ydiagonale[0]));   \
                    temperature_de_la_fonction = TEMPERATURE(longueur_de_la_fonction,longueur_de_la_diagonale) - TEMPERATURE(1.0,1.0);  \
                                        /* On retranche 'TEMPERATURE(1.0,1.0)' qui correspond a la temperature la plus basse que     */ \
                                        /* l'on puisse atteindre et qui correspond au cas ou la courbe est confondue avec sa         */ \
                                        /* "diagonale" (cas de la fonction constante...). On notera qu'en fait, on pourrait          */ \
                                        /* evidemment retrancher 'TEMPERATURE(x,x)' et ce quel que soit 'x'...                       */ \
                                                                                                                                        \
                    rapport_de_la_fonction_a_la_diagonale=longueur_de_la_fonction/longueur_de_la_diagonale;                             \
                                                                                                                                        \
                    printf("     L/D=%+9.4f",rapport_de_la_fonction_a_la_diagonale);                                                    \
                    printf("     T=%+9.4f",temperature_de_la_fonction);                                                                 \
                    }                                                                                                                   \
                                        /* Calcul de la "temperature" de la fonction.                                                */

#define   EPSILON_AIRE                                                                                                                  \
                    1.0e-1

#define   AIRE_SIGNEE_ENTRE_LA_FONCTION_ET_SA_DIAGONALE                                                                                 \
                    {                                                                                                                   \
                    int       n;                                                                                                        \
                                                                                                                                        \
                    aire_signee_entre_la_fonction_et_sa_diagonale=0;                                                                    \
                                                                                                                                        \
                    for       (n=(PREMIER+1) ; n <= DERNIER ; n++)                                                                      \
                              {                                                                                                         \
                              aire_signee_entre_la_fonction_et_sa_diagonale                                                             \
                                = aire_signee_entre_la_fonction_et_sa_diagonale                                                         \
                                + ((Yfonction[n-1] - Ydiagonale[n]) * (Xcommun[n] - Xcommun[n-1]))                                      \
                                + (((Ydiagonale[n] - Ydiagonale[n-1]) * (Xcommun[n] - Xcommun[n-1]))/2)                                 \
                                + (((Yfonction[n] - Yfonction[n-1]) * (Xcommun[n] - Xcommun[n-1]))/2);                                  \
                              }                                                                                                         \
                                                                                                                                        \
                    printf("     A=%+9.4f",aire_signee_entre_la_fonction_et_sa_diagonale);                                              \
                    }                                                                                                                   \
                                        /* Calcul de l'aire "signee" comprise entre la fonction et sa "diagonale".                   */

#define   VARIATION_DE_LA_FONCTION                                                                                                      \
                    {                                                                                                                   \
                    MOYENNE_DE_LA_DERIVEE_PREMIERE_DE_LA_FONCTION;                                                                      \
                    MOYENNE_DE_LA_DERIVEE_SECONDE_DE_LA_FONCTION;                                                                       \
                    TEMPERATURE_DE_LA_FONCTION;                                                                                         \
                    AIRE_SIGNEE_ENTRE_LA_FONCTION_ET_SA_DIAGONALE;                                                                      \
                    }                                                                                                                   \
                                        /* Quelques etudes de variation de la fonction.                                              */

#define   ANALYSE_DE_LA_FONCTION                                                                                                        \
                    {                                                                                                                   \
                    if        (ABSO(temperature_de_la_fonction) <= TEMPERATURE_BASSE)                                                   \
                              {                                                                                                         \
                              printf("     Lineaire");                                                                                  \
                                        /* Tres faible temperature.                                                                  */ \
                                                                                                                                        \
                              if        (ABSO(derivee_premiere_moyenne) <= EPSILON_DERIVEE_PREMIERE)                                    \
                                        {                                                                                               \
                                        printf(" Constante");                                                                           \
                                        /* Tres faible temperature et tres faible derivee.                                           */ \
                                        }                                                                                               \
                              else                                                                                                      \
                                        {                                                                                               \
                                        if        (derivee_premiere_moyenne >= 0)                                                       \
                                                  {                                                                                     \
                                                  printf(" Croissante");                                                                \
                                        /* Tres faible temperature et derivee positive significativement.                            */ \
                                                  }                                                                                     \
                                        else                                                                                            \
                                                  {                                                                                     \
                                                  printf(" Decroissante");                                                              \
                                        /* Tres faible temperature et derivee negative significativement.                            */ \
                                                  }                                                                                     \
                                        }                                                                                               \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              if        (ABSO(aire_signee_entre_la_fonction_et_sa_diagonale) <= EPSILON_AIRE)                           \
                                        {                                                                                               \
                                        if        (ABSO(derivee_premiere_moyenne) <= EPSILON_DERIVEE_PREMIERE)                          \
                                                  {                                                                                     \
                                                  printf("     (Quasi-)Periodique");                                                    \
                                                  }                                                                                     \
                                        else                                                                                            \
                                                  {                                                                                     \
                                                  printf("     Oscillante (autour de la Diagonale)");                                   \
                                                  }                                                                                     \
                                        /* Temperature significative et aire tres faible.                                            */ \
                                        }                                                                                               \
                              else                                                                                                      \
                                        {                                                                                               \
                                        if        (ABSO(temperature_de_la_fonction) >= TEMPERATURE_ELEVEE)                              \
                                                  {                                                                                     \
                                                  printf("     Chaotique");                                                             \
                                        /* Temperature tres elevee et aire significative.                                            */ \
                                                  }                                                                                     \
                                        else                                                                                            \
                                                  {                                                                                     \
                                                  if        (ABSO(derivee_premiere_moyenne) <= EPSILON_DERIVEE_PREMIERE)                \
                                                            {                                                                           \
                                                            if        (derivee_seconde_moyenne >= 0)                                    \
                                                                      {                                                                 \
                                                                      printf("     Concavite Haut");                                    \
                                        /* Derivee seconde positive.                                                                 */ \
                                                                      }                                                                 \
                                                            else                                                                        \
                                                                      {                                                                 \
                                                                      printf("     Concavite Bas");                                     \
                                        /* Derivee seconde negative.                                                                 */ \
                                                                      }                                                                 \
                                                            }                                                                           \
                                                  else                                                                                  \
                                                            {                                                                           \
                                                            if        (derivee_premiere_moyenne >= 0)                                   \
                                                                      {                                                                 \
                                                                      printf("     Croissante");                                        \
                                        /* Temperature intermediaire, aire significative et derivee premiere assez positive.         */ \
                                                                      }                                                                 \
                                                            else                                                                        \
                                                                      {                                                                 \
                                                                      printf("     Decroissante");                                      \
                                        /* Temperature intermediaire, aire significative et derivee premiere assez negative.         */ \
                                                                      }                                                                 \
                                                            }                                                                           \
                                                  }                                                                                     \
                                        }                                                                                               \
                              }                                                                                                         \
                    }                                                                                                                   \
                                        /* Analyse heuristique de la fonction.                                                       */

#define   ETUDE_DE_LA_FONCTION(Xmin,Yformule,titre)                                                                                     \
                    {                                                                                                                   \
                    INITIALISATION_DE_LA_FONCTION(Xmin,Yformule,titre);                                                                 \
                    VARIATION_DE_LA_FONCTION;                                                                                           \
                    ANALYSE_DE_LA_FONCTION;                                                                                             \
                    }                                                                                                                   \
                                        /* Etude de la fonction.                                                                     */

main()
          {
          double    Xcommun[NOMBRE];
                                        /* Axe des 'X' defini point par point.                                                       */
          double    Yfonction[NOMBRE];
                                        /* Fonction definie point par point.                                                         */
          double    Xfonction_minimum,Xfonction_maximum;
          double    Yfonction_minimum,Yfonction_maximum;
                                        /* Extrema de la fonction.                                                                   */
          double    Yderivee_premiere[NOMBRE];
          double    Yderivee_seconde[NOMBRE];
                                        /* Derivees definies point par point.                                                        */
          double    Ydiagonale[NOMBRE];
                                        /* "Diagonale" de la fonction definie point par point.                                       */
          double    derivee_premiere_moyenne;
          double    derivee_seconde_moyenne;
          double    longueur_de_la_fonction,longueur_de_la_diagonale;
          double    rapport_de_la_fonction_a_la_diagonale,temperature_de_la_fonction;
          double    aire_signee_entre_la_fonction_et_sa_diagonale;
                                        /* Quelques valeurs caracteristiques de la fonction.                                         */

          ETUDE_DE_LA_FONCTION(0.0
                              ,1.0
                              ,"F=1 ............"
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,+fn
                              ,"F=+x ..........."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,-fn
                              ,"F=-x ..........."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,EXP2(fn-0.5)
                              ,"F=(x-0.5)^2  ..."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,+EXP2(fn)
                              ,"F=+(x)^2 ......."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,-EXP2(fn)
                              ,"F=-(x)^2 ......."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,sin(1*PI*fn)
                              ,"F=sin(1*pi*x) .."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,sin(2*PI*fn)
                              ,"F=sin(2*pi*x) .."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,sin(3*PI*fn)
                              ,"F=sin(3*pi*x) .."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,sin(4*PI*fn)
                              ,"F=sin(4*pi*x) .."
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,fn+sin(1*PI*fn)
                              ,"F=x+sin(1*pi*x) "
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,fn+sin(2*PI*fn)
                              ,"F=x+sin(2*pi*x) "
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,fn+sin(3*PI*fn)
                              ,"F=x+sin(3*pi*x) "
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,fn+sin(4*PI*fn)
                              ,"F=x+sin(4*pi*x) "
                               );

          ETUDE_DE_LA_FONCTION(0.0
                              ,drand48()
                              ,"F=rdn() ........"
                               );

          printf("\n\n");
          printf(" DX=[%+5.2f,%+5.2f]",Xfonction_minimum,Xfonction_maximum);
          printf("\n\n");
          }



Copyright © Jean-François Colonna, 2021-2023.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 2021-2023.