/* * * Mathman.c - Mathmatical function of the mailbox program. * * By: Theo Van Dinter - 96/09/09 * * I call this routine 'mathman' due to a character from "Square One TV", * a math show on PBS, which had a Pacman-like character who had to go around * the game board trying to answer various math questions while chanting * "mathman mathman mathman ..." * */ #include "mailbox.h" /* Mr. Standard Header */ /* * adder - 96/09/09 * * By: Theo Van Dinter (felicity@kluge.net) * * Child process to handle number range summation and range passing. * * Calling Parameters: myid = Child # * * No return values. * */ void adder(int myid) { /* Total = total integers added msg_to = which child to send a message to flag = a queue flag N1/N2 = current range to deal with R1/R2 = full range to deal with MR = max range to add at one time loo = general loop variable msg = incoming message variable msg2 = outgoing message variable */ int total=0, msg_to, flag=1,N1,N2,R1,R2,MR,loo; struct msg msg,msg2; while (1) /* Loop to infinity and beyond */ { if (flag) /* True when not dealing with queued numbers */ { while(RecvMsg(myid,&msg)==-1) /* This isn't the greatest, but if this process dies, the parent is deadlocked. */ { printf("Process %d got an error with RecvMsg.\n",myid); } if (msg.wType==2) /* Additional request */ { flag=0; /* Go through until the queue is finished */ R1=msg.wVal1; /* Full range 1 */ R2=msg.wVal2; /* Full range 2 */ MR=msg.wTotal; /* Max range per addition cycle */ if (myid!=NUMPROC-1) /* Not the last child */ { if (R2-R1>1) /* Something to actually send... */ { /* Current process keeps last 1/3 of range */ N1=R2-(R2-R1+1)/3+1; msg2.wVal1=R1; msg2.wVal2=N1-1; msg2.iFrom=myid; msg2.wTotal=MR; msg2.wType=2; printf("Process %d sending %d-%d to Process %d\n",myid, msg2.wVal1,msg2.wVal2,myid+1); while(SendMsg(myid+1,&msg2)==-1) /* Again, not the greatest way of doing this, but better us than the parent. */ { printf("SendMsg error in Proc %d.\n",myid); } R1=N1; } } } else /* Process full range, the parent is the boss. */ { R1=1; /* For queue checking later on, R1>R2 ... */ R2=0; N1=msg.wVal1; N2=msg.wVal2; } msg_to=flag?msg.iFrom:0; /* Return to sender if normal, or else send the results to the parent if we're doing 'additional' stuff. */ } if (msg.wType==2) /* An additional request ... */ { /* Setup the range to be added from the available full range */ N1=R1; if (R2-R1+1>MR) /* There are at least maxrange digits left */ { N2=R1+MR-1; R1+=MR; } else /* There are less than (or equal to) maxrange digits left */ { N2=R2; R1=R2+1; } } if (msg.wType==-1) /* Terminate */ { msg2.iFrom=myid; msg2.wType=-1; msg2.wTotal=total; while(SendMsg(msg_to,&msg2)==-1) printf("SendMsg failed for Proc %d.\n",myid); exit(0); } else if (msg.wType==0||msg.wType==2) /* Request */ { total+=N2-N1+1; /* Total integers summed is increased */ msg2.iFrom=myid; msg2.wType=1; msg2.wTotal=addrange(N1,N2); /* total=sum of the range */ msg2.wVal1=N1; msg2.wVal2=N2; sleep(myid); /* sleep the correct amount */ while(SendMsg(msg_to,&msg2)==-1) /* return the result */ printf("SendMsg failed for Proc %d.\n",myid); } else if (msg.wType==1) /* A Result, but I shouldn't get one of these.. */ { printf("Child %d (%d) received a result message from process ID ", myid,getpid); printf("%d.\n",msg.iFrom); } if (msg.wType==2) /* Add. Request, check to reset flag. */ { if (R1>R2) /* If the full range is finished, set flag=1 so that */ flag=1; /* another message can be received. */ } } /* While(1) */ } /* adder(int) */ /* * addrange - 96/09/09 * * By: Theo Van Dinter (felicity@kluge.net) * * Returns the sum of the range from N1-N2 inclusive. * * Calling Parameters: N1 = First number in range * N2 = Last number in range * * Return Values: Sum of the range inclusively. * * Math: * * If the sum from 0-N = n(n+1)/2, then from N1-N2 = n2(n2+1)/2 - (n1-1)(n1)/2 * so, 2*sum = n2(n2+1) - (n1-1)(n1) = n2^2+n2 - n1^2-n1 * and finally, sum = (n2*n2 + n2 + n1 - n1*n1)/2 * */ int addrange(int N1,int N2) { return((N2*N2+N2+N1-N1*N1)/2); }