Example #1
0
File: convol.c Project: alkra/MPIMP
int main(int argc, char *argv[]) {

  /* Variables se rapportant a l'image elle-meme */
  Raster r;
  int    w, h;	/* nombre de lignes et de colonnes de l'image */

  /* Variables liees au traitement de l'image */
  int 	 filtre;		/* numero du filtre */
  int 	 nbiter;		/* nombre d'iterations */

  /* Variables liees au chronometrage */
  double debut, fin;

  /* Variables de boucle */
  int 	i;

  if (argc != 4) {
    fprintf( stderr, usage, argv[0]);
    return 1;
  }
      
  /* Saisie des paramètres */
  filtre = atoi(argv[2]);
  nbiter = atoi(argv[3]);
        
  /* Lecture du fichier Raster */
  lire_rasterfile( argv[1], &r);
  h = r.file.ras_height;
  w = r.file.ras_width;
    
  /* debut du chronometrage */
  debut = my_gettimeofday();            

  /* La convolution a proprement parler */
  for(i=0 ; i < nbiter ; i++){
    convolution( filtre, r.data, h, w);
  } /* for i */

  /* fin du chronometrage */
  fin = my_gettimeofday();
  printf("Temps total de calcul : %g seconde(s) \n", fin - debut);
    
    /* Sauvegarde du fichier Raster */
  { 
    char nom_sortie[100] = "";
    sprintf(nom_sortie, "post-convolution_filtre%d_nbIter%d.ras", filtre, nbiter);
    sauve_rasterfile(nom_sortie, &r);
  }

  return 0;
}
Example #2
0
int get_waite_interval()
{
	int interval = 0;
	struct timeval time, timeintval;
	my_gettimeofday(&time, NULL);

	pthread_mutex_lock(&timerq.mutex);
	if (timerq.last) {
		if (TV_LESS_THAN(time, timerq.last->timeout)) {
			TV_MINUS(timerq.last->timeout, time, timeintval);
		} else {
			memset(&timeintval, 0, sizeof(struct timeval));
		}
		
		interval = timeintval.tv_sec;

		interval = (interval>(60*10)) ? 600 : interval;
		interval = interval < 0 ? 0: interval;
	}
	pthread_mutex_unlock(&timerq.mutex);
	
	return (interval);
}
Example #3
0
int get_rest_time(struct timeval *abs_rest)
{
	struct timeval abs_now;
	struct timeval *abs_to = NULL;

	if (abs_rest == NULL || timerq.first == NULL) {
		return -1;
	}

	abs_to = &(timerq.first->timeout);
	memset(abs_rest, 0, sizeof(struct timeval));
	/* absolute to relative time */
	my_gettimeofday(&abs_now, NULL);
	
	if (TV_LESS_THAN(abs_now, *abs_to)) {
		/* ok, timeout is in the future */
		TV_MINUS(*abs_to, abs_now, *abs_rest);
	} else {
		abs_rest->tv_sec = 0;
		abs_rest->tv_usec = ALMOST_NOW;
	}

	return 0;
}
Example #4
0
int main(int argc, char **argv)
#endif
{
    struct hostent *hp;
    MyTimeval start, stop;
    int i, fd, ires, tries;
    CORBA_Environment *env;
    char *this_node_name = NULL;
    char *peer_node = NULL;
    char *cookie = NULL;
    char host[HOSTNAMESZ + 1];
    char this_node[NODENAMESZ + 1];
    erlang_msg msg;
    int status, loop; 
    
#ifdef __WIN32__
    WORD wVersionRequested;
    WSADATA wsaData;
    
    wVersionRequested = MAKEWORD(2, 0);
    
    if (WSAStartup(wVersionRequested, &wsaData) != 0) {
	fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
	exit(1);
    }
#endif
    
    progname = argv[0];
    host[HOSTNAMESZ] = '\0';
    if (gethostname(host, HOSTNAMESZ) < 0) {
	fprintf(stderr, "Can't find own hostname\n");
	done(1);
    } 
    if ((hp = gethostbyname(host)) == 0) {
	fprintf(stderr, "Can't get ip address for host %s\n", host);
	done(1);
    }
    for (i = 1; i < argc; i++) {
	if (strcmp(argv[i], "-help") == 0) {
	    usage();
	    done(0);
	} else if (strcmp(argv[i], "-this-node-name") == 0) {
	    i++;
	    this_node_name = argv[i];
	} else if (strcmp(argv[i], "-peer-node") == 0) {
	    i++;
	    peer_node = argv[i];
	} else if (strcmp(argv[i], "-cookie") == 0) {
	    i++;
	    cookie = argv[i];
	} else {
	    fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
	    usage();
	    done(1);
	}
    }

    if (this_node_name == NULL || peer_node == NULL || cookie == NULL) {
	fprintf(stderr, "Error: missing option\n");
	usage();
	done(1);
    }

    /* Behead hostname at first dot */
    for (i=0; host[i] != '\0'; i++) {
	if (host[i] == '.') { host[i] = '\0'; break; }
    }
    sprintf(this_node, "%s@%s", this_node_name, host);

    fprintf(stderr, "c_server: this node: \"%s\"\n", this_node);
    fprintf(stderr, "c_server: peer node: \"%s\"\n", peer_node);

    /* initialize erl_interface */
    erl_init(NULL, 0);

    for (tries = 0; tries < MAXTRIES; tries++) {
	/* connect to peer node */ 
    	ires = erl_connect_xinit(host, this_node_name, this_node, 
				 (struct in_addr *)*hp->h_addr_list, 
				 cookie, 0);
	fprintf(stderr, "c_server: erl_connect_xinit(): %d\n", ires);
    
	fd = erl_connect(peer_node);
	fprintf(stderr, "c_server: erl_connect(): %d\n", fd);
	if (fd >= 0) 
	    break;
	fprintf(stderr, "c_server: cannot connect, retrying\n");
    }
    if (fd < 0) {
	fprintf(stderr, "c_server: cannot connect, exiting\n");
	done(1);
    }
    env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
    env->_fd = fd; 

    status = 1;
    loop = 1;
    my_gettimeofday(&start);
    while (status >= 0 && loop > 0) {
        status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz, 
				    &msg, &env->_iin); 
	switch(status) {
	case ERL_SEND:
	case ERL_REG_SEND:
	    /* get result */
	    m_i__switch(NULL, env);
	    switch(env->_major) {
	    case CORBA_NO_EXCEPTION:
		break;
	    case CORBA_SYSTEM_EXCEPTION:
		fprintf(stderr, "Request failure, reason : %s\n", 
			(char *) CORBA_exception_value(env));
		CORBA_exception_free(env);
		break;
	    default: /* Should not happen */
		CORBA_exception_free(env);
		break;
	    }
	    /* send back result data */
	    if (env->_iout > 0) 
		ei_send_encoded(env->_fd, &env->_caller, env->_outbuf, 
				env->_iout);
	    loop = 0;
	    break;
	case ERL_TICK:
	    break;
	default: 
	    if (status < 0) {
		fprintf(stderr, "Status negative: %d\n", status);
		loop = 0;
	    }
	    break;
	}
    }	
    my_gettimeofday(&stop);
    showtime(&start, &stop);

    erl_close_connection(fd);

    CORBA_free(env->_inbuf);
    CORBA_free(env->_outbuf);
    CORBA_free(env);
    if (status < 0) 
	done(-status);
    else 
	done(0); 
}
Example #5
0
int main(int argc, char **argv)
#endif
{
    struct hostent *hp;
    erlang_pid pid;
    MyTimeval start, stop;
    int i, fd, ires, tres;
    IC_Env *env;
    int tries = 0;
    char *this_node_name = NULL;
    char *peer_node = NULL;
    char *peer_process_name = NULL;
    char *cookie = NULL;
    char host[HOSTNAMESZ + 1];
    TestFunc test_func = NULL;
    TestCase *test_case;
    char *test_case_name = NULL;
    
#ifdef __WIN32__
    WORD wVersionRequested;
    WSADATA wsaData;
    
    wVersionRequested = MAKEWORD(2, 0);
    
    if (WSAStartup(wVersionRequested, &wsaData) != 0) {
	fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
	exit(1);
    }
#endif
    
    progname = argv[0];
    host[HOSTNAMESZ] = '\0';
    if (gethostname(host, HOSTNAMESZ) < 0) {
	fprintf(stderr, "Can't find own hostname\n");
	done(1);
    } 
    if ((hp = gethostbyname(host)) == 0) {
	fprintf(stderr, "Can't get ip address for host %s\n", host);
	done(1);
    }
    for (i = 1; i < argc; i++) {
	if (cmp_str(argv[i], "-help")) {
	    usage();
	    done(0);
	} else if (cmp_str(argv[i], "-this-node-name")) {
	    i++;
	    this_node_name = argv[i];
	} else if (cmp_str(argv[i], "-peer-node")) {
	    i++;
	    peer_node = argv[i];
	} else if (cmp_str(argv[i], "-peer-process-name")) {
	    i++;
	    peer_process_name = argv[i];
	} else if (cmp_str(argv[i], "-cookie")) {
	    i++;
	    cookie = argv[i];
	} else if (cmp_str(argv[i], "-test-case")) {
	    i++;
	    test_case_name = argv[i];
	} else {
	    fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
	    usage();
	    done(1);
	}
    }

    if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL 
	|| peer_process_name == NULL || cookie == NULL) {
	fprintf(stderr, "Error: missing option\n");
	usage();
	done(1);
    }

    test_case = test_cases;
    while (test_case->func) {
	if (cmp_str(test_case->name, test_case_name)) {
	    test_func = test_case->func;
	    break;
	}
	test_case++;
    }
    if (test_func == NULL) {
	fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name);
	done(1);
    }
    
    /* Behead hostname at first dot */
    for (i=0; host[i] != '\0'; i++) {
	if (host[i] == '.') { host[i] = '\0'; break; }
    }
    sprintf(this_node, "%s@%s", this_node_name, host);
    fprintf(stderr, "c_client: this node: \"%s\"\n", this_node);
    fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node);
    fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name);

    fprintf(stderr, "c_client: starting\n");

    /* initialize erl_interface */
    erl_init(NULL, 0);

    for (tries = 0; tries < MAXTRIES; tries++) {

	/* connect to erlang node */ 

    	ires = erl_connect_xinit(host, this_node_name, this_node, 
				 (struct in_addr *)*hp->h_addr_list, 
				 cookie, 0);

	fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires);
    
	fd = erl_connect(peer_node);
	fprintf(stderr, "c_client: erl_connect(): %d\n", fd);
    
	if (fd >= 0) 
	    break;
	fprintf(stderr, "c_client: cannot connect, retrying\n");
    }
    if (fd < 0) {
	fprintf(stderr, "c_client: cannot connect, exiting\n");
	done(1);
    }
    env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
    env->_fd = fd; 
    strcpy(env->_regname, peer_process_name);
    env->_to_pid = NULL;
    env->_from_pid = &pid;
    
    strcpy(pid.node, this_node);
    pid.num = fd;
    pid.serial = 0;
    pid.creation = 0;

    my_gettimeofday(&start);
    tres = test_func(env);	/* Call test case */
    my_gettimeofday(&stop);
    showtime(&start, &stop);
    erl_close_connection(fd);

    printf("c_client: env->_inbuf before : %d\n", INBUFSZ);
    printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ);
    printf("c_client: env->_inbuf after : %d\n", env->_inbufsz);
    printf("c_client: env->_outbuf after : %d\n", env->_outbufsz);

    CORBA_free(env->_inbuf);
    CORBA_free(env->_outbuf);
    CORBA_free(env);
    done(tres);
}
Example #6
0
int add_timernode_to_list(tl_timer_t *msg)
{
	struct timeval new_time;
	tl_timer_t *tmp = NULL;
	tl_timer_t *app = NULL;
	int id = 0, ret = 0;

	if (msg == NULL)
		return -1;

	/* ensure timeout is in the future */
	if ((msg->timeout.tv_sec < 0) || (msg->timeout.tv_usec < 0) || ((msg->timeout.tv_sec == 0) && (msg->timeout.tv_usec == 0))) {
		msg->id = -1;
		ret = -1;
		goto done;
	}

	app = (tl_timer_t *) malloc(sizeof(tl_timer_t));
	if (app == NULL) {
		msg->id = -1;
		ret = -1;
		goto done;
	}

	/* relative to absolute time for timer */
	my_gettimeofday(&new_time, NULL);

	/* add 10^6 microsecond units to seconds */
	new_time.tv_sec += msg->timeout.tv_sec + (new_time.tv_usec + msg->timeout.tv_usec) / MICRO_PER_SEC;
	/* keep microseconds inside allowed range */
	new_time.tv_usec = (new_time.tv_usec + msg->timeout.tv_usec) % MICRO_PER_SEC;

	memcpy(&app->timeout, &new_time, sizeof(struct timeval));
	app->handler = msg->handler;
	app->handler_arg = msg->handler_arg;

	pthread_mutex_lock(&timerq.mutex);

	id = timerq.cur_id++;
	if (id == -1) {
		id = timerq.cur_id++;
	}
	app->id = id;

	if (timerq.first == NULL) {
		/* timer queue empty */
		timerq.first = app;
		timerq.last = app;
		app->prev = NULL;
		app->next = NULL;
		msg->id = id;
		goto done;
	}

	/* there is at least a timer in the queue */
	tmp = timerq.first;

	/* find the first timer that expires before app */
	while (tmp != NULL) {

		if (TV_LESS_THAN(app->timeout, tmp->timeout))
			break;

		tmp = tmp->next;
	}

	if (tmp == NULL) {
		/* app is the longest timer */
		app->prev = timerq.last;
		app->next = NULL;
		timerq.last->next = app;
		timerq.last = app;
		msg->id = id;
		goto done;
	}

	if (tmp->prev == NULL) {
		/* app is the shoprtest timer */
		app->prev = NULL;
		app->next = tmp;
		tmp->prev = app;
		timerq.first = app;

	} else {
		app->prev = tmp->prev;
		app->next = tmp;
		tmp->prev->next = app;
		tmp->prev = app;
	}

	msg->id = id;

done:
	pthread_mutex_unlock(&timerq.mutex);
	return ret;
}
Example #7
0
int main(int argc, char *argv[]) {
  /* Domaine de calcul dans le plan complexe */
  double xmin, ymin;
  double xmax, ymax;
  /* Dimension de l'image */
  int w,h;
  /* Le nombre de lignes pour chaque block*/
  int nb_lignes = 20;
  /* Pas d'incrementation */
  double xinc, yinc;
  /* Profondeur d'iteration */
  int prof;
  /* Déclaration de true et false*/
  int true = 1;
  int false = 0;
  /* Image resultat */
  unsigned char *ima, *pima, *ima_loc, *pima_loc;
  /* Variables intermediaires */
  int  i, j;
  double x, y;
  /* Chronometrage */
  double debut, fin;

  /* debut du chronometrage */
  debut = my_gettimeofday();


  if( argc == 1) fprintf( stderr, "%s\n", info);
  
  /* Valeurs par defaut de la fractale */
  xmin = -2; ymin = -2;
  xmax =  2; ymax =  2;
  w = h = 800;
  prof = 10000;
  
  /* Recuperation des parametres */
  if( argc > 1) w    = atoi(argv[1]);
  if( argc > 2) h    = atoi(argv[2]);
  if( argc > 3) xmin = atof(argv[3]);
  if( argc > 4) ymin = atof(argv[4]);
  if( argc > 5) xmax = atof(argv[5]);
  if( argc > 6) ymax = atof(argv[6]);
  if( argc > 7) prof = atoi(argv[7]);

  /* Calcul des pas d'incrementation */
  xinc = (xmax - xmin) / (w-1);
  yinc = (ymax - ymin) / (h-1);
  
  /**** INIT MPI  ****/
  int rank, p;
  MPI_Init(&argc, &argv); /* starts MPI */
  MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* get current process id */
  MPI_Comm_size(MPI_COMM_WORLD, &p);

  if (p < 2) {
    printf("Erreur : le nombre de processeurs n'est pas suffisant\n");
    MPI_Finalize();
    return 0;
  }

  if (h % nb_lignes != 0) {
    printf("Erreur : la hauteur n'est pas multiple du nombre de lignes de chaque bloc");
    MPI_Finalize();
    return 0;
  }

  int fini = 0;
  int nb_blocs = h / nb_lignes;
  int nb_bloc_recus = 0;
  int nb_bloc_envoyes = 0; // numero du bloc à envoyé mais aussi le nombre de blocs envoyés
  int num_bloc = 0;
  //int end_nb_bloc = -1;
  MPI_Status status;
  /**** ****/

  if (p-1 > nb_blocs) {
    printf("Erreur : le nombre de processeurs n'est pas suffisant car inférieur au nombre de blocs\n");
    MPI_Finalize();
    return 0;
  }

  if (rank == MAITRE) {
    /* affichage parametres pour verificatrion */
    fprintf(stdout, "Affichage des paramètres pour vérification\n");
    fprintf( stderr, "Master : %d/%d\n", rank+1, p);
    fprintf( stderr, "    Domaine: {[%lg,%lg]x[%lg,%lg]}\n", xmin, ymin, xmax, ymax);
    fprintf( stderr, "    Increment : %lg %lg\n", xinc, yinc);
    fprintf( stderr, "    Prof: %d\n",  prof);
    fprintf( stderr, "    Dim image: %dx%d\n", w, h);

    /* Allocation memoire du tableau resultat */
    pima = ima = (unsigned char *)malloc(w * h * sizeof(unsigned char));
    if (ima == NULL) {
      fprintf(stderr, "Erreur allocation mémoire du tableau \n");
      return 0;
    }

    for (i = 1; i < p; i++) {
      MPI_Send(&nb_bloc_envoyes, 1, MPI_INT, i, TAG_REQ, MPI_COMM_WORLD);
      nb_bloc_envoyes++;
    }

    while (fini == false) {
      MPI_Probe(MPI_ANY_SOURCE, TAG_REQ, MPI_COMM_WORLD, &status);
      int s = status.MPI_SOURCE;
      if(s != MAITRE) {

        MPI_Recv(&num_bloc, 1, MPI_INT, MPI_ANY_SOURCE, TAG_REQ, MPI_COMM_WORLD, &status);
        MPI_Recv(&ima[num_bloc * nb_lignes * w], nb_lignes * w, MPI_CHAR, s, TAG_DATA, MPI_COMM_WORLD, &status);
        nb_bloc_recus++;

        if (nb_bloc_envoyes < nb_blocs) {
          /*Il reste encore des blocs à calculer */
          MPI_Send(&nb_bloc_envoyes, 1, MPI_INT, s, TAG_REQ, MPI_COMM_WORLD);
          MPI_Send(&false, 1, MPI_INT, s, TAG_END, MPI_COMM_WORLD);
          nb_bloc_envoyes++;
        } else {
          /*Il reste plus de calcul à faire*/
          MPI_Send(&true, 1, MPI_INT, s, TAG_END, MPI_COMM_WORLD);
        }

        if (nb_bloc_recus == nb_blocs) {
          // Le calcul est fini
          fini = true;

          /* fin du chronometrage */
          fin = my_gettimeofday();
          fprintf(stderr, "Temps total de calcul : %g sec\n", fin - debut);
          //fprintf(stdout, "%g\n", fin - debut);

          /* Sauvegarde de la grille dans le fichier resultat "mandel.ras" */
          sauver_rasterfile("output/mandel2.ras", w, h, ima);
        }
      }
    }

  } else {
    // Allocation en local
    ima_loc = (unsigned char *)malloc(nb_lignes * w * sizeof(unsigned char));
    
    if (ima_loc == NULL) {
      fprintf(stderr, "Erreur allocation mémoire du tableau !\n");
      return 0;
    }

    while (fini == false) {

      MPI_Recv(&num_bloc, 1, MPI_INT, MAITRE, TAG_REQ, MPI_COMM_WORLD, &status);

      pima_loc = ima_loc;

      /* Traitement de la grille point par point */
      y = ymin + nb_lignes * num_bloc * yinc; 
      for (i = 0; i < nb_lignes; i++) { 
        x = xmin;
        for (j = 0; j < w; j++) {
          *pima_loc++ = xy2color(x, y, prof); 
          x += xinc;
        }
        y += yinc; 
      }

      MPI_Send(&num_bloc, 1, MPI_INT, MAITRE, TAG_REQ, MPI_COMM_WORLD);
      MPI_Send(ima_loc, nb_lignes * w, MPI_CHAR, MAITRE, TAG_DATA, MPI_COMM_WORLD);

      MPI_Recv(&fini, 1, MPI_INT, MAITRE, TAG_END, MPI_COMM_WORLD, &status);
    }
    fin = my_gettimeofday();
    fprintf(stderr, "Fin du processus : %d , Temps de calcul total : %g sec\n", rank+1, fin - debut);
  }

  MPI_Finalize();
  
  return 0;
}
int main(int argc, char **argv)
{
	mpz_t g, gMul, s, u, v, uMinusV;
	mpz_t nMinus3, nMinus1;

	gmp_randstate_t rnd_state;
	int found=0, finished=0;
	double start, end;

	mpz_init(n); mpz_init(xSquared);

	if(argc < 2)
	{
		printf("Use %s N\n", argv[0]);
		exit(2);
	}

    //if p q are provided
	if(argc == 3)
	{
		mpz_t p, q;
		mpz_init_set_str(p, argv[1], 10);
		mpz_init_set_str(q, argv[2], 10);

		mpz_addmul(n, p, q);
	}
	else if(mpz_set_str(n, argv[1], 10) == -1)
	{
		printf("Cannot load %s\n", argv[1]);
		exit(2);
	}

	printf("Factorizing %s ..\n", mpz_get_str(NULL, 10, n));

	//a belongs to [1, n-2]
	//u, v <-> s belongs to [0, n-1]
	mpz_init_set(nMinus3, n);
	mpz_sub_ui(nMinus3, nMinus3, 4);

	mpz_init_set(nMinus1, n);
	mpz_sub_ui(nMinus1, nMinus1, 1);

//[1 choose seeds]
	gmp_randinit_default(rnd_state);
	mpz_init(a); mpz_init(s);

	//mpz_urandomm(a, rnd_state, nMinus3);
	//mpz_add_ui(a, a, 1);

	//a is set to 1, comment this if you want it random
	mpz_set_ui(a, 1);
	mpz_urandomm(s, rnd_state, nMinus1);

	mpz_init_set(u, s);
	mpz_init_set(v, s);

	mpz_init(uMinusV); mpz_init(g); mpz_init_set_ui(gMul, 1);

	//Pollard's rho cannot tell if a number is prime, test before getting into an infinite loop
	if(mpz_probab_prime_p(n, 5) > 0)
	{
		printf("%s is prime\n", mpz_get_str(NULL, 10, n));
		exit(0);
	}

	unsigned long steps = 0;
	start = my_gettimeofday();

	while(!finished)
	{
//[Factor search]
	while(!found)
	{
		f(u);
		f(v);
		f(v);

		mpz_set(uMinusV, u);
		mpz_sub(uMinusV, uMinusV, v);
		mpz_abs(uMinusV, uMinusV);

		//We don't calculate gcd everytime, we do 100 multiplications and use the result to
		//extract the gcd, since it must be among the product
		mpz_mul(gMul, gMul, uMinusV);

		if(steps%100 == 0)
		{
			mpz_gcd(g, gMul, n);

			if(mpz_cmp_ui(g, 1) != 0)
			{
				found = 1;
			}

			mpz_set_ui(gMul, 1);
		}

		steps++;
	}

	printf("Testing GCD: %s\n", mpz_get_str(NULL, 10, g));

//[Bad seed]
	if(mpz_cmp(g, n) != 0)
		finished = 1;
	}

	end = my_gettimeofday();

	printf("Found divisor g = %s in %lu steps [%.3f s]\n", mpz_get_str(NULL, 0, g), steps,
			end - start);
}
Example #9
0
int main(int argc, char *argv[]) {
  /* Domaine de calcul dans le plan complexe */
  double xmin, ymin;
  double xmax, ymax;
  /* Dimension de l'image */
  int w,h;
  /* Pas d'incrementation */
  double xinc, yinc;
  /* Profondeur d'iteration */
  int prof;
  /* Image resultat */
  unsigned char *ima, *pima, *ima_loc, *pima_loc;
  /* Variables intermediaires */
  int  i, j;
  double x, y;
  /* Chronometrage */
  double debut, fin;

  /* debut du chronometrage */
  debut = my_gettimeofday();


  if( argc == 1) fprintf( stderr, "%s\n", info);
  
  /* Valeurs par defaut de la fractale */
  xmin = -2; ymin = -2;
  xmax =  2; ymax =  2;
  w = h = 800;
  prof = 10000;
  
  /* Recuperation des parametres */
  if( argc > 1) w    = atoi(argv[1]);
  if( argc > 2) h    = atoi(argv[2]);
  if( argc > 3) xmin = atof(argv[3]);
  if( argc > 4) ymin = atof(argv[4]);
  if( argc > 5) xmax = atof(argv[5]);
  if( argc > 6) ymax = atof(argv[6]);
  if( argc > 7) prof = atoi(argv[7]);

  /* Calcul des pas d'incrementation */
  xinc = (xmax - xmin) / (w-1);
  yinc = (ymax - ymin) / (h-1);
  
  /* affichage parametres pour verificatrion */
  fprintf( stderr, "Domaine: {[%lg,%lg]x[%lg,%lg]}\n", xmin, ymin, xmax, ymax);
  fprintf( stderr, "Increment : %lg %lg\n", xinc, yinc);
  fprintf( stderr, "Prof: %d\n",  prof);
  fprintf( stderr, "Dim image: %dx%d\n", w, h);

  /**** INIT MPI  ****/
  int rank, p;
  MPI_Init(&argc, &argv); /* starts MPI */
  MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* get current process id */
  MPI_Comm_size(MPI_COMM_WORLD, &p);

  if (h % p != 0) {
    printf("Erreur : la hauteur n'est pas divisible pas le nombre de processus\n");
    MPI_Finalize();
    return 0;
  }

  if (p < 1) {
    printf("Erreur : le nombre de processus n'est pas suffisant\n");
    MPI_Finalize();
    return 0;
  }

  //nb_lignes = 10; // pour la distri dynamique
  int h_loc = h / p;
  /**** ****/

  if (rank == MAITRE) {

    /* Allocation memoire du tableau resultat */  
    pima = ima = (unsigned char *)malloc(w * h * sizeof(unsigned char));
    if( ima == NULL) {
      fprintf( stderr, "Erreur allocation mémoire du tableau \n");
      return 0;
    }

    // Decalage à la position du master
    //pima += rank * w * h_loc; // inutile car MAITRE == 0

    /* Traitement de la grille point par point */
    y = ymin + h_loc * rank * yinc;
    for (i = 0; i < h_loc; i++) {
      x = xmin;
      for (j = 0; j < w; j++) {
        *pima++ = xy2color(x, y, prof); 
        x += xinc;
      }
      y += yinc;
    }

    // Reception des slaves :
    MPI_Status status;

    for (i = 0; i < p; i++) {
      if (i != MAITRE) {
        MPI_Probe(MPI_ANY_SOURCE, TAG_DATA, MPI_COMM_WORLD, &status);
        int s = status.MPI_SOURCE; // rank de la source

        if (s != MAITRE) {
          MPI_Recv(ima + s * h_loc * w * sizeof(unsigned char), h_loc * w, MPI_CHAR, s, TAG_DATA, MPI_COMM_WORLD, &status);
        }
      }
    }

    /* fin du chronometrage */
    fin = my_gettimeofday();
    fprintf( stderr, "Temps total de calcul : %g sec\n", fin - debut);
    fprintf( stdout, "%g\n", fin - debut);

    /* Sauvegarde de la grille dans le fichier resultat "mandel.ras" */
    sauver_rasterfile( "output/mandel.ras", w, h, ima);

  } else {

    // Allocation en local
    pima_loc = ima_loc = (unsigned char *)malloc(w * h_loc * sizeof(unsigned char));

    /* Traitement de la grille point par point */
    y = ymin + h_loc * rank * yinc; // y_rank
    for (i = 0; i < h_loc; i++) { 
      x = xmin;
      for (j = 0; j < w; j++) {
        *pima_loc++ = xy2color(x, y, prof); 
        x += xinc;
      }
      y += yinc; 
    }

    // Envoie au master
    MPI_Send(ima_loc, h_loc * w, MPI_CHAR, MAITRE, TAG_DATA, MPI_COMM_WORLD);
  }

  MPI_Finalize();
  
  return 0;
}