/* include standard library so we can print stuff out */
#include <stdio.h>
/*include standard library to trun ascii to integers */
#include <stdlib.h>
/* include pvm3 library so we can use pvm */
#include "pvm3.h"

int colapse(int);
/* program enterence */
main(int argc,char *argv[]){

  
  int ints[255];
  int i,length;
  int sum = 0;
  int temp;
  int left[128];
  int right[128];
  int left_length = 0;
  int right_length = 0;
  int numt = 0;
  int tids[2];
  int parent = 0;

  /* initailzize array */
  for (i = 0;i < 255; i++){
    ints[i] = 0;
  }
  /* see if we are the parent or not */
  if (pvm_parent() < 0){
    length = argc-1;
    for (i = 1;i < argc;i++){
      ints[i-1] = atoi(argv[i]);
    }
    /* Split the array in half if there are more than two numbers */
    if (length > 2){
      for(i = 0;i < length /2;i++){
	left[i] = ints[i];
      }
      left_length = i;
      for(i;i < length;i++){
	right[i-(length/2)] = ints[i];
      }
      right_length = i - left_length;
    }
    else {
      sum = 0;
      for (i = 0 ; i < length; i ++){
	sum = sum + colapse(ints[i]);
      }
    }
    /* spawn to children */
    numt=pvm_spawn("colapse_pwm", (char**)0, 0, "", 2, tids);
    printf("spawned %d children\n",numt);
    /* kill ourselves if we don't get enough children */
    if (numt < 2){
      printf("failed to get required number or TIDS %d\n",numt); 
      exit(1);
    }
    /* initialize the message buffer */
    pvm_initsend(PvmDataDefault);
    /* store the amount of numbers ew are going to send */
    pvm_pkint(&left_length,1,1);
    for (i = 0;i < left_length;i++){
      /* pack all the numbers in, won't handle an array for some reason */
      pvm_pkint(&left[i], 1, 242);
    }
    /* send the left half to the child */
    pvm_send(tids[0],242);
    printf("sent left of size %d to %d\n",left_length,tids[0]);
    /* initialize a new message buffer */
    pvm_initsend(PvmDataDefault);
    /* store the length we are about to send */
    pvm_pkint(&right_length,1,1);
    for (i = 0;i < right_length;i++){
      /* pack all the number s in */
      pvm_pkint(&right[i],1, 242);
    }
    /* send it to the second child */
    pvm_send(tids[1],242);
    printf("sent right of size %d to %d\n",right_length,tids[1]);
    for (i = 0;i < 2;i++){
      /* receive any messages */
      pvm_recv(-1,-1);
      /* get the value returned from the child 
       it should be the collapse of all numbers sent to it */
      pvm_upkint(&temp,1,1);
      /* sum up the two childrens results */
      sum = sum + colapse(temp);
    }
    /* colapse them one more time */
    sum = colapse(sum);
    printf("Grand Collapsed Sum = %d\n",sum); 
  }



  /* start the child section of the code */
  else {
    /* get the parent's TID */
    parent = pvm_parent();
    /* wait for a message */
    pvm_recv(-1,-1);
    /* unpack the length of numbers to receive */
    pvm_upkint(&length,1,1);
    /* unpack all the numbers and store in the ints array */
    for (i = 0; i < length;i++){
      pvm_upkint(&ints[i],1,1);
    }
    if (length > 2){
      /* spawn some children if we can devided up the work somemore */
      numt=pvm_spawn("colapse_pwm", (char**)0, 0, "", 2, tids);
      if (numt < 2){
	/* if we don't get enough children do all the work ourselves */
	sum = 0;
	for(i = 0 ; i < length; i ++){
	  sum = sum + colapse(ints[i]);
	  if (sum > 9)
	    sum = colapse(sum);
	}
      }
      /* if we do get enough children send them all the work */
      else {
	/* devide up all the work */
	for(i = 0;i < length /2;i++){
	  left[i] = ints[i];
	}
	left_length = i;
	for(i;i < length;i++){
	  right[i-(length/2)] = ints[i];
	}
	right_length = i - left_length;
	/* initialize a new message buffer */
	pvm_initsend(PvmDataDefault);
	/* pcak in the length of numbers we are about to send */
	pvm_pkint(&left_length,1,1);
	for (i = 0;i < left_length;i++){
	  /* store all the numbers */
	  pvm_pkint(&left[i],1, 242);
	}
	/* send the message to the first child */
	pvm_send(tids[0],242);
	/* initialize a new message buffer */
	pvm_initsend(PvmDataDefault);
	/* pcak in the length of the remainig numbers */
	pvm_pkint(&right_length,1,1);
	for (i = 0;i < right_length;i++){
	  /* pcak in all thenumbers */
	  pvm_pkint(&right[i],1, 242);
	}
	/* send the message the the seconf child */
	pvm_send(tids[1],242);
	for (i = 0;i < 2;i++){
	  /* receive any messages */
	  pvm_recv(-1,-1);
	  /* get the returned sum */
	  pvm_upkint(&temp,1,1);
	  /* add it to our running total */
	  sum = sum + colapse(temp);
	}
      }
    }
    else {
      /* if we don't have more then two numbers to collapse 
	 do the work our selves */
      sum = 0;
      for (i = 0 ; i < length; i ++){
	sum = sum + colapse(ints[i]);
      }
    }
    /* make sure the the sum is collapsed */
    sum = colapse(sum);
    /* make a new message buffer */
    pvm_initsend(PvmDataDefault);
    /* pack in our return value */
    pvm_pkint(&sum,1,1);
    /* send it to our parent */
    pvm_send(parent,242);
    /* exit */
    pvm_exit();
  }

  /* this is the function to colapse a number */
}
int colapse(int number){
  int sum;
  sum = 0;
  /* if our number can be collapsed some more do so. */
  while(number > 9){
    /* while there are any digits left in the number 
       keep chopping them off */
    while(0 != number){
      /* get the number in the ones position */
      sum = sum + (number % 10);
      /* remove the number from the ones position */
      number = number / 10;
    }  
    /* set number equal to the sum */
   number = sum;
   /* reinit sum just incase we are still greater than 9 */
   sum = 0;
  }
  /* return the collapsed sum */
  return(number);
}


/* example of output: */
/* pvm@deltabell:/home/pvm/src>./colapse_pwm 123 345 3425 347 637 123 2345 23645 345 3465 098 09435 025 60234 50 2360 9234 50 452345 2342 234234 346 457 32452345 46 4567 578 5 2345 768 879 698 576 346 789 7890 547 346 435 546356 3262345 2435234 347634 2345234 458487 346234 234236 6060908 3245 768 2435 687 2345123 568 84575 234554 */
/* spawned 2 children */
/* sent left of size 28 to 262798 */
/* sent right of size 28 to 262799 */
/* Grand Collapsed Sum = 4 */
/* pvm@deltabell:/home/pvm/src> */

/* a little proof that it's working: */

/* pvm      19153  0.0  0.0  1448     0  p2 SW  Feb  2   0:00 (su) */
/* pvm      19154  0.0  1.3  1872   872  p2 S   Feb  2   0:02 -tcsh  */
/* pvm      26093  0.1  1.3  1244   832  p2 R    02:50   0:04 /home/pvm/pvm3/lib/LINUX/pvmd3  */
/* pvm      26806  0.0  0.7   900   492  p2 S    03:43   0:00 ./colapse_pwm 123 345 3425 347 637 123 2345 23645 345 3465 098 09435 025 60234 50 2360 9234 50 4523 */
/* pvm      26807  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26808  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26809  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26810  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26811  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26812  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26813  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26814  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26815  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26816  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26817  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26818  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26819  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26820  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26821  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26822  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26823  0.0  0.7   896   476  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26824  0.0  0.7   896   472  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26825  0.0  0.7   896   464  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26826  0.0  0.7   896   444  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26827  0.0  0.7   896   444  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26828  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26829  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26830  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26831  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26832  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26833  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26834  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26835  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26836  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26837  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26838  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26839  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26840  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26841  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26842  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26843  0.0  0.6   888   428  p2 S    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* pvm      26844  0.0  0.2   888   168  p2 R    03:43   0:00 /home/pvm/pvm3/bin/LINUX/colapse_pwm  */
/* root         1  0.0  0.1   764    68  ?  S   Jan 29   0:09 init */ 

