public class TestDeveloppementLimiteSinus {

///////////////////////////////////////////////////////

/* Calcul de la valeur de sin(a) au voisinage de 0.0 */
/* Utilisation du developpement limite               */
/* Les valeurs a et n sont donnees                   */

  static double sinus1(double a,int n) {
    double sn = a;
    double terme = a;
    for ( int i = 3 ; i <= n ; i = i+2 ) {
      terme = -terme*a*a/i/(i-1);
      sn = sn + terme; }
    return sn;
  }

/* Calcul de la puissance entiere d'un reel          */
/* Les valeurs a reelle et n entiere sont donnees    */
  
  static double puissance(double a,int n) {
    double res = a;
    for ( int i = 1 ; i < n ; i++ )
      res = res*a;
    return(res);
  }

/* Calcul de n!                                      */
/* La valeur n entiere est donnee                    */
  
  static long factoriel(int n) {
    long fct = 1L;
    for ( int i = 2 ; i <= n ; i++ )
      fct = fct*i;
    return(fct);
  }
  
/* Calcul de la valeur de sin(a) au voisinage de 0.0 */
/* Utilisation du developpement limite               */
/* Les valeurs a et n sont donnees                   */

  static double sinus2(double a,int n) {
    double signe = -1.0;
    double sn = a;
    for ( int i = 3 ; i <= n ; i = i+2 ) {
      sn = sn + signe*puissance(a,i)/factoriel(i);
      signe = -signe; }
    return sn;
  }
  
  static void testsRapiditeDeveloppementLimite(double a,int temps,int ni,int nf,int inc) {
    Ecran.formater("%6s","Taille");
    Ecran.formater("%12s","Appels");
    Ecran.formater("%14s","Temps total");
    Ecran.formater("%14s","Temps moyen");
    Ecran.formater("\n");
    for ( int n = ni ; n <= nf ; n = n+inc ) {
      Utilitaires.Minuteur minuteur = new Utilitaires.Minuteur();
      minuteur.temps = temps*1000;
      minuteur.lancement();
      long i = 0;
      long ti = System.nanoTime();
      do {
        sinus2(a,n);
        i++; }
      while ( minuteur.enCours ) ;
      long t = System.nanoTime()-ti;
      Ecran.formater("%6d",n);
      Ecran.formater("%12d",i);
      Ecran.formater("%14d",t);
      Ecran.formater("%14d",t/i);
      Ecran.formater("%14.4f\n",((double)t/i)/(n*n)); }
  }
  
  static void testsRapiditeDeveloppementLimiteOptimise(double a,int temps,int ni,int nf,int inc) {
    Ecran.formater("%6s","Taille");
    Ecran.formater("%12s","Appels");
    Ecran.formater("%14s","Temps total");
    Ecran.formater("%14s","Temps moyen");
    Ecran.formater("\n");
    for ( int n = ni ; n <= nf ; n = n+inc ) {
      Utilitaires.Minuteur minuteur = new Utilitaires.Minuteur();
      minuteur.temps = temps*1000;
      minuteur.lancement();
      long i = 0;
      long ti = System.nanoTime();
      do {
        sinus1(a,n);
        i++; }
      while ( minuteur.enCours ) ;
      long t = System.nanoTime()-ti;
      Ecran.formater("%6d",n);
      Ecran.formater("%12d",i);
      Ecran.formater("%14d",t);
      Ecran.formater("%14d",t/i);
      Ecran.formater("%14.4f\n",((double)t/i)/n); }
  }

///////////////////////////////////////////////////////

/* Programme principal                               */

  public static void main(String [] args) {
    double angle;
    int temps;
    int ni;
    int nf;
    int inc;
    Ecran.afficher("Angle? ");
    angle = Clavier.saisirDouble();
    Ecran.afficher("Nombre de secondes de test? ");
    temps = Clavier.saisirInt();
    Ecran.afficher("Taille initiale? ");
    ni = Clavier.saisirInt();
    Ecran.afficher("Taille finale  ? ");
    nf = Clavier.saisirInt();
    Ecran.afficher("Increment      ? ");
    inc = Clavier.saisirInt();
    testsRapiditeDeveloppementLimite(angle,temps,ni,nf,inc);
    testsRapiditeDeveloppementLimiteOptimise(angle,temps,ni,nf,inc);
  }
}