I have managed to compile and link the more useful parts of CLHEP into
a shared library, which can be loaded into root. It contains the following
pieces:
Hep3Vector, HepRotation HepTranslation HepTransformation, HepPoint
HepLorentzVector, HepLorentzRotation
HepGenMatrix HepMatrix HepSymMatrix HepDiagMatrix HepVector
HepAList<T>, HepConstAList<T>, HepAListR<T>
HepAIterator<T>, ConstAIterator<T>
The 3 and Lorentzvectors together with the transformation classes provide
a quite complete command set for many calculation typical in HEP.
The HepMatrix and Co. classes contain a convenient set of linear algebra
functions including inversion, diagonalisation and solving of sets of
linear equations. Compared to the root-matrix classes one wins on ease of
use (IMHO) and the lack of efficiency doesn't really matter for small to
medium scale computations performed on the command line or in a macro.
For large computations in batch jobs one might suffer from a performance
penalty.
The CLHEP template based lists and corresponding iterators can be used
only with instantiated templates in a separate precompiled shared library.
The template class HepAListR<T> is ready for root-IO, such that one can
write lists of any root-streamable objects to root files.
The CLHEP package can be found in by anonymous ftp to persil.lbl.gov in
pub/CLHEP-root. You find there also an example application of using the
HepAListR<T> template container to contruct a ntuple-like tree in the
archive streamCLHEP.tar.gz.
Please let me know of any comments, questions or additions you might have.
cheers, Stefan
PS: Below I append my root-template-howto:
It is possible to fully link precompiled instantiated template classes
into root by following this recipie:
1) Insert the macros ClassDefT and ClassImpT in place of the normal
root macros ClassDef and ClassImp in your template class code.
Here is the ClassDefT and ClassImpT macro defintion I use:
#define ClassDefT(name,id) \
private: \
static TClass *fgIsA; \
public: \
static const char *DeclFileName() { return __FILE__; } \
static int DeclFileLine() { return __LINE__; } \
static const char *ImplFileName(); \
static int ImplFileLine(); \
static Version_t Class_Version() { return id; } \
static TClass *Class(); \
static const char* SetClassName(); \
static void Dictionary(); \
virtual TClass *IsA() const { return name::Class(); } \
virtual void ShowMembers(TMemberInspector &insp, char *parent); \
virtual void Streamer(TBuffer &b); \
friend TBuffer &operator>> (TBuffer &buf, name *&obj);
#define _ClassImpT_(name,Tmpl) \
template <class Tmpl> TClass* name<Tmpl>::Class() \
{ if (!fgIsA) name<Tmpl>::Dictionary(); return fgIsA; } \
template <class Tmpl> const char* name<Tmpl>::ImplFileName() \
{ return __FILE__; } \
template <class Tmpl> int name<Tmpl>::ImplFileLine() { return __LINE__; } \
template <class Tmpl> TClass* name<Tmpl>::fgIsA = 0;
// Don't know how to deal with this yet
// _ClassInit_(name)
#define ClassImpT(name,Tmpl) \
template <class Tmpl> void name<Tmpl>::Dictionary() { \
TClass *c = CreateClass(SetClassName(), Class_Version(), \
DeclFileName(), ImplFileName(), \
DeclFileLine(), ImplFileLine()); \
fgIsA = c; \
} \
_ClassImpT_(name,Tmpl)
#endif
These could in principle be part of Rtypes.h. For the moment you will
have to put these in a private additional header file. The main difference
is the additional member function SetClassName() and the insertion of
"template <class Tmpl>" in front of member functions which depend on
the template parameter.
I could not work out how to extend the statements in the macro
_ClassInit_(name), so I just don't use it. Empirically, it doesn't
seem to do any harm.
2) Produce some "application code", which instantiates the templates
you want to use in root. For example, a piece of code containing the
line
HepAListR<HepLorentzVector> vl;
will result in the instantiation of HepAListR<HepLorentzVector>. A simple
but complete example is provided in the package streamCLHEP.tar.gz
3) Proceed as usual, i.e. create a linkdef.h file with a line for every
template instantiation you need, e.g.
#pragma link C++ class HepAListR<HepLorentzVector>-;
The "-" is there, because the streamable HepAListR<T> has a custom
Streamer method. Now run rootcint in the usual way. This will produce
the defintions for some of the functions declared above in the macros
separately for every template instantiation.
The definition for SetClassName() is produced by a special program which
is run directly after the rootcint step. It produces e.g.
// Set the class name for HepAList<HepLorentzVector>:
const char* HepAListR<HepLorentzVector>::SetClassName() {
return "HepAListR<HepLorentzVector>";
}
This step could be done by rootcint itself, of course. An example of the
program can be found in the CLHEP-root package CLHEP.tar.gz as clhepcint.cc.
4) Compile and link your "application code" together with the output
from running rootcint and clhepcint into a shared lib in the usual way.
5) Start root and load the shared lib. Now you can use your instantiated
template as a type and for example do:
root [1] HepAListR<HepLorentzVector> vlist;
root [2] HepLorentzVector l1=(1,2,3,4);
root [3] HepLorentzVector l2=(5,6,7,8);
root [4] vlist.append( l1 );
root [4] vlist.append( l2 );
---Stefan Kluth---------------Lynen Fellow----------------|\--|\-------
- LBNL, MS 50A 2160 - phone: +1 510 495 2376 - |/ |/ -
- 1 Cyclotron Rd. - fax: +1 510 495 2957 - |\/\|\/\|' -
---Berkeley, CA94720, USA-----e-mail: SKluth@lbl.gov------|/\/|/\/|----