#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>
#include "Alinit.h"

static  STOR ustor;

//static  char stor0[LEN_G];
static  char stor0[10];
int N_alloc=0;

/*-------------------------------------------------------*/
/* Инициализация управления памятью                      */
/*-------------------------------------------------------*/
int alinit()
{
  return 0;
} /* inita */
/*-------------------------------------------------------*/
/* Инициализация управления памятью                      */
/*-------------------------------------------------------*/

int alinit0()
{
  ustor.nep=1;
  ustor.nop=0;
  ustor.befep[0]=(char*)stor0;
  ustor.lefep[0]=LEN_G;
  ustor.lefep[0]=LEN_G;
  ustor.flagep[0]=0;
  return 0;
} /* inita */
/*-------------------------------------------------------*/
/* Размещение вектора (новый вариант)                    */
/*-------------------------------------------------------*/

char* alvec(int len, int *rc)
{
  char * vect;
  if (len<0) {
     *rc = ERRDATA;
     return NULL;
  }
  *rc=NOSTOR;
  vect = (char*) malloc(len);
  if (vect==NULL) return NULL;
  N_alloc++;
  *rc=0;
  return vect;

} /* alvec */
/*-------------------------------------------------------*/
/* Размещение вектора (старый вариант)                   */
/*-------------------------------------------------------*/

char* alvec0(int len, int *rc)
{
  int i,ng;
  char * vect;
  if (len<0) {
    *rc = ERRDATA;
    return NULL;
  }
  vect=NULL;
  *rc=NOSTOR;
  ng=ustor.nep+ustor.nop;
  N_alloc ++;
  for (i=0; i<ng; i++){
  if (ustor.flagep[i]==0){
     if (ustor.lefep[i]>=len){
        vect=ustor.befep[i];
        ustor.flagep[i]=1;
        ustor.nop++;
        ustor.nep--;
        if (i==ng-1){
           if (ng<NPL){
           ustor.nep++;
           ustor.befep[ng] = ustor.befep[i] + len;
           ustor.lefep[ng] = ustor.lefep[i] - len;
           ustor.lefep[i]=len;
           ustor.flagep[ng]=0;
           }
           else
           {
               *rc=NOFRPLOT;
               break;
          }
        }
        *rc=0;
        break;
     }
  }
  }
  return vect;

} /* alvec0 */
/*-------------------------------------------------------*/
/* Размещение матрицы                                    */
/*-------------------------------------------------------*/
double** almat(int pol, int len, int *rc)
//int pol;  /* число строк */
//int len;  /* размер строки */
//int *rc;
{
   double  **mac;
   double  *aril;
   int  i;
   mac=(double**)alvec((int)(sizeof(double**)*pol),rc);
   if (*rc != 0) return NULL;
   aril=(double*)alvec((int)(pol*len*sizeof(double)),rc);
   if (*rc != 0) return NULL;
   for (i=0; i<pol; i++){
       mac[i]=aril;
       aril += len;
   }
   return mac;
}  /* almat */
/*-------------------------------------------------------*/
/* Размещение матрицы элементов int                      */
/*-------------------------------------------------------*/
int** almat_i(int pol, int len, int *rc)
//int pol;  /* число строк */
//int len;  /* размер строки */
//int *rc;
{
   int  **mac;
   int  *aril;
   int  i;
   mac=(int**)alvec((int)(sizeof(int**)*pol),rc);
   if (*rc != 0) return NULL;
   aril=(int*)alvec((int)(pol*len*sizeof(int)),rc);
   if (*rc != 0) return NULL;
   for (i=0; i<pol; i++){
       mac[i]=aril;
       aril += len;
   }
   return mac;
}  /* almat_i */
/*-------------------------------------------------------*/
/* Размещение матрицы элементов float                    */
/*-------------------------------------------------------*/
float** almat_f(int pol, int len, int *rc)
//int pol;  /* число строк */
//int len;  /* размер строки */
//int *rc;
{
   float  **mac;
   float  *aril;
   int  i;
   mac=(float**)alvec((int)(sizeof(float**)*pol),rc);
   if (*rc != 0) return NULL;
   aril=(float*)alvec((int)(pol*len*sizeof(float)),rc);
   if (*rc != 0) return NULL;
   for (i=0; i<pol; i++){
       mac[i]=aril;
       aril += len;
   }
   return mac;
}  /* almat_i */
/*-------------------------------------------------------*/
/* Размещение матрицы элементов bool                      */
/*-------------------------------------------------------*/
bool** almat_b(int pol, int len, int *rc)
//int pol;  /* число строк */
//int len;  /* размер строки */
//int *rc;
{
   bool  **mac;
   bool  *aril;
   int  i;
   mac=(bool**)alvec((int)(sizeof(bool**)*pol),rc);
   if (*rc != 0) return NULL;
   aril=(bool*)alvec((int)(pol*len*sizeof(bool)),rc);
   if (*rc != 0) return NULL;
   for (i=0; i<pol; i++){
       mac[i]=aril;
       aril += len;
   }
   return mac;
}  /* almat_b */
/*-------------------------------------------------------*/
/* Размещение матрицы произвольной размерности           */
/*-------------------------------------------------------*/
char** almat_size(int pol, int len, int size, int *rc)
//int pol;  /* число строк */
//int len;  /* размер строки */
//int *rc;
{
   char  **mac;
   char  *aril;
   int  i;
   mac=(char**)alvec((int)(sizeof(char**)*pol),rc);
   if (*rc != 0) return NULL;
   aril=(char*)alvec((int)(pol*len*size),rc);
   if (*rc != 0) return NULL;
   for (i=0; i<pol; i++){
       mac[i]=aril;
       aril += len*size;
   }
   return mac;
}  /* almat_i */

/*-------------------------------------------------------*/
/* Размещение массива векторов                           */
/*-------------------------------------------------------*/
int almvc(DSC_MVC  * mvc, int pol, int size) {
// DSC_MVC  * mvc;
// int pol;  /* число векторов */
// int size;

   int  rc;
   int  i;
   mvc->len_mvc=0;
   mvc->addr_page=(char**)alvec((int)(sizeof(char**)*pol),&rc);
   if (rc != 0) return rc;
   mvc->shift=(short*)alvec((int)(sizeof(short)*pol),&rc);
   if (rc != 0) return rc;
   mvc->len=(short*)alvec((int)(sizeof(short)*pol),&rc);
   if (rc != 0) return rc;
   for (i=0; i<pol; i++) {
      mvc->addr_page[i]=NULL;
      mvc->len[i]=-1;
   }
   mvc->size = size;
   mvc->len_mvc=pol;
   mvc->cur_num = -1;
   return 0;
}  /*  almvc  */
/*-------------------------------------------------------*/
/* Размещение вектора в массиве векторов                 */
/*-------------------------------------------------------*/
char* almveco(DSC_MVC * mvc, int pol, int len, int * rc) {
//DSC_MVC  * mvc;
//int pol;  /* номер вектора */
//int len;
//int *rc;
   int  i;
   if (mvc->cur_num != pol-1) {
      *rc = NOSEQ;
      return NULL;
   }
   if ( mvc->len_mvc == pol) {
      *rc = BIGLENMVC;
      return NULL;
   }
   if (len*mvc->size > SIZE_PG) {
      *rc = BIGLENV;
      return NULL;
   }
   if (mvc->cur_num==-1) {
      mvc->addr_page[0]=(char*)alvec(SIZE_PG,rc);
      if (*rc != 0) return NULL;
      mvc->shift[0]=0;
   }
   else {
      if (mvc->size*(mvc->shift[pol-1] + mvc->len[pol-1] + len) > SIZE_PG) {
         mvc->addr_page[pol]=(char*)alvec(SIZE_PG,rc);
         if (*rc != 0) return NULL;
         mvc->shift[pol]=0;
      }
      else {
         mvc->shift[pol] = mvc->shift[pol-1] + mvc->len[pol-1];
         mvc->addr_page[pol]=mvc->addr_page[pol-1];
      }
   }
   *rc=0;
   mvc->len[pol]=len;
   mvc->cur_num++;
   return (char*)(mvc->addr_page[pol] + mvc->shift[pol]*mvc->size);
}  /*  almveco  */
/*-------------------------------------------------------*/
/* Получение доступа к вектору в массиве векторов        */
/*-------------------------------------------------------*/
char * almvec(DSC_MVC  * mvc, int pol, int * len, int * rc) {
//DSC_MVC  * mvc;
//int pol;  /* номер вектора */
//int *len;
//int *rc;
   int  i;
   if ( mvc->len_mvc <= pol) {
      *rc = BIGLENMVC;
      return NULL;
   }
   *len=mvc->len[pol];
   if (*len== -1) {
      *rc=NOVEC;
      return NULL;
   }
   *rc=0;
   return (char*)(mvc->addr_page[pol] + mvc->shift[pol]*mvc->size);
}  /*  almvec  */
/*-------------------------------------------------------*/
/* Освобождение матрицы                                  */
/*-------------------------------------------------------*/

int fremat( char *** mat) {
//char *** mat;
   int  rc;
   rc = frevec((char**)mat[0]);
   if (rc !=0 ) return rc;
   rc = frevec((char**)mat);
   if (rc !=0 ) return rc;
   return 0;
}  /* ocism */

/*-------------------------------------------------------*/
/* Освобождение вектора                                  */
/*-------------------------------------------------------*/
int frevec(char ** vec) {

  if (*vec != NULL) {
    free(*vec);
    *vec = NULL;
    N_alloc --;
  }  
  return 0;
}  // frevec
/*-------------------------------------------------------*/
/* Освобождение вектора                                  */
/*-------------------------------------------------------*/
int frevec0(char ** vec) {
//char ** vec;
  int i,j,ng;
  int rc;

  rc=NOUSTN;
  ng=ustor.nep+ustor.nop;
  N_alloc --;
  for (i=0; i<ng; i++){
  if (ustor.flagep[i]==1){
     if (ustor.befep[i]== *vec){
        ustor.flagep[i]=0;
        *vec = NULL;
        ustor.nop--;
        ustor.nep++;
        if (i<ng-1)
        {
          if (ustor.flagep[i+1]==0){
             ustor.nep--;
             ustor.lefep[i] += ustor.lefep[i+1];
             for (j=i+1; j<ng-1; j++){
                ustor.befep[j]=ustor.befep[j+1];
                ustor.lefep[j]=ustor.lefep[j+1];
                ustor.flagep[j]=ustor.flagep[j+1];
             }
             ng--;
          }
        }
        if  (i>0)
        {
          if (ustor.flagep[i-1]==0){
             ustor.nep--;
             ustor.lefep[i-1] += ustor.lefep[i];
             for (j=i; j<ng-1; j++){
                ustor.befep[j]=ustor.befep[j+1];
                ustor.lefep[j]=ustor.lefep[j+1];
                ustor.flagep[j]=ustor.flagep[j+1];
             }
             ng--;
          }
        }
        rc=0;
        break;
      }
    }
}  // старый вариант frevec

  return rc;
}  /* frevec */
/*-------------------------------------------------------*/
/* Освобождение массива векторов                         */
/*-------------------------------------------------------*/
int fremvc(DSC_MVC * mvc) {
//DSC_MVC  * mvc;
   int  rc;
   int  i;
   
   for (i=mvc->len_mvc-1; i>=0; i--) {
      if (mvc->addr_page[i]!=NULL && mvc->shift[i]==0) {
         rc = frevec(mvc->addr_page+i);
         if (rc!=0) return rc;
      }
   }      
   rc = frevec((char**)&mvc->len);
   if (rc != 0) return rc;
   rc = frevec((char**)&mvc->shift);
   if (rc != 0) return rc;
   rc = frevec((char**)&mvc->addr_page);
   if (rc != 0) return rc;
   mvc->len_mvc=0;
   return 0;
}  /*  fremvc  */
//---------------------------------------------------
int get_count() {
   return N_alloc;
}
//---------------------------------------------------
int check_count(int count, int diff) {
   if (N_alloc - count !=  diff)
     return 1;
   else
     return 0;
}
