```// @(#)root/mathcore:\$Id\$
// Authors: W. Brown, M. Fischler, L. Moneta    2005

/**********************************************************************
*                                                                    *
* Copyright (c) 2005 , LCG ROOT MathLib Team  and                    *
*                                                                    *
*                                                                    *
**********************************************************************/

// Header file for class Cylindrica3D
//
// Created by: Lorenzo Moneta  at Tue Dec 06 2005
//
//
#ifndef ROOT_Math_GenVector_Cylindrical3D
#define ROOT_Math_GenVector_Cylindrical3D  1

#ifndef ROOT_Math_Math
#include "Math/Math.h"
#endif

#ifndef ROOT_Math_GenVector_eta
#include "Math/GenVector/eta.h"
#endif

#include <limits>

namespace ROOT {

namespace Math {

//__________________________________________________________________________________________
/**
Class describing a cylindrical coordinate system based on rho, z and phi.
The base coordinates are rho (transverse component) , z and phi
Phi is restricted to be in the range [-PI,PI)

@ingroup GenVector
*/

template <class T>
class Cylindrical3D {

public :

typedef T Scalar;

/**
Default constructor with rho=z=phi=0
*/
Cylindrical3D() : fRho(0), fZ(0), fPhi(0) {  }

/**
Construct from rho eta and phi values
*/
Cylindrical3D(Scalar rho, Scalar zz, Scalar phi) :
fRho(rho), fZ(zz), fPhi(phi) { Restrict(); }

/**
Construct from any Vector or coordinate system implementing
Rho(), Z() and Phi()
*/
template <class CoordSystem >
explicit Cylindrical3D( const CoordSystem & v ) :
fRho( v.Rho() ),  fZ( v.Z() ),  fPhi( v.Phi() ) { Restrict(); }

// for g++  3.2 and 3.4 on 32 bits found that the compiler generated copy ctor and assignment are much slower
// re-implement them ( there is no no need to have them with g++4)

/**
copy constructor
*/
Cylindrical3D(const Cylindrical3D & v) :
fRho(v.Rho() ),  fZ(v.Z() ),  fPhi(v.Phi() )  {   }

/**
assignment operator
*/
Cylindrical3D & operator= (const Cylindrical3D & v) {
fRho = v.Rho();
fZ   = v.Z();
fPhi = v.Phi();
return *this;
}

/**
Set internal data based on an array of 3 Scalar numbers ( rho, z , phi)
*/
void SetCoordinates( const Scalar src[] )
{ fRho=src[0]; fZ=src[1]; fPhi=src[2]; Restrict(); }

/**
get internal data into an array of 3 Scalar numbers ( rho, z , phi)
*/
void GetCoordinates( Scalar dest[] ) const
{ dest[0] = fRho; dest[1] = fZ; dest[2] = fPhi; }

/**
Set internal data based on 3 Scalar numbers ( rho, z , phi)
*/
void SetCoordinates(Scalar  rho, Scalar  zz, Scalar  phi)
{ fRho=rho; fZ=zz; fPhi=phi; Restrict(); }

/**
get internal data into 3 Scalar numbers ( rho, z , phi)
*/
void GetCoordinates(Scalar& rho, Scalar& zz, Scalar& phi) const
{rho=fRho; zz=fZ; phi=fPhi;}

private:
inline static Scalar pi() { return M_PI; }
inline void Restrict() {
if ( fPhi <= -pi() || fPhi > pi() )
fPhi = fPhi - std::floor( fPhi/(2*pi()) +.5 ) * 2*pi();
return;
}
public:

// accessors

Scalar Rho()   const { return fRho; }
Scalar Z()     const { return fZ;   }
Scalar Phi()   const { return fPhi; }

Scalar X()     const { return fRho*std::cos(fPhi); }
Scalar Y()     const { return fRho*std::sin(fPhi); }

Scalar Mag2()  const { return fRho*fRho + fZ*fZ;   }
Scalar R()     const { return std::sqrt( Mag2());  }
Scalar Perp2() const { return fRho*fRho;           }
Scalar Theta() const { return (fRho==0 && fZ==0 ) ? 0 : atan2(fRho,fZ); }

// pseudorapidity - use same implementation as in Cartesian3D
Scalar Eta() const {
return Impl::Eta_FromRhoZ( fRho, fZ);
}

// setters (only for data members)

/**
set the rho coordinate value keeping z and phi constant
*/
void SetRho(T rho) {
fRho = rho;
}

/**
set the z coordinate value keeping rho and phi constant
*/
void SetZ(T zz) {
fZ = zz;
}

/**
set the phi coordinate value keeping rho and z constant
*/
void SetPhi(T phi) {
fPhi = phi;
Restrict();
}

/**
set all values using cartesian coordinates
*/
void SetXYZ(Scalar x, Scalar y, Scalar z);

/**
scale by a scalar quantity a --
for cylindrical coords only rho and z change
*/
void Scale (T a) {
if (a < 0) {
Negate();
a = -a;
}
fRho *= a;
fZ *= a;
}

/**
negate the vector
*/
void Negate ( ) {
fPhi = ( fPhi > 0 ? fPhi - pi() : fPhi + pi() );
fZ = -fZ;
}

// assignment operators
/**
generic assignment operator from any coordinate system implementing Rho(), Z() and Phi()
*/
template <class CoordSystem >
Cylindrical3D & operator= ( const CoordSystem & c ) {
fRho = c.Rho();
fZ   = c.Z();
fPhi = c.Phi();
return *this;
}

/**
Exact component-by-component equality
*/
bool operator==(const Cylindrical3D & rhs) const {
return fRho == rhs.fRho && fZ == rhs.fZ && fPhi == rhs.fPhi;
}
bool operator!= (const Cylindrical3D & rhs) const
{return !(operator==(rhs));}

// ============= Compatibility section ==================

// The following make this coordinate system look enough like a CLHEP
// vector that an assignment member template can work with either
T x() const { return X();}
T y() const { return Y();}
T z() const { return Z(); }

// ============= Specializations for improved speed ==================

// (none)

#if defined(__MAKECINT__) || defined(G__DICTIONARY)

// ====== Set member functions for coordinates in other systems =======

void SetX(Scalar x);

void SetY(Scalar y);

void SetEta(Scalar eta);

void SetR(Scalar r);

void SetTheta(Scalar theta);

#endif

private:

T fRho;
T fZ;
T fPhi;

};

} // end namespace Math

} // end namespace ROOT

// move implementations here to avoid circle dependencies

#ifndef ROOT_Math_GenVector_Cartesian3D
#include "Math/GenVector/Cartesian3D.h"
#endif

#if defined(__MAKECINT__) || defined(G__DICTIONARY)
#ifndef ROOT_Math_GenVector_GenVector_exception
#include "Math/GenVector/GenVector_exception.h"
#endif
#ifndef ROOT_Math_GenVector_CylindricalEta3D
#include "Math/GenVector/CylindricalEta3D.h"
#endif
#ifndef ROOT_Math_GenVector_Polar3D
#include "Math/GenVector/Polar3D.h"
#endif
#endif

namespace ROOT {

namespace Math {

template <class T>
void Cylindrical3D<T>::SetXYZ(Scalar xx, Scalar yy, Scalar zz) {
*this = Cartesian3D<Scalar>(xx, yy, zz);
}

#if defined(__MAKECINT__) || defined(G__DICTIONARY)

// ====== Set member functions for coordinates in other systems =======

template <class T>
void Cylindrical3D<T>::SetX(Scalar xx) {
GenVector_exception e("Cylindrical3D::SetX() is not supposed to be called");
throw e;
Cartesian3D<Scalar> v(*this); v.SetX(xx); *this = Cylindrical3D<Scalar>(v);
}
template <class T>
void Cylindrical3D<T>::SetY(Scalar yy) {
GenVector_exception e("Cylindrical3D::SetY() is not supposed to be called");
throw e;
Cartesian3D<Scalar> v(*this); v.SetY(yy); *this = Cylindrical3D<Scalar>(v);
}
template <class T>
void Cylindrical3D<T>::SetR(Scalar r) {
GenVector_exception e("Cylindrical3D::SetR() is not supposed to be called");
throw e;
Polar3D<Scalar> v(*this); v.SetR(r);
*this = Cylindrical3D<Scalar>(v);
}
template <class T>
void Cylindrical3D<T>::SetTheta(Scalar theta) {
GenVector_exception e("Cylindrical3D::SetTheta() is not supposed to be called");
throw e;
Polar3D<Scalar> v(*this); v.SetTheta(theta);
*this = Cylindrical3D<Scalar>(v);
}
template <class T>
void Cylindrical3D<T>::SetEta(Scalar eta) {
GenVector_exception e("Cylindrical3D::SetEta() is not supposed to be called");
throw e;
CylindricalEta3D<Scalar> v(*this); v.SetEta(eta);
*this = Cylindrical3D<Scalar>(v);
}

#endif

} // end namespace Math

} // end namespace ROOT

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