#include <vcl.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "TypeData.h"
#include "SortP.h"
#include "ListConst.h"
//#include "LinkScad.h"
#include "message.h"
#include "Data_Gen.h"
//#include "Bend_Elem.h"
//#include "MultiSupportBeam.h"

 /*----------------------------------------------------*/
 /*  Рычков                                            */
 /*----------------------------------------------------*/
 /*----------------------------------------------------*/
 //  Двоичный поиск с заданным допустимым отклонением
  char*  bsearch_diff(char* var, char *diff, char *list, int n, int size, int(*cfun_diff)(const void *, const void *, const void*))
  // char *list;      //  Сортированный список
  // char *var;       //  Адрес элемента, который нужно найти
  // char *diff;       //  Адрес отклонения
  // unsigned int  size;        /*  Размер элементов списка    */
  // int (*cfun_diff)(const void *, const void *, const void*);  /*  Адрес функции сравнения    */
    {
      int l1, l2, k;
      if (n==0)
         return NULL;
      l1 = 0;        //  нижняя граница
      l2 = n - 1;    //  верхняя граница
      do {
        k = (l1 + l2)/2;
        if ( k < 0) return NULL;
        if ( (*cfun_diff)( var, list + k*size, diff) > 0 ) { // var > list[k]
            l1 = k+1;
        }
        else {
          if ( (*cfun_diff)( var, list + k*size, diff) < 0 ) { // var > list[k]
            l2 = k-1;
          }
          else
            return (list + k*size);
        }
      } while (l1 <= l2);
      if ( (*cfun_diff)( var, list + k*size, diff) == 0 )  // var == list[k]
        return (list + k*size);
      else
        return NULL;
}    //  bsearch_diff
 /*----------------------------------------------------*/
 /*  Выбор уникальных элементов в сортированном списке */
  void  unitv(char *lis, unsigned int  *ln, unsigned int  size, int (*cfun)(const void *, const void * ))
  //char *lis;      /*  Сортированный список   */
  //unsigned int  *ln;        /*  Адрес числа элементов списка  */
  //unsigned int  size;        /*  Размер элементов списка    */
  //int (*cfun)(const void *, const void * );  /*  Адрес функции сравнения    */
    {
      unsigned int l,k;
      unsigned long i;
      for ( i=size,l=0,k=0; i< (*ln)*size; i += size)
         {
         if ( (*cfun)( lis + l , lis + i ) != 0 )
            {
              k++;
              l += size;
              memcpy((char*)(lis+l),(char*)(lis+i),(int)size);
            }
         }
     *ln=k+1;
    }    /*  unitv */
  /*-------------------------------------------------------------*/
  /*   упорядочение собственных значений в порядке возрастания и */
  /*   перестановка соответствующих им собственных векторов      */
  /*-------------------------------------------------------------*/
int repev(int n, int p, double  *vecd, double  **matv)
   //int n;
   //double  * vecd;    /* вектор собственных значений */
   //double  ** matv;   /* матрица собственных векторов  */
   {
      int i,j,k;
      int  rc;
      int  *rep,*num;
      double  temp;
      double  *temp0;
      double  *v0;

      ALLOCVEC(temp0,n,double);
      ALLOCVEC(rep,2*p,int);
      num=rep+p;
      for (i=0; i<p; i++)
          num[i]=i;
      rc=qsortkr((char*)vecd,(char*)num,(unsigned int)p,
                 (int)sizeof(double),(fptr)cmpd,
                 (int)sizeof(int));
      for (i=0; i<p; i++)
      {
          j=num[i];
          num[i]=0;
          rep[j]=i;
      }
      for (i=0; i<p; i++)
      {
         k=i;
         for (j=0; j<n; j++)
             temp0[j]= matv[j][i];
         while(num[k]==0)
         {
           num[k]=1;
           k=rep[k];
           if (k>p)
              return 1;
           for (j=0; j<n; j++)
           {
              temp = matv[j][k];
              matv[j][k] = temp0[j];
              temp0[j]=temp;
           }
         }
    }
    FREEVEC(rep);
    FREEVEC(temp0);
    return 0;
}   /* repev */
//----------------------------------------------------------
//   упорядочение собственных значений в порядке убывания
// абсолютных значений и
// перестановка соответствующих им собственных векторов
//----------------------------------------------------------
int repev_maxabs(int n, int p, double *vecd, double **matv)
//   int n;             // Размерность вектора собственных векторов
//   int p;             // Количество собственных значений
//   double  * vecd;    // вектор собственных значений
//   double  ** matv;   // матрица собственных векторов
   {
      int i, j, k;
      int  rc;
      int  *rep, *num;
      double  temp;
      double  temp_v;
      double  *temp0;
      double  *v0;

      ALLOCVEC(temp0, n, double);
      ALLOCVEC(v0, p, double);
      ALLOCVEC(rep, p, int);
      ALLOCVEC(num, p, int);

      for (i=0; i<p; i++)
          v0[i] = ABS(vecd[i]);
      for (i=0; i<p; i++)
          num[i]=i;
      rc=qsortkr((char*)v0, (char*)num, (unsigned int)p,
                 (int)sizeof(double),(fptr)cmpd,
                 (int)sizeof(int));
      for (i=0; i<p; i++)
      {
          j=num[i];
          num[i]=0;
          rep[j]=i;
      }
      for (i=0; i<p; i++)
      {
         k = i;
         for (j=0; j<n; j++)
           temp0[j]= matv[j][i];
         while(num[k] == 0) {
           num[k] = 1;
           k=rep[k];
           if (k > p)
              return 1;
           for (j=0; j<n; j++) {
              temp = matv[j][k];
              matv[j][k] = temp0[j];
              temp0[j]=temp;
           }
           // Перестановка собственных значений
           temp_v = vecd[i];
           vecd[i] = vecd[k];
           vecd[k] = temp_v;
         }
    }
    FREEVEC(rep);
    FREEVEC(temp0);
    FREEVEC(v0);
    FREEVEC(num);
    return 0;
}   /* repev_maxabs */
//-------------------------------------------------------------
// Перестановка элементов вектора int в соответствии со списком
void rep_int(int* list, int* vec, int n)
//int  *list;         /* список перестановок */
//int  *vec;         /* вектор  */
//int  n;              /* Размер вектора перестановок */
{
   int i,j,k;
   int temp0,temp1;
   for (i=0; i<n; i++)
   {
       if (list[i]<0) {
           list[i] += n;
           continue;
       }
       k=i;
       temp0 = vec[i];
       while(list[k]>=0)
       {
         j=k;
         k=list[k];
         list[j] -= n;
         temp1=vec[k];
         vec[k]=temp0;
         temp0=temp1;
       }
    }
   for (i=0; i<n; i++)
      if (list[i]<0) list[i] += n;
}   /* rep_int */
//-------------------------------------------------------------
// Перестановка элементов вектора double в соответствии со списком
void rep_double(int* list, double* vec, int n)
//int  *list;         /* список перестановок */
//double  *vec;         /* вектор  */
//int  n;              /* Размер вектора перестановок */
{
   int i,j,k;
   double temp0, temp1;
   for (i=0; i<n; i++)
   {
       if (list[i]<0) {
           list[i] += n;
           continue;
       }
       k=i;
       temp0 = vec[i];
       while(list[k]>=0)
       {
         j=k;
         k=list[k];
         list[j] -= n;
         temp1=vec[k];
         vec[k]=temp0;
         temp0=temp1;
       }
    }
   for (i=0; i<n; i++)
      if (list[i]<0) list[i] += n;
}   /* rep_int */
//-----------------------------------------------------------------------
//   функция сравнения двух ключей при сортировке в порядке возрастания
int cmpd (double *a, double *c)
//double        *a,*c;
{
        if (*a<*c)  return -1 ;
        if (*a>*c) return  1 ;
        return 0 ;
}   /* cmpd   */
//-----------------------------------------------------------------------
//   функция сравнения двух ключей при сортировке в порядке возрастания
int cmpf (float* a, float* c)
//float        *a,*c;
{
        if (*a<*c)  return -1 ;
        if (*a>*c) return  1 ;
        return 0 ;
}   /* cmpf   */
//-------------------------------------------------------------
int cvci0 (int* a, int* b, int* c)
//int           *a,*b,*c;
{
  return 0;
}
//-------------------------------------------------------------------
int cmpi (int* a, int* c)
//int           *a,*c;
{
        if (*a<*c)  return -1 ;
        if (*a>*c) return  1 ;
        return 0 ;
}   /* cmpi   */
//---------------------------------------------------------
int cmps (unsigned short *a, unsigned short* c)
//unsigned short           *a,*c;
{
        if (*a<*c)  return -1 ;
        if (*a>*c) return  1 ;
        return 0 ;
}   /* cmps   */
/*   функция сравнения двух ключей при сортировке в порядке убывания */
int cmpdi (double *a, double *c)
//double        *a,*c;
{
        if (*a>*c)  return -1 ;
        if (*a<*c) return  1 ;
        return 0 ;
}   /* cmpd   */
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения элементов структуры VNAME - наименования       */
 /*  неизвестных.                                                     */
 /*  int cmpvname();                                                  */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmpvname(VNAME *elem1, VNAME *elem2)
   //VNAME *elem1, *elem2;
   {
     if ( elem1 -> node1 > elem2 -> node1 )
        return 1;
     if ( elem1 -> node1 < elem2 -> node1 )
        return -1;
     if ( elem1 -> node2 > elem2 -> node2 )
        return 1;
     if ( elem1 -> node2 < elem2 -> node2 )
        return -1;
     if (elem1 -> direct > elem2 -> direct )
        return 1;
     if (elem1 -> direct < elem2 -> direct )
        return -1;
        else
        return 0;
    }
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения элементов структуры CONT - оглавления          */
 /*  элементов.                                                       */
 /*  int cmpcont();                                                  */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmpcont(CONT *elem1, CONT *elem2)
{
     if ( elem1 -> num_gr > elem2 -> num_gr )
        return 1;
     if ( elem1 -> num_gr < elem2 -> num_gr )
        return -1;
     if ( elem1 -> num_el > elem2 -> num_el )
        return 1;
     if ( elem1 -> num_el < elem2 -> num_el )
        return -1;
        else
        return 0;
    }
//-------------
int   cmpdouble( double *elem1,  double *elem2)
   //double *elem1, *elem2;
   {
     if ( elem1 > elem2 )
        return 1;
     if ( elem1 < elem2 )
        return -1;
     return 0;
    }
//----------------------
int   cmpint(int *elem1, int *elem2)
   //int *elem1, *elem2;
   {
     if ( *elem1 > *elem2 )
        return 1;
     if ( *elem1 < *elem2  )
        return -1;
        else
        return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов - узлов граней      */
 /*  сравнение заканчивается, когда последние элементы =0;                                                  */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_gran(GRAN* elem1, GRAN* elem2)
//   GRAN *elem1, *elem2;
{
   short i;
     for (i=0; i<MAX_GRAN_NE+1; i++) {
       if ( elem1->gran_node[i] > elem2->gran_node[i])
          return 1;
       if ( elem1->gran_node[i] < elem2->gran_node[i])
          return -1;
       if (elem1->gran_node[i] == -1)
          return 0;
     }
     return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов длиной 3                               */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_double3(DOUBLE3 *elem1, DOUBLE3 *elem2)  {

       if ( elem1->g[0] > elem2->g[0])
          return 1;
       if ( elem1->g[0] < elem2->g[0])
          return -1;
       if ( elem1->g[1] > elem2->g[1])
          return 1;
       if ( elem1->g[1] < elem2->g[1])
          return -1;
       if ( elem1->g[2] > elem2->g[2])
          return 1;
       if ( elem1->g[2] < elem2->g[2])
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов длиной 9                              */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_double9(DOUBLE9 *elem1, DOUBLE9 *elem2)  {

    int i;

    for (i=0; i<9; i++) {
       if ( elem1->g[i] > elem2->g[i])
          return 1;
       if ( elem1->g[i] < elem2->g[i])
          return -1;
    }
    return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов длиной 11                              */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_double11(DOUBLE11 *elem1, DOUBLE11 *elem2)  {

    int i;

    for (i=0; i<11; i++) {
       if ( elem1->g[i] > elem2->g[i])
          return 1;
       if ( elem1->g[i] < elem2->g[i])
          return -1;
    }
    return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов - координат точки в 3D     */
 /*  сравнение заканчивается, когда последние элементы =0;                                                  */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_point3d(POINT_3D *elem1, POINT_3D *elem2)
{
       if ( elem1->x > elem2->x)
          return 1;
       if ( elem1->x < elem2->x)
          return -1;
       if ( elem1->y > elem2->y)
          return 1;
       if ( elem1->y < elem2->y)
          return -1;
       if ( elem1->z > elem2->z)
          return 1;
       if ( elem1->z < elem2->z)
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов - координат точки в 3D     */
 /*  сравнение заканчивается, когда последние элементы =0;                                                  */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_pointYZ(POINT_3D *elem1, POINT_3D *elem2)
{
       if ( elem1->y > elem2->y)
          return 1;
       if ( elem1->y < elem2->y)
          return -1;
       if ( elem1->z > elem2->z)
          return 1;
       if ( elem1->z < elem2->z)
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов - локализация точки в 3D              */
 /*  сравнение заканчивается, когда последние элементы =0;            */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_local3d(POINT_3D *elem1, POINT_3D *elem2)
   //POINT_3D *elem1, *elem2;
{
       if ( elem1->x > elem2->x)
          return 1;
       if ( elem1->x < elem2->x)
          return -1;
       if ( elem1->y > elem2->y)
          return 1;
       if ( elem1->y < elem2->y)
          return -1;
       if ( elem1->z > elem2->z)
          return 1;
       if ( elem1->z < elem2->z)
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения координат узлов                                */
 /*  сравнение заканчивается, когда последние элементы =0;            */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_NodeCoor(double *coor1, double *coor2)
{
       if ( coor1[0] > coor2[0])
          return 1;
       if ( coor1[0] < coor2[0])
          return -1;
       if ( coor1[1] > coor2[1])
          return 1;
       if ( coor1[1] < coor2[1])
          return -1;
       if ( coor1[2] > coor2[2])
          return 1;
       if ( coor1[2] < coor2[2])
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов - координат точки типа TPoint         */
 /*  сравнение заканчивается, когда последние элементы =0;            */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_TPoint(TPoint *elem1, TPoint *elem2)
{
       if ( elem1->x > elem2->x)
          return 1;
       if ( elem1->x < elem2->x)
          return -1;
       if ( elem1->y > elem2->y)
          return 1;
       if ( elem1->y < elem2->y)
          return -1;
       else
          return 0;
}
// Сравнение с допуском
int   cmp_TPoint_diff(TPoint *elem1, TPoint *elem2, TPoint *diff)
{
       if ( (ABS(elem1->x - elem2->x)) < diff->x &&  (ABS(elem2->y - elem1->y)) < diff->y)
          return 0;
       if ( elem1->x > elem2->x)
          return 1;
       if ( elem1->x < elem2->x)
          return -1;
       if ( elem1->y > elem2->y)
          return 1;
       if ( elem1->y < elem2->y)
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения координат узлов балочных элементов             */
 /*  сравнение заканчивается, когда последние элементы =0;            */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int  cmp_coor_el(COOR_EL *elem1, COOR_EL *elem2)
{
       if ( elem1->x1 - elem2->x1 > 1e-3)
          return 1;
       if ( elem2->x1 - elem1->x1 > 1e-3)
          return -1;
       if ( elem1->x2 - elem2->x2 > 1e-3)
          return 1;
       if ( elem2->x2 - elem1->x2 > 1e-3)
          return -1;
       if ( elem1->z1 - elem2->z1 > 1e-3)
          return 1;
       if ( elem2->z1 - elem1->z1 > 1e-3)
          return -1;
       if ( elem1->z2 - elem2->z2 > 1e-3)
          return 1;
       if ( elem2->z2 - elem1->z2 > 1e-3)
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов - нагрузок в узлах                    */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_load_nodal(LOAD_NODAL *elem1, LOAD_NODAL *elem2) {

       if ( elem1->node > elem2->node)
          return 1;
       if ( elem1->node < elem2->node)
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов - нагрузок в элементах                */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_load_elemental(LOAD_ELEMENTAL *elem1, LOAD_ELEMENTAL *elem2) {

       if ( elem1->element > elem2->element)
          return 1;
       if ( elem1->element < elem2->element)
          return -1;
       else
          return 0;
}
//-------------------------------------------------------------------
int cmp_var_name(VAR_ANALYSIS *elem1, VAR_ANALYSIS *elem2) {

       if ((AnsiString)(elem1->var_name) > (AnsiString)(elem2->var_name))
          return 1;
       if ((AnsiString)(elem1->var_name) < (AnsiString)(elem2->var_name))
          return -1;
       else
          return 0;
}
//-------------------------------------------------------------------
// Сравнение нагрузок
int cmp_load_force(LOAD_FORCE *elem1, LOAD_FORCE *elem2) {
        if (elem1->ref_pos_sectA > elem2->ref_pos_sectA) return 1;
        if (elem1->ref_pos_sectA < elem2->ref_pos_sectA) return -1;
        if (elem1->ref_pos_sectB > elem2->ref_pos_sectB) return 1;
        if (elem1->ref_pos_sectB < elem2->ref_pos_sectB) return -1;
        if (elem1->load_A > elem2->load_A) return 1;
        if (elem1->load_A < elem2->load_A) return -1;
        if (elem1->load_B > elem2->load_B) return 1;
        if (elem1->load_B < elem2->load_B) return -1;
        if (elem1->flag_dir > elem2->flag_dir) return 1;
        if (elem1->flag_dir < elem2->flag_dir) return -1;
        if (elem1->excentr > elem2->excentr) return 1;
        if (elem1->excentr < elem2->excentr) return -1;
        return 0;
}
//-------------------------------------------------------------------
// Сравнение сечений изгибаемых элементов по позиции
/*
int cmp_sbend(BEND_SECT *elem1, BEND_SECT *elem2) {
        if (elem1->pos_sect > elem2->pos_sect) return 1;
        if (elem1->pos_sect < elem2->pos_sect) return -1;
        return 0;
}
*/
/*
void   dump_gran(n,elem1)
   int n;
   GRAN *elem1;
{
   short i,k;
     fprintf(output_g,"Gran %d:",n);
     for (i=0; i<MAX_GRAN_NE+1; i++) {
          fprintf(output_g," %d",elem1->gran_node[i]);
     }
     fprintf(output_g,"\n");
}
*/
