/*
			    Sieve of Eratosthenes
			       Using Coroutines

				    CS509
				 Winter 1995
				 G. Lindstrom

		    Class and global variable declarations
		      Also, main() function for testing
*/

import sim.*;

class filter			/* sieve stage class */
      extends process { 

  static int val;		/* for communication between filter stages */

  int p;			/* saves constructor argument */

  process lower;		/* saves prior sieve stage;
				   == current, at construction time */
  process higher;		/* saves next stage;
				   == NULL, at construction time */
  
  filter(String s, int p_) 	/* constructor */
  {
    super(s);
    p = p_;
    lower = scheduler.current;
    higher = null;
  }

  void body()			/* filter coroutine body */
  {
    while (val != 0)
    { /* not shut down yet */
      if (val % p != 0)
	{ /* val is not a multiple of this filter stage's p */
	  if (higher == null) {
	    /* next stage needs to be created */
	    higher = new filter("filter", val);
	  } else
	    scheduler.pass_baton(higher);
	}
      /* get next val */
      scheduler.pass_baton(lower);
    }

   /* do shut down */
   System.out.print(p + " is prime.\n");
   if (higher != null) {
    scheduler.pass_baton(higher);
   }
   scheduler.pass_baton(lower, true);
  }

  public void print() 		/* print type, name, p;
				   also lower->print() if lower != NULL;
				   similarly for higher */
  {
    System.out.print(name + ", p=" + p + " (val = " + val + ")\n");
  }

}

class filter_base 		/* special case: first stage of sieve */ 
  extends filter {

  filter_base(String s, int p) 	/* constructor */
  {
    super(s, p);
  }

  void body()			/* filter_base coroutine body */
     {
      higher = new filter("filter_2", 2);

      for (int i = 3; i<=p; i++)
	{ val = i;
	  scheduler.pass_baton(higher); }

      /* signal shut down */
      val = 0;
      scheduler.pass_baton(higher);
      terminate();
    }

public static void main(String av[]) {
  /* create controller */
  filter_base fb = new filter_base("filter base", 1000);

  /* start controller */
  scheduler.pass_baton(fb);

  /* delete controller */
  fb.terminate();

}

}  // end filter


