
struct AverageStrikeAmericanPut
{
  bool pathDependent;

  double stockSum;
  unsigned int averageStrikeN;

  void derivativeInit(unsigned int N)
  {
    stockSum = 0.0;
    averageStrikeN = N + 1;
    
    pathDependent = true;
  }

  double payOff(double K, double inStockValue)
  {
    double returnValue;
    
    // printf("  payOff, average %f\n", stockSum / averageStrikeN);
    
    returnValue = MAX(0.0, (stockSum / averageStrikeN) - inStockValue);
    
    stockSum -= inStockValue;

    return returnValue;
  }

  double derivativeValue(stack<double> *childStack, unsigned int T, vector< vector<double> > P, 
			 vector<double> disc, double K, double stockValue)
  {
    int pindex;                     // index into first vector of P
                                   // needed because P might be time dependent or time independent

    if(P.size() > 1)     // is P time dependent?
      pindex = T;
    else
      pindex = 0;
    
    double derivativeValue = 0.0;

    for(int childNum = P[pindex].size() - 1; childNum >= 0; childNum--)
      {
	derivativeValue += childStack->top() * P[pindex][childNum];
	
	// printf("childStack->top is %f, result is %f (%f * %f)\n", childStack->top(), derivativeValue, childStack->top(), P[pindex][childNum]);

	childStack->pop();
      }
    
    double r;
    
    if(disc.size() > 1)   // is R time dependent?
      r = disc[T];
    else
      r = disc[0];

    double depth = T + 1.0;
    
    double returnVal = MAX(r * derivativeValue, MAX(0.0, ((stockSum / depth) - stockValue)) );

    // printf("returnVal is %f, average is %f, T is %2.0f\n", returnVal, (stockSum / depth), depth);

    stockSum -= stockValue;
    
    return returnVal;
  }
  
  void visitStock(unsigned int depth, unsigned int c, double inStockValue)
  {
    stockSum += inStockValue;

    // printf("visitStock: depth = %d, c = %d, inStockValue = %f, stockSum = %f\n", depth, c, inStockValue, stockSum);
  }
};




