// @(#)root/base:$Id$
// Author: Maarten Ballintijn   21/06/2004

/*************************************************************************
 * 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.             *
 *************************************************************************/

#ifndef ROOT_TParameter
#define ROOT_TParameter


//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TParameter<AParamType>                                               //
//                                                                      //
// Named parameter, streamable and storable.                            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifndef ROOT_Riostream
#include "Riostream.h"
#endif

#ifndef ROOT_TClass
#include "TClass.h"
#endif

#ifndef ROOT_TObject
#include "TObject.h"
#endif

#ifndef ROOT_TCollection
#include "TCollection.h"
#endif

#ifndef ROOT_TString
#include "TString.h"
#endif

#ifndef ROOT_TROOT
#include "TROOT.h"
#endif

template <class AParamType>
class TParameter : public TObject {

public:
   // Defines options / status while merging:
   enum EStatusBits { kMultiply   = BIT(16),    // Use multiplication
                      kMax        = BIT(17),    // Take max value
                      kMin        = BIT(18),    // Take min value
                      kFirst      = BIT(19),    // Take the first value
                      kLast       = BIT(20),    // Take the last value
                      kIsConst    = BIT(21)     // Set if all values are equal
   };

private:
   TString     fName;
   AParamType  fVal;

   void        Reset() { ResetBit(kMultiply); ResetBit(kMax); ResetBit(kMin);
                         ResetBit(kFirst); ResetBit(kLast); }

public:
   TParameter(): fVal() { Reset(); SetBit(kIsConst); }
   TParameter(const char *name, const AParamType &val)
             : fName(name), fVal(val) { Reset(); SetBit(kIsConst);}
   TParameter(const char *name, const AParamType &val, char mergemode)
             : fName(name), fVal(val) { SetMergeMode(mergemode); SetBit(kIsConst);}
   ~TParameter() { }

   const char       *GetName() const { return fName; }
   const AParamType &GetVal() const { return fVal; }
   Bool_t            IsConst() const { return (TestBit(kIsConst) ? kTRUE : kFALSE); }
   void              SetVal(const AParamType &val) { fVal = val; }

   // Merging modes:
   //  '+'             addition ('OR' for booleans)               [default]
   //  '*'             multiplication ('AND' for booleans)
   //  'M'             maximum ('OR' for booleans)
   //  'm'             minimum ('AND' for booleans)
   //  'f'             first value
   //  'l'             last value
   void  SetMergeMode(char mergemode = '+') {
      Reset();
      if (mergemode == '*') {
         SetBit(kMultiply);
      } else if (mergemode == 'M') {
         SetBit(kMax);
      } else if (mergemode == 'm') {
         SetBit(kMin);
      } else if (mergemode == 'f') {
         SetBit(kFirst);
      } else if (mergemode == 'l') {
         SetBit(kLast);
      }
   }
   virtual ULong_t  Hash() const { return fName.Hash(); }
   virtual Bool_t   IsSortable() const { return kTRUE; }
   virtual Int_t    Compare(const TObject *obj) const {
      // Compare two TParameter objects. Returns 0 when equal, -1 when this is
      // smaller and +1 when bigger (like strcmp).

      if (this == obj) return 0;
      return fName.CompareTo(obj->GetName());
   }

   virtual void ls(Option_t *) const {
      // Print this parameter content
      TROOT::IndentLevel();
      std::cout << "OBJ: " << IsA()->GetName() << "\t" << fName << " = " << fVal << std::endl;
   }

   virtual void Print(Option_t *) const {
      // Print this parameter content
      TROOT::IndentLevel();
      std::cout << IsA()->GetName() << "\t" << fName << " = " << fVal << std::endl;
   }

   virtual Int_t Merge(TCollection *in);

   ClassDef(TParameter,2)  //Named templated parameter type
};

template <class AParamType>
inline Int_t TParameter<AParamType>::Merge(TCollection *in) {
   // Merge objects in the list.
   // Returns the number of objects that were in the list.
   TIter nxo(in);
   Int_t n = 0;
   while (TObject *o = nxo()) {
      TParameter<AParamType> *c = dynamic_cast<TParameter<AParamType> *>(o);
      if (c) {
         // Check if constant
         if (fVal != c->GetVal()) ResetBit(kIsConst);
         if (TestBit(kMultiply)) {
            // Multiply
            fVal *= c->GetVal();
         } else if (TestBit(kMax)) {
            // Take max
            if (c->GetVal() > fVal) fVal = c->GetVal();
         } else if (TestBit(kMin)) {
            // Take min
            if (c->GetVal() < fVal) fVal = c->GetVal();
         } else if (TestBit(kLast)) {
            // Take the last
            fVal = c->GetVal();
         } else if (!TestBit(kFirst)) {
            // Add, if not asked to take the first
            fVal += c->GetVal();
         }
         n++;
      }
   }

   return n;
}

// Specialization of Merge for Bool_t
template <>
inline Int_t TParameter<Bool_t>::Merge(TCollection *in)
{
   // Merge bool objects in the list.
   // Returns the number of objects that were in the list.
   TIter nxo(in);
   Int_t n = 0;
   while (TObject *o = nxo()) {
      TParameter<Bool_t> *c = dynamic_cast<TParameter<Bool_t> *>(o);
      if (c) {
         // Check if constant
         if (fVal != (Bool_t) c->GetVal()) ResetBit(kIsConst);
         if (TestBit(TParameter::kMultiply) || TestBit(kMin)) {
            // And
            fVal &= (Bool_t) c->GetVal();
         } else if (TestBit(kLast)) {
            // Take the last
            fVal = (Bool_t) c->GetVal();
         } else if (!TestBit(kFirst) || TestBit(kMax)) {
            // Or
            fVal |= (Bool_t) c->GetVal();
         }
         n++;
      }
   }

   return n;
}

#endif
 TParameter.h:1
 TParameter.h:2
 TParameter.h:3
 TParameter.h:4
 TParameter.h:5
 TParameter.h:6
 TParameter.h:7
 TParameter.h:8
 TParameter.h:9
 TParameter.h:10
 TParameter.h:11
 TParameter.h:12
 TParameter.h:13
 TParameter.h:14
 TParameter.h:15
 TParameter.h:16
 TParameter.h:17
 TParameter.h:18
 TParameter.h:19
 TParameter.h:20
 TParameter.h:21
 TParameter.h:22
 TParameter.h:23
 TParameter.h:24
 TParameter.h:25
 TParameter.h:26
 TParameter.h:27
 TParameter.h:28
 TParameter.h:29
 TParameter.h:30
 TParameter.h:31
 TParameter.h:32
 TParameter.h:33
 TParameter.h:34
 TParameter.h:35
 TParameter.h:36
 TParameter.h:37
 TParameter.h:38
 TParameter.h:39
 TParameter.h:40
 TParameter.h:41
 TParameter.h:42
 TParameter.h:43
 TParameter.h:44
 TParameter.h:45
 TParameter.h:46
 TParameter.h:47
 TParameter.h:48
 TParameter.h:49
 TParameter.h:50
 TParameter.h:51
 TParameter.h:52
 TParameter.h:53
 TParameter.h:54
 TParameter.h:55
 TParameter.h:56
 TParameter.h:57
 TParameter.h:58
 TParameter.h:59
 TParameter.h:60
 TParameter.h:61
 TParameter.h:62
 TParameter.h:63
 TParameter.h:64
 TParameter.h:65
 TParameter.h:66
 TParameter.h:67
 TParameter.h:68
 TParameter.h:69
 TParameter.h:70
 TParameter.h:71
 TParameter.h:72
 TParameter.h:73
 TParameter.h:74
 TParameter.h:75
 TParameter.h:76
 TParameter.h:77
 TParameter.h:78
 TParameter.h:79
 TParameter.h:80
 TParameter.h:81
 TParameter.h:82
 TParameter.h:83
 TParameter.h:84
 TParameter.h:85
 TParameter.h:86
 TParameter.h:87
 TParameter.h:88
 TParameter.h:89
 TParameter.h:90
 TParameter.h:91
 TParameter.h:92
 TParameter.h:93
 TParameter.h:94
 TParameter.h:95
 TParameter.h:96
 TParameter.h:97
 TParameter.h:98
 TParameter.h:99
 TParameter.h:100
 TParameter.h:101
 TParameter.h:102
 TParameter.h:103
 TParameter.h:104
 TParameter.h:105
 TParameter.h:106
 TParameter.h:107
 TParameter.h:108
 TParameter.h:109
 TParameter.h:110
 TParameter.h:111
 TParameter.h:112
 TParameter.h:113
 TParameter.h:114
 TParameter.h:115
 TParameter.h:116
 TParameter.h:117
 TParameter.h:118
 TParameter.h:119
 TParameter.h:120
 TParameter.h:121
 TParameter.h:122
 TParameter.h:123
 TParameter.h:124
 TParameter.h:125
 TParameter.h:126
 TParameter.h:127
 TParameter.h:128
 TParameter.h:129
 TParameter.h:130
 TParameter.h:131
 TParameter.h:132
 TParameter.h:133
 TParameter.h:134
 TParameter.h:135
 TParameter.h:136
 TParameter.h:137
 TParameter.h:138
 TParameter.h:139
 TParameter.h:140
 TParameter.h:141
 TParameter.h:142
 TParameter.h:143
 TParameter.h:144
 TParameter.h:145
 TParameter.h:146
 TParameter.h:147
 TParameter.h:148
 TParameter.h:149
 TParameter.h:150
 TParameter.h:151
 TParameter.h:152
 TParameter.h:153
 TParameter.h:154
 TParameter.h:155
 TParameter.h:156
 TParameter.h:157
 TParameter.h:158
 TParameter.h:159
 TParameter.h:160
 TParameter.h:161
 TParameter.h:162
 TParameter.h:163
 TParameter.h:164
 TParameter.h:165
 TParameter.h:166
 TParameter.h:167
 TParameter.h:168
 TParameter.h:169
 TParameter.h:170
 TParameter.h:171
 TParameter.h:172
 TParameter.h:173
 TParameter.h:174
 TParameter.h:175
 TParameter.h:176
 TParameter.h:177
 TParameter.h:178
 TParameter.h:179
 TParameter.h:180
 TParameter.h:181
 TParameter.h:182
 TParameter.h:183
 TParameter.h:184
 TParameter.h:185
 TParameter.h:186
 TParameter.h:187
 TParameter.h:188
 TParameter.h:189
 TParameter.h:190
 TParameter.h:191
 TParameter.h:192
 TParameter.h:193