// @(#)root/hist:$Id$
// Author: Nicolas Brun   19/08/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
// ---------------------------------- Formula.h

#ifndef ROOT_TFormula
#define ROOT_TFormula



//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TFormula                                                             //
//                                                                      //
// The formula base class  f(x,y,z,par)                                 //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifndef ROOT_TNamed
#include "TNamed.h"
#endif
#ifndef ROOT_TBits
#include "TBits.h"
#endif
#ifndef ROOT_TObjArray
#include "TObjArray.h"
#endif

class TFormulaPrimitive;

const Int_t kMAXFOUND = 500;
const Int_t kTFOperMask = 0x7fffff;
const UChar_t kTFOperShift = 23;


class  TOperOffset {
   friend class TFormula;
public:
   enum {
      kVariable  = 0,
      kParameter = 1,
      kConstant  = 2
   };
   TOperOffset();
protected:
   Short_t fType0;            // type     of operand  0
   Short_t fOffset0;          // offset   of operand  0
   Short_t fType1;            // type     of operand  1
   Short_t fOffset1;          // offset   of operand  1
   Short_t fType2;            // type     of operand  2
   Short_t fOffset2;          // offset   of operand  2
   Short_t fType3;            // type     of operand  3
   Short_t fOffset3;          // offset   of operand  3
   Short_t fToJump;           // where to jump in case of optimized boolen
   Short_t fOldAction;        // temporary variable used during optimization
};

class TFormula : public TNamed {

protected:

   typedef Double_t (TObject::*TFuncG)(const Double_t*,const Double_t*) const;

   Int_t      fNdim;            //Dimension of function (1=1-Dim, 2=2-Dim,etc)
   Int_t      fNpar;            //Number of parameters
   Int_t      fNoper;           //Number of operators
   Int_t      fNconst;          //Number of constants
   Int_t      fNumber;          //formula number identifier
   Int_t      fNval;            //Number of different variables in expression
   Int_t      fNstring;         //Number of different constants character strings
   TString   *fExpr;            //[fNoper] List of expressions
private:
   Int_t     *fOper;            //[fNoper] List of operators. (See documentation for changes made at version 7)
protected:
   Double_t  *fConst;           //[fNconst] Array of fNconst formula constants
   Double_t  *fParams;          //[fNpar] Array of fNpar parameters
   TString   *fNames;           //[fNpar] Array of parameter names
   TObjArray  fFunctions;       //Array of function calls to make
   TObjArray  fLinearParts;     //Linear parts if the formula is linear (contains '|' or "++")

   TBits      fAlreadyFound;    //! cache for information

   // Optimized expression
   Int_t                fNOperOptimized; //!Number of operators after optimization
   TString             *fExprOptimized;  //![fNOperOptimized] List of expressions
   Int_t               *fOperOptimized;  //![fNOperOptimized] List of operators. (See documentation for changes made at version 7)
   TOperOffset         *fOperOffset;     //![fNOperOptimized]         Offsets of operrands
   TFormulaPrimitive  **fPredefined;      //![fNPar] predefined function
   TFuncG               fOptimal; //!pointer to optimal function

   Int_t             PreCompile();
   virtual Bool_t    CheckOperands(Int_t operation, Int_t &err);
   virtual Bool_t    CheckOperands(Int_t leftoperand, Int_t rightoperartion, Int_t &err);
   virtual Bool_t    StringToNumber(Int_t code);
   void              MakePrimitive(const char *expr, Int_t pos);
   inline Int_t     *GetOper() const { return fOper; }
   inline Short_t    GetAction(Int_t code) const { return fOper[code] >> kTFOperShift; }
   inline Int_t      GetActionParam(Int_t code) const { return fOper[code] & kTFOperMask; }

   inline void       SetAction(Int_t code, Int_t value, Int_t param = 0) {
      fOper[code]  = (value) << kTFOperShift;
      fOper[code] += param;
   }
   inline Int_t     *GetOperOptimized() const { return fOperOptimized; }
   inline Short_t    GetActionOptimized(Int_t code) const { return fOperOptimized[code] >> kTFOperShift; }
   inline Int_t      GetActionParamOptimized(Int_t code) const { return fOperOptimized[code] & kTFOperMask; }

   inline void       SetActionOptimized(Int_t code, Int_t value, Int_t param = 0) {
      fOperOptimized[code]  = (value) << kTFOperShift;
      fOperOptimized[code] += param;
   }

   void            ClearFormula(Option_t *option="");
   virtual Bool_t  IsString(Int_t oper) const;

   virtual void    Convert(UInt_t fromVersion);
   //
   // Functions  - used for formula evaluation
   Double_t        EvalParFast(const Double_t *x, const Double_t *params);
   Double_t        EvalPrimitive(const Double_t *x, const Double_t *params);
   Double_t        EvalPrimitive0(const Double_t *x, const Double_t *params);
   Double_t        EvalPrimitive1(const Double_t *x, const Double_t *params);
   Double_t        EvalPrimitive2(const Double_t *x, const Double_t *params);
   Double_t        EvalPrimitive3(const Double_t *x, const Double_t *params);
   Double_t        EvalPrimitive4(const Double_t *x, const Double_t *params);

   // Action code for Version 6 and above.
   enum {
      kEnd      = 0,
      kAdd      = 1, kSubstract = 2,
      kMultiply = 3, kDivide    = 4,
      kModulo   = 5,

      kcos      = 10, ksin  = 11 , ktan  = 12,
      kacos     = 13, kasin = 14 , katan = 15,
      katan2    = 16,
      kfmod     = 17,

      kpow      = 20, ksq = 21, ksqrt     = 22,

      kstrstr   = 23,

      kmin      = 24, kmax = 25,

      klog      = 30, kexp = 31, klog10 = 32,

      kpi     = 40,

      kabs    = 41 , ksign= 42,
      kint    = 43 ,
      kSignInv= 44 ,
      krndm   = 50 ,

      kAnd      = 60, kOr          = 61,
      kEqual    = 62, kNotEqual    = 63,
      kLess     = 64, kGreater     = 65,
      kLessThan = 66, kGreaterThan = 67,
      kNot      = 68,

      kcosh   = 70 , ksinh  = 71, ktanh  = 72,
      kacosh  = 73 , kasinh = 74, katanh = 75,

      kStringEqual = 76, kStringNotEqual = 77,

      kBitAnd    = 78, kBitOr     = 79,
      kLeftShift = 80, kRightShift = 81,

      kJumpIf = 82, kJump = 83,

      kexpo   = 100 , kxexpo   = 100, kyexpo   = 101, kzexpo   = 102, kxyexpo   = 105,
      kgaus   = 110 , kxgaus   = 110, kygaus   = 111, kzgaus   = 112, kxygaus   = 115,
      klandau = 120 , kxlandau = 120, kylandau = 121, kzlandau = 122, kxylandau = 125,
      kpol    = 130 , kxpol    = 130, kypol    = 131, kzpol    = 132,

      kParameter       = 140,
      kConstant        = 141,
      kBoolOptimize    = 142,
      kStringConst     = 143,
      kVariable        = 144,
      kFunctionCall    = 145,
      kData            = 146,
      kUnary           = 147,
      kBinary          = 148,
      kThree           = 149,
      kDefinedVariable = 150,
      kDefinedString   = 151,
      //
      kPlusD           = 152,
      kPlusDD          = 153,
      kMultD           = 154,
      kMultDD          = 155,
      kBoolOptimizeOr  = 156,
      kBoolOptimizeAnd = 157,
      kBoolSet         = 158,
      kFDM             = 159,
      kFD0             = 160,
      kFD1             = 161,
      kFD2             = 162,
      kFD3             = 163
   };

public:
   // TFormula status bits
   enum {
      kNotGlobal     = BIT(10),  // don't store in gROOT->GetListOfFunction
      kNormalized    = BIT(14),   // set to true if the function (ex gausn) is normalized
      kLinear        = BIT(16)    //set to true if the function is for linear fitting
   };

               TFormula();
               TFormula(const char *name,const char *formula);
               TFormula(const TFormula &formula);
   TFormula&   operator=(const TFormula &rhs);
   virtual    ~TFormula();

 public:
   void                Optimize();
   virtual void        Analyze(const char *schain, Int_t &err, Int_t offset=0);
   virtual Bool_t      AnalyzeFunction(TString &chaine, Int_t &err, Int_t offset=0);
   virtual Int_t       Compile(const char *expression="");
   virtual void        Copy(TObject &formula) const;
   virtual void        Clear(Option_t *option="");
   virtual char       *DefinedString(Int_t code);
   virtual Double_t    DefinedValue(Int_t code);
   virtual Int_t       DefinedVariable(TString &variable,Int_t &action);
   virtual Double_t    Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const;
   virtual Double_t    EvalParOld(const Double_t *x, const Double_t *params=0);
   virtual Double_t    EvalPar(const Double_t *x, const Double_t *params=0){return ((*this).*fOptimal)(x,params);};
   virtual const TObject *GetLinearPart(Int_t i);
   virtual Int_t       GetNdim() const {return fNdim;}
   virtual Int_t       GetNpar() const {return fNpar;}
   virtual Int_t       GetNumber() const {return fNumber;}
   virtual TString     GetExpFormula(Option_t *option="") const;
   Double_t            GetParameter(Int_t ipar) const;
   Double_t            GetParameter(const char *name) const;
   virtual Double_t   *GetParameters() const {return fParams;}
   virtual void        GetParameters(Double_t *params){for(Int_t i=0;i<fNpar;i++) params[i] = fParams[i];}
   virtual const char *GetParName(Int_t ipar) const;
   virtual Int_t       GetParNumber(const char *name) const;
   virtual Bool_t      IsLinear() const {return TestBit(kLinear);}
   virtual Bool_t      IsNormalized() const {return TestBit(kNormalized);}
   virtual void        Print(Option_t *option="") const; // *MENU*
   virtual void        ProcessLinear(TString &replaceformula);
   virtual void        SetName(const char* name);
   virtual void        SetNumber(Int_t number) {fNumber = number;}
   virtual void        SetParameter(const char *name, Double_t parvalue);
   virtual void        SetParameter(Int_t ipar, Double_t parvalue);
   virtual void        SetParameters(const Double_t *params);
   virtual void        SetParameters(Double_t p0,Double_t p1,Double_t p2=0,Double_t p3=0,Double_t p4=0,
                                     Double_t p5=0,Double_t p6=0,Double_t p7=0,Double_t p8=0,
                                     Double_t p9=0,Double_t p10=0); // *MENU*
   virtual void        SetParName(Int_t ipar, const char *name);
   virtual void        SetParNames(const char *name0="p0",const char *name1="p1",const char
                                   *name2="p2",const char *name3="p3",const char
                                   *name4="p4", const char *name5="p5",const char *name6="p6",const char *name7="p7",const char
                                   *name8="p8",const char *name9="p9",const char *name10="p10"); // *MENU*
   virtual void        Update() {;}

   static  void        SetMaxima(Int_t maxop=1000, Int_t maxpar=1000, Int_t maxconst=1000);
   static  void        GetMaxima(Int_t& maxop, Int_t& maxpar, Int_t& maxconst);

   ClassDef(TFormula,8)  //The formula base class  f(x,y,z,par)
};

#endif
 TFormula.h:1
 TFormula.h:2
 TFormula.h:3
 TFormula.h:4
 TFormula.h:5
 TFormula.h:6
 TFormula.h:7
 TFormula.h:8
 TFormula.h:9
 TFormula.h:10
 TFormula.h:11
 TFormula.h:12
 TFormula.h:13
 TFormula.h:14
 TFormula.h:15
 TFormula.h:16
 TFormula.h:17
 TFormula.h:18
 TFormula.h:19
 TFormula.h:20
 TFormula.h:21
 TFormula.h:22
 TFormula.h:23
 TFormula.h:24
 TFormula.h:25
 TFormula.h:26
 TFormula.h:27
 TFormula.h:28
 TFormula.h:29
 TFormula.h:30
 TFormula.h:31
 TFormula.h:32
 TFormula.h:33
 TFormula.h:34
 TFormula.h:35
 TFormula.h:36
 TFormula.h:37
 TFormula.h:38
 TFormula.h:39
 TFormula.h:40
 TFormula.h:41
 TFormula.h:42
 TFormula.h:43
 TFormula.h:44
 TFormula.h:45
 TFormula.h:46
 TFormula.h:47
 TFormula.h:48
 TFormula.h:49
 TFormula.h:50
 TFormula.h:51
 TFormula.h:52
 TFormula.h:53
 TFormula.h:54
 TFormula.h:55
 TFormula.h:56
 TFormula.h:57
 TFormula.h:58
 TFormula.h:59
 TFormula.h:60
 TFormula.h:61
 TFormula.h:62
 TFormula.h:63
 TFormula.h:64
 TFormula.h:65
 TFormula.h:66
 TFormula.h:67
 TFormula.h:68
 TFormula.h:69
 TFormula.h:70
 TFormula.h:71
 TFormula.h:72
 TFormula.h:73
 TFormula.h:74
 TFormula.h:75
 TFormula.h:76
 TFormula.h:77
 TFormula.h:78
 TFormula.h:79
 TFormula.h:80
 TFormula.h:81
 TFormula.h:82
 TFormula.h:83
 TFormula.h:84
 TFormula.h:85
 TFormula.h:86
 TFormula.h:87
 TFormula.h:88
 TFormula.h:89
 TFormula.h:90
 TFormula.h:91
 TFormula.h:92
 TFormula.h:93
 TFormula.h:94
 TFormula.h:95
 TFormula.h:96
 TFormula.h:97
 TFormula.h:98
 TFormula.h:99
 TFormula.h:100
 TFormula.h:101
 TFormula.h:102
 TFormula.h:103
 TFormula.h:104
 TFormula.h:105
 TFormula.h:106
 TFormula.h:107
 TFormula.h:108
 TFormula.h:109
 TFormula.h:110
 TFormula.h:111
 TFormula.h:112
 TFormula.h:113
 TFormula.h:114
 TFormula.h:115
 TFormula.h:116
 TFormula.h:117
 TFormula.h:118
 TFormula.h:119
 TFormula.h:120
 TFormula.h:121
 TFormula.h:122
 TFormula.h:123
 TFormula.h:124
 TFormula.h:125
 TFormula.h:126
 TFormula.h:127
 TFormula.h:128
 TFormula.h:129
 TFormula.h:130
 TFormula.h:131
 TFormula.h:132
 TFormula.h:133
 TFormula.h:134
 TFormula.h:135
 TFormula.h:136
 TFormula.h:137
 TFormula.h:138
 TFormula.h:139
 TFormula.h:140
 TFormula.h:141
 TFormula.h:142
 TFormula.h:143
 TFormula.h:144
 TFormula.h:145
 TFormula.h:146
 TFormula.h:147
 TFormula.h:148
 TFormula.h:149
 TFormula.h:150
 TFormula.h:151
 TFormula.h:152
 TFormula.h:153
 TFormula.h:154
 TFormula.h:155
 TFormula.h:156
 TFormula.h:157
 TFormula.h:158
 TFormula.h:159
 TFormula.h:160
 TFormula.h:161
 TFormula.h:162
 TFormula.h:163
 TFormula.h:164
 TFormula.h:165
 TFormula.h:166
 TFormula.h:167
 TFormula.h:168
 TFormula.h:169
 TFormula.h:170
 TFormula.h:171
 TFormula.h:172
 TFormula.h:173
 TFormula.h:174
 TFormula.h:175
 TFormula.h:176
 TFormula.h:177
 TFormula.h:178
 TFormula.h:179
 TFormula.h:180
 TFormula.h:181
 TFormula.h:182
 TFormula.h:183
 TFormula.h:184
 TFormula.h:185
 TFormula.h:186
 TFormula.h:187
 TFormula.h:188
 TFormula.h:189
 TFormula.h:190
 TFormula.h:191
 TFormula.h:192
 TFormula.h:193
 TFormula.h:194
 TFormula.h:195
 TFormula.h:196
 TFormula.h:197
 TFormula.h:198
 TFormula.h:199
 TFormula.h:200
 TFormula.h:201
 TFormula.h:202
 TFormula.h:203
 TFormula.h:204
 TFormula.h:205
 TFormula.h:206
 TFormula.h:207
 TFormula.h:208
 TFormula.h:209
 TFormula.h:210
 TFormula.h:211
 TFormula.h:212
 TFormula.h:213
 TFormula.h:214
 TFormula.h:215
 TFormula.h:216
 TFormula.h:217
 TFormula.h:218
 TFormula.h:219
 TFormula.h:220
 TFormula.h:221
 TFormula.h:222
 TFormula.h:223
 TFormula.h:224
 TFormula.h:225
 TFormula.h:226
 TFormula.h:227
 TFormula.h:228
 TFormula.h:229
 TFormula.h:230
 TFormula.h:231
 TFormula.h:232
 TFormula.h:233
 TFormula.h:234
 TFormula.h:235
 TFormula.h:236
 TFormula.h:237
 TFormula.h:238
 TFormula.h:239
 TFormula.h:240
 TFormula.h:241
 TFormula.h:242
 TFormula.h:243
 TFormula.h:244
 TFormula.h:245
 TFormula.h:246
 TFormula.h:247
 TFormula.h:248
 TFormula.h:249
 TFormula.h:250
 TFormula.h:251
 TFormula.h:252
 TFormula.h:253
 TFormula.h:254
 TFormula.h:255
 TFormula.h:256
 TFormula.h:257
 TFormula.h:258
 TFormula.h:259
 TFormula.h:260
 TFormula.h:261
 TFormula.h:262
 TFormula.h:263
 TFormula.h:264
 TFormula.h:265
 TFormula.h:266
 TFormula.h:267
 TFormula.h:268
 TFormula.h:269
 TFormula.h:270
 TFormula.h:271
 TFormula.h:272