// =======================================================================
//                    Исходный код основного внешнего модуля.
//                             Смирнов В.А., 1999.
// =======================================================================

#include  <windows.h>
#pragma   hdrstop
#include  <string.h>
#include  <math.h>
#include  "IToModel.hpp"

// =======================================================================
// Прототипы интерфейсов определены в заголовке "IToModel.h".  Здесь  соз-
// даются их потомки (VMT потомка совпадает с VMT интерфейса),  обладающие
// дополнительной функциональностью.
// =======================================================================

class   CAddenBase : public   IAdden
{
public:
  virtual pchar __stdcall      Description(void);
  virtual pchar __stdcall      StdName(void);
  virtual pchar __stdcall      StdBName(void);
  virtual int   __stdcall      RequiredDimension(void);
  virtual void  __stdcall      Value(double *M,double *Res);
protected:
  char    *Desc;
  char    *Name;
  char    *BName;
  int     ReqDim;
};

class   CModelBase : public   IModel
{
public:
  virtual pchar __stdcall      Description();
  virtual int   __stdcall      RequiredDimension(void);
  virtual int   __stdcall      AddenCount();
  virtual pIAdden __stdcall    Addens(int Index);
  virtual void  __stdcall      Value(double *M,double *B,double *Res);
protected:
  char                        *Desc;
  int                         ReqDim;
  int                         AddensCount;
  IAdden                      ***_Addens;
};

class   CGeneratorBase : public IGenerator
{
public:
  virtual pchar __stdcall      Description();
  virtual void  __stdcall      RequiredDimensions(int *nRows,int *nCols);
  virtual void  __stdcall      Generate(double **Rows);
  virtual pIModel __stdcall    DefaultModel();
protected:
  char                        *Desc;
  int                         ReqRows,ReqCols;
  IModel                      **DefModel;
};

// =======================================================================
//      Создание и уничтожение экземпляров класса
// =======================================================================

#define CREATE_INSTANCE(CLASS,INSTANCE)\
        INSTANCE=new CLASS;

#define RELEASE_INSTANCE(INSTANCE)\
        if(INSTANCE) {delete INSTANCE;INSTANCE=NULL;}

// =======================================================================
// Определения конкретных слагаемых, моделей и генераторов содержат  сход-
// ные синтаксические элементы, объединенные в макросы.
// =======================================================================

#define INHERIT_ADDEN_BASE(DERIVED_NAME)\
{\
public:\
                              DERIVED_NAME();\
   virtual void  __stdcall      Value(double *M,double *Res);\
}

#define INHERIT_MODEL_BASE(DERIVED_NAME)\
{\
public:\
                              DERIVED_NAME();\
};

#define INHERIT_GENERATOR_BASE(DERIVED_NAME)\
{\
public:\
                              DERIVED_NAME();\
  virtual void  __stdcall      Generate(double **Rows);\
};


// =======================================================================
//      Слагаемые
// =======================================================================

//      Свободный член
class   CAddenUnit         : public CAddenBase INHERIT_ADDEN_BASE(CAddenUnit);

CAddenUnit::CAddenUnit()
{
  Desc="Единица";
  Name="1";
  BName="B0";
  ReqDim=0;
}

void __stdcall CAddenUnit::Value(double *M,double *Res)
{
  *Res=1;
}

//      Линейные слагаемые
class   CAdden1       : public CAddenBase INHERIT_ADDEN_BASE(CAdden1);

CAdden1::CAdden1()
{
  Desc="Первый фактор";
  Name="x1";
  BName="B1";
  ReqDim=1;
}

void __stdcall CAdden1::Value(double *M,double *Res)
{
  *Res=M[0];
}

class   CAdden2       : public CAddenBase INHERIT_ADDEN_BASE(CAdden2);

CAdden2::CAdden2()
{
  Desc="Второй фактор";
  Name="x2";
  BName="B2";
  ReqDim=2;
}

void __stdcall CAdden2::Value(double *M,double *Res)
{
  *Res=M[1];
}

class   CAdden3       : public CAddenBase INHERIT_ADDEN_BASE(CAdden3);

CAdden3::CAdden3()
{
  Desc="Третий фактор";
  Name="x3";
  BName="B3";
  ReqDim=3;
}

void __stdcall CAdden3::Value(double *M,double *Res)
{
  *Res=M[2];
}

class   CAdden4       : public CAddenBase INHERIT_ADDEN_BASE(CAdden4);

CAdden4::CAdden4()
{
  Desc="Четвертый фактор";
  Name="x4";
  BName="B4";
  ReqDim=4;
}

void __stdcall CAdden4::Value(double *M,double *Res)
{
  *Res=M[3];
}

//      Квадратичные слагаемые
class   CAdden11      : public CAddenBase INHERIT_ADDEN_BASE(CAdden11);

CAdden11::CAdden11()
{
  Desc="Квадрат первого фактора";
  Name="x1^2";
  BName="B11";
  ReqDim=1;
}

void __stdcall CAdden11::Value(double *M,double *Res)
{
  *Res=M[0]*M[0];
}

class   CAdden12      : public CAddenBase INHERIT_ADDEN_BASE(CAdden12);

CAdden12::CAdden12()
{
  Desc="Произведение первого и второго факторов";
  Name="x1*x2";
  BName="B12";
  ReqDim=2;
}

void __stdcall CAdden12::Value(double *M,double *Res)
{
  *Res=M[0]*M[1];
}

class   CAdden13      : public CAddenBase INHERIT_ADDEN_BASE(CAdden13);

CAdden13::CAdden13()
{
  Desc="Произведение первого и третьего факторов";
  Name="x1*x3";
  BName="B13";
  ReqDim=3;
}

void __stdcall CAdden13::Value(double *M,double *Res)
{
  *Res=M[0]*M[2];
}

class   CAdden14      : public CAddenBase INHERIT_ADDEN_BASE(CAdden14);

CAdden14::CAdden14()
{
  Desc="Произведение первого и четвертого факторов";
  Name="x1*x4";
  BName="B14";
  ReqDim=4;
}

void __stdcall CAdden14::Value(double *M,double *Res)
{
  *Res=M[0]*M[3];
}

class   CAdden22      : public CAddenBase INHERIT_ADDEN_BASE(CAdden22);

CAdden22::CAdden22()
{
  Desc="Квадрат второго фактора";
  Name="x2^2";
  BName="B22";
  ReqDim=2;
}

void __stdcall CAdden22::Value(double *M,double *Res)
{
  *Res=M[1]*M[1];
}

class   CAdden23      : public CAddenBase INHERIT_ADDEN_BASE(CAdden23);

CAdden23::CAdden23()
{
  Desc="Произведение второго и третьего факторов";
  Name="x2*x3";
  BName="B23";
  ReqDim=3;
}

void __stdcall CAdden23::Value(double *M,double *Res)
{
  *Res=M[1]*M[2];
}

class   CAdden24      : public CAddenBase INHERIT_ADDEN_BASE(CAdden24);

CAdden24::CAdden24()
{
  Desc="Произведение второго и четвертого факторов";
  Name="x2*x4";
  BName="B24";
  ReqDim=4;
}

void __stdcall CAdden24::Value(double *M,double *Res)
{
  *Res=M[1]*M[3];
}

class   CAdden33      : public CAddenBase INHERIT_ADDEN_BASE(CAdden33);

CAdden33::CAdden33()
{
  Desc="Квадрат третьего фактора";
  Name="x3^2";
  BName="B33";
  ReqDim=3;
}

void __stdcall CAdden33::Value(double *M,double *Res)
{
  *Res=M[2]*M[2];
}

class   CAdden34      : public CAddenBase INHERIT_ADDEN_BASE(CAdden34);

CAdden34::CAdden34()
{
  Desc="Произведение третьего и четвертого факторов";
  Name="x3*x4";
  BName="B34";
  ReqDim=4;
}

void __stdcall CAdden34::Value(double *M,double *Res)
{
  *Res=M[2]*M[3];
}

class   CAdden44      : public CAddenBase INHERIT_ADDEN_BASE(CAdden44);

CAdden44::CAdden44()
{
  Desc="Квадрат четвертого фактора";
  Name="x4^2";
  BName="B44";
  ReqDim=4;
}

void __stdcall CAdden44::Value(double *M,double *Res)
{
  *Res=M[3]*M[3];
}

//      Кубические слагаемые
class   CAdden111     : public CAddenBase INHERIT_ADDEN_BASE(CAdden111);

CAdden111::CAdden111()
{
  Desc="Куб первого фактора";
  Name="x1^3";
  BName="B111";
  ReqDim=1;
}

void __stdcall CAdden111::Value(double *M,double *Res)
{
  *Res=M[0]*M[0]*M[0];
}

class   CAdden112     : public CAddenBase INHERIT_ADDEN_BASE(CAdden112);

CAdden112::CAdden112()
{
  Desc="Произведение квадрата первого фактора на второй";
  Name="x1^2*x2";
  BName="B112";
  ReqDim=2;
}

void __stdcall CAdden112::Value(double *M,double *Res)
{
  *Res=M[0]*M[0]*M[1];
}

class   CAdden113     : public CAddenBase INHERIT_ADDEN_BASE(CAdden113);

CAdden113::CAdden113()
{
  Desc="Произведение квадрата первого фактора на третий";
  Name="x1^2*x3";
  BName="B113";
  ReqDim=3;
}

void __stdcall CAdden113::Value(double *M,double *Res)
{
  *Res=M[0]*M[0]*M[2];
}

class   CAdden114     : public CAddenBase INHERIT_ADDEN_BASE(CAdden114);

CAdden114::CAdden114()
{
  Desc="Произведение квадрата первого фактора на четвертый";
  Name="x1^2*x4";
  BName="B114";
  ReqDim=4;
}

void __stdcall CAdden114::Value(double *M,double *Res)
{
  *Res=M[0]*M[0]*M[3];
}

class   CAdden122     : public CAddenBase INHERIT_ADDEN_BASE(CAdden122);

CAdden122::CAdden122()
{
  Desc="Произведение первого фактора на квадрат второго";
  Name="x1*x2^2";
  BName="B122";
  ReqDim=2;
}

void __stdcall CAdden122::Value(double *M,double *Res)
{
  *Res=M[0]*M[1]*M[1];
}

class   CAdden123     : public CAddenBase INHERIT_ADDEN_BASE(CAdden123);

CAdden123::CAdden123()
{
  Desc="Произведение первого, второго и третьего факторов";
  Name="x1*x2*x3";
  BName="B123";
  ReqDim=3;
}

void __stdcall CAdden123::Value(double *M,double *Res)
{
  *Res=M[0]*M[1]*M[2];
}

class   CAdden124     : public CAddenBase INHERIT_ADDEN_BASE(CAdden124);

CAdden124::CAdden124()
{
  Desc="Произведение первого, второго и четвертого факторов";
  Name="x1*x2*x4";
  BName="B124";
  ReqDim=4;
}

void __stdcall CAdden124::Value(double *M,double *Res)
{
  *Res=M[0]*M[1]*M[3];
}

class   CAdden133     : public CAddenBase INHERIT_ADDEN_BASE(CAdden133);

CAdden133::CAdden133()
{
  Desc="Произведение первого фактора на квадрат третьего";
  Name="x1*x3^2";
  BName="B133";
  ReqDim=3;
}

void __stdcall CAdden133::Value(double *M,double *Res)
{
  *Res=M[0]*M[2]*M[2];
}

class   CAdden134     : public CAddenBase INHERIT_ADDEN_BASE(CAdden134);

CAdden134::CAdden134()
{
  Desc="Произведение первого, третьего и четвертого факторов";
  Name="x1*x3*x4";
  BName="B134";
  ReqDim=4;
}

void __stdcall CAdden134::Value(double *M,double *Res)
{
  *Res=M[0]*M[2]*M[3];
}

class   CAdden144     : public CAddenBase INHERIT_ADDEN_BASE(CAdden144);

CAdden144::CAdden144()
{
  Desc="Произведение первого фактора на квадрат четвертого";
  Name="x1*x4^2";
  BName="B144";
  ReqDim=4;
}

void __stdcall CAdden144::Value(double *M,double *Res)
{
  *Res=M[0]*M[3]*M[3];
}

class   CAdden222     : public CAddenBase INHERIT_ADDEN_BASE(CAdden222);

CAdden222::CAdden222()
{
  Desc="Куб второго фактора";
  Name="x2^3";
  BName="B222";
  ReqDim=2;
}

void __stdcall CAdden222::Value(double *M,double *Res)
{
  *Res=M[1]*M[1]*M[1];
}

class   CAdden223     : public CAddenBase INHERIT_ADDEN_BASE(CAdden223);

CAdden223::CAdden223()
{
  Desc="Произведение квадрата второго фактора на третий";
  Name="x2^2*x3";
  BName="B223";
  ReqDim=3;
}

void __stdcall CAdden223::Value(double *M,double *Res)
{
  *Res=M[1]*M[1]*M[2];
}

class   CAdden224     : public CAddenBase INHERIT_ADDEN_BASE(CAdden224);

CAdden224::CAdden224()
{
  Desc="Произведение квадрата второго фактора на четвертый";
  Name="x2^2*x4";
  BName="B224";
  ReqDim=4;
}

void __stdcall CAdden224::Value(double *M,double *Res)
{
  *Res=M[1]*M[1]*M[3];
}

class   CAdden233     : public CAddenBase INHERIT_ADDEN_BASE(CAdden233);

CAdden233::CAdden233()
{
  Desc="Произведение второго фактора на квадрат третьего";
  Name="x2*x3^2";
  BName="B233";
  ReqDim=3;
}

void __stdcall CAdden233::Value(double *M,double *Res)
{
  *Res=M[1]*M[2]*M[2];
}

class   CAdden234     : public CAddenBase INHERIT_ADDEN_BASE(CAdden234);

CAdden234::CAdden234()
{
  Desc="Произведение второго, третьего и четвертого факторов";
  Name="x2*x3*x4";
  BName="B234";
  ReqDim=4;
}

void __stdcall CAdden234::Value(double *M,double *Res)
{
  *Res=M[1]*M[2]*M[3];
}

class   CAdden244     : public CAddenBase INHERIT_ADDEN_BASE(CAdden244);

CAdden244::CAdden244()
{
  Desc="Произведение второго фактора на квадрат четвертого";
  Name="x2*x4^2";
  BName="B244";
  ReqDim=4;
}

void __stdcall CAdden244::Value(double *M,double *Res)
{
  *Res=M[1]*M[3]*M[3];
}

class   CAdden333     : public CAddenBase INHERIT_ADDEN_BASE(CAdden333);

CAdden333::CAdden333()
{
  Desc="Куб третьего фактора";
  Name="x3^3";
  BName="B333";
  ReqDim=3;
}

void __stdcall CAdden333::Value(double *M,double *Res)
{
  *Res=M[2]*M[2]*M[2];
}

class   CAdden334     : public CAddenBase INHERIT_ADDEN_BASE(CAdden334);

CAdden334::CAdden334()
{
  Desc="Произведение квадрата третьего фактора на четвертый";
  Name="x3^2*x4";
  BName="B334";
  ReqDim=4;
}

void __stdcall CAdden334::Value(double *M,double *Res)
{
  *Res=M[2]*M[2]*M[3];
}

class   CAdden344     : public CAddenBase INHERIT_ADDEN_BASE(CAdden344);

CAdden344::CAdden344()
{
  Desc="Произведение третьего фактора на квадрат четвертого";
  Name="x3*x4^2";
  BName="B344";
  ReqDim=4;
}

void __stdcall CAdden344::Value(double *M,double *Res)
{
  *Res=M[2]*M[3]*M[3];
}

class   CAdden444     : public CAddenBase INHERIT_ADDEN_BASE(CAdden444);

CAdden444::CAdden444()
{
  Desc="Куб четвертого фактора";
  Name="x4^3";
  BName="B444";
  ReqDim=4;
}

void __stdcall CAdden444::Value(double *M,double *Res)
{
  *Res=M[3]*M[3]*M[3];
}

// =======================================================================
//      Слагаемые для MQ - моделей
class   CAdden1Sub2   : public CAddenBase INHERIT_ADDEN_BASE(CAdden1Sub2);

CAdden1Sub2::CAdden1Sub2()
{
  Desc="Произведение первого фактора, второго и их разности";
  Name="x1*x2*(x1-x2)";
  BName="B1-2";
  ReqDim=3;
}

void __stdcall CAdden1Sub2::Value(double *M,double *Res)
{
  *Res=M[0]*M[1]*(M[0]-M[1]);
}
  
class   CAdden1Sub3   : public CAddenBase INHERIT_ADDEN_BASE(CAdden1Sub3);

CAdden1Sub3::CAdden1Sub3()
{
  Desc="Произведение первого фактора, третьего и их разности";
  Name="x1*x3*(x1-x3)";
  BName="B1-3";
  ReqDim=3;
}

void __stdcall CAdden1Sub3::Value(double *M,double *Res)
{
  *Res=M[0]*M[2]*(M[0]-M[2]);
}
  
class   CAdden2Sub3   : public CAddenBase INHERIT_ADDEN_BASE(CAdden2Sub3);

CAdden2Sub3::CAdden2Sub3()
{
  Desc="Произведение второго фактора, третьего и их разности";
  Name="x2*x3*(x2-x3)";
  BName="B2-3";
  ReqDim=3;
}

void __stdcall CAdden2Sub3::Value(double *M,double *Res)
{
  *Res=M[1]*M[2]*(M[1]-M[2]);
}


/*
=======================
  23.11.99 - экспоненциальное слагаемое (к реологии)
=======================
*/

class   CAddenExp1   : public CAddenBase INHERIT_ADDEN_BASE(CAddenExp1);

CAddenExp1::CAddenExp1()
{
  Desc="Экспонента в степени первого фактора";
  Name="exp(x1)";
  BName="E1";
  ReqDim=1;
}

void __stdcall CAddenExp1::Value(double *M,double *Res)
{
  *Res=exp(M[0]);
}

/*
 *	19.03.00
 *	Слагаемые четвертой степени.
 *	Только для двух факторов.
 *	1111,1112,1122,1222,2222
 */


/* 
 *	1111
 */

class	CAdden1111	: public CAddenBase	INHERIT_ADDEN_BASE(CAdden1111);

CAdden1111::CAdden1111()
{
  Desc="Первый фактор в четвертой степени";
  Name="x1^4";
  BName="B1111";
  ReqDim=1;
}

void __stdcall CAdden1111::Value(double *M,double *Res)
{
  double temp=M[0]*M[0];
  *Res=temp*temp;
}

/*
 *	1112
 */

class	CAdden1112	: public CAddenBase	INHERIT_ADDEN_BASE(CAdden1112);

CAdden1112::CAdden1112()
{
  Desc="Произведение куба первого фактора на второй";
  Name="x1^3*x2";
  BName="B1112";
  ReqDim=2;
}


void __stdcall CAdden1112::Value(double *M,double *Res)
{
  *Res=M[0]*M[0]*M[0]*M[1];
}

/*
 *	1122
 */
 
class	CAdden1122	: public CAddenBase	INHERIT_ADDEN_BASE(CAdden1122);

CAdden1122::CAdden1122()
{
  Desc="Произведение квадрата первого фактора на квадрат второго";
  Name="x1^2*x2^2";
  BName="B1122";
  ReqDim=2;
}

void __stdcall CAdden1122::Value(double *M,double *Res)
{
  *Res=M[0]*M[0]*M[1]*M[1];
}

/*
 *	1222
 */

class	CAdden1222	: public CAddenBase	INHERIT_ADDEN_BASE(CAdden1222);

CAdden1222::CAdden1222()
{
  Desc="Произведение первого фактора на куб второго";
  Name="x1*x2^3";
  BName="B1222";
  ReqDim=2;
}

void __stdcall CAdden1222::Value(double *M,double *Res)
{
  *Res=M[0]*M[1]*M[1]*M[1];
}

/*
 *	2222
 */

class	CAdden2222	: public CAddenBase	INHERIT_ADDEN_BASE(CAdden2222);

CAdden2222::CAdden2222()
{
  Desc="Второй фактор в четвертой степени";
  Name="x2^4";
  BName="B2222";
  ReqDim=2;
}

void __stdcall CAdden2222::Value(double *M,double *Res)
{
  double temp=M[1]*M[1];
  *Res=temp*temp;
}

// =======================================================================
//      Указатели на экземпляры классов - слагаемых ======================
// =======================================================================

CAddenUnit     *AddenUnit=NULL;
CAdden1   *Adden1=NULL;
CAdden2   *Adden2=NULL;
CAdden3   *Adden3=NULL;
CAdden4   *Adden4=NULL;
CAdden11  *Adden11=NULL;
CAdden12  *Adden12=NULL;
CAdden13  *Adden13=NULL;
CAdden14  *Adden14=NULL;
CAdden22  *Adden22=NULL;
CAdden23  *Adden23=NULL;
CAdden24  *Adden24=NULL;
CAdden33  *Adden33=NULL;
CAdden34  *Adden34=NULL;
CAdden44  *Adden44=NULL;
CAdden111 *Adden111=NULL;
CAdden112 *Adden112=NULL;
CAdden113 *Adden113=NULL;
CAdden114 *Adden114=NULL;
CAdden122 *Adden122=NULL;
CAdden123 *Adden123=NULL;
CAdden124 *Adden124=NULL;
CAdden133 *Adden133=NULL;
CAdden134 *Adden134=NULL;
CAdden144 *Adden144=NULL;
CAdden222 *Adden222=NULL;
CAdden223 *Adden223=NULL;
CAdden224 *Adden224=NULL;
CAdden233 *Adden233=NULL;
CAdden234 *Adden234=NULL;
CAdden244 *Adden244=NULL;
CAdden333 *Adden333=NULL;
CAdden334 *Adden334=NULL;
CAdden344 *Adden344=NULL;
CAdden444 *Adden444=NULL;
CAdden1Sub2 *Adden1Sub2=NULL;
CAdden1Sub3 *Adden1Sub3=NULL;
CAdden2Sub3 *Adden2Sub3=NULL;
CAddenExp1 *AddenExp1=NULL;
CAdden1111	*Adden1111=NULL;
CAdden1112	*Adden1112=NULL;
CAdden1122	*Adden1122=NULL;
CAdden1222	*Adden1222=NULL;
CAdden2222	*Adden2222=NULL;
//      Список слагаемых, используемый при их перечислении
static  IAdden **DefaultAddens[]=
{
  (IAdden**)&AddenUnit,
  (IAdden**)&Adden1,(IAdden**)&Adden2,(IAdden**)&Adden3,(IAdden**)&Adden4,
  (IAdden**)&Adden11,(IAdden**)&Adden12,(IAdden**)&Adden13,
  (IAdden**)&Adden14,(IAdden**)&Adden22,(IAdden**)&Adden23,
  (IAdden**)&Adden24,(IAdden**)&Adden33,(IAdden**)&Adden34,
  (IAdden**)&Adden44,(IAdden**)&Adden44,(IAdden**)&Adden111,
  (IAdden**)&Adden112,(IAdden**)&Adden113,(IAdden**)&Adden114,
  (IAdden**)&Adden122,(IAdden**)&Adden123,(IAdden**)&Adden124,
  (IAdden**)&Adden133,(IAdden**)&Adden134,(IAdden**)&Adden144,
  (IAdden**)&Adden222,(IAdden**)&Adden223,(IAdden**)&Adden224,
  (IAdden**)&Adden233,(IAdden**)&Adden234,(IAdden**)&Adden244,
  (IAdden**)&Adden333,(IAdden**)&Adden334,(IAdden**)&Adden344,
  (IAdden**)&Adden444,(IAdden**)&Adden1Sub2,(IAdden**)&Adden1Sub3,
  (IAdden**)&Adden2Sub3,
  /* 23.11.99 */
  (IAdden**)&AddenExp1,
  /* 19.03.00 */
  (IAdden**)&Adden1111,(IAdden**)&Adden1112,(IAdden**)&Adden1122,
  (IAdden**)&Adden1222,(IAdden**)&Adden2222
};

static  void InitializeAddens(void)
{
  CREATE_INSTANCE(CAddenUnit,AddenUnit);

  CREATE_INSTANCE(CAdden1,Adden1);
  CREATE_INSTANCE(CAdden2,Adden2);
  CREATE_INSTANCE(CAdden3,Adden3);
  CREATE_INSTANCE(CAdden4,Adden4);

  CREATE_INSTANCE(CAdden11,Adden11);
  CREATE_INSTANCE(CAdden12,Adden12);
  CREATE_INSTANCE(CAdden13,Adden13);
  CREATE_INSTANCE(CAdden14,Adden14);
  CREATE_INSTANCE(CAdden22,Adden22);
  CREATE_INSTANCE(CAdden23,Adden23);
  CREATE_INSTANCE(CAdden24,Adden24);
  CREATE_INSTANCE(CAdden33,Adden33);
  CREATE_INSTANCE(CAdden34,Adden34);
  CREATE_INSTANCE(CAdden44,Adden44);
  CREATE_INSTANCE(CAdden44,Adden44);

  CREATE_INSTANCE(CAdden111,Adden111);
  CREATE_INSTANCE(CAdden112,Adden112);
  CREATE_INSTANCE(CAdden113,Adden113);
  CREATE_INSTANCE(CAdden114,Adden114);
  CREATE_INSTANCE(CAdden122,Adden122);
  CREATE_INSTANCE(CAdden123,Adden123);
  CREATE_INSTANCE(CAdden124,Adden124);
  CREATE_INSTANCE(CAdden133,Adden133);
  CREATE_INSTANCE(CAdden134,Adden134);
  CREATE_INSTANCE(CAdden144,Adden144);
  CREATE_INSTANCE(CAdden222,Adden222);
  CREATE_INSTANCE(CAdden223,Adden223);
  CREATE_INSTANCE(CAdden224,Adden224);
  CREATE_INSTANCE(CAdden233,Adden233);
  CREATE_INSTANCE(CAdden234,Adden234);
  CREATE_INSTANCE(CAdden244,Adden244);
  CREATE_INSTANCE(CAdden333,Adden333);
  CREATE_INSTANCE(CAdden334,Adden334);
  CREATE_INSTANCE(CAdden344,Adden344);
  CREATE_INSTANCE(CAdden444,Adden444);
  
  CREATE_INSTANCE(CAdden1Sub2,Adden1Sub2);
  CREATE_INSTANCE(CAdden1Sub3,Adden1Sub3);
  CREATE_INSTANCE(CAdden2Sub3,Adden2Sub3);
  /* 23.11.99 */
  CREATE_INSTANCE(CAddenExp1,AddenExp1);
  /* 19.03.00 */
  CREATE_INSTANCE(CAdden1111,Adden1111);
  CREATE_INSTANCE(CAdden1112,Adden1112);
  CREATE_INSTANCE(CAdden1122,Adden1122);
  CREATE_INSTANCE(CAdden1222,Adden1222);
  CREATE_INSTANCE(CAdden2222,Adden2222);
}
  
static  void FinalizeAddens(void)
{
  RELEASE_INSTANCE(AddenUnit);
  
  RELEASE_INSTANCE(Adden1);
  RELEASE_INSTANCE(Adden2);
  RELEASE_INSTANCE(Adden3);
  RELEASE_INSTANCE(Adden4);

  RELEASE_INSTANCE(Adden11);
  RELEASE_INSTANCE(Adden12);
  RELEASE_INSTANCE(Adden13);
  RELEASE_INSTANCE(Adden14);
  RELEASE_INSTANCE(Adden22);
  RELEASE_INSTANCE(Adden23);
  RELEASE_INSTANCE(Adden24);
  RELEASE_INSTANCE(Adden33);
  RELEASE_INSTANCE(Adden34);
  RELEASE_INSTANCE(Adden44);
  RELEASE_INSTANCE(Adden44);

  RELEASE_INSTANCE(Adden111);
  RELEASE_INSTANCE(Adden112);
  RELEASE_INSTANCE(Adden113);
  RELEASE_INSTANCE(Adden114);
  RELEASE_INSTANCE(Adden122);
  RELEASE_INSTANCE(Adden123);
  RELEASE_INSTANCE(Adden124);
  RELEASE_INSTANCE(Adden133);
  RELEASE_INSTANCE(Adden134);
  RELEASE_INSTANCE(Adden144);
  RELEASE_INSTANCE(Adden222);
  RELEASE_INSTANCE(Adden223);
  RELEASE_INSTANCE(Adden224);
  RELEASE_INSTANCE(Adden233);
  RELEASE_INSTANCE(Adden234);
  RELEASE_INSTANCE(Adden244);
  RELEASE_INSTANCE(Adden333);
  RELEASE_INSTANCE(Adden334);
  RELEASE_INSTANCE(Adden344);
  RELEASE_INSTANCE(Adden444);

  RELEASE_INSTANCE(Adden1Sub2);
  RELEASE_INSTANCE(Adden1Sub3);
  RELEASE_INSTANCE(Adden2Sub3);
  
	/* 23.11.99 */
	RELEASE_INSTANCE(AddenExp1);
	/* 19.03.00 */
	RELEASE_INSTANCE(Adden1111);
	RELEASE_INSTANCE(Adden1112);
	RELEASE_INSTANCE(Adden1122);
	RELEASE_INSTANCE(Adden1222);
	RELEASE_INSTANCE(Adden2222);
}
  
//      Списки слагаемых для моделей =====================================
//      Первая цифра - количество факторов, вторая - степень полинома.

//      Однофакторные модели
//      Первый порядок
static  IAdden **aPoly11[]=
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1                     
};
//      Второй порядок
static  IAdden **aPoly12[]=
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden11            
};
//      Третий порядок
static  IAdden **aPoly13[]=
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden11,
  (IAdden**)&Adden111
};
//      Двухфакторные модели
//      Первый порядок
static  IAdden **aPoly21[]=
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2         
};
//      Неполная квадратичная модель
static  IAdden **aPoly22nf[]=
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden12 
};
//      Второй порядок
static  IAdden **aPoly22[]=    
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden12,(IAdden**)&Adden11,(IAdden**)&Adden22
};
//      Неполная кубическая модель
static  IAdden **aPoly23nf[]=  
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden12,(IAdden**)&Adden11,(IAdden**)&Adden22,
  (IAdden**)&Adden112,(IAdden**)&Adden122
};
//      Третий порядок
static  IAdden **aPoly23[]=    
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden12,(IAdden**)&Adden11,(IAdden**)&Adden22,
  (IAdden**)&Adden112,(IAdden**)&Adden122,(IAdden**)&Adden111,
  (IAdden**)&Adden222
};

//      Трехфакторные модели
static  IAdden **aPoly31[]=
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3  // Первый порядок
};
//      Неполная квадратичная модель
static  IAdden **aPoly32nf[]=  
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden12,(IAdden**)&Adden13,
  (IAdden**)&Adden23
};
//      Второй порядок
static  IAdden **aPoly32[]=    
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden12,(IAdden**)&Adden13,
  (IAdden**)&Adden23,(IAdden**)&Adden11,(IAdden**)&Adden22,
  (IAdden**)&Adden33
};
//      Неполная кубическая модель
static  IAdden **aPoly33nf[]=  
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden12,(IAdden**)&Adden13,
  (IAdden**)&Adden23,(IAdden**)&Adden11,(IAdden**)&Adden22,
  (IAdden**)&Adden33,(IAdden**)&Adden112,(IAdden**)&Adden113,
  (IAdden**)&Adden122,(IAdden**)&Adden123,(IAdden**)&Adden133,
  (IAdden**)&Adden134,(IAdden**)&Adden223,(IAdden**)&Adden233
};
//      Третий порядок
static  IAdden **aPoly33[]=    
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden12,(IAdden**)&Adden13,
  (IAdden**)&Adden23,(IAdden**)&Adden11,(IAdden**)&Adden22,
  (IAdden**)&Adden33,(IAdden**)&Adden112,(IAdden**)&Adden113,
  (IAdden**)&Adden122,(IAdden**)&Adden123,(IAdden**)&Adden133,
  (IAdden**)&Adden134,(IAdden**)&Adden223,(IAdden**)&Adden233,
  (IAdden**)&Adden111,(IAdden**)&Adden222,(IAdden**)&Adden333
};

//      Четырехфакторные модели
//      Первый порядок
static  IAdden **aPoly41[]=    
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden4
};
//      Неполная квадратичная модель
static  IAdden **aPoly42nf[]=  
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden4,(IAdden**)&Adden12,
  (IAdden**)&Adden13,(IAdden**)&Adden14,(IAdden**)&Adden23,
  (IAdden**)&Adden24,  (IAdden**)&Adden34
};
//      Полная квадратичная модель
static  IAdden **aPoly42[]=    
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden4,(IAdden**)&Adden12,
  (IAdden**)&Adden13,(IAdden**)&Adden14,(IAdden**)&Adden23,
  (IAdden**)&Adden24,(IAdden**)&Adden34,(IAdden**)&Adden11,
  (IAdden**)&Adden22,(IAdden**)&Adden33,(IAdden**)&Adden44
};
//      Неполная кубическая модель
static  IAdden **aPoly43nf[]=  
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden4,(IAdden**)&Adden12,
  (IAdden**)&Adden13,(IAdden**)&Adden14,(IAdden**)&Adden23,
  (IAdden**)&Adden24,(IAdden**)&Adden34,(IAdden**)&Adden11,
  (IAdden**)&Adden22,(IAdden**)&Adden33,(IAdden**)&Adden44,
  (IAdden**)&Adden112,(IAdden**)&Adden113,(IAdden**)&Adden114,
  (IAdden**)&Adden122,(IAdden**)&Adden123,(IAdden**)&Adden124,
  (IAdden**)&Adden133,(IAdden**)&Adden134,(IAdden**)&Adden144,
  (IAdden**)&Adden223,(IAdden**)&Adden224,(IAdden**)&Adden233,
  (IAdden**)&Adden234,(IAdden**)&Adden244,(IAdden**)&Adden334,
  (IAdden**)&Adden344
};
//      Полная кубическая модель
static  IAdden **aPoly43[]=    
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&Adden2,
  (IAdden**)&Adden3,(IAdden**)&Adden4,(IAdden**)&Adden12,
  (IAdden**)&Adden13,(IAdden**)&Adden14,(IAdden**)&Adden23,
  (IAdden**)&Adden24,(IAdden**)&Adden34,(IAdden**)&Adden11,
  (IAdden**)&Adden22,(IAdden**)&Adden33,(IAdden**)&Adden44,
  (IAdden**)&Adden112,(IAdden**)&Adden113,(IAdden**)&Adden114,
  (IAdden**)&Adden122,(IAdden**)&Adden123,(IAdden**)&Adden124,
  (IAdden**)&Adden133,(IAdden**)&Adden134,(IAdden**)&Adden144,
  (IAdden**)&Adden223,(IAdden**)&Adden224,(IAdden**)&Adden233,
  (IAdden**)&Adden234,(IAdden**)&Adden244,(IAdden**)&Adden334,
  (IAdden**)&Adden344,(IAdden**)&Adden111,(IAdden**)&Adden222,
  (IAdden**)&Adden333,(IAdden**)&Adden444
};

//      Приведенный полином второго порядка
static  IAdden **aSheffe32[]=  
{
  (IAdden**)&Adden1,(IAdden**)&Adden2,(IAdden**)&Adden3,
  (IAdden**)&Adden12,(IAdden**)&Adden13,(IAdden**)&Adden23
};

//      Приведенный полином неполного третьего порядка
static  IAdden **aSheffe33nf[]=  
{
  (IAdden**)&Adden1,(IAdden**)&Adden2,(IAdden**)&Adden3,
  (IAdden**)&Adden12,(IAdden**)&Adden13,(IAdden**)&Adden23,
  (IAdden**)&Adden123
};

//      Приведенный полином третьего порядка
static  IAdden **aSheffe33[]=  
{
  (IAdden**)&Adden1,(IAdden**)&Adden2,(IAdden**)&Adden3,
  (IAdden**)&Adden12,(IAdden**)&Adden13,(IAdden**)&Adden23,
  (IAdden**)&Adden1Sub2,(IAdden**)&Adden1Sub3,
  (IAdden**)&Adden2Sub3,(IAdden**)&Adden123
  
};

/*
  23.11.99 - однофакторная модель, применяемая в исследовании реологических свойств
*/
static IAdden **aLinExp1[]=
{
  (IAdden**)&AddenUnit,(IAdden**)&Adden1,(IAdden**)&AddenExp1
};

//      Модели ===========================================================
#define DECLARE_MODEL(CLASS,INSTANCE,DESCRIPTION,DIMENSION,ADDEN_LIST)\
class   CLASS : public CModelBase INHERIT_MODEL_BASE(CLASS); \
CLASS::CLASS()\
{\
  Desc=DESCRIPTION;\
  ReqDim=DIMENSION;\
  AddensCount=sizeof(ADDEN_LIST)/sizeof(CAddenBase**);\
  _Addens=(IAdden***)ADDEN_LIST;\
} \
CLASS   *INSTANCE=NULL;

DECLARE_MODEL(CPoly11,Poly11,\
              "Однофакторная линейная регрессия (прямая)",1,aPoly11)
DECLARE_MODEL(CPoly12,Poly12,\
              "Однофакторная квадратичная регрессия (парабола)",1,aPoly12)
DECLARE_MODEL(CPoly13,Poly13,\
              "Однофакторная кубическая регрессия",1,aPoly13)

DECLARE_MODEL(CPoly21,Poly21,\
              "Линейная регрессия (два фактора)",2,aPoly21)
DECLARE_MODEL(CPoly22nf,Poly22nf,\
              "Неполная квадратичная регрессия (два фактора)",2,aPoly22nf)
DECLARE_MODEL(CPoly22,Poly22,\
              "Квадратичная регрессия (два фактора)",2,aPoly22)
DECLARE_MODEL(CPoly23nf,Poly23nf,\
              "Неполная кубическая регрессия (два фактора)",2,aPoly23nf)
DECLARE_MODEL(CPoly23,Poly23,\
              "Кубическая регрессия (два фактора)",2,aPoly23)

DECLARE_MODEL(CPoly31,Poly31,\
              "Линейная регрессия (три фактора)",3,aPoly31)
DECLARE_MODEL(CPoly32nf,Poly32nf,\
              "Неполная квадратичная регрессия (три фактора)",3,aPoly32nf)
DECLARE_MODEL(CPoly32,Poly32,\
              "Квадратичная регрессия (три фактора)",3,aPoly32)
DECLARE_MODEL(CPoly33nf,Poly33nf,\
              "Неполная кубическая регрессия (три фактора)",3,aPoly33nf)
DECLARE_MODEL(CPoly33,Poly33,\
              "Кубическая регрессия (три фактора)",3,aPoly33)

DECLARE_MODEL(CPoly41,Poly41,\
              "Линейная регрессия (четыре фактора)",4,aPoly41)
DECLARE_MODEL(CPoly42nf,Poly42nf,\
              "Неполная квадратичная регрессия (четыре фактора)",4,aPoly42nf)
DECLARE_MODEL(CPoly42,Poly42,\
              "Квадратичная регрессия (четыре фактора)",4,aPoly42)
DECLARE_MODEL(CPoly43nf,Poly43nf,\
              "Неполная кубическая регрессия (четыре фактора)",4,aPoly43nf)
DECLARE_MODEL(CPoly43,Poly43,\
              "Кубическая регрессия (четыре фактора)",4,aPoly43)

DECLARE_MODEL(CSheffe32,Sheffe32,\
              "Полином Шеффе второго порядка от трех факторов",3,aSheffe32)

DECLARE_MODEL(CSheffe33nf,Sheffe33nf,"Полином Шеффе неполного третьего"
              " порядка от трех факторов",3,aSheffe33nf)
              
DECLARE_MODEL(CSheffe33,Sheffe33,\
              "Полином Шеффе третьего порядка от трех факторов",3,aSheffe33)

/*
  23.11.99
*/

DECLARE_MODEL(CLinExp1,LinExp1,\
              "Сумма линейной функции и экспоненты",1,aLinExp1)

static IModel **DefaultModels[]=
{
  (IModel**)&Poly11,(IModel**)&Poly12,(IModel**)&Poly13,
  (IModel**)&Poly21,(IModel**)&Poly22nf,(IModel**)&Poly22,
  (IModel**)&Poly23nf,(IModel**)&Poly23,(IModel**)&Poly31,
  (IModel**)&Poly32nf,(IModel**)&Poly32,(IModel**)&Poly33nf,
  (IModel**)&Poly33,(IModel**)&Poly41,(IModel**)&Poly42nf,
  (IModel**)&Poly42,(IModel**)&Poly43nf,(IModel**)&Poly43,
  (IModel**)&Sheffe32,(IModel**)&Sheffe33nf,(IModel**)&Sheffe33,
  (IModel**)&LinExp1
};

static void InitializeModels()
{
  CREATE_INSTANCE(CPoly11,Poly11);
  CREATE_INSTANCE(CPoly12,Poly12);
  CREATE_INSTANCE(CPoly13,Poly13);

  CREATE_INSTANCE(CPoly21,Poly21);
  CREATE_INSTANCE(CPoly22nf,Poly22nf);
  CREATE_INSTANCE(CPoly22,Poly22);
  CREATE_INSTANCE(CPoly23nf,Poly23nf);
  CREATE_INSTANCE(CPoly23,Poly23);

  CREATE_INSTANCE(CPoly31,Poly31);
  CREATE_INSTANCE(CPoly32nf,Poly32nf);
  CREATE_INSTANCE(CPoly32,Poly32);
  CREATE_INSTANCE(CPoly33nf,Poly33nf);
  CREATE_INSTANCE(CPoly33,Poly33);

  CREATE_INSTANCE(CPoly41,Poly41);
  CREATE_INSTANCE(CPoly42nf,Poly42nf);
  CREATE_INSTANCE(CPoly42,Poly42);
  CREATE_INSTANCE(CPoly43nf,Poly43nf);
  CREATE_INSTANCE(CPoly43,Poly43);

  CREATE_INSTANCE(CSheffe32,Sheffe32);
  CREATE_INSTANCE(CSheffe33nf,Sheffe33nf);
  CREATE_INSTANCE(CSheffe33,Sheffe33);
  
  CREATE_INSTANCE(CLinExp1,LinExp1);
}

static void FinalizeModels()
{
  RELEASE_INSTANCE(Poly11);
  RELEASE_INSTANCE(Poly12);
  RELEASE_INSTANCE(Poly13);

  RELEASE_INSTANCE(Poly21);
  RELEASE_INSTANCE(Poly22nf);
  RELEASE_INSTANCE(Poly22);
  RELEASE_INSTANCE(Poly23nf);
  RELEASE_INSTANCE(Poly23);

  RELEASE_INSTANCE(Poly31);
  RELEASE_INSTANCE(Poly32nf);
  RELEASE_INSTANCE(Poly32);
  RELEASE_INSTANCE(Poly33nf);
  RELEASE_INSTANCE(Poly33);

  RELEASE_INSTANCE(Poly41);
  RELEASE_INSTANCE(Poly42nf);
  RELEASE_INSTANCE(Poly42);
  RELEASE_INSTANCE(Poly43nf);
  RELEASE_INSTANCE(Poly43);
  
  RELEASE_INSTANCE(Sheffe32);
  RELEASE_INSTANCE(Sheffe33nf);
  RELEASE_INSTANCE(Sheffe33);
  
  RELEASE_INSTANCE(LinExp1);
}

//      Генераторы =======================================================

//      Создание плана полного факторного эксперимента. Этот код был  пер-
//      воначально написан на VBA для Excel, затем перенесен на Pascal, и,
//      наконец, - переписан на C.

static void CreateFFE(double **lpdRows,int K)
{
  int i,j,k,t;
  double codef;
  k=1;
  codef=-1;
  for(j=0;j<K;j++)
  {
    i=0;
    while(i<(1<<K))
    {
      for(t=0;t<k;t++)
        lpdRows[i+t][j]=codef;
      codef=-codef;
      i=i+k;
    }
    k<<=1;
  }
}

double GetAlpha(int K,int IsCCR)
{
#define	SQRTD(arg) (sqrt((double)(arg)))

  if(IsCCR)
  {
    return SQRTD(SQRTD(1<<K));
  }
  else
  {
    int N = (1 << K) + (K << 1) + 1;
    return SQRTD((SQRTD((1 << K) * N) - (1<<K) )/2);
  }
#undef	SQRTD
}

// Функция дополняет план звездными точками
static void CreateCC(double **lpdRows,int K, int IsCCR)
{
  int i,j,t;
  double Alpha;
  int N;
  N = (1 << K) + (K << 1) + 1;
  Alpha=GetAlpha(K,IsCCR);
  t=0;
  i=1<<K;
  while(i<(N-1))
  {
    j=0;
    while(j<t)
    {
      lpdRows[i][j]=0;
      lpdRows[i+1][j]=0;
      j=j+1;
    }
    lpdRows[i][t]=-Alpha;
    lpdRows[i+1][t]=Alpha;
    j=t+1;
    while(j<K)
    {
      lpdRows[i][j]=0;
      lpdRows[i+1][j]=0;
      j=j+1;
    }
    // Звездная точка - в следующем столбце
    t=t+1;
    // Шаг - две строки
    i=i+2;
  }
  // Последняя точка - опыт в центре плана
  for(j=0;j<K;j++)
    lpdRows[N-1][j]=0;
}

static void CreateCCR(double **lpdRows,int K)
{
  CreateFFE(lpdRows,K);
  CreateCC(lpdRows,K,1);
}

/*
static void CreateCCO(double **lpdRows,int K)
{
  CreateFFE(lpdRows,K);
  CreateCC(lpdRows,K,0);
}
*/

#define DECLARE_GEN(CLASS,INSTANCE,DESCRIPTION,DIMY,DIMX,MODEL)\
class   CLASS : public CGeneratorBase INHERIT_GENERATOR_BASE(CLASS) \
CLASS::CLASS()\
{\
  Desc=DESCRIPTION;\
  ReqRows=DIMY;\
  ReqCols=DIMX;\
  DefModel=(IModel**)&MODEL;\
} \
CLASS   *INSTANCE=NULL;

// DECLARE_GEN(CGen11,Gen11,"",2,1,Poly11)
// DECLARE_GEN(CGen12,Gen12,"",3,1,Poly12)
// DECLARE_GEN(CGen13,Gen13,"",4,1,Poly13)

DECLARE_GEN(CGen21,Gen21,\
            "Полный двухфакторный эксперимент",4,2,Poly21)
DECLARE_GEN(CGen22nf,Gen22nf,\
            "Двухфакторный композиционный (ротатабельный) эксперимент с "
            "неполной квадратичной моделью",9,2,Poly22nf)
DECLARE_GEN(CGen22,Gen22,\
            "Двухфакторный композиционный (ротатабельный) эксперимент с "
            "квадратичной моделью",9,2,Poly22)
// DECLARE_GEN(CGen23nf,Gen23nf,"",0,2,Poly23nf)
// DECLARE_GEN(CGen23,Gen23,"",0,2,Poly23)

DECLARE_GEN(CGen31,Gen31,\
            "Полный трехфакторный эксперимент",8,3,Poly31)
DECLARE_GEN(CGen32nf,Gen32nf,\
            "Трехфакторный композиционный (ротатабельный) эксперимент с "
            "неполной квадратичной моделью",15,3,Poly32nf)
DECLARE_GEN(CGen32,Gen32,\
            "Трехфакторный композиционный (ротатабельный) эксперимент с "
            "квадратичной моделью",15,3,Poly32)
// DECLARE_GEN(CGen33nf,Gen33nf,"",0,3,Poly33nf)
// DECLARE_GEN(CGen33,Gen33,"",0,3,Poly33)

DECLARE_GEN(CGen41,Gen41,\
            "Полный четырехфакторный эксперимент",16,4,Poly41)
DECLARE_GEN(CGen42nf,Gen42nf,\
            "Четырехфакторный композиционный (ротатабельный) эксперимент "
            "с неполной квадратичной моделью",25,4,Poly42nf)
DECLARE_GEN(CGen42,Gen42,\
            "Четырехфакторный композиционный (ротатабельный) эксперимент "
            "с квадратичной моделью",25,4,Poly42)
// DECLARE_GEN(CGen43nf,Gen43nf,"",0,4,Poly43nf)
// DECLARE_GEN(CGen43,CGen43,"",0,4,Poly43)

DECLARE_GEN(CSheffeGen32,SheffeGen32,"Насыщенный симплекс - решетчатый "
  "план на плоскости с квадратичной моделью",6,3,Sheffe32)
DECLARE_GEN(CSheffeGen33nf,SheffeGen33nf,"Насыщенный симплекс - решетчатый "
  "план на плоскости с неполной кубической моделью",7,3,Sheffe33nf)
DECLARE_GEN(CSheffeGen33,SheffeGen33,"Насыщенный симплекс - решетчатый "
  "план на плоскости с кубической моделью",10,3,Sheffe33)

static IGenerator** DefaultGens[]=
{
  (IGenerator**)&Gen21,
  (IGenerator**)&Gen22nf,
  (IGenerator**)&Gen22,
  (IGenerator**)&Gen31,
  (IGenerator**)&Gen32nf,
  (IGenerator**)&Gen32,
  (IGenerator**)&Gen41,
  (IGenerator**)&Gen42nf,
  (IGenerator**)&Gen42,
  (IGenerator**)&SheffeGen32,
  (IGenerator**)&SheffeGen33nf,
  (IGenerator**)&SheffeGen33
};

void __stdcall CGen21::Generate(double **Rows)
{
  CreateFFE(Rows,2);
}

void __stdcall CGen22nf::Generate(double **Rows)
{
  CreateCCR(Rows,2);
}

void __stdcall CGen22::Generate(double **Rows)
{
  CreateCCR(Rows,2);
}

void __stdcall CGen31::Generate(double **Rows)
{
  CreateFFE(Rows,3);
}

void __stdcall CGen32nf::Generate(double **Rows)
{
  CreateCCR(Rows,3);
}

void __stdcall CGen32::Generate(double **Rows)
{
  CreateCCR(Rows,3);
}

void __stdcall CGen41::Generate(double **Rows)
{
  CreateFFE(Rows,4);
}

void __stdcall CGen42::Generate(double **Rows)
{
  CreateCCR(Rows,4);
}

void __stdcall CGen42nf::Generate(double **Rows)
{
  CreateCCR(Rows,4);
}

// =======================================================================
// Матрицы планов Шеффе
// =======================================================================
// Вторая степень
static double Simplex32[6][3]=
{
  {1,0,0},
  {0,1,0},
  {0,0,1},
  {.5,.5,0},
  {.5,0,.5},
  {0,.5,.5}
};

void __stdcall CSheffeGen32::Generate(double **Rows)
{
  int i,j;
  for(i=0;i<6;i++)
    for(j=0;j<3;j++)
      Rows[i][j]=Simplex32[i][j];
}

// Неполная третья степень
static double Simplex33nf[7][3]=
{
  {1,0,0},
  {0,1,0},
  {0,0,1},
  {.5,.5,0},
  {.5,0,.5},
  {0,.5,.5},
  {1./3.,1./3.,1./3.}
};

void __stdcall CSheffeGen33nf::Generate(double **Rows)
{
  int i,j;
  for(i=0;i<7;i++)
    for(j=0;j<3;j++)
      Rows[i][j]=Simplex33nf[i][j];
}

// Третья степень
static double Simplex33[10][3]=
{
  {1,0,0},
  {0,1,0},
  {0,0,1},
  {2./3.,1./3.,0},
  {1./3.,2./3.,0},
  {0,2./3.,1./3.},
  {0,1./3.,2./3.},
  {2./3.,0,1./3.},
  {1./3.,0,2./3.},
  {1./3.,1./3.,1./3.}
};

void __stdcall CSheffeGen33::Generate(double **Rows)
{
  int i,j;
  for(i=0;i<10;i++)
    for(j=0;j<3;j++)
      Rows[i][j]=Simplex33[i][j];
}

/*// Четвертая степень
static double Simplex34[15][3]=
{
  {1,0,0},
  {0,1,0},
  {0,0,1},
  {.5,.5,0},
  {.5,0,.5},
  {0,.5,.5},
  {.75,.25,0},
  {.25,.75,0},
  {.75,0,.25},
  {.25,0,.75},
  {0,.75,.25},
  {0,.25,.75},
  {.5,.25,.25},
  {.25,.5,.25},
  {.25,.25,.5},
};*/

static void InitializeGens()
{
//  CREATE_INSTANCE(CGen11,Gen11);
//  CREATE_INSTANCE(CGen12,Gen12);
//  CREATE_INSTANCE(CGen13,Gen13);

  CREATE_INSTANCE(CGen21,Gen21);
  CREATE_INSTANCE(CGen22nf,Gen22nf);
  CREATE_INSTANCE(CGen22,Gen22);
//  CREATE_INSTANCE(CGen23nf,Gen23nf);
//  CREATE_INSTANCE(CGen23,Gen23);

  CREATE_INSTANCE(CGen31,Gen31);
  CREATE_INSTANCE(CGen32nf,Gen32nf);
  CREATE_INSTANCE(CGen32,Gen32);
//  CREATE_INSTANCE(CGen33nf,Gen33nf);
//  CREATE_INSTANCE(CGen33,Gen33);

  CREATE_INSTANCE(CGen41,Gen41);
  CREATE_INSTANCE(CGen42nf,Gen42nf);
  CREATE_INSTANCE(CGen42,Gen42);
//  CREATE_INSTANCE(CGen43nf,Gen43nf);
//  CREATE_INSTANCE(CGen43,CGen43);
  CREATE_INSTANCE(CSheffeGen32,SheffeGen32);
  CREATE_INSTANCE(CSheffeGen33nf,SheffeGen33nf);
  CREATE_INSTANCE(CSheffeGen33,SheffeGen33);
}

static void FinalizeGens()
{
//  RELEASE_INSTANCE(Gen11);
//  RELEASE_INSTANCE(Gen12);
//  RELEASE_INSTANCE(Gen13);

  RELEASE_INSTANCE(Gen21);
  RELEASE_INSTANCE(Gen22nf);
  RELEASE_INSTANCE(Gen22);
//  RELEASE_INSTANCE(Gen23nf);
//  RELEASE_INSTANCE(Gen23);

  RELEASE_INSTANCE(Gen31);
  RELEASE_INSTANCE(Gen32nf);
  RELEASE_INSTANCE(Gen32);
//  RELEASE_INSTANCE(Gen33nf);
//  RELEASE_INSTANCE(Gen33);

  RELEASE_INSTANCE(Gen41);
  RELEASE_INSTANCE(Gen42nf);
  RELEASE_INSTANCE(Gen42);
//  RELEASE_INSTANCE(Gen43nf);
//  RELEASE_INSTANCE(Gen43);
  RELEASE_INSTANCE(SheffeGen32);
  RELEASE_INSTANCE(SheffeGen33nf);
  RELEASE_INSTANCE(SheffeGen33);
}

static void Initialize()
{
  InitializeAddens();
  InitializeModels();
  InitializeGens();
}

static void Finalize()
{
  FinalizeAddens();
  FinalizeModels();
  FinalizeGens();
}

int UEXPORT AddensEnumerate(GenericEnumProc EnumProc)
{
  int i;
  int s;
  s=sizeof(DefaultAddens)/sizeof(CAddenBase**);
  for(i=0;i<s;i++)
    if(EnumProc(*(DefaultAddens[i]))!=ADENUM_OK) 
      return 0;
  return 1;
}

int UEXPORT ModelsEnumerate(GenericEnumProc EnumProc)
{
  int i;
  int s;
  s=sizeof(DefaultModels)/sizeof(CModelBase**);
  for(i=0;i<s;i++)
    if(EnumProc(*(DefaultModels[i]))!=MODENUM_OK)
      return 0;
  return 1;
}

int UEXPORT GensEnumerate(GenericEnumProc EnumProc)
{
  int i;
  int s;
  s=sizeof(DefaultGens)/sizeof(CGeneratorBase**);
  for(i=0;i<s;i++)
    if(EnumProc(*(DefaultGens[i]))!=PLENUM_OK)
      return 0;
  return 1;
}

// =======================================================================

pchar __stdcall CAddenBase::Description(void)
{
  return Desc;
}

pchar __stdcall CAddenBase::StdName(void)
{
  return Name;
}

pchar __stdcall CAddenBase::StdBName(void)
{
  return BName;
}

int	CAddenBase::RequiredDimension(void)
{
  return ReqDim;
}

void	CAddenBase::Value(double *M,double *Res)
{
}

// =======================================================================

pchar __stdcall CModelBase::Description()
{
  return Desc;
}

int   __stdcall CModelBase::RequiredDimension(void)
{
  return ReqDim;
}

int __stdcall CModelBase::AddenCount()
{
  return AddensCount;
}

pIAdden __stdcall CModelBase::Addens(int Index)
{
  return *(_Addens[Index]);
}

void __stdcall CModelBase::Value(double *M,double *B,double *Res)
{
  int i;
  double s=0,v;
  for(i=0;i<AddensCount;i++)
  {
    (*(_Addens[i]))->Value(M,&v);
    s+=B[i]*v;
  }
  *Res=s;
}

// =======================================================================

pchar __stdcall CGeneratorBase::Description()
{
  return Desc;
}

void  __stdcall CGeneratorBase::RequiredDimensions(int *nRows,int *nCols)
{
  *nRows=ReqRows;
  *nCols=ReqCols;
}

pIModel __stdcall CGeneratorBase::DefaultModel()
{
  return *DefModel;
}

void	CGeneratorBase::Generate(double **Rows)
{
}

// =======================================================================
// Точка входа, инициализация и завершение
// =======================================================================

int UEXPORT GetModuleVersionInfo(ModuleVersionInfo *lpVersionInfo)
{
  lpVersionInfo->wMajor=1;
  lpVersionInfo->wMinor=0;
  lpVersionInfo->pszDescription=
    "Основной внешний модуль.\r\n"
    "Смирнов В.А., 1998-1999";
  return 1;
}

static int volatile ReferenceCount=0;

static void AddRef()
{
  if(ReferenceCount==0)
    Initialize();
  ReferenceCount++;
}

static void Release()
{
  ReferenceCount--;
  if(ReferenceCount==0) 
    Finalize();
}

// Точка входа
int WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void*)
{
  switch(reason)
  {
  case DLL_PROCESS_ATTACH:
    AddRef();
    break;
  case DLL_PROCESS_DETACH:
    Release();
    break;
  }
  return 1;
}
