The isNear() Mechanism
For all objects in these classes, the operators ==
and == have
obvious meanings, in terms of exact equality.
However, when working with actual vectors, it is useful to have a looser
criterion for practical equality.
And boolean methods such as isOrthogonal()
are more certainly useful if they allow for some tolerance.
The methods in the PhysicsVectors package
support checking for
equality within a given relative tolerance using these rules:
-
For each object, the exact
== comparision is supplemented by
an isNear()
method, which takes an object of the same class and returns a bool
result (true or false). For example,
SpaceVector v1, v2;
if ( v1.isNear(v2) ) { /* do whatever */ }
-
The meaning of isNear() is dependent upon some relative
tolerance:
An optional last argument to all such functions is a relative
error which we will call
tolerance.
Normally this would be omitted, in which case it defaults to a universal
tolerance which will be 100 times the machine epsilon.
SpaceVectors and UnitVectors
Ordinary 3-vectors are supported via the
SpaceVector class.
Directions in 3-space are supported via the
UnitVector class.
Where only a direction is needed, methods are supplied to take advantage
of the knowledge that a UnitVector has magnitude 1.
However,
there is a conversion constructor, valid for any non-zero
SpaceVector, to a UnitVector, so anywhere a UnitVector, a
SpaceVector may be substitued.
Vector Coordinates
This package recognizes three forms of coordinates: Cartesian (x, y, z),
Polar (r, theta, phi), and Cylindrical (rho, phi, z).
A SpaceVector may be constructed using any of these forms.
A given component may be read off in any of these coordinate systems.
And a given component may be set while keeping the other two components in that
coordinate system fixed.
| Components |
Meaning |
| x, y, z |
Cartesian Coordinates |
| r, theta, phi |
(Spherical) polar coordinates |
| rho, phi, z |
Cylindrical coordinates |
Scalar x, y, z, r, theta, phi, rho;
SpaceVector v1( x, y, z );
SpaceVector v2( r, theta, RADIANS, phi, RADIANS );
SpaceVector v3( rho, phi, RADIANS, z );
Scalar c1, c2, c3, r, pa, aa, rho;
c1 = v.x(); c2 = v.y(); c3 = v.z();
c1 = v.r(); pa = v.theta(); aa = v.phi();
c1 = v.rho(); aa = v.phi(); c3 = v.z(); // only rho() is new
v.x() = c1; v.y() = c2; v.z() = c3;
v.r() = r; v.theta() = pa; v.phi() = aa;
v.rho() = rho;
Notice the funny-looking keyword RADIANS in the example.
This is an
argument which
serves to distinguish one signature of constructor from another.
Instead of RADIANS you can substitute
DEGREES or
(when supplying theta) ETA.
UnitVector
is a class that inherits from SpaceVector, but some methods of
SpaceVector which don't
make sense for unit vectors are made private to flag their use as an error at
compile time.
UnitVectors may be constructed from a non-zero SpaceVector, or by supplying the
polar (theta, phi).
Scalar theta, phi;
UnitVector u1( theta DEGREES, phi, RADIANS );
SpaceVector Operations and Properties
SpaceVectors form a vector space (well, duh?!):
Supported operations on SpaceVector
include assignment, unary minus, multiplication (left or right) and
division by a Scalar, and addition/subtraction of two SpaceVectors.
v1 = v2 + c*v3; v1 = v2 - v3*c; v1 = v2 - v3/c;
v1 *= c; v1 += v2; v1 -= v2;
UnitVectors do not form a vector space; they may be multiplied by
a Scalar or added tegether, but the result is an ordinary SpaceVector.
There are methods representing the usual binary 3-vector operations:
Dot and cross products. There are also logical tests for whether vectors are
parallel or orthogonal.
Scalar v1.dot(v2)
SpaceVector v1.cross(v2)
Scalar v1.diff2(v2) // squared difference
bool v1.isNear(v2)
bool v1.parallel(v2)
bool v1.orthogonal(v2)
The boolean methods test for near-alignment with a relative tolerance
rather than perfect alignment.
The SpaceVector class provides a variety of methods returning numerical
properties of a single vector:
Scalar v.mag(), Scalar v.mag2()
Scalar v.beta(), Scalar v.gamma()
SpaceVector v.unit()
There are also methods returning properties of a vector,
or performing operations on two vectors,
with respect to some reference direction.
Typically the physicist wants these properties
relative to the Z direction.
We call these ``z-implied'' methods:
The reference direction is usually omitted, and the Z axis is assumed.
This example shows a signature using a reference direction only in the
most commonly used case: The angle between a vecotr and a direction.
Scalar v.perp() Scalar v.perp2()
Scalar v.angle() v.angle(dir)
Scalar v.cosTheta() Scalar v.cos2Theta()
Scalar v.eta() Scalar v.rapidity()
SpaceVector v.project() SpaceVector v.perpPart()
Scalar v.azimAngle(v2) Scalar v.polarAngle(v2)
See the Formulas and Definitions document for precise
meanings of these methods, particularly rapidity and angular decomposition.
Transformations by Rotating
The SpaceVector class, which has no knowledge of the
Rotation class,
contains methods to rotate this vector by some amount specified in
the method arguments.
The class has methods which rotate the vector itself --
v.applyRotation() --
as well as methods which return a new vector
leaving the original unchanged --
v2=v.rotated().
The rotation may be specified in terms of an axis and angle of rotation, or
by specifying a set of Euler Angles.
Rotation about one of the coordinate axes is a special case; methods are
provided to take advantage of the simpler form of operation.
SpaceVector v.rotated.(Scalar phi, Scalar theta, Scalar psi);
SpaceVector v.rotated.(UnitVector dir, Scalar delta);
SpaceVector v.rotatedX.(Scalar delta);
SpaceVector v.rotatedY.(Scalar delta);
SpaceVector v.rotatedZ.(Scalar delta);
v.applyRotation.(Scalar phi, Scalar theta, Scalar psi);
v.applyRotation.(UnitVector dir, Scalar delta);
v.applyRotationX.(Scalar delta);
v.applyRotationY.(Scalar delta);
v.applyRotationZ.(Scalar delta);
LorentzVectors
4-vectors in Minkowski space are supported via the
LorentzVector class.
| Components |
Meaning |
x, y, z, t t, x, y, z |
Cartesian Coordinates
(time component must be a
Tcomponent and may be
placed first or last) |
v, t t, v |
SpaceVector and time component
(supplied as a Tcomponent
or as a Scalar |
| t |
Time component only
(for particle at rest) |
When constructing or setting a
LorentzVector
from four cartesian components, one could be confused as to
whether to supply (x, y, z, t) or (t, x, y, z).
To eliminate possible accidents,
the signature for such methods takes
three Scalars x, y, and z, and an instance of Tcomponent
for t.
LorentzVector w ( 1, 3, 5, Tcomponent(40) ); // Preferred
LorentzVector w ( Tcomponent(40), 1, 3, 5 ); // Also accepted
LorentzVector w ( 40, 1, 3, 5 ); // Nope. No such signature.
Constructors for are also provided taking
a SpaceVector and a time component,
or just a
time component for a particle at rest.
Access is supported for these forms of components.
LorentzVector w(SpaceVector v, Tcomponent t);
LorentzVector w(SpaceVector v, Scalar t); // OK
LorentzVector w(Tcomponent t); // (0,0,0,t)
LorentzVector w(Scalar t); // (0,0,0,t) // OK
Scalar x = w.x(); Scalar x = w.y();
Scalar z = w.z(); Scalar t = w.t();
SpaceVector v = w.v(); v = w.getV();
w.set(Tcomponent t, Scalar x, Scalar y, Scalar z);
w.set(Scalar x, Scalar y, Scalar z, Tcomponent t);
w.x() = x; w.y() = y; w.z() = z; w.t() = t;
As shown,
in cases where no ambiguity would result, a Scalar value of t
may be used in place of the
Tcomponent.
LorentzVector Operations and Properties
Supported operations on LorentzVectors
include assignment, unary minus, multiplication (left or right) and
division by a Scalar, and addition/subtraction of two LorentzVectors.
w1 = w2 + c*w3; w1 = w2 - w3*c; w1 = w2 - w3/c;
w1 *= c; w1 += w2; w1 -= w2; w2 = -w1;
The dot product is supported; by default, a (- - - +) metric applies.
That is, if w is timelike, w.dot(w) will be positive.
LorentzVector w, w1;
Scalar x = w.dot(w1); /* Metric-dependant */
Scalar x = w.diff2(w1); /* Metric-dependant */
Scalar x = w.delta2Euclidean(w1);
bool b = w.isNear(w1); bool b = w.isNearCM(w1);
bool b = w.isParallel(w1);
Notice that isNearCM(), a Lorentz-invariant test for
near-equality in the center-of-mass
frame--applicable only to timelike LorentzVectors--is provided along with the
Euclidean-norm method isNear().
The mathematical meanings of near-equivalence and isParallel are
listed in the Formulas and Definitions document.
There are three special boolean methods isTimelike(),
isLightlike(), and isSpacelike(),
and {\tt isTimelike()},
which test whether the squared norm w.dot(w)
is positive, zero, or negative.
The isLightlike() method implies a check for equality,
and therefore uses a tolerance as described in the section about
isNear().
Several other simple property methods are provided as well:
LorentzVector w;
bool b = w.isSpacelike(); b = w.isLightlike(); b = w.isTimelike();
Scalar x = w.mag2(); /* w.dot(w) -- Metric-dependant */
Scalar w.plus(); Scalar w.minus(); /* t + z and t - z */
Scalar w. euclideanNorm2(); Scalar w.euclideanNorm()
4-Vector Kinematics
Methods implementing useful kinematic concepts are provided.
These methods all return results independent of the choice of metric.
There are kinematic functions relating to the boost it
would take to bring a particle at rest into having some specified
LorentzVector as its 4-momentum.
These return the relativistic beta, gamma, and
boostVector,
the SpaceVector
which when used as a boost would make this transformation.
There are also methods to extract the rest mass, and the invariant mass of
a pair or a list of \LV s.
Pseudorapidity and rapidity are computed with respect to some reference
direction, which defaults to the Z direction; see the Formulas and
Definitions document for precise meanings.
Scalar restMass2() Scalar restMass()
LorentzVector rest4Vector() /* ( 0, 0, 0, restMass() ) */
SpaceVector boostVector()
Scalar eta() Scalar rapidity()
Scalar w1.invariantMass(w2) Scalar w1.invariantMass2(w2)
SpaceVector w1.findBoostToCM(w2) /* boost to joint CM frame */
These important concepts are also provided for standard containers of
LorentzVectors:
list<LorentzVector> w_list;
Float8 m = w_list.invariantMass();
Rotations and Boosts of LorentzVectors
The LorentzVector
class contains methods to transform the vector by some amount
specified in the method arguments:
A LorentzVector may be rotated by in the same manner as a SpaceVector,
leaving the time component intact.
And a LorentzVector may be boosted by some fraction beta
of the speed of light
along one of the three space axes or in a
given direction, or by some SpaceVector with magnitude less than 1, which is
treated as a velocity (in units where $c = 1$).
The class has methods that rotate the 4-vector itself
(v.applyRotation()
and v.applyBoost())
as well as methods that
return a new 4-vector leaving the original unchanged
(v2 = v.rotated() and
v2 = v.boosted().
Rotation about one of the coordinate axes, or boosts along a coordinate axis,
are special cases; methods are
provided to take advantage of the simpler form of these operations.
LorentzVector w, w2;
UnitVector dir;
w2 = w.boosted(UnitVector dir, Scalar beta);
w2 = w.boosted(SpaceVector v);
w2 = w.boostedX(beta); w2 = w.boostedY(beta); w2 = w.boostedZ(beta);
Scalar phi;
w2 = w.rotated(UnitVector dir, phi);
w2 = w.rotatedX(phi); w2 = w.rotatedY(phi); w2 = w.rotatedZ(phi);
Rotations
This package deals with Rotations
(and LorentzTransformations)
as objects, representing members of a group.
Thus you can construct a Rotation of some value,
multiply two Rotations
to produce a third, and invert a Rotation.
The Rotation and LorentzTransformation classes are not yet released.
This section and the next should be read for generalities and not details.
A Rotation is conceptually a re-orientation all of space with respect to
the axes of some fixed coordinate system, which when applied to
a SpaceVector will modify the coordinates of the vector.
That is, we are talking about active rotations (and later boosts),
rather than transformations of the reference frame.
A Rotation can be represented by a real, orthogonal matrix with
determinant +1.
Combining two Rotations is represented by multiplying their matrices.
Constructing and Accessing Rotations
A Rotation can be constructed as an angle of rotation about an axis direction
(as always, a SPaceVector may be substituted for the \Direction),
or in terms of Euler Angles.
Also, you may construct a Rotation by supplying three orthogonal UnitVectors
to use as its rows.
The value of a Rotation may be obtained in any of those forms, and also
in the form of individual components of the matrix representing the
Rotation.
| Components |
Meaning |
| phi, theta, psi |
Individual Euler Angles |
| eulerAngles |
A struct holding the three Euler Angles |
| axis, delta |
axis and angle of rotation about that axis |
| axisAngle |
A struct holding a UnitVector axis and angle of rotation |
| colX, colY, colZ |
three orthogonal UnitVectors |
As is the case for vectors, methods are supplied to set one "component" of a
Rotation keeping the remaing ones fixed.
But here by "component" we mean
one argument to a possible constructor of Rotation, keeping the other arguments
in that constructor fixed.
The default constructor sets the \Rotation\ to the identity rotation.
The package also provides a static constant Rotation::IDENTITY.
Rotation r0 (); ASSERT (r0 == Rotation::IDENTITY);
Rotation r1 ( SpaceVector(1,2,3), .02 ); // axis and delta
Rotation r2 ( PI/4, PI/3, PI/6 ); // Euler angles phi, theta, psi
EulerAngles ex (phi, theta, psi);
Rotation r4 (ex);
UnitVector v = r1.axis(); // unit vector
Scalar angle = r1.delta(); // Angle of rotation about an axis
Scalar psi = r1.psi(); // Euler psi (==angle psi around axis)
Scalar theta = r1.theta(); // Will always be <= 90 degrees
Scalar phi = r1.phi();
r.setDelta(Scalar delta); // change delta, keep axis fixed
r.setPsi(Scalar psi); // change psi, keep phi, theta fixed
In addition to the forms of components, you can obtain, but cannot
individually change, the values of a row or a element of the
matrix representation of a Rotation.
Rotation r1;
Scalar elem = r1.xx();
elem = r1.tz();
UnitVector u1 = r1.rowY();
u1 = r1.rowT();
Operations in the Rotation Group
The usual assignment operator and comparisons for equality apply to Rotations.
Moreover, a multiplication operator is defined, and Rotations form a group
under this operation.
Multiplication of Rotations is written
using the usual * (or *=) operator.
Inversion of a Rotation, represented by inverting the
orthogonal matrix representation, is provided by the inverse() method.
Note that r1.inverse() produces a result of the inverse of r1;
it does not change r1 itself.
To invert a Rotation in place, use
r1.invert().
Equality (and dictionary ordering) comparison is supported. The
isNear
mechanism is also supported among rotations; see the Formulas and
Definitions document for a precise definition.
Rotation r1, r2, r3;
r3 = r2 * r1;
r2 = r1.inverse();
r3 = r2 * r1;
ASSERT ( r3.isNear(Rotation::IDENTITY));
Applying Rotations
A Rotation may be used as a "functor," applying to a SpaceVector
and yielding a new SpaceVector. The notation reflects this point of view:
Rotation r1;
SpaceVector v1, v2;
v2 = r1(v1);
The application of a Rotation to a SpaceVector may be viewed as left multiplying
the vector representation by the matrix representing that rotation.
Similarly, a Rotation applied to a UnitVector produces a UnitVector,
and a Rotation applied to a LorentzVector produces a LorentzVector.
And a Rotation may be applied an EBvector, rotating each component to
yield a new EBvector.
The * multiplication notation is not used.
Multiplication of a rotation by by a vector on its left is not permitted.
A Rotation may be applied in bulk to each element of a container of
SpaceVectors, UnitVectors, LorentzVectors, or EBvectors.
A new container is returned, each of
whose elements is the corresponding vector in the original, rotated by
the specified Rotation.
The container may be any of the standard container types.
Rotation r1;
list v_list;
list vprime_list = r1(v_list);
Special-case Rotations
The package provides three additional classes, representing rotations around the
X, Y, and Z axes.
RotationX, RotationY, RotationZ,
have internal representations
which are more compact that that for a general Rotation, and the forms of
their constructors are simpler.
Aside from the simpler constructors (and correspondingly simpler {\tt set()}
methods), all methods and signatures available for Rotation
are available
RotationX, RotationY, and RotationZ.
Of course, the implementations will take advantage of the simpler forms, to do
much less work.
RotationX rx1 (.25); // delta is specified in radians, the axis is X
SpaceVector v1, v2;
v2 = rx1(v1);
These specialized rotation objects are defined in
Rotation.h.
Multiplying two rotations--combining two specialized
rotations of different types will give a general \Rotation.
LorentzTransformations
LorentzTransformations
are general combinations of pure rotations and pure
LorentzBoosts.
LorentzTransformations form a group.
Generally, these LorentzTransformations are useful because they
may be applied to a LorentzVector.
mag2() as the original.
A few words of orientation:
We always work with c = 1,
and never consider "tachyonic" transformations.
And in defining Lorentz Transformations we have use the same
"active" viewpoint
as was used in defining rotations: Space (or in this case, spacetime) is
"rotated" by some amount, rather than saying that the new coordinate system is
"rotated" by some amount relative to the old.
A pure boost by beta in the X direction can be represented by a matrix
gamma 0 0 beta*gamma
0 1 0 0
0 0 1 0
beta*gamma 0 0 gamma
LorentzBoosts and Lorentz Transformations
A general LorentzTransformation has six degrees of
freedom; any LorentzTransformation can be expressed as the product
of a rotation and a pure boost
(though this decomposition is not trivial to find.)
However, many (probably most) HEP applications use pure boosts, and not mixed
combinations of rotations and boosts.
Since the operations with a LorentzTransformation known to be a pure boost
can be accomplished with less work than for the general case,
this package supports a class LorentzBoost
representing a pure boost in some direction.
LorentzBoost is on the same footing as Rotation:
Each represents three of the
six degrees of freedom of a general LorentzTransformation.
Other than constructors and component
access,
the same set of methods apply to LorentzBoost
as to the more general LorentzTransformation.
In particular, LorentzBoosts, Rotations, and LorentzTransformations
may be multiplied by
one another, with the obvious form of results:
Boost times boost remains a pure
boost, rotation times rotation remains a pure rotation, and all other
combinations result in a general LorentzTransformation.
The package also provides additional classes, representing pure boosts
along the X, Y, and Z axes.
{\tt LorentzBoostX}, {\tt LorentzBoostY}, {\tt LorentzBoostZ}
have internal representations
which are more compact that that for a general \LB, and the forms of
their constructors are simpler.
Again, aside from the simpler constructors and access methods,
all methods and signatures available for LorentzBoost
and LorentzTransformation are available
for these classes, but implementations will take advantage of the simpler
forms.
All these boost objects are defined in
LorentzTransformation.h.
Constructing and Accessing Lorentz Transformations
A LorentzBoost
can be constructed by supplying a UnitVector direction and beta
between -1 and 1, or by
supplying a SpaceVector of less than unit length to use as the boost vector.
| Components |
Meaning |
| direction, beta |
Boost by beta (|beta| < 1) along direction |
| boostVector |
Pure boost velocity (taking c=1) |
UnitVector dir; SpaceVector bv;
LorentzBoost t1 ( dir, -.04);
LorentzBoost t2 ( bv ); // bv.mag2() must be < 1
The default constructor sets the LorentzBoost to the identity transformation,
which is equivalent to using a boost vector of zero.
A LorentzTransformation
can be constructed as a pure rotation or a pure boost, or by combining
the two (in either order).
It can also be constructed by supplying four LorentzVectors obeying appropriate
conditions.
| Components |
Meaning |
| boostVector, rotation |
Apply rotation, then boost the result |
| boostVector, rotation |
Apply boost, then rotate the result |
| col1, col2, col3, col4 |
Four orthosymplectic Lorentzvectors |
Rotation r1; SpaceVector bv;
LorentzTransformation t3 ( r1 );
LorentzTransformation t4 ( bv );
LorentzTransformation t5 ( bv, r1 ); // t5 = t4*t3
LorentzTransformation t6 ( bv, r1 ); // t6 = t3*t4
LorentzVector lam1, lam2, lam3, lam4;
LorentzTransformation t7 (lam1, lam2, lam3, lam4);
You may, as for t4 in the example,
construct a general LorentzTransformation (instead of a LorentzBoost)
from just its boost vector. Since LorentzBoost supports all the functionality
that LorentzTransformation does, the only case where this is reasonable is if
you anticipate the need
to change the value of t4 to a general transformation later.
The form supplying four LorentzVectors requires that the 4-vectors w1, w2, w3,
and w4 be orthosymplectic:
w1.dot(w2) = w1.dot(w3) = w1.dot(w4) = 0
w2.dot(w3) = w2.dot(w4) = 0
w3.dot(w4) = 0
w1.dot(w1) = w2.dot(w2) = w3.dot(w3) = -1
w4.dot(w4) = 1
There are methods to get and/or modify components of a LorentzBoost:
LorentzBoost lb;
SpaceVector v;
UnitVector u;
Float8 bet;
bet = lb.beta(); lb.beta() = bet;
u = lb.direction(); lb.direction() = u;
v = lb.boostVector(); lb.boostVector() = v;
In addition, all
the access methods available for a general LorentzTransformation
are
available for LorentzBoost (and for Rotation as well), although most of these
are trivial in one respect or another.
Every LorentzTransformation can be expressed as a pure boost
along some direction, followed by a pure rotation (or by a rotation followed
by a boost) and methods are provided to decompose the transformation in this
way.
Rotation r1;
LorentzTransformation t1;
LorentzBoost b1;
t1.decompose(&r1, &b1); // T = R*B
t1.decompose(&b1, &r1); // T = B*R
Finally, one can get (but not change) the rows, columns, or
individual components of the representation
matrix for a LorentzTransformation:
LorentzTransformation t1;
Scalar u;
LorentzVector v;
v = t1.row1(); v = t1.row2(); v = t1.row3(); v = t1.row4();
v = t1.col1(); v = t1.col2(); v = t1.col3(); v = t1.col4();
u = t1.xx(); u = t1.yz(); u = t1.tz(); u = t1.tt();
Combining and Manipulating LorentzTransformations
The usual assignment operator and comparisons for equality apply to
LorentzTransformations.
The group operation among LorentzTransformations is written as multiplication,
using the usual * (or *=) operator.
This multiplication is associative but not commutative.
It may be pictured as matrix multiplication of the matrices
representing the two transformations.
Equality (and dictionary ordering) comparison is supported. The
isNear()
mechanism is also supported among LorentzTransformations;
see the Formulas and Definitions document
for a precise definition of when two Lorentz
transformations are considered to be near one another.
Inversion of a LorentzTransformation, represented by inverting the
matrix representation, is provided by the inverse() method.
t1.inverse() returns a result of the inverse of t1;
it does not change t1 itself.
t1.invert() inverts t1 in place.
LorentzTransformation t1, t2, t3;
t3 = t2 * t1;
t2 = t1.inverse();
t3 = t2 * t1;
ASSERT ( t3.isNear(LorentzTransformation::IDENTITY));
Applying LorentzTransformations
A LorentzTransformation, LorentzBoost or Rotation
may be used as a "functor", applying to a LorentzVector.
The notation reflects this point of view:
LorentzTransformation t1;
LorentzVector w1, w2;
w2 = t1(w1);
The application of a LorentzTransformation
to a LorentzVector may be viewed as left multiplying
the vector representation by the matrix representing that transformation.
An LorentzTransformation may also be applied to an EBvector.
This is mathematically defined as
applying the transformation to the field tensor F and reading
off the new E and B from that transformed tensor.
This of course mixes E and B.
LorentzTransfromation t1;
EBvector eb1, eb2;
eb2 = t1(eb1);
A LorentzTransformation may be applied in bulk to each element of a
container of
LorentzVectors or EBvectors.
A new container is returned, each of
whose elements is the corresponding vector in the original, transformed by
the specified Lorentz transformation.
LorentzTransformation t1;
list w_list;
list wprime_list;
wprime_list = t1(w_list);
The container may be any of the standard container types, or for that matter
any container having the same iterator semantics.
Extended Features
The PhysicsVectors packages implements several feature sets not in the original
concept of the package, buy supplying header and implementation fieles that the
user may optionally include.
- PlaneVector
PlaneVector.h gives the users a 2-component vector class.
- CLHEP Compatibility headers
- HepThreeVector.h
- HepLorentzVector.h
- HepRotation.h
- HepLorentzRotation.h
By including these instead of the original CLHEP headers, the user
can use code that instatiates HepThreeVector, HepLorentzVector, and so
forth without changing code in any other way. The advantage is that
the additional functions of the underlying ZOOM classes are also
available.
- Notational convenience header PhysVec.h.
- LinearAlgebra package coordination header pv-la.h.

ZOOM Home Page -
Fermilab at Work -
Fermilab Home
Mark Fischler
Last modified: June 11, 1998