/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        C O M P R E H E N S I O N   D U   P L U S   P E T I T   P R O G R A M M E   D E   C A L C U L   D E   P I  :               */
/*        ( ' P O U R   L A   S C I E N C E ' ,   M A I   1 9 9 4 )                                                                  */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xtc/pi_mini.04$c' :                                                                                            */
/*                                                                                                                                   */
/*                    Unknown and Jean-Francois Colonna (LACTAMME, AAAAMMJJhhmmss).                                                  */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

extern    double    pow();

#define   PRECISION                                                                                                                     \
                    (2)                                                                                                                 \
                                        /* Le nombre de chiffre par paquet (4) peut etre reduit, mais pas augmente...                */
#define   DECIMALES                                                                                                                     \
                    (1*PRECISION)                                                                                                       \
                                        /* Nombre de decimales calculees (ce parametre peut etre change sans probleme, mais en       */ \
                                        /* restant un multiple de 'PRECISION'...). ATTENTION, la liste des decimales inclut la       */ \
                                        /* partie entiere (3).                                                                       */
#define   RAPPORT_TERMES_DECIMALES                                                                                                      \
                    (14)                                                                                                                \
                                        /* Constante representant le "rapport" entre le nombre de termes calcules et le nombre       */ \
                                        /* de decimales alors obtenues ; elle peut donc etre augmentee, mais pas reduite. Elle       */ \
                                        /* donne le nombre de termes d'une certaine serie qui semblent etre calcules "en parallele". */ \
                                        /* Chacun d'eux est calcule pour une precision donnee (la boucle 'while' externe) dans un    */ \
                                        /* element du tableau 'termes' ; par exemple on aura :                                       */ \
                                        /*                                                                                           */ \
                                        /*                  termes[14] <-O-> 1/27 = 1/(2x14-1)                                       */ \
                                        /*                  termes[13] <-O-> 1/25 = 1/(2x13-1)                                       */ \
                                        /*                  (...)                                                                    */ \
                                        /*                  termes[02] <-O-> 1/03 = 1/(2x02-1)                                       */ \
                                        /*                  termes[01] <-O-> 1/01 = 1/(2x01-1)                                       */ \
                                        /*                                                                                           */ \
                                        /* dans la boucle 'while' interne, auquel cas, cela ressemble a la formule de Wallis, sauf   */ \
                                        /* qu'il faudrait que cela soit des carres, et d'autre part cette methode converge tres      */ \
                                        /* lentement alors que ce programme semble relativement rapide...                            */
#define   INDICE_DE_GAUCHE                                                                                                              \
                    0                                                                                                                   \
                                        /* Indice de depart d'un tableau.                                                            */
#define   TAILLE                                                                                                                        \
                    (((DECIMALES * RAPPORT_TERMES_DECIMALES) / PRECISION) + 1)                                                          \
                                        /* Taille du tableau 'termes'.                                                               */

#define   P                                                                                                                             \
                    (1*precision)
#define   DP                                                                                                                            \
                    (2*precision)
                                        /* Precisions d'edition des entiers...                                                       */
#define   EDIT(fonction)                                                                                                                \
                    {                                                                                                                   \
                    if        (editer != 0)                                                                                             \
                              {                                                                                                         \
                              fonction;                                                                                                 \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              }                                                                                                         \
                    }                                                                                                                   \
                                        /* Fonction d'edition conditionnelle.                                                        */

main()
          {
          int       editer=1;
                                        /* Controleur d'edition (0=NON, 1=OUI).                                                      */
          int       base=(int)pow((double)10,(double)PRECISION);
          int       precision = PRECISION;
                                        /* Nombre de chiffre par paquet...                                                           */
          int       paquet=0;
                                        /* Paquet courant de 'precision' decimales.                                                  */
          int       termes[TAILLE];
                                        /* Tableau contenant les differents termes de la serie (et non pas la suite des decimales)   */
                                        /* qui sont calcules d'une part dans l'ordre inverse (N, N-1, ..., 2, 1) dans la boucle      */
                                        /* 'while' interne, et d'autre part a un certain niveau de precision grace a la boucle       */
                                        /* 'while' externe.                                                                          */
          int       indice_de_gauche=INDICE_DE_GAUCHE;
                                        /* Indice d'indexation du tableau 'termes'.                                                  */

          int       indice_de_droite=TAILLE-1;

          int       retenue;
                                        /* Pseudo-retenue propagee de la droite vers la gauche...                                    */
          int       inverse_du_coefficient;
                                        /* Il s'agit de l'inverse du coefficient '1/(2n+1)', mais malheureusement, comme il n'y      */
                                        /* nulle part de soustractions il ne doit pas s'agir du developpement en serie des           */
                                        /* fonctions arc-tangentes puisque cette serie est "alternee"...                             */

          EDIT(printf("\n initialisation du processus\n"));
          for       (indice_de_gauche=INDICE_DE_GAUCHE ; indice_de_gauche < TAILLE ; indice_de_gauche++)
                    {
                    termes[indice_de_gauche] = (int)base*(2.0/10.0);
                    EDIT(printf(" %0*d",P,termes[indice_de_gauche]));
                                        /* L'initialisation est la meme partout (2 a 'base' pres) car en fait le tableau 'termes'    */
                                        /* ne correspond pas aux decimales mais aux differents termes de la serie pour une precision */
                                        /* donnee (et fixee par la boucle 'while' externe) ; voir les commentaires relatifs a la     */
                                        /* constante 'RAPPORT_TERMES_DECIMALES'. La division par 10 est destinee a mettre la partie  */
                                        /* entiere ('3') comme premiere decimale, c'est-a-dire a calculer pi/10.                     */
                    }

          while     ((inverse_du_coefficient=indice_de_droite*2) != 0)
                    {
                    int       repeter=1;
                    retenue = 0;
                    indice_de_gauche = indice_de_droite;
                    EDIT(printf("\n boucle exterieure, indice de droite=%0*d",P,indice_de_droite));
                    while     (repeter == 1)
                                        /* Exemple d'imbrication en demandant 2*4 decimales :                                        */
                                        /*                                                                                           */
                                        /*                          14     28                                                        */
                                        /*                  ________________                                                         */
                                        /*                  \ _______       |                                                        */
                                        /*                   \\ 5926 | 3141 |                                                        */
                                        /*                    \\     |      |                                                        */
                                        /*                     \\    |      |                                                        */
                                        /*                      \\   |      |                       G = indice_de_gauche             */
                                        /*                       \\  |      |                       D = indice_de_droite             */
                                        /*                        \\ |      |                                                        */
                                        /*                         \\|      |                                                        */
                                        /*                          \       |                                                        */
                                        /*                           \      |                                                        */
                                        /*                            \     |                                                        */
                                        /*                       G --> \    | <-- D                                                  */
                                        /*                              \   |                                                        */
                                        /*                               \  |                                                        */
                                        /*                                \ |                                                        */
                                        /*                                 \|                                                        */
                                        /*                                                                                           */
                                        /* le grand triangle correspondant a la premiere boucle 'while' externe, alors que le        */
                                        /* petit triangle correspond a la seconde (et derniere).                                     */
                              {
                              int       Sretenue;

                              inverse_du_coefficient = inverse_du_coefficient - 2;
                              EDIT(printf("\n      boucle interieure, indice de gauche=%0*d",P,indice_de_gauche));
                              EDIT(printf("   diviseur=%0*d",P,inverse_du_coefficient+1));
                              EDIT(printf("   retenue=%0*d",DP,retenue));
                              retenue = retenue + (termes[indice_de_gauche]*base);
                              EDIT(printf("+(%0*d*%0*d) --> %0*d"
                                         ,DP,termes[indice_de_gauche]
                                         ,DP,base
                                         ,DP,retenue
                                          )
                                   );
                                        /* Cette multiplication par 'base' permet de cumuler les differents termes successifs de     */
                                        /* la serie utilisee, ainsi a la fin de chaque boucle 'while' interne, le dernier element    */
                                        /* calcule a gauche est le paquet courant de decimales. En ce qui concerne la nature de      */
                                        /* la serie utilisee, voir le programme 'v $xtc/pi_mini.02$c'.                               */
                              EDIT(Sretenue = retenue);
                              termes[indice_de_gauche] = retenue%(inverse_du_coefficient+1);
                              retenue = retenue/(inverse_du_coefficient+1);
                              EDIT(printf("/%0*d --> %0*d"
                                         ,DP,inverse_du_coefficient+1
                                         ,DP,retenue
                                          )
                                   );
                              indice_de_gauche = indice_de_gauche - 1;
                              if        (indice_de_gauche == INDICE_DE_GAUCHE)
                                        {
                                        repeter = 0;
                                        EDIT(printf(" %*s     %*s"
                                                   ,DP,""
                                                   ,DP,""
                                                    )
                                             );
                                        }
                              else
                                        {
                                        retenue = retenue * indice_de_gauche;
                                        EDIT(printf("*%0*d --> %0*d"
                                                   ,DP,indice_de_gauche
                                                   ,DP,retenue
                                                    )
                                             );
                                        }
                              EDIT(printf("   termes[%0*d]=%0*d%%%0*d=%0*d"
                                         ,P,indice_de_gauche+1
                                         ,DP,Sretenue
                                         ,DP,inverse_du_coefficient+1
                                         ,DP,termes[indice_de_gauche+1]
                                          )
                                   );
                              }
                    indice_de_droite = indice_de_droite - RAPPORT_TERMES_DECIMALES;
                    EDIT(printf("\n paquet courant=%0*d+(%0*d/%0*d)=",DP,paquet,DP,retenue,DP,base));
                    printf("%.*d",precision,paquet+(retenue/base));
                    paquet = retenue % base;
                    EDIT(printf("\n paquet=%0*d%%%0*d=%0*d",DP,retenue,DP,base,DP,paquet));
                    }
          EDIT(printf("\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.