#include <stdio.h>
#include <math.h>
#include <vcl.h>
#include "TypeData.h"
#include "ListConst.h"
//#include "summer.h"
#include "message.h"

//void InfMessage(AnsiString text);
AnsiString Format_tabl(double x);
extern FILE * stek_0;
extern FILE * output_g;
static char stroka[240];
//---------------------------------------------------------------------------
// Поиск индекса элемента в массиве большего или равного value
int search_ind(int dim, double *tabl_, double value) {
   int i;
       for (i=0; i<dim; i++) {
          if (tabl_[i] >= value)
             break;
       }
	   if (i == dim) {
           i--;
       }
   return i;
}
//---------------------------------------------------------------------------
double Round(double value, int n_sign) {
  double i, j;
  double x1, x2, xr, mult;

  mult = pow(10.0, double(n_sign));
  xr = value*mult;
  i=floor(xr);
  j=ceil(xr);
  x1=xr-i;
  x2=j-xr;
  if (x1<x2) return (double)i/mult;
  else return (double)j/mult;
}
//---------------------------------------------------------------------------
double Round_plus(double value, int n_sign) {
  int j;
  double mult, xr;

  mult = pow(10.0, n_sign);
  xr = value*mult;
  j=ceil(xr);
  return (double)j/mult;
}
//---------------------------------------------------------------------------
// округление по шагу в большую сторону
double Round_step(double value, double step) {
  int v1, s1, i1;
  double v2;

  /*
  v1 = ceil(value);
  s1 = step;
  i1 = v1%s1;
  if (i1>0)
     v2 = v1 - i1 + s1;
  else
     v2 = v1;
  */
  if (step < 1.0) {
    v2 = value;
  }
  v1 = ceil(value/step);
  v2 = v1*step;

  return v2;
}
//---------------------------------------------------------------------------
// округление по шагу в меньшую сторону
double Round_step_floor(double value, double step) {
  int v1;
  double v2;

  v1 = floor(value/step);
  v2 = v1*step;
  return v2;
}
//---------------------------------------------------------------------------
//  aппроксимация по двум массивам                       */
double l_app(double *f1, double* f2, double x1, int n) {
// double *f1;   массив абсцисс */
// double *f2;  массив ординат */
// double x1;
// int n;
   int i;
   if (x1 < f1[0]) {
      return f2[0];
   }
   for (i=1; i<n; i++)
     if (f1[i]>x1) break;
   if (i==n )
      return (f2[n-1]);
   else {
      return(f2[i]-(f1[i]-x1)*(f2[i]-f2[i-1])/(f1[i]-f1[i-1]));
   }
}
//-------------------------------------------------
//  Линеиная интерполяция
double lin_interpol(double x1, double x2, double y1, double y2, double x) {
   if (x1 == x2)
     return y1;
   return (y1 + (x - x1)*(y2 - y1)/(x2 - x1));
}
//-------------------------------------------------
//  Линеиная аппроксимация функции
double l_linap(int npoint, double *y, double step, double xi)
//int npoint;   /* количество точек */
//double *y;    /* значения функциии */
//double step;  /* шаг */
//double xi;    /* значение аргумента */
{
    double d,yo,del_1, del_s;
    int i;

    if  (npoint<2)
        return 0.0;
    if (xi>step*(npoint-1)) {
        // return (y[npoint-1]);
        del_1 = y[npoint-1] - y[npoint-2];
        del_s = xi - step*(npoint-1);
        return (y[npoint-1] + del_s*del_1/step);
    }
    if (xi<0)
        return 0.0;

    i= floor(xi/step);
    if (i>npoint-2) yo=y[npoint-1];
    else {
       d= xi - i*step;
       if (step<1e-10 || (y[i+1]-y[i])>1e20 || d >1e20) {
              return y[i+1];
       }
       yo = y[i]+(y[i+1]-y[i])*d/step;

    }
    return(yo);
}  // l_linap
//--------------------------------------------------------
//  печать вектора
void prinv(char *str, int n, double *vec)  {
   int  i;
   sprintf(stroka,"\nВектоp %s, n=%d :",str,n);
   for (i=0; i<n; i++)
   {
      if (i%10==0) {
         InfMessage(stroka);
         stroka[0]='\0';
      }
      sprintf(stroka+strlen(stroka),"%13.6e", vec[i]);
   }
   InfMessage(stroka);
}
//--------------------------------------------------------
//  печать вектора
void prinv_bool(char *str, int n, bool *vec)  {
   int  i;
   sprintf(stroka,"\nВектоp %s, n=%d :",str,n);
   for (i=0; i<n; i++)
   {
      if (i%10==0) {
         InfMessage(stroka);
         stroka[0]='\0';
      }
      if (vec[i])
        sprintf(stroka+strlen(stroka),"  true " );
      else
        sprintf(stroka+strlen(stroka)," false " );
   }
   InfMessage(stroka);
}
//--------------------------------------------------------
//  печать вектора
void prinv_F(char *str, int n, double *vec)  {
   int  i;
   sprintf(stroka,"Вектоp %s, n=%d", str, n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (i=0; i<n; i++)
   {
      if ((i+1)%20==0) {
         InfMessage(stroka);
         stroka[0]='\0';
      }
      if ((ABS(vec[i])) >10000 )
          sprintf(stroka+strlen(stroka),"%10.0e", vec[i]);
      else {
        if ((ABS(vec[i])) >= 0.1)
          sprintf(stroka+strlen(stroka),"%10.2f", vec[i]);
        else
          sprintf(stroka+strlen(stroka),"%10.3e", vec[i]);
      }
   }
   Message(stroka);
}
//--------------------------------------------------------------
//   печать списка
void prinv_point_3d(char *str, int n, POINT_3D *vec)
{
   int  i;
   sprintf(stroka,"Вектоp %s, n=%d",str,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (i=0; i<n; i++)  {
      sprintf(stroka+strlen(stroka),"%d: %13.6e %13.6e %13.6e",i, vec[i].x, vec[i].y, vec[i].z);
      InfMessage(stroka);
      stroka[0]='\0';
   }
}
//---------------------------------------------------------------
// печать вектора
void prin_lis( char* str, int n, VNAME *list)
{
   int  i;
   sprintf(stroka,"Вектоp %s, n=%d ",str,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (i=0; i<n; i++)
   {
      if (i%6==0) {
         InfMessage(stroka);
         stroka[0]='\0';
      }
      if (list[i].node2==HUGES)
         sprintf(stroka+strlen(stroka),"  %5d%c     ", list[i].node1, list[i].direct);
      else
         sprintf(stroka+strlen(stroka),"  %5d%c%-5d", list[i].node1, list[i].direct, list[i].node2);
   }
   InfMessage(stroka);
}
//-----------------------------------------------------------
// печать вектора по направлениям
void prinv_lis(char* str, int n, double *vec, VNAME *list)
{
   int  i;
   sprintf(stroka,"Вектоp %s, n=%d ",str,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (i=0; i<n; i++)
   {
      if (i%3==0) {
         InfMessage(stroka);
         stroka[0]='\0';
      }
      if (list[i].node2==HUGES)
         sprintf(stroka+strlen(stroka),"       %5d%c%14.1f", list[i].node1, list[i].direct, vec[i]);
      else
         sprintf(stroka+strlen(stroka),"  %5d%c%-5d%14.1f", list[i].node1, list[i].direct, list[i].node2, vec[i]);
   }
   InfMessage(stroka);
}
//-----------------------------------------------------------
// печать вектора по направлениям u, v, w
void prinv_tran(char* str0, int n, double *vec, VNAME *list)
{
   int  i, k;
   char stroka[80], str[20];
   sprintf(stroka,"%s, n=%d ",str0,n);
   InfMessage(stroka);
   InfMessage(" Узел |      dX      |      dY      |     dZ      ");
   k=0;
   for (i=0; i<n; i++) {
      if (k != list[i].node1) {
         if (k>0)
           InfMessage((AnsiString)stroka);
         strcpy(stroka,"      |     0.0      |     0.0      |     0.0       ");
         sprintf(str,"%6d", list[i].node1);
         memcpy(stroka, str,6);
         k = list[i].node1;
      }
      sprintf(str,"%14.5e",vec[i]);
      switch (list[i].direct) {
        case 'u':
         memcpy(stroka+7, str,14);
        break;
        case 'v':
         memcpy(stroka+22, str,14);
        break;
        case 'w':
         memcpy(stroka+37, str,14);
        break;
      }
   }
   InfMessage(stroka);
}
//----------------------------------------------------------------
// Вывод таблицы собственных частот
void  prin_eig(int n_real, double *v_d) {
 int i;
 sprintf(stroka,"%10s|%20s|%20s|%15s|%20s",
         "Номер тона","Собственнoe значение","Круговая частота",
         "Частота (гц)","Идентификация");
 InfMessage(stroka);
 for (i=0; i<n_real; i++) {
    sprintf(stroka,"%10d|%20.2f|%20.1f|%15.2f| ",
    i+1,v_d[i],sqrt(v_d[i]),sqrt(v_d[i])/(2*M_PI));
    InfMessage(stroka);
 }
}
//------------------------------------------------------------------------
//
void prinv_cord(char *str, int n, CORDSYS* cord) {
   int i;
   InfMessage(str);
   for (i=0; i<n; i++) {
       sprintf(stroka,"NCSys=%d, %c meth=%d, rid=%d, %d, %d, %d",i,cord[i].type, cord[i].meth, cord[i].rid,
       cord[i].num[0],cord[i].num[1],cord[i].num[2]);
       InfMessage(stroka);
       sprintf(stroka,"%5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f",
       cord[i].coor[0][0],cord[i].coor[0][1],cord[i].coor[0][2],
       cord[i].coor[1][0],cord[i].coor[1][1],cord[i].coor[1][2],
       cord[i].coor[2][0],cord[i].coor[2][1],cord[i].coor[2][2]);
       InfMessage(stroka);
   }
}
//------------------------------------------------------------------------
// печать вектора int*
void prinvi(char *str, int n, int *vec)  /* печать вектора */
{
   int  i;
   sprintf(stroka,"Вектоp %s, n=%d",str,n);
   for (i=0; i<n; i++)
   {
      if (i%10==0) {
         InfMessage((AnsiString)stroka);
         stroka[0]='\0';
      }
      sprintf(stroka+strlen(stroka),"%10d ",vec[i]);
   }
   InfMessage((AnsiString)stroka);
}
//------------------------------------------------------------------------
// печать нумерованного вектора int*
void prinvi_num(char *str, int n, int *vec)  /* печать вектора */
{
   int  i;
   sprintf(stroka,"Вектоp %s, n=%d",str,n);
   for (i=0; i<n; i++)
   {
      if (i%10==0) {
         InfMessage((AnsiString)stroka);
         stroka[0]='\0';
      }
      sprintf(stroka+strlen(stroka),"%3d-%10d ", i, vec[i]);
   }
   InfMessage((AnsiString)stroka);
}
//--------------------------------------------------------------------------------
//  Печать матрицы
void prinm_G(char *str, int m, int n, double **mat)  /* печать матрицы по строкам */
{
   int  i,j;
   sprintf(stroka,"Матpица %s %d*%d (по строкам)",str,m,n);
   InfMessage((AnsiString)stroka);
   stroka[0]='\0';
   for (j=0; j<m; j++) {
     for (i=0; i<n; i++)
     {
        if (i%12==0) {
           Message((AnsiString)stroka);
           sprintf(stroka,"(%4d) ",j);
        }
        //sprintf(stroka+strlen(stroka),Format_tabl(mat[j][i]).c_str(),mat[j][i]);
        sprintf(stroka+strlen(stroka),"%10.2f",mat[j][i]);
     }
   }
   Message((AnsiString)stroka);
}
//------------------------------------------------------------------
// печать вектора float*
void prinvf(char *str, int n, float *vec)  /* печать вектора */
{
   int  i;
   sprintf(stroka,"Вектоp %s, n=%d",str,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (i=0; i<n; i++)
   {
      if (i%6==0) {
         InfMessage(stroka);
         stroka[0]='\0';
      }
      sprintf(stroka+strlen(stroka),"%10.0f ",vec[i]);
   }
   InfMessage(stroka);
}
//-----------------------------------------------------------------
//  печать m-го столбца
void prinm(char* str, int m, int n, double** mat)   {
   int  i;
   sprintf(stroka,"Матpица %s (%d столбец) n=%d",str,m,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (i=0; i<n; i++)
   {
      if (i%12==0) {
           InfMessage(stroka);
           stroka[0]='\0';
      }
      sprintf(stroka+strlen(stroka),"%12.5e",mat[i][m]);
   }
   InfMessage(stroka);
}
//--------------------------------------------------------------------------------
//  Печать матрицы
void prinm0(char *str, int m, int n, double **mat)  /* печать матрицы по строкам */
{
   int  i,j;
   sprintf(stroka,"Матpица %s %d*%d (по строкам)",str,m,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (j=0; j<m; j++) {
     for (i=0; i<n; i++)
     {
        if (i%12==0) {
           InfMessage(stroka);
           sprintf(stroka,"(%4d) ",j);
        }
        sprintf(stroka+strlen(stroka),Format_tabl(mat[j][i]).c_str(),mat[j][i]);
        //sprintf(stroka+strlen(stroka),"%12.5e",mat[j][i]);
     }
   }
   InfMessage(stroka);
}
//--------------------------------------------------------------------------------
//  Печать матрицы
void prinm_f(char *str, int m, int n, float **mat)  /* печать матрицы по строкам */
{
   int  i,j;
   sprintf(stroka,"Матpица %s %d*%d (по строкам)",str,m,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (j=0; j<m; j++) {
     for (i=0; i<n; i++)
     {
        if (i%8==0) {
           InfMessage(stroka);
           sprintf(stroka,"(%4d) ",j);
        }
        sprintf(stroka+strlen(stroka)," %8.2f", mat[j][i]);
        //sprintf(stroka+strlen(stroka),"%12.5e",mat[j][i]);
     }
   }
   InfMessage(stroka);
}
//--------------------------------------------------------------------------------
//  Печать матрицы int
void prinm_i(char *str, int m, int n, int **mat)  /* печать матрицы по строкам */
{
   int  i,j;
   sprintf(stroka,"Матpица %s %d*%d (по строкам)",str,m,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (j=0; j<m; j++) {
     for (i=0; i<n; i++)
     {
        if (i%8==0) {
           InfMessage(stroka);
           sprintf(stroka,"(%4d) ",j);
        }
        sprintf(stroka+strlen(stroka)," %8d", mat[j][i]);
     }
   }
   InfMessage(stroka);
}
//-----------------------------------------------------------------
// печать матрицы по столбцам
void prinm0t(char *str, int m, int n, double **mat)
{
   int  i,j;
   fprintf(output_g,"Матpица %s %d*%d (по столбцам)",str,m,n);
   for (i=0; i<n; i++) {
     for (j=0; j<m; j++)
     {
        if (j%6==0) fprintf(output_g,"\n");
        fprintf(output_g,"%12.4e",mat[j][i]);
     }
     fprintf(output_g,"\n");
   }  
}
// печать треугольной матрицы
void prinmt0(char *str, int n, double **mat)
{
   int  i,j;
   sprintf(stroka,"Треугольная матpица %s порядка %d",str,n);
   InfMessage(stroka);
   stroka[0]='\0';
   for (j=0; j<n; j++) {
	 for (i=0; i<n; i++) {
       if (i%6==0) {
          InfMessage(stroka);
          stroka[0]='\0';
       }
       if (i<j) sprintf(stroka+strlen(stroka),"            ");
       else
         sprintf(stroka+strlen(stroka),"%12.4e",mat[j][i]);
	}
   }
   InfMessage(stroka);
}
//---------------------------------------------------------------------------
// Преобразование числа в строку с обрезкой нулей
AnsiString FloatToStrFCut(double value, int w1, int w2) {
  AnsiString Str;
  char *stroka;

  Str = FloatToStrF(value, ffFixed, w1, w2);
  stroka = Str.c_str();
  int len = strlen(stroka);
  for (int i=len-1; i>0; i--) {
	 if (stroka[i]!='0' || stroka[i-1]=='.')
	   break;
	 stroka[i]=' ';
  }
  return Str;
}


