#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <math.h>
#include "C:\Programmi\MATLAB7\extern\include\engine.h"
using namespace std;
class alberi{
  public:
  int n;
  int lun;
  double *S, *f, *c;
  alberi(int);
  ~alberi();
  double max(double, double);
  int lunghezza(int);
  void look(double, double, double,  double);
  void visualizza();
  void stampa();
};

double alberi::max(double a, double b){
 if (a >= b){return a;}
 else{return b;}
}

int alberi::lunghezza(int dim){
 int i,lung=0;
 for (i=0; i<=dim; i++) {
  lung = lung + pow(2,i);
 }
 return lung;
}

alberi::alberi(int step){
  n = step;
  lun = lunghezza(n)+1;
  S = new (nothrow) double[lun];
  f = new (nothrow) double[lun];
  c = new (nothrow) double[lun];
  if (S == NULL || f == NULL || c == NULL) {
    exit(1);
  }
}

alberi::~alberi(){
  delete [] S;
  delete [] f;
  delete [] c;
}

void alberi::look(double price, double rate, double vol, double time){
  int i;
  double prob;
  double dt = time/n;
  double comp = exp(rate*dt);
  double up = exp(vol*sqrt(dt));
  double down = 1/up;
  double ud[2] = {up,down};
  prob = (comp - down)/(up - down);
  S[0]=0;
  S[1] = price;
  f[0]=0;
  f[1] = price;
  for (i = 2; i < lun; i++){
    S[i] = S[i/2]*ud[i%2];
    f[i] = max(f[i/2],S[i]);
  }

  for (i = lun; i >= pow(2,n); i--){
    c[i] = max(f[i]-S[i],0);
  }
  for (i =lun-pow(2,n)-1; i >= 1; i--){
    c[i] = (prob*(c[i*2]) + (1- prob)*(c[(i*2)+1])) / comp;
    c[i] = max(f[i] - S[i],c[i]);
  }

}

void alberi::visualizza(){
  Engine *ep;
  ep = engOpen("");
  mxArray *m_n, *m_stock, *m_f ,*m_c;
  m_n =  mxCreateDoubleScalar(n);
  m_stock = mxCreateDoubleMatrix(lun,1,mxREAL);
  m_f = mxCreateDoubleMatrix(lun,1,mxREAL);
  m_c = mxCreateDoubleMatrix(lun,1,mxREAL);
  if (m_n == NULL || m_f == NULL || m_c == NULL || m_n == NULL) {
    printf("Errore nell'allocazione della memoria\n");
    engClose(ep);
    return;
  }
  memcpy(mxGetPr(m_f), f, lun*sizeof(double));
  memcpy(mxGetPr(m_stock), S, lun*sizeof(double));
  memcpy(mxGetPr(m_c), c, lun*sizeof(double));
  engEvalString(ep,"clear;");
  engPutVariable(ep,"N",m_n);
  engPutVariable(ep,"S",m_stock);
  engPutVariable(ep,"F",m_f);
  engPutVariable(ep,"C",m_c);
  engEvalString(ep,"treesv2;");
}

void alberi::stampa(){
int i;
printf("%d",n);
for (i = 0; i < lun; i++){
  printf("%f\n",f[i]);
}
}
int main( int argc, char * argv[] ){
  alberi opzione(3);
  opzione.look(10,0.08,0.3,0.25);
  opzione.stampa();
  opzione.visualizza();
  while(getchar() !='u');
  return 0;

}

