#include <iomanip>
#include <cilk/cilk.h>
#include <cilk/cilk_api.h>
#include "config.hpp"
#include "coeffs.hpp"
#include "polygon_generator.hpp"
#include "avx_matrix.hpp"
#include "results.hpp"

ResultsReducer cilk_result;

void box(string str){
  size_t w=str.size();
  cout<<"\u250c";
  for(size_t i=0;i<w+2;++i) cout<<"\u2500";
  cout<<"\u2510"<<endl;
  cout<<"\u2502 "<<str<<" \u2502"<<endl;
  cout<<"\u2514";
  for(size_t i=0;i<w+2;++i) cout<<"\u2500";
  cout<<"\u2518"<<endl;
}

void disp_info(){
  box("Compute Fp's series of Self Avoiding Polygon");
  cout<<endl;
  cout<<" Maximal length is "<<max_len<<endl;
  cout<<" Workers number is "<<__cilkrts_get_nworkers()<<endl;
}

void treat(Polygon* P){
  size_t l=P->length;
  size_t i=l/2-1;
  ++cilk_result.numbers(i);
  Reel fp=P->fp();
  cilk_result.sum_fp(i)+=fp;
  delete P;
}
int main(){
  cout<<std::setprecision(20);
  disp_info();
  compute_coeffs();
  size_t nb[max_len/2];
  Reel res[max_len/2];
  Reel coeff[max_len/2];
  for(size_t i=0;2*i<max_len;++i){
    nb[i]=0;
    res[i]=0;
  }
  PolygonGenerator gen;
  size_t total=0;
  Polygon* P;
  while(gen.next()){
    P=new Polygon;
    gen.set(*P);
    cilk_spawn
    treat(P);
    ++total;
  }
  cilk_sync;
  Reel d=256;
  for(size_t i=1;2*i<max_len;++i){
    Reel l=2*i+2;
    cout<<endl<<"=== Length "<<l<<" ==="<<endl;
    Reel r=cilk_result.sum_fp(i);
    Reel n=2*l;
    coeff[i]=(n*r)/d;
    cout<<" > number : "<<cilk_result.numbers(i)<<endl;
    cout<<" >  value : "<<coeff[i]<<endl;
    d*=16;
  }
  cout<<endl<<">>> Total : "<<total<<endl;
  cout<<endl<<">>> Coefficients list : "<<endl;
  for(size_t i=1;2*i<max_len;++i){
    cout<<coeff[i]<<" ";
  }
  cout<<endl;
  
}
