/*
 *                 	Exemple "Dotnode.c" PVM versio 3.3
 *		 Susana Maria Bajo Sanchez (ei05646@salleURL.edu)
 *		 Josep Maria Garrell i Guiu (josepmg@salleURL.edu)
 *				Software Paral.lel
 *		           Departament d'Informatica (DI)
 *		         Enginyeria i Arquitectura La Salle
 *		           Universitat Ramon Llull (URL)
 * 			          Curs 1999/2000
*/

#include <stdio.h>
#include <stdlib.h>
#include "pvm3.h"

int info;

//----------------------------------------------------------------
int *attach_slaves(int *NPROC, int *ME)
{
int mytid = pvm_mytid();
int parent = pvm_parent();
int *taskid;
int i, msglabel = 0;

	if (parent>0)
		{
		// Recibo los taskids del "master"
		info = pvm_recv(parent,msglabel);
		if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_recv()\n");

		info = pvm_upkint(NPROC,1,1);
		if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_upkint()\n");

		taskid = (int *)malloc((*NPROC+1)*sizeof(*taskid));

		info = pvm_upkint(taskid,*NPROC,1);
		if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_upkint()\n");

		
		taskid[*NPROC] = parent; 	// Salva taskid del "master"

		// Encuentra el índice del proceso en la tabla de taskid
		for (i=0;i<*NPROC;i++)
			{
			if (taskid[i]==mytid)
				{
				*ME=i;
				return taskid;
				}
			 }
		}
		
	*ME = -1;
	return NULL;
}

//----------------------------------------------------------------
int main()
{
int i;
int Nlocal, NPROC, ME;
int *taskid,HOST;
double *a, *b, partial_sum;

	taskid = attach_slaves(&NPROC,&ME);
	HOST = taskid[NPROC];

	// Lee los datos del "master"
	{	
	int msglabel = 1000;
	
	info = pvm_recv(HOST,msglabel);
	if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_recv()\n");

	info = pvm_upkint(&Nlocal,1,1);
	if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_upkint()\n");

	a = (double *)malloc(Nlocal*sizeof(*a));
	b = (double *)malloc(Nlocal*sizeof(*b));

	info = pvm_upkdouble(a,Nlocal,1);
	if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_upkdouble()\n");

	info = pvm_upkdouble(b,Nlocal,1);
	if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_upkdouble()\n");
	}

	// Calcula los resultados parciales
	partial_sum = 0;
	for (i=0;i<Nlocal;i++) partial_sum += a[i]*b[i];
	
	// Envía la suma parcial al "master"
	{
	int msglabel = 2000;

	info = pvm_initsend(PvmDataDefault);
	if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_initsend()\n");

	info = pvm_pkdouble(&partial_sum,1,1);
	if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_pkdouble()\n");

    	info = pvm_send(HOST,msglabel);
	if (info<0) pvm_perror("DOTNODE: <ERROR> Despues pvm_send()\n");

	free(a);
	free(b);
	}

	pvm_exit(); 

	return 0;
}
