
#include "global.h"
#include <stdio.h>


/******************************************************************************/
/* CONSTANTES                                                                 */
/******************************************************************************/

#define FICHIER "pile.dat"


/******************************************************************************/
/* STRUCTURE DE TAILLE D'UN ELEMENT DE LA PILE                                */
/*                                                                            */
/* Stocke le nombre total de doubles, la dimension de la matrice Qr, le nombre*/
/* de tirages (xi,yi,ri,wi,...) et la longueur du vecteur des zones.          */
/******************************************************************************/

typedef struct {
  long N;
  long MQr;
  long NQr;
  long Nva;
  long Nzones;
} taille_elt_t;


/******************************************************************************/
/* EMPILEMENT / DEPILEMENT                                                    */
/*                                                                            */
/* Gestion de la pile des donnees. Lorsque l'on zoome sur la texture, on em-  */
/* pile les variables sous matlab dans une fichier. Lorsque l'on fait un zoom */
/* arriere, on depile.                                                        */
/*                                                                            */
/* ENTREES (empilement) / SORTIES (depilement) :                              */
/*   -> tailles      : vecteur des tailles des elements de la pile            */
/*   -> Qr           : matrice de texture                                     */
/*   -> va           : variables aleatoires tirees pour generer la texture    */
/*   -> x_max, y_max : dimensions de la texture                               */
/*   -> r_min        : resolution de la cascade                               */
/*   -> dx           : pas d'espace                                           */
/*   -> ng_min       : niveau de gris minimum de l'image                      */
/*   -> ng_max       : niveau de gris maximum de l'image                      */
/*   -> zones        : zones presentes dans la texture                        */
/* SORTIES (empilement) / ENTREES (depilement) :                              */
/*   -> tailles      : vecteur des tailles des elements de la pile            */
/******************************************************************************/

void mexFunction(int nb_sorties,      mxArray *sorties[],
                 int nb_entrees,const mxArray *entrees[]) {

  /* variables locales */

  unsigned char action;
  long taille_pile,somme,i;
  double *Qr,*va,*x_max,*y_max,*r_min,*dx,*ng_min,*ng_max,*zones;
  taille_elt_t taille_elt,*tailles_entree,*tailles_sortie;
  FILE *f;


  /* lecture des entrees */

  if      (nb_entrees==10 && nb_sorties==1 ) action=1; /* empiler */
  else if (nb_entrees==1  && nb_sorties==10) action=2; /* depiler */
  else mexErrMsgTxt("Mauvais nombre d'arguments !");
  tailles_entree=(taille_elt_t *)mxGetData(entrees[0]);
  taille_pile=mxGetN(entrees[0]);
  if (action==1) { /* cas empilement */
    Qr    =mxGetPr(entrees[1]);
    va    =mxGetPr(entrees[2]);
    x_max =mxGetPr(entrees[3]);
    y_max =mxGetPr(entrees[4]);
    r_min =mxGetPr(entrees[5]);
    dx    =mxGetPr(entrees[6]);
    ng_min=mxGetPr(entrees[7]);
    ng_max=mxGetPr(entrees[8]);
    zones =mxGetPr(entrees[9]);
    taille_elt.MQr   =mxGetM(entrees[1]);
    taille_elt.NQr   =mxGetN(entrees[1]);
    taille_elt.Nva   =mxGetN(entrees[2]);
    taille_elt.Nzones=mxGetN(entrees[9]);
    taille_elt.N=taille_elt.MQr*taille_elt.NQr
                +(sizeof(tirage_t)/sizeof(double))*taille_elt.Nva
                +taille_elt.Nzones+6;
  }


  /* allocation memoire pour les sorties */

  if (action==1) { /* cas empilement */

    sorties[0]=mxCreateNumericMatrix(sizeof(taille_elt_t)/sizeof(long),
                                     taille_pile+1,mxINT32_CLASS,mxREAL);

  } else {         /* cas depilement */

    sorties[0]=mxCreateNumericMatrix(sizeof(taille_elt_t)/sizeof(long),
                                     taille_pile-1,mxINT32_CLASS,mxREAL);
    sorties[1]=mxCreateDoubleMatrix(tailles_entree[taille_pile-1].MQr,
                                    tailles_entree[taille_pile-1].NQr,mxREAL);
    sorties[2]=mxCreateDoubleMatrix(sizeof(tirage_t)/sizeof(double),
                                    tailles_entree[taille_pile-1].Nva,mxREAL);
    sorties[3]=mxCreateDoubleMatrix(1,1,mxREAL);
    sorties[4]=mxCreateDoubleMatrix(1,1,mxREAL);
    sorties[5]=mxCreateDoubleMatrix(1,1,mxREAL);
    sorties[6]=mxCreateDoubleMatrix(1,1,mxREAL);
    sorties[7]=mxCreateDoubleMatrix(1,1,mxREAL);
    sorties[8]=mxCreateDoubleMatrix(1,1,mxREAL);
    sorties[9]=mxCreateDoubleMatrix(1,tailles_entree[taille_pile-1].Nzones,mxREAL);
    Qr    =mxGetPr(sorties[1]);
    va    =mxGetPr(sorties[2]);
    x_max =mxGetPr(sorties[3]);
    y_max =mxGetPr(sorties[4]);
    r_min =mxGetPr(sorties[5]);
    dx    =mxGetPr(sorties[6]);
    ng_min=mxGetPr(sorties[7]);
    ng_max=mxGetPr(sorties[8]);
    zones =mxGetPr(sorties[9]);

  }
  tailles_sortie=(taille_elt_t *)mxGetData(sorties[0]);
  

  /* gestion de la pile */
  
  if (action==1) { /* empilement */

    if (taille_pile==0) { /* la pile est vide, on vide le fichier */
      f=fopen(FICHIER,"wb");
    } else {
      somme=0;
      for (i=0;i<taille_pile;i++) somme+=tailles_entree[i].N;
      f=fopen(FICHIER,"r+b");
      fseek(f,somme*sizeof(double),SEEK_SET);
    }
    fwrite(Qr    ,sizeof(double),taille_elt.MQr*taille_elt.NQr,f);
    fwrite(va    ,sizeof(tirage_t),taille_elt.Nva,f);
    fwrite(x_max ,sizeof(double),1,f);
    fwrite(y_max ,sizeof(double),1,f);
    fwrite(r_min ,sizeof(double),1,f);
    fwrite(dx    ,sizeof(double),1,f);
    fwrite(ng_min,sizeof(double),1,f);
    fwrite(ng_max,sizeof(double),1,f);
    fwrite(zones ,sizeof(double),taille_elt.Nzones,f);
    fclose(f);
    for (i=0;i<taille_pile;i++) tailles_sortie[i]=tailles_entree[i];
    tailles_sortie[taille_pile]=taille_elt;

  } else {         /* depilement */

    somme=0;
    for (i=0;i<taille_pile-1;i++) somme+=tailles_entree[i].N;
    taille_elt=tailles_entree[taille_pile-1];
    f=fopen(FICHIER,"rb");
    fseek(f,somme*sizeof(double),SEEK_SET);
    fread(Qr    ,sizeof(double),taille_elt.MQr*taille_elt.NQr,f);
    fread(va    ,sizeof(tirage_t),taille_elt.Nva,f);
    fread(x_max ,sizeof(double),1,f);
    fread(y_max ,sizeof(double),1,f);
    fread(r_min ,sizeof(double),1,f);
    fread(dx    ,sizeof(double),1,f);
    fread(ng_min,sizeof(double),1,f);
    fread(ng_max,sizeof(double),1,f);
    fread(zones ,sizeof(double),taille_elt.Nzones,f);
    fclose(f);
    if (taille_pile==1) { /* la pile est vide, on vide le fichier */
      f=fopen(FICHIER,"wb");
      fclose(f);
    }
    for (i=0;i<taille_pile-1;i++) tailles_sortie[i]=tailles_entree[i];

  }
}

