
// PiWorker.java
// Andrew Davison, ad@coe.psu.ac.th, May 2023

/* Each PiWorker threads reads one RANGE tuple
   and converts the steps into x values using the xStep value
   stored in the ("XSTEP", xStep) tuple. 

   PiWorker uses the same areaRange() function as in the
   sequential version of this problem in CalcPiSeq.java, but the
   subarea answer is stored in the space as a tuple of the form:
     ("AREA", <worker id>, area)

  Usage:
    > compile.bat PiWorker.java

    Part of the application made up of:
       * CalcPiSpace.java
       * PiWorker.java
*/

import java.util.*;
import java.math.*;

import org.jspace.*;


public class PiWorker implements Runnable
{
  private Space space;
  private int id;


  public PiWorker(int id, Space space)
  {
    this.space = space;
    this.id = id;
  }


  public void run()
  {
    try {
      Object[] stepObj = 
          space.query( new ActualField("XSTEP"),
                     new FormalField(BigDecimal.class));
      BigDecimal xStep = (BigDecimal)stepObj[1];

      Object[] rangeObj = 
          space.get( new ActualField("RANGE"),
                     new FormalField(Integer.class),
                     new FormalField(Integer.class));
      int startStep = (int)rangeObj[1];
      int endStep = (int)rangeObj[2];
 
      BigDecimal area = areaRange(startStep, endStep, xStep);

      space.put("AREA", id, area);
      // System.out.println("W-" + id + "=" + area + " ");
    }
    catch (InterruptedException e) 
    {  System.out.println("W-" + id + " error: " + e);  }
  } /* run */



  private BigDecimal areaRange(int startStep, int endStep, 
                                      BigDecimal xStep)
  /* The calculation range is supplied in terms of the
     number of steps within this range. startStep is converted
     into a BigDecimal x value before the function is called,
     and then incremented using xStep.
     This is almost the same function as used in CalcPiSeq.java
  */
  { System.out.println("Steps range for W-" + id + ": " + 
                             startStep + " --> " + endStep);

    BigDecimal four = BigDecimal.valueOf(4);
    BigDecimal result = BigDecimal.ZERO; 
    BigDecimal x = BigDecimal.valueOf(startStep).multiply(xStep);
          // starting x value == startStep*xStep
    BigDecimal divisor;

    for(int i=startStep; i < endStep; i++) { 
      divisor = (BigDecimal.ONE).add(x.multiply(x));  // (1.0+x*x)
      result = result.add(
           four.divide(divisor, 15, RoundingMode.HALF_UP));
         // result += 4.0/(1.0+x*x); 
      x = x.add(xStep); // next x value
    }

    // return the area under the curve
    return result.multiply(xStep);
  }  // end of areaRange()


}  // end of PiWorker class
