diff --git a/.github/workflows/root-ci-config/buildconfig/fedora41.txt b/.github/workflows/root-ci-config/buildconfig/fedora41.txt index 41df17ddea7cf..ec779824cbe52 100644 --- a/.github/workflows/root-ci-config/buildconfig/fedora41.txt +++ b/.github/workflows/root-ci-config/buildconfig/fedora41.txt @@ -2,5 +2,7 @@ builtin_zstd=ON builtin_zlib=ON builtin_nlohmannjson=On builtin_vdt=On +experimental_adaptivecpp=ON +experimental_genvectorx=ON pythia8=Off ccache=On diff --git a/.github/workflows/root-ci-config/buildconfig/fedora42.txt b/.github/workflows/root-ci-config/buildconfig/fedora42.txt index b9c895b0a227e..0013f42882ca6 100644 --- a/.github/workflows/root-ci-config/buildconfig/fedora42.txt +++ b/.github/workflows/root-ci-config/buildconfig/fedora42.txt @@ -3,6 +3,8 @@ builtin_unuran=OFF builtin_zlib=ON builtin_zstd=ON ccache=ON +experimental_adaptivecpp=ON +experimental_genvectorx=ON pythia8=OFF unuran=OFF -vdt=OFF +vdt=OFF \ No newline at end of file diff --git a/.github/workflows/root-ci-config/buildconfig/global.txt b/.github/workflows/root-ci-config/buildconfig/global.txt index e40f12788fb65..c1206cfa342b3 100644 --- a/.github/workflows/root-ci-config/buildconfig/global.txt +++ b/.github/workflows/root-ci-config/buildconfig/global.txt @@ -45,6 +45,8 @@ davix=ON dcache=OFF dev=OFF distcc=OFF +experimental_adaptivecpp=OFF +experimental_genvectorx=OFF fail-on-missing=On fcgi=OFF fftw3=ON diff --git a/.github/workflows/root-ci-config/buildconfig/ubuntu2404-cuda.txt b/.github/workflows/root-ci-config/buildconfig/ubuntu2404-cuda.txt index b7b693c1dbcfd..d36538b8c8a5a 100644 --- a/.github/workflows/root-ci-config/buildconfig/ubuntu2404-cuda.txt +++ b/.github/workflows/root-ci-config/buildconfig/ubuntu2404-cuda.txt @@ -2,6 +2,8 @@ CMAKE_BUILD_TYPE=RelWithDebInfo pythia8=OFF cuda=ON ccache=ON +experimental_adaptivecpp=ON +experimental_genvectorx=ON tmva=ON tmva-cpu=ON tmva-gpu=ON @@ -14,4 +16,4 @@ sqlite=OFF test_distrdf_dask=OFF test_distrdf_pyspark=OFF unfold=OFF -webgui=ON +webgui=ON \ No newline at end of file diff --git a/.github/workflows/root-ci-config/buildconfig/ubuntu2404.txt b/.github/workflows/root-ci-config/buildconfig/ubuntu2404.txt index 287ce0f69d122..355a32db539c3 100644 --- a/.github/workflows/root-ci-config/buildconfig/ubuntu2404.txt +++ b/.github/workflows/root-ci-config/buildconfig/ubuntu2404.txt @@ -1,3 +1,5 @@ +experimental_adaptivecpp=ON +experimental_genvectorx=ON pythia8=OFF tmva-sofie=ON -ccache=On +ccache=On \ No newline at end of file diff --git a/.github/workflows/root-ci-config/buildconfig/ubuntu2504.txt b/.github/workflows/root-ci-config/buildconfig/ubuntu2504.txt index 9439d1f4057e1..7f54d7491a6ae 100644 --- a/.github/workflows/root-ci-config/buildconfig/ubuntu2504.txt +++ b/.github/workflows/root-ci-config/buildconfig/ubuntu2504.txt @@ -1,2 +1,4 @@ +experimental_adaptivecpp=ON +experimental_genvectorx=ON ccache=ON -pythia8=OFF +pythia8=OFF \ No newline at end of file diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 3fa55ef5a0e3e..b1d6b88b40e63 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -1643,6 +1643,126 @@ if (vecgeom) endif() endif() +if(experimental_builtin_adaptivecpp) + ROOT_CHECK_CONNECTION_AND_DISABLE_OPTION("experimental_builtin_adaptivecpp") +endif() + +#---Check for AdaptiveCpp------------------------------------------------------------------- +if (experimental_adaptivecpp OR experimental_builtin_adaptivecpp) + if (experimental_oneapi) + message(WARNING "Disable OneAPI to load AdaptiveCpp") + set(sycl OFF CACHE BOOL "Disabled because AdaptiveCpp is enabled" FORCE) + else() + + if(NOT experimental_builtin_adaptivecpp) + message(STATUS "Looking for AdaptiveCpp") + find_package(AdaptiveCpp) + + if(NOT AdaptiveCpp_FOUND) + message(STATUS "AdaptiveCpp not found. Ensure that the installation of AdaptiveCpp is in the CMAKE_PREFIX_PATH") + if(NO_CONNECTION) + set(experimental_builtin_adaptivecpp OFF CACHE BOOL "Disabled because not found and no internet connection" FORCE) + set(sycl OFF CACHE BOOL FORCE) + if(fail-on-missing) + message(FATAL_ERROR "AdaptiveCpp cannot be built.") + endif() + else() + message(STATUS " Switching ON 'experimental_builtin_adaptivecpp' option") + set(experimental_builtin_adaptivecpp ON CACHE BOOL "Enabled because external AdaptiveCpp not found" FORCE) + endif() + endif() + endif() + + if(experimental_builtin_adaptivecpp) + # Use ADAPTIVE_CPP_SOURCE_DIR variable if it is defined in the CMake + # configuration + if(NOT DEFINED ADAPTIVE_CPP_SOURCE_DIR) + include(FetchContent) + set(ADAPTIVE_CPP_SOURCE_DIR "${CMAKE_BINARY_DIR}/AdaptiveCpp") + FetchContent_Declare( + AdaptiveCpp + GIT_REPOSITORY https://github.com/devajithvs/AdaptiveCpp.git + GIT_TAG 3fb375fdc84ad0423139e05167739e9e906ca183 + ) + FetchContent_GetProperties(AdaptiveCpp) + if(NOT AdaptiveCpp_POPULATED) + FetchContent_Populate(AdaptiveCpp) + endif() + + set(ADAPTIVE_CPP_SOURCE_DIR "${adaptivecpp_SOURCE_DIR}") + endif() + + set(AdaptiveCpp_FOUND True) + + list(INSERT CMAKE_MODULE_PATH 0 "${ADAPTIVE_CPP_SOURCE_DIR}/cmake/") + + set(ADAPTIVE_CPP_HEADER_BUILD_PATH + "${CMAKE_CURRENT_BINARY_DIR}/include/AdaptiveCpp") + set(ADAPTIVE_CPP_HEADER_INSTALL_PATH + "${CMAKE_INSTALL_PREFIX}/include/AdaptiveCpp") + + add_subdirectory( + ${ADAPTIVE_CPP_SOURCE_DIR} + ${adaptivecpp_BINARY_DIR} + ) + + set(ACPP_EXPORTS + acpp-common + acpp-rt + acpp-clang-cbs + acpp-clang + llvm-to-backend + llvm-to-host + rt-backend-omp) + + if(WITH_CUDA_BACKEND) + list(APPEND ACPP_EXPORTS llvm-to-ptx rt-backend-cuda) + endif() + + if(WITH_OPENCL_BACKEND) + list(APPEND ACPP_EXPORTS llvm-to-spirv rt-backend-ocl ocl-cxx-headers ocl-headers) + endif() + + if(WITH_ROCM_BACKEND) + list(APPEND ACPP_EXPORTS llvm-to-amdgpu rt-backend-hip) + endif() + endif() + + if (AdaptiveCpp_FOUND) + set(sycl ON) + set(SYCL_COMPILER_FLAGS "-ffast-math ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${_BUILD_TYPE_UPPER}}") + message(STATUS "SYCL compiler flags: ${SYCL_COMPILER_FLAGS}") + separate_arguments(SYCL_COMPILER_FLAGS NATIVE_COMMAND ${SYCL_COMPILER_FLAGS}) + function(add_sycl_library_to_root_target) + CMAKE_PARSE_ARGUMENTS(ARG "" "TARGET" "SOURCES" ${ARGN}) + add_sycl_to_target(TARGET ${ARG_TARGET} SOURCES ${ARG_SOURCES}) + target_link_libraries(${ARG_TARGET} INTERFACE AdaptiveCpp::acpp-rt) + target_compile_options(${ARG_TARGET} PUBLIC ${SYCL_COMPILER_FLAGS}) + endfunction() + function(add_sycl_library_to_main_root_target) + CMAKE_PARSE_ARGUMENTS(ARG "" "TARGET" "SOURCES" ${ARGN}) + add_sycl_to_target(TARGET ${ARG_TARGET} SOURCES ${ARG_SOURCES}) + target_link_libraries(${ARG_TARGET} INTERFACE AdaptiveCpp::acpp-rt) + target_compile_options(${ARG_TARGET} PUBLIC ${SYCL_COMPILER_FLAGS}) + endfunction() + function(add_sycl_to_root_target) + CMAKE_PARSE_ARGUMENTS(ARG "" "TARGET" "SOURCES" ${ARGN}) + add_sycl_to_target(TARGET ${ARG_TARGET} SOURCES ${ARG_SOURCES}) + target_link_libraries(${ARG_TARGET} INTERFACE AdaptiveCpp::acpp-rt) + target_compile_options(${ARG_TARGET} PUBLIC ${SYCL_COMPILER_FLAGS}) + endfunction() + message(STATUS "AdaptiveCpp sycl enabled") + else() + if(fail-on-missing) + message(FATAL_ERROR "AdaptiveCpp library not found") + else() + message(STATUS "AdaptiveCpp library not found") + set(sycl OFF CACHE BOOL "Disabled because no SYCL implementation is not found" FORCE) + endif() + endif() + endif() +endif() + #---Check for protobuf------------------------------------------------------------------- if(tmva-sofie) diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt index 543adbf6b1e8d..fddecb1db1a1e 100644 --- a/math/CMakeLists.txt +++ b/math/CMakeLists.txt @@ -20,6 +20,9 @@ add_subdirectory(smatrix) add_subdirectory(splot) #add_subdirectory(mathcore/test EXCLUDE_FROM_ALL) add_subdirectory(genvector) +if(sycl AND experimental_genvectorx) + add_subdirectory(experimental/genvectorx) +endif() if(tmva) add_subdirectory(genetic) endif() diff --git a/math/experimental/genvectorx/CMakeLists.txt b/math/experimental/genvectorx/CMakeLists.txt new file mode 100644 index 0000000000000..e0aff45a3b552 --- /dev/null +++ b/math/experimental/genvectorx/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. +# All rights reserved. +# +# For the licensing terms see $ROOTSYS/LICENSE. +# For the list of contributors see $ROOTSYS/README/CREDITS. + +############################################################################ +# CMakeLists.txt file for building ROOT math/genvector package +############################################################################ + +message(STATUS "Experimental GenVectorX") + + ROOT_LINKER_LIBRARY(GenVectorSYCL + src/3DConversions.cxx + src/3DDistances.cxx + src/AxisAngle.cxx + src/AxisAngleXother.cxx + src/BitReproducible.cxx + src/Boost.cxx + src/BoostX.cxx + src/BoostY.cxx + src/BoostZ.cxx + src/EulerAngles.cxx + src/LorentzRotation.cxx + src/Quaternion.cxx + src/QuaternionXaxial.cxx + src/Rotation3D.cxx + src/Rotation3DxAxial.cxx + src/RotationZYX.cxx + src/VectorUtil.cxx + DEPENDENCIES + Core + MathCore + ) + + add_sycl_library_to_root_target( + TARGET + GenVectorSYCL + SOURCES + src/3DConversions.cxx + src/3DDistances.cxx + src/AxisAngle.cxx + src/AxisAngleXother.cxx + src/BitReproducible.cxx + src/Boost.cxx + src/BoostX.cxx + src/BoostY.cxx + src/BoostZ.cxx + src/EulerAngles.cxx + src/LorentzRotation.cxx + src/Quaternion.cxx + src/QuaternionXaxial.cxx + src/Rotation3D.cxx + src/Rotation3DxAxial.cxx + src/RotationZYX.cxx + src/VectorUtil.cxx + COMPILE_DEFINITIONS + ROOT_MATH_SYCL + ) + +target_compile_definitions(GenVectorSYCL PUBLIC ROOT_MATH_SYCL) + +ROOT_ADD_TEST_SUBDIRECTORY(test) + +ROOT_INSTALL_HEADERS() \ No newline at end of file diff --git a/math/experimental/genvectorx/doc/index.md b/math/experimental/genvectorx/doc/index.md new file mode 100644 index 0000000000000..00379def5d4ec --- /dev/null +++ b/math/experimental/genvectorx/doc/index.md @@ -0,0 +1,220 @@ +\defgroup GenVector Physics Vectors +\ingroup Math +\brief Vector classes (2D, 3D and 4D / Lorentz vector) and their transformations. + +These classes represent vectors and their operations and transformations, such as rotations and Lorentz transformations, in two, three and four dimensions. +The 4D space-time is used for physics vectors representing relativistic particles in [Minkowski-space](https://en.wikipedia.org/wiki/Minkowski_space). +These vectors are different from Linear Algebra vectors or `std::vector` which describe generic N-dimensional vectors. + +Hint: the most commonly used Lorentz vector class is ROOT::Math::PtEtaPhiMVector, a typedef to ROOT::Math::LorentzVector < ROOT::Math::PtEtaPhiM4D < double > >. + +## Points and Vector concept + +Mathematically, vectors and points are two distinct concepts. They have different +transformations: vectors can only be rotated, while points can be rotated or translated. +You can add two vectors but not two points, and the difference between two points is a vector. +We then distinguish for the 2 and 3 dimensional case, between points and vectors, +modeling them with different classes: +* ROOT::Math::DisplacementVector2D and ROOT::Math::DisplacementVector3D describe + 2- and 3-component direction and magnitude vectors, not rooted at any particular point; +* ROOT::Math::PositionVector2D and ROOT::Math::PositionVector3D model points in + 2 and 3 dimensions. + +ROOT::Math::LorentzVector models 4D space-time vectors. There is no class for a 4D point. + + +\anchor GenVectorCoordinateSystems +## Coordinate Systems + +### Generic Coordinate System + +The vector classes are based on a generic type of coordinate system, expressed as a +template parameter of the class. Various classes exist to describe the various +coordinates systems: +* **2D coordinate system** classes: + * ROOT::Math::Cartesian2D, based on (x,y) ; + * ROOT::Math::Polar2D, based on (r, phi) ; +* **3D coordinate system** classes: + * ROOT::Math::Cartesian3D, based on (x,y,z); + * ROOT::Math::Polar3D, based on (r, theta, phi); + * ROOT::Math::Cylindrical3D, based on (rho, z, phi) + * ROOT::Math::CylindricalEta3D, based on (rho, eta, phi); +* **4D coordinate system** classes: + * ROOT::Math::PxPyPzE4D, based on based on (px,py,pz,E); + * ROOT::Math::PxPyPzM4D, based on based on (px,py,pz,M); + * ROOT::Math::PtEtaPhiE4D, based on based on (pt,eta,phi,E); + * ROOT::Math::PtEtaPhiM4D, based on based on (pt,eta,phi,M); + +The angle _theta_ is defined between [0,\f$\pi\f$] and _phi_ between [-\f$\pi\f$,\f$\pi\f$]. +The angles are expressed in radians. +The _eta_ component is known as [pseudo-rapidity](https://en.wikipedia.org/wiki/Pseudorapidity). + +Users can define the Vectors according to the coordinate type which +is most efficient for their use. Transformations between the various coordinate +systems are available through copy constructors or the assignment `operator =`. +The coordinate system classes are templated on the scalar type for maximum flexibility, +and to minimize memory usage for some use cases. + +### Coordinate System Tag + +The 2D and 3D point and vector classes can be associated to a tag defining the +coordinate system. This can be used to distinguish between vectors of different +coordinate systems like global or local vectors. The coordinate system tag is a +template parameter of the ROOT::Math::DisplacementVector3D +(and ROOT::Math::DisplacementVector2D) and ROOT::Math::PositionVector3D +(and ROOT::Math::PositionVector2D) classes. A default tag, +ROOT::Math::DefaultCoordinateSystemTag, exists for users who don't need this +functionality. + + +\anchor GenVectorTypedefs +## Concrete Vector typedefs + +To avoid exposing templated parameters to the users, typedefs are defined for all types of vectors based an `double`s and `float`s. +The table below lists the `double` versions; the `float` counterpart ends on an extra `F`, such as ROOT::Math::XYPointF instead of ROOT::Math::XYPoint. + +### Point2D + +Type definitions for points in two dimensions, based on ROOT::Math::PositionVector2D, are defined by `MathX/Point2D.h`: + +* ROOT::Math::XYPoint vector based on x,y coordinates (cartesian) +* ROOT::Math::Polar2DPoint vector based on r,phi coordinates (polar) + +### Vector2D + +Type definitions for vectors in two dimensions, based on ROOT::Math::DisplacementVector2D, are defined by `MathX/Vector2D.h`: + +* ROOT::Math::XYVector vector based on x,y coordinates (cartesian) +* ROOT::Math::Polar2DVector vector based on r,phi coordinates (polar) + +### Point3D + +Type definitions for points in three dimensions, based on ROOT::Math::PositionVector3D, are defined by `MathX/Point3D.h`: + +* ROOT::Math::XYZPoint point based on x,y,z coordinates (cartesian) +* ROOT::Math::Polar3DPoint point based on r,theta,phi coordinates (polar) +* ROOT::Math::RhoZPhiPoint point based on rho,z,phi coordinates (cylindrical using z) +* ROOT::Math::RhoEtaPhiPoint point based on rho,eta,phi coordinates (cylindrical using eta instead of z) + +### Vector3D + +Type definitions for vectors in three dimensions, based on ROOT::Math::DisplacementVector3D, are defined by `MathX/Vector3D.h`: + +* ROOT::Math::XYZVector vector based on x,y,z coordinates (cartesian) +* ROOT::Math::Polar3DVector vector based on r,theta,phi coordinates (polar) +* ROOT::Math::RhoZPhiVector vector based on rho, z,phi coordinates (cylindrical) +* ROOT::Math::RhoEtaPhiVector vector based on rho,eta,phi coordinates (cylindrical using eta instead of z) + +### LorentzVector + +Type definitions for Lorentz vectors in four dimensions, based on ROOT::Math::LorentzVector, are defined by `MathX/Vector4D.h`: + +* ROOT::Math::XYZTVector vector based on x,y,z,t coordinates (cartesian) +* ROOT::Math::PtEtaPhiEVector vector based on pt (rho),eta,phi and E (t) coordinates +* ROOT::Math::PtEtaPhiMVector vector based on pt (rho),eta,phi and M (t) coordinates +* ROOT::Math::PxPyPzMVector vector based on px,py,pz and M (mass) coordinates +* ROOT::Math::PxPyPzEVector vector based on px,py,pz and E (energy) coordinates + +The metric used for any such LorentzVector is (-,-,-,+). + + +\anchor GenVectorOperations +## Operations + +### Constructors and Assignment + +A vector can be constructed from its coordinate representation: + +~~~{.cpp} +ROOT::Math::PtEtaPhiMVector v1(10. /*pt*/, 0.1 /*eta*/, 0.24 /*phi*/, 5 /*M*/); +~~~ + +In addition, the vector classes can be constructed from any object that implements the +accessors x(), y() and z(). This can be a vector using a different coordinate +system, or even an object from a different package as long as it implements the required signatures. +One such vector type is CLHEP's `Hep3Vector`: + +~~~{.cpp} +XYZVector v1(1,2,3); +RhoEtaPhiVector r2(v1); +CLHEP::Hep3Vector q(1,2,3); +XYZVector v3(q) +~~~ + +### Arithmetic Operations + +The following operations are possible between vector classes, even of different +coordinate system types: + +~~~{.cpp} +v1 += v2; +v1 -= v2; +v1 = - v2; +v1 *= a; +v1 /= a; +v2 = a * v1; +v2 = v1 / a; +v2 = v1 * a; +v3 = v1 + v2; +v3 = v1 - v2; +~~~ + +Note that the multiplication between two vectors using the `operator *` is not supported +because it is ambiguous. + +### Other Methods + +The vector classes support methods for: + +- computation of the dot product via Dot(), +- computation of the cross product via Cross(), +- construction of a unit vector via Unit(). + + +\anchor GenVectorTransformations +## Transformations + +The transformations are modeled using simple (non-template) classes, using `double` as +the scalar type to avoid too large numerical errors. The transformations are grouped +in Rotations (in 3 dimensions), Lorentz transformations. Each group has several members which may +model physically equivalent transformations but with different internal representations. +Transformation classes can operate on all type of vectors using the `operator()` +or the `operator *` and the transformations can also be combined via the `operator *`. +In more detail the transformations available are: + +### 3D Rotations + +* ROOT::Math::Rotation3D, rotation described by a 3x3 matrix of doubles +* ROOT::Math::EulerAngles rotation described by the three Euler angles (phi, theta and psi) following the GoldStein [definition](http://mathworld.wolfram.com/EulerAngles.html). +* ROOT::Math::RotationZYX rotation described by three angles defining a rotation first along the Z axis, then along the rotated Y' axis and then along the rotated X'' axis. +* ROOT::Math::AxisAngle, rotation described by a vector (axis) and an angle +* ROOT::Math::Quaternion, rotation described by a quaternion (4 numbers) +* ROOT::Math::RotationX, specialized rotation along the X axis +* ROOT::Math::RotationY, specialized rotation along the Y axis +* ROOT::Math::RotationZ, specialized rotation along the Z axis + +### 3D Transformation + +* ROOT::Math::Translation3D, (only translation) described by a 3D vector +* ROOT::Math::Transform3D, (rotations and then translation) described by a 3x4 matrix (12 numbers) + +### Lorentz Rotation + +* ROOT::Math::LorentzRotation , 4D rotation (3D rotation plus a boost) described by a 4x4 matrix +* ROOT::Math::Boost, a Lorentz boost in an arbitrary direction and described by a 4x4 symmetric matrix (10 numbers) +* ROOT::Math::BoostX, a boost in the X axis direction +* ROOT::Math::BoostY, a boost in the Y axis direction +* ROOT::Math::BoostZ, a boost in the Z axis direction + +## Compatibility with CLHEP Vector classes + +For compatibility with CLHEP, the vector classes can be constructed easily +from a CLHEP `Hep3Vector` or `HepLorentzVector`, by using a template constructor, which +requires only that the classes implement the accessors `x()`, `y()` and `z()` (and `t()` +for `HepLorentzVector`). +The vector classes also provide member function with the same naming convention +as CLHEP for the most used functions like `x()`, `y()` and `z()`. + +## Additional Documentation + +A more detailed description of all the GenVector classes is available in this [document](https://root.cern/topical/GenVector.pdf). diff --git a/math/experimental/genvectorx/inc/MathX/AxisAngle.h b/math/experimental/genvectorx/inc/MathX/AxisAngle.h new file mode 100644 index 0000000000000..c392b495d1285 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/AxisAngle.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_AxisAngle +#define ROOT_MathX_AxisAngle + + +#include "MathX/GenVectorX/AxisAngle.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Boost.h b/math/experimental/genvectorx/inc/MathX/Boost.h new file mode 100644 index 0000000000000..1214f34bc12b0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Boost.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Boost +#define ROOT_MathX_Boost + + +#include "MathX/GenVectorX/Boost.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/BoostX.h b/math/experimental/genvectorx/inc/MathX/BoostX.h new file mode 100644 index 0000000000000..a37e6085416f2 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/BoostX.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_BoostX +#define ROOT_MathX_BoostX + + +#include "MathX/GenVectorX/BoostX.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/BoostY.h b/math/experimental/genvectorx/inc/MathX/BoostY.h new file mode 100644 index 0000000000000..b6b66c9a32927 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/BoostY.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_BoostY +#define ROOT_MathX_BoostY + + +#include "MathX/GenVectorX/BoostY.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/BoostZ.h b/math/experimental/genvectorx/inc/MathX/BoostZ.h new file mode 100644 index 0000000000000..dde11746bb429 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/BoostZ.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_BoostZ +#define ROOT_MathX_BoostZ + + +#include "MathX/GenVectorX/BoostZ.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Cartesian2D.h b/math/experimental/genvectorx/inc/MathX/Cartesian2D.h new file mode 100644 index 0000000000000..1c16820ebd474 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Cartesian2D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Cartesian2D +#define ROOT_MathX_Cartesian2D + + +#include "MathX/GenVectorX/Cartesian2D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Cartesian3D.h b/math/experimental/genvectorx/inc/MathX/Cartesian3D.h new file mode 100644 index 0000000000000..f9bd13558d66d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Cartesian3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Cartesian3D +#define ROOT_MathX_Cartesian3D + + +#include "MathX/GenVectorX/Cartesian3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Cylindrical3D.h b/math/experimental/genvectorx/inc/MathX/Cylindrical3D.h new file mode 100644 index 0000000000000..ab2701a71f25b --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Cylindrical3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Cylindrical3D +#define ROOT_MathX_Cylindrical3D + + +#include "MathX/GenVectorX/Cylindrical3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/CylindricalEta3D.h b/math/experimental/genvectorx/inc/MathX/CylindricalEta3D.h new file mode 100644 index 0000000000000..0bac60e00d9f8 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/CylindricalEta3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_CylindricalEta3D +#define ROOT_MathX_CylindricalEta3D + + +#include "MathX/GenVectorX/CylindricalEta3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/DisplacementVector2D.h b/math/experimental/genvectorx/inc/MathX/DisplacementVector2D.h new file mode 100644 index 0000000000000..4e626b6d04ef4 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/DisplacementVector2D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_DisplacementVector2D +#define ROOT_MathX_DisplacementVector2D + + +#include "MathX/GenVectorX/DisplacementVector2D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/DisplacementVector3D.h b/math/experimental/genvectorx/inc/MathX/DisplacementVector3D.h new file mode 100644 index 0000000000000..3da419ca28ebb --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/DisplacementVector3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_DisplacementVector3D +#define ROOT_MathX_DisplacementVector3D + + +#include "MathX/GenVectorX/DisplacementVector3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/EulerAngles.h b/math/experimental/genvectorx/inc/MathX/EulerAngles.h new file mode 100644 index 0000000000000..d84337aa93468 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/EulerAngles.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_EulerAngles +#define ROOT_MathX_EulerAngles + + +#include "MathX/GenVectorX/EulerAngles.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/3DConversions.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/3DConversions.h new file mode 100644 index 0000000000000..ba2a5b047096f --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/3DConversions.h @@ -0,0 +1,132 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005, LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Rotation in 3 dimensions, represented by 3x3 matrix +// +// Created by: Mark Fischler and Walter Brown Thurs July 7, 2005 +// +// Last update: Wed Thurs July 7, 2005 +// +#ifndef ROOT_MathX_GenVectorX_3DConversions +#define ROOT_MathX_GenVectorX_3DConversions 1 + +#include "MathX/GenVectorX/Rotation3Dfwd.h" +#include "MathX/GenVectorX/AxisAnglefwd.h" +#include "MathX/GenVectorX/EulerAnglesfwd.h" +#include "MathX/GenVectorX/Quaternionfwd.h" +#include "MathX/GenVectorX/RotationXfwd.h" +#include "MathX/GenVectorX/RotationYfwd.h" +#include "MathX/GenVectorX/RotationZfwd.h" +#include "MathX/GenVectorX/RotationZYXfwd.h" + + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +namespace gv_detail { + +// flag a link time error when a wrong conversion is instantiated + struct ERROR_This_Rotation_Conversion_is_NOT_Supported { + ERROR_This_Rotation_Conversion_is_NOT_Supported(); + }; +template +void convert( R1 const &, R2 const) { + ERROR_This_Rotation_Conversion_is_NOT_Supported(); +} + +// ---------------------------------------------------------------------- +// conversions from Rotation3D +/** + conversion functions from 3D rotation. + For converting to Euler Angles see + here + */ + +void convert( Rotation3D const & from, AxisAngle & to); +void convert( Rotation3D const & from, EulerAngles & to); +void convert( Rotation3D const & from, Quaternion & to); +void convert( Rotation3D const & from, RotationZYX & to); + + +// ---------------------------------------------------------------------- +// conversions from AxisAngle + +void convert( AxisAngle const & from, Rotation3D & to); +void convert( AxisAngle const & from, EulerAngles & to); +void convert( AxisAngle const & from, Quaternion & to); +void convert( AxisAngle const & from, RotationZYX & to); + + +// ---------------------------------------------------------------------- +// conversions from EulerAngles + +void convert( EulerAngles const & from, Rotation3D & to); +void convert( EulerAngles const & from, AxisAngle & to); +void convert( EulerAngles const & from, Quaternion & to); +void convert( EulerAngles const & from, RotationZYX & to); + + +// ---------------------------------------------------------------------- +// conversions from Quaternion + +void convert( Quaternion const & from, Rotation3D & to); +void convert( Quaternion const & from, AxisAngle & to); +void convert( Quaternion const & from, EulerAngles & to); +void convert( Quaternion const & from, RotationZYX & to); + +// ---------------------------------------------------------------------- +// conversions from RotationZYX + +void convert( RotationZYX const & from, Rotation3D & to); +void convert( RotationZYX const & from, AxisAngle & to); +void convert( RotationZYX const & from, EulerAngles & to); +void convert( RotationZYX const & from, Quaternion & to); + + +// ---------------------------------------------------------------------- +// conversions from RotationX + +void convert( RotationX const & from, Rotation3D & to); +void convert( RotationX const & from, RotationZYX & to); +void convert( RotationX const & from, AxisAngle & to); +void convert( RotationX const & from, EulerAngles & to); +void convert( RotationX const & from, Quaternion & to); + + +// ---------------------------------------------------------------------- +// conversions from RotationY + +void convert( RotationY const & from, Rotation3D & to); +void convert( RotationY const & from, RotationZYX & to); +void convert( RotationY const & from, AxisAngle & to); +void convert( RotationY const & from, EulerAngles & to); +void convert( RotationY const & from, Quaternion & to); + + +// ---------------------------------------------------------------------- +// conversions from RotationZ + +void convert( RotationZ const & from, Rotation3D & to); +void convert( RotationZ const & from, RotationZYX & to); +void convert( RotationZ const & from, AxisAngle & to); +void convert( RotationZ const & from, EulerAngles & to); +void convert( RotationZ const & from, Quaternion & to); + + +} //namespace gv_detail +} //namespace Math +} //namespace ROOT + +#endif // ROOT_MathX_GenVectorX_3DConversions diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/3DDistances.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/3DDistances.h new file mode 100644 index 0000000000000..b44860b55fe60 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/3DDistances.h @@ -0,0 +1,155 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005, LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class implementations of Distance() functions among +// Rotations in 3 dimensions +// +// Created by: Mark Fischler and Walter Brown Thurs July 7, 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_3DDistances +#define ROOT_MathX_GenVectorX_3DDistances 1 + +#include "MathX/GenVectorX/Rotation3Dfwd.h" +#include "MathX/GenVectorX/AxisAnglefwd.h" +#include "MathX/GenVectorX/EulerAnglesfwd.h" +#include "MathX/GenVectorX/Quaternionfwd.h" +#include "MathX/GenVectorX/RotationZYXfwd.h" +#include "MathX/GenVectorX/RotationXfwd.h" +#include "MathX/GenVectorX/RotationYfwd.h" +#include "MathX/GenVectorX/RotationZfwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { +namespace ROOT_MATH_ARCH { +namespace gv_detail { + +// Technical note: +// +// Most of these functions are identical, converting to Quaternions +// and then taking the simple distance between two Quaternions. This +// makes it tempting to use a template function (which could appear in +// each individual rotation header). +// +// However, then we would have to include Quaternion.h in this header, +// and by induction, each rotation class would depend on Quaternion, which +// would be undesirable. + + +// ---------------------------------------------------------------------- +// Distance from Rotation3D + +double dist( Rotation3D const & r1, Rotation3D const & r2); +double dist( Rotation3D const & r1, AxisAngle const & r2); +double dist( Rotation3D const & r1, EulerAngles const & r2); +double dist( Rotation3D const & r1, Quaternion const & r2); +double dist( Rotation3D const & r1, RotationZYX const & r2); +double dist( Rotation3D const & r1, RotationX const & r2); +double dist( Rotation3D const & r1, RotationY const & r2); +double dist( Rotation3D const & r1, RotationZ const & r2); + + +// ---------------------------------------------------------------------- +// Distance from AxisAngle + +double dist( AxisAngle const & r1, Rotation3D const & r2); +double dist( AxisAngle const & r1, AxisAngle const & r2); +double dist( AxisAngle const & r1, EulerAngles const & r2); +double dist( AxisAngle const & r1, Quaternion const & r2); +double dist( AxisAngle const & r1, RotationZYX const & r2); +double dist( AxisAngle const & r1, RotationX const & r2); +double dist( AxisAngle const & r1, RotationY const & r2); +double dist( AxisAngle const & r1, RotationZ const & r2); + + +// ---------------------------------------------------------------------- +// Distance from EulerAngles + +double dist( EulerAngles const & r1, Rotation3D const & r2); +double dist( EulerAngles const & r1, AxisAngle const & r2); +double dist( EulerAngles const & r1, EulerAngles const & r2); +double dist( EulerAngles const & r1, Quaternion const & r2); +double dist( EulerAngles const & r1, RotationZYX const & r2); +double dist( EulerAngles const & r1, RotationX const & r2); +double dist( EulerAngles const & r1, RotationY const & r2); +double dist( EulerAngles const & r1, RotationZ const & r2); + + +// ---------------------------------------------------------------------- +// Distance from Quaternion + +double dist( Quaternion const & r1, Rotation3D const & r2); +double dist( Quaternion const & r1, AxisAngle const & r2); +double dist( Quaternion const & r1, EulerAngles const & r2); +double dist( Quaternion const & r1, Quaternion const & r2); +double dist( Quaternion const & r1, RotationZYX const & r2); +double dist( Quaternion const & r1, RotationX const & r2); +double dist( Quaternion const & r1, RotationY const & r2); +double dist( Quaternion const & r1, RotationZ const & r2); + +// ---------------------------------------------------------------------- +// Distance from RotationZYX + +double dist( RotationZYX const & r1, Rotation3D const & r2); +double dist( RotationZYX const & r1, AxisAngle const & r2); +double dist( RotationZYX const & r1, EulerAngles const & r2); +double dist( RotationZYX const & r1, Quaternion const & r2); +double dist( RotationZYX const & r1, RotationZYX const & r2); +double dist( RotationZYX const & r1, RotationX const & r2); +double dist( RotationZYX const & r1, RotationY const & r2); +double dist( RotationZYX const & r1, RotationZ const & r2); + + + +// ---------------------------------------------------------------------- +// Distance from RotationX + +double dist( RotationX const & r1, Rotation3D const & r2); +double dist( RotationX const & r1, AxisAngle const & r2); +double dist( RotationX const & r1, EulerAngles const & r2); +double dist( RotationX const & r1, Quaternion const & r2); +double dist( RotationX const & r1, RotationX const & r2); +double dist( RotationX const & r1, RotationY const & r2); +double dist( RotationX const & r1, RotationZ const & r2); + + +// ---------------------------------------------------------------------- +// Distance from RotationY + +double dist( RotationY const & r1, Rotation3D const & r2); +double dist( RotationY const & r1, AxisAngle const & r2); +double dist( RotationY const & r1, EulerAngles const & r2); +double dist( RotationY const & r1, Quaternion const & r2); +double dist( RotationY const & r1, RotationX const & r2); +double dist( RotationY const & r1, RotationY const & r2); +double dist( RotationY const & r1, RotationZ const & r2); + + +// ---------------------------------------------------------------------- +// Distance from RotationZ + +double dist( RotationZ const & r1, Rotation3D const & r2); +double dist( RotationZ const & r1, AxisAngle const & r2); +double dist( RotationZ const & r1, EulerAngles const & r2); +double dist( RotationZ const & r1, Quaternion const & r2); +double dist( RotationZ const & r1, RotationX const & r2); +double dist( RotationZ const & r1, RotationY const & r2); +double dist( RotationZ const & r1, RotationZ const & r2); + + +} //namespace gv_detail +} //namespace Math +} //namespace ROOT + +#endif // ROOT_MathX_GenVectorX_3DDistances diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/AccHeaders.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/AccHeaders.h new file mode 100644 index 0000000000000..c05375a33aa3d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/AccHeaders.h @@ -0,0 +1,42 @@ +#ifndef ROOT_AccHeaders_H +#define ROOT_AccHeaders_H + +#if defined(ROOT_MATH_SYCL) + +#include +#ifndef ROOT_MATH_ARCH +#define ROOT_MATH_ARCH MathSYCL +#endif // ROOT_MATH_ARCH + +#elif defined(ROOT_MATH_CUDA) + +#include +#ifndef ROOT_MATH_ARCH +#define ROOT_MATH_ARCH MathCUDA +#endif // ROOT_MATH_ARCH + +#else + +#include +#ifndef ROOT_MATH_ARCH +#define ROOT_MATH_ARCH Math +#endif // ROOT_MATH_ARCH + +#endif + +#if defined(ROOT_MATH_CUDA) && defined(__CUDACC__) + +#define __roodevice__ __device__ +#define __roohost__ __host__ +#define __rooglobal__ __global__ + +#else + +#define __roodevice__ +#define __roohost__ +#define __rooglobal__ + +#endif + + +#endif // ROOT_AccHeaders_H diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/AxisAngle.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/AxisAngle.h new file mode 100644 index 0000000000000..003a89765614b --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/AxisAngle.h @@ -0,0 +1,349 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class AxisAngle +// +// Created by: Lorenzo Moneta at Wed May 11 10:37:10 2005 +// +// Last update: Wed May 11 10:37:10 2005 +// +#ifndef ROOT_MathX_GenVectorX_AxisAngle +#define ROOT_MathX_GenVectorX_AxisAngle 1 + +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/3DConversions.h" +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + AxisAngle class describing rotation represented with direction axis (3D Vector) and an + angle of rotation around that axis. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ +class AxisAngle { + +public: + + typedef double Scalar; + + /** + definition of vector axis + */ + typedef DisplacementVector3D > AxisVector; + + + /** + Default constructor (axis is z and angle is zero) + */ + AxisAngle() : fAxis(0,0,1), fAngle(0) { } + + /** + Construct from a non-zero vector (x,y,z) and an angle. + Precondition: the Vector needs to implement x(), y(), z(), and unit() + */ + template + AxisAngle(const AnyVector & v, Scalar angle) : + fAxis(v.unit()), fAngle(angle) { } + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of four Scalars, to be treated as + the x, y, and z components of a unit axis vector, and the angle + of rotation. + Precondition: The first three components are assumed to represent + the rotation axis vector and the 4-th the rotation angle. + The angle is assumed to be in the range (-pi,pi]. + The axis vector is automatically normalized to be a unit vector + */ + template + AxisAngle(IT begin, IT end) { SetComponents(begin,end); } + + // The compiler-generated copy ctor, copy assignment, and dtor are OK. + + /** + Re-adjust components to eliminate small deviations from the axis + being a unit vector and angles out of the canonical range (-pi,pi] + */ + void Rectify(); + + // ======== Construction From other Rotation Forms ================== + + /** + Construct from another supported rotation type (see gv_detail::convert ) + */ + template + explicit AxisAngle(const OtherRotation & r) {gv_detail::convert(r,*this);} + + + /** + Assign from another supported rotation type (see gv_detail::convert ) + */ + template + AxisAngle & operator=( OtherRotation const & r ) { + gv_detail::convert(r,*this); + return *this; + } + + // ======== Components ============== + + /** + Set the axis and then the angle given a pair of pointers or iterators + defining the beginning and end of an array of four Scalars. + Precondition: The first three components are assumed to represent + the rotation axis vector and the 4-th the rotation angle. + The angle is assumed to be in the range (-pi,pi]. + The axis vector is automatically normalized to be a unit vector + */ + template + void SetComponents(IT begin, IT end) { + IT a = begin; IT b = ++begin; IT c = ++begin; + fAxis.SetCoordinates(*a,*b,*c); + fAngle = *(++begin); + (void)end; + assert (++begin==end); + // re-normalize the vector + double tot = fAxis.R(); + if (tot > 0) fAxis /= tot; + } + + /** + Get the axis and then the angle into data specified by an iterator begin + and another to the end of the desired data (4 past start). + */ + template + void GetComponents(IT begin, IT end) const { + IT a = begin; IT b = ++begin; IT c = ++begin; + fAxis.GetCoordinates(*a,*b,*c); + *(++begin) = fAngle; + (void)end; + assert (++begin==end); + } + + /** + Get the axis and then the angle into data specified by an iterator begin + */ + template + void GetComponents(IT begin) const { + double ax,ay,az = 0; + fAxis.GetCoordinates(ax,ay,az); + *begin++ = ax; + *begin++ = ay; + *begin++ = az; + *begin = fAngle; + } + + /** + Set components from a non-zero vector (x,y,z) and an angle. + Precondition: the Vector needs to implement x(), y(), z(), and unit() + */ + template + void SetComponents(const AnyVector & v, Scalar angle) { + fAxis=v.unit(); + fAngle=angle; + } + + /** + Set components into a non-zero vector (x,y,z) and an angle. + The vector is intended to be a cartesian displacement vector + but any vector class assignable from one will work. + */ + template + void GetComponents(AnyVector & axis, Scalar & angle) const { + axis = fAxis; + angle = fAngle; + } + + /** + access to rotation axis + */ + AxisVector Axis() const { return fAxis; } + + /** + access to rotation angle + */ + Scalar Angle() const { return fAngle; } + + // =========== operations ============== + + /** + Rotation operation on a cartesian vector + */ + typedef DisplacementVector3D, DefaultCoordinateSystemTag > XYZVector; + XYZVector operator() (const XYZVector & v) const; + + /** + Rotation operation on a displacement vector in any coordinate system + */ + template + DisplacementVector3D + operator() (const DisplacementVector3D & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.X(), v.Y(), v.Z()); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + DisplacementVector3D< CoordSystem, Tag > vNew; + vNew.SetXYZ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + return vNew; + } + + /** + Rotation operation on a position vector in any coordinate system + */ + template + PositionVector3D + operator() (const PositionVector3D & p) const { + DisplacementVector3D< Cartesian3D,Tag > xyz(p); + DisplacementVector3D< Cartesian3D,Tag > rxyz = operator()(xyz); + return PositionVector3D ( rxyz ); + } + + /** + Rotation operation on a Lorentz vector in any 4D coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector< PxPyPzE4D > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E()); + return LorentzVector ( xyzt ); + } + + + /** + Rotation operation on an arbitrary vector v. + Preconditions: v must implement methods x(), y(), and z() + and the arbitrary vector type must have a constructor taking (x,y,z) + */ + template + ForeignVector + operator() (const ForeignVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + AVector operator* (const AVector & v) const + { + return operator()(v); + } + + /** + Invert an AxisAngle rotation in place + */ + void Invert() { fAngle = -fAngle; } + + /** + Return inverse of an AxisAngle rotation + */ + AxisAngle Inverse() const { AxisAngle result(*this); result.Invert(); return result; } + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) two rotations + */ + AxisAngle operator * (const Rotation3D & r) const; + AxisAngle operator * (const AxisAngle & a) const; + AxisAngle operator * (const EulerAngles & e) const; + AxisAngle operator * (const Quaternion & q) const; + AxisAngle operator * (const RotationZYX & r) const; + AxisAngle operator * (const RotationX & rx) const; + AxisAngle operator * (const RotationY & ry) const; + AxisAngle operator * (const RotationZ & rz) const; + + /** + Post-Multiply (on right) by another rotation : T = T*R + */ + template + AxisAngle & operator *= (const R & r) { return *this = (*this)*r; } + + + /** + Distance between two rotations + */ + template + Scalar Distance ( const R & r ) const {return gv_detail::dist(*this,r);} + + /** + Equality/inequality operators + */ + bool operator == (const AxisAngle & rhs) const { + if( fAxis != rhs.fAxis ) return false; + if( fAngle != rhs.fAngle ) return false; + return true; + } + bool operator != (const AxisAngle & rhs) const { + return ! operator==(rhs); + } + +private: + + AxisVector fAxis; // rotation axis (3D vector) + Scalar fAngle; // rotation angle + + void RectifyAngle(); + + static double Pi() { return 3.14159265358979323; } + +}; // AxisAngle + +// ============ Class AxisAngle ends here ============ + +/** + Distance between two rotations + */ +template +inline +typename AxisAngle::Scalar +Distance ( const AxisAngle& r1, const R & r2) {return gv_detail::dist(r1,r2);} + +/** + Multiplication of an axial rotation by an AxisAngle + */ +AxisAngle operator* (RotationX const & r1, AxisAngle const & r2); +AxisAngle operator* (RotationY const & r1, AxisAngle const & r2); +AxisAngle operator* (RotationZ const & r1, AxisAngle const & r2); + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +std::ostream & operator<< (std::ostream & os, const AxisAngle & a); + +#endif + +} // namespace Math +} // namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_AxisAngle */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/AxisAnglefwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/AxisAnglefwd.h new file mode 100644 index 0000000000000..636bc679963ab --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/AxisAnglefwd.h @@ -0,0 +1,23 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_AxisAnglefwd +#define ROOT_MathX_GenVectorX_AxisAnglefwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a rotation represented + by an axis and an angle of rotation + */ + +class AxisAngle; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_AxisAnglefwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/BitReproducible.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/BitReproducible.h new file mode 100644 index 0000000000000..c7edf0f43079c --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BitReproducible.h @@ -0,0 +1,133 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** + * * + * Copyright (c) 2005 , LCG / FNAL ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class LorentzVector +// +// Created by: fischler at Mon Jun 25 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_BitReproducible +#define ROOT_MathX_GenVectorX_BitReproducible 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +#include +#include +#include + +#include + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +namespace ROOT { + namespace ROOT_MATH_ARCH { + namespace GenVector_detail { + +class BitReproducibleException : public std::exception +{ +public: + BitReproducibleException(const std::string & w) noexcept : fMsg(w) {} + ~BitReproducibleException() noexcept override {} + const char *what() const noexcept override { return fMsg.c_str(); } + private: + std::string fMsg; +}; + +class BitReproducible { +public: + + // dto2longs(d, i1, i2) returns (in i1 and i2) two unsigned ints + // representation of its double input. This is byte-ordering + // independent, and depends for complete portability ONLY on adherence + // to the IEEE 754 standard for 64-bit floating point representation. + // The first unsigned int contains the high-order bits in IEEE; thus + // 1.0 will always be 0x3FF00000, 00000000 + static void Dto2longs(double d, unsigned int & i1, unsigned int & i2); + + // longs2double (i1,i2) returns a double containing the value represented by + // its input, which must be a 2 unsigned ints. + // The input is taken to be the representation according to + // the IEEE 754 standard for a 64-bit floating point number, whose value + // is returned as a double. The byte-ordering of the double result is, + // of course, tailored to the proper byte-ordering for the system. + static double Longs2double (unsigned int i1, unsigned int i2); + + // dtox(d) returns a 16-character string containing the (zero-filled) hex + // representation of its double input. This is byte-ordering + // independent, and depends for complete portability ONLY on adherence + // to the IEEE 754 standard for 64-bit floating point representation. + static std::string D2x(double d); + + static void Output ( std::ostream & os, double d ) { + unsigned int i1, i2; + Dto2longs(d, i1, i2); + os << " " << i1 << " " << i2; + } + + static void Input ( std::istream & is, double & d ) { + unsigned int i1, i2; + is >> i1 >> i2; + d = Longs2double(i1, i2); + } + + static void Output ( std::ostream & os, float f ) { + unsigned int i1, i2; + Dto2longs( double(f), i1, i2 ); + os << " " << i1 << " " << i2; + } + + static void Input ( std::istream & is, float & f ) { + unsigned int i1, i2; + is >> i1 >> i2; + f = float( Longs2double(i1, i2) ); + } + + +private: + union DB8 { + unsigned char fB[8]; + double fD; + }; + static void Fill_byte_order (); + static bool fgByte_order_known; + static int fgByte_order[8]; + // Meaning of byte_order: The first (high-order in IEEE 754) byte to + // output (or the high-order byte of the first unsigned int) + // is of db.b[byte_order[0]]. Thus the index INTO byte_order + // is a position in the IEEE representation of the double, and the value + // of byte_order[k] is an offset in the memory representation of the + // double. + +}; // BitReproducible + +} // namespace _GenVector_detail +} // namespace Math +} // namespace ROOT + +// A note about floats and long doubles: +// +// BitReproducible can be used with floats by doing the equivalent of +// float x = x0; BitReproducible::dto2longs (x, i, j); +// float y = BitReproducible::longs2double (i, j); +// The results are correct. +// The only inefficiency is that two integers are used where one would suffice. +// +// The same artifice will compile for long double. However, any value of the +// long double which is not precisely representable as a double will not +// give exact results for the read-back. +// +// We intend in the near future to create a templated version of this class +// which cures both the above flaws. (In the case of long double, this is +// contingent upon finding some IEEE standard for the bits in a 128-bit double.) + +#endif + +#endif // DOUBCONV_HH diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Boost.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Boost.h new file mode 100644 index 0000000000000..1710af71c2058 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Boost.h @@ -0,0 +1,313 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for Boost +// +// Created by: Mark Fischler Mon Nov 1 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_Boost +#define ROOT_MathX_GenVectorX_Boost 1 + +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" + +#include "MathX/GenVectorX/BoostX.h" +#include "MathX/GenVectorX/BoostY.h" +#include "MathX/GenVectorX/BoostZ.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + Lorentz boost class with the (4D) transformation represented internally + by a 4x4 orthosymplectic matrix. + See also BoostX, BoostY and BoostZ for classes representing + specialized Lorentz boosts. + Also, the 3-D rotation classes can be considered to be special Lorentz + transformations which do not mix space and time components. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class Boost { + +public: + + typedef double Scalar; + + enum ELorentzRotationMatrixIndex { + kLXX = 0, kLXY = 1, kLXZ = 2, kLXT = 3 + , kLYX = 4, kLYY = 5, kLYZ = 6, kLYT = 7 + , kLZX = 8, kLZY = 9, kLZZ = 10, kLZT = 11 + , kLTX = 12, kLTY = 13, kLTZ = 14, kLTT = 15 + }; + + enum EBoostMatrixIndex { + kXX = 0, kXY = 1, kXZ = 2, kXT = 3 + , kYY = 4, kYZ = 5, kYT = 6 + , kZZ = 7, kZT = 8 + , kTT = 9 + }; + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity transformation) + */ + Boost() { SetIdentity(); } + + /** + Construct given a three Scalars beta_x, beta_y, and beta_z + */ + Boost(Scalar beta_x, Scalar beta_y, Scalar beta_z) + { SetComponents(beta_x, beta_y, beta_z); } + + /** + Construct given a beta vector (which must have methods x(), y(), z()) + */ + template + explicit + Boost(const Avector & beta) { SetComponents(beta); } + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of three Scalars to use as beta_x, _y, and _z + */ + template + Boost(IT begin, IT end) { SetComponents(begin,end); } + + /** + copy constructor + */ + Boost(Boost const & b) { + *this = b; + } + + /** + Construct from an axial boost + */ + + explicit Boost( BoostX const & bx ) {SetComponents(bx.BetaVector());} + explicit Boost( BoostY const & by ) {SetComponents(by.BetaVector());} + explicit Boost( BoostZ const & bz ) {SetComponents(bz.BetaVector());} + + // The compiler-generated copy ctor, copy assignment, and dtor are OK. + + /** + Assignment operator + */ + Boost & + operator=(Boost const & rhs ) { + for (unsigned int i=0; i < 10; ++i) { + fM[i] = rhs.fM[i]; + } + return *this; + } + + /** + Assign from an axial pure boost + */ + Boost & + operator=( BoostX const & bx ) { return operator=(Boost(bx)); } + Boost & + operator=( BoostY const & by ) { return operator=(Boost(by)); } + Boost & + operator=( BoostZ const & bz ) { return operator=(Boost(bz)); } + + /** + Re-adjust components to eliminate small deviations from a perfect + orthosyplectic matrix. + */ + void Rectify(); + + // ======== Components ============== + + /** + Set components from beta_x, beta_y, and beta_z + */ + void + SetComponents (Scalar beta_x, Scalar beta_y, Scalar beta_z); + + /** + Get components into beta_x, beta_y, and beta_z + */ + void + GetComponents (Scalar& beta_x, Scalar& beta_y, Scalar& beta_z) const; + + /** + Set components from a beta vector + */ + template + void + SetComponents (const Avector & beta) + { SetComponents(beta.x(), beta.y(), beta.z()); } + + /** + Set given a pair of pointers or iterators defining the beginning and end of + an array of three Scalars to use as beta_x,beta _y, and beta_z + */ + template + void SetComponents(IT begin, IT end) { + IT a = begin; IT b = ++begin; IT c = ++begin; + (void)end; + assert (++begin==end); + SetComponents (*a, *b, *c); + } + + /** + Get given a pair of pointers or iterators defining the beginning and end of + an array of three Scalars into which to place beta_x, beta_y, and beta_z + */ + template + void GetComponents(IT begin, IT end) const { + IT a = begin; IT b = ++begin; IT c = ++begin; + (void)end; + assert (++begin==end); + GetComponents (*a, *b, *c); + } + + /** + Get given a pointer or an iterator defining the beginning of + an array into which to place beta_x, beta_y, and beta_z + */ + template + void GetComponents(IT begin ) const { + double bx,by,bz = 0; + GetComponents (bx,by,bz); + *begin++ = bx; + *begin++ = by; + *begin = bz; + } + + /** + The beta vector for this boost + */ + typedef DisplacementVector3D, DefaultCoordinateSystemTag > XYZVector; + XYZVector BetaVector() const; + + /** + Get elements of internal 4x4 symmetric representation, into a data + array suitable for direct use as the components of a LorentzRotation + Note -- 16 Scalars will be written into the array; if the array is not + that large, then this will lead to undefined behavior. + */ + void + GetLorentzRotation (Scalar r[]) const; + + // =========== operations ============== + + /** + Lorentz transformation operation on a Minkowski ('Cartesian') + LorentzVector + */ + LorentzVector< PxPyPzE4D > + operator() (const LorentzVector< PxPyPzE4D > & v) const; + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return LorentzVector ( r_xyzt ); + } + + /** + Lorentz transformation operation on an arbitrary 4-vector v. + Preconditions: v must implement methods x(), y(), z(), and t() + and the arbitrary vector type must have a constructor taking (x,y,z,t) + */ + template + Foreign4Vector + operator() (const Foreign4Vector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return Foreign4Vector ( r_xyzt.X(), r_xyzt.Y(), r_xyzt.Z(), r_xyzt.T() ); + } + + /** + Overload operator * for boost on a vector + */ + template + inline + A4Vector operator* (const A4Vector & v) const + { + return operator()(v); + } + + /** + Invert a Boost in place + */ + void Invert(); + + /** + Return inverse of a boost + */ + Boost Inverse() const; + + /** + Equality/inequality operators + */ + bool operator == (const Boost & rhs) const { + for (unsigned int i=0; i < 10; ++i) { + if( fM[i] != rhs.fM[i] ) return false; + } + return true; + } + bool operator != (const Boost & rhs) const { + return ! operator==(rhs); + } + +protected: + + void SetIdentity(); + +private: + + Scalar fM[10]; + +}; // Boost + +// ============ Class Boost ends here ============ +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form + +std::ostream & operator<< (std::ostream & os, const Boost & b); +#endif + +} //namespace Math +} //namespace ROOT + + + + + + + +#endif /* ROOT_MathX_GenVectorX_Boost */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostX.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostX.h new file mode 100644 index 0000000000000..d14c20ca32017 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostX.h @@ -0,0 +1,225 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for BoostX +// +// Created by: Mark Fischler Mon Nov 1 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_BoostX +#define ROOT_MathX_GenVectorX_BoostX 1 + +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + Class representing a Lorentz Boost along the X axis, by beta. + For efficiency, gamma is held as well. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class BoostX { + +public: + + typedef double Scalar; + + enum ELorentzRotationMatrixIndex { + kLXX = 0, kLXY = 1, kLXZ = 2, kLXT = 3 + , kLYX = 4, kLYY = 5, kLYZ = 6, kLYT = 7 + , kLZX = 8, kLZY = 9, kLZZ = 10, kLZT = 11 + , kLTX = 12, kLTY = 13, kLTZ = 14, kLTT = 15 + }; + + enum EBoostMatrixIndex { + kXX = 0, kXY = 1, kXZ = 2, kXT = 3 + , kYY = 4, kYZ = 5, kYT = 6 + , kZZ = 7, kZT = 8 + , kTT = 9 + }; + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity transformation) + */ + BoostX(); + + /** + Construct given a Scalar beta_x + */ + explicit BoostX(Scalar beta_x) { SetComponents(beta_x); } + + + // The compiler-generated copy ctor, copy assignment, and dtor are OK. + + /** + Re-adjust components to eliminate small deviations from a perfect + orthosyplectic matrix. + */ + void Rectify(); + + // ======== Components ============== + + /** + Set components from a Scalar beta_x + */ + void + SetComponents (Scalar beta_x); + + /** + Get components into a Scalar beta_x + */ + void + GetComponents (Scalar& beta_x) const; + + + /** + Retrieve the beta of the Boost + */ + Scalar Beta() const { return fBeta; } + + /** + Retrieve the gamma of the Boost + */ + Scalar Gamma() const { return fGamma; } + + /** + Set the given beta of the Boost + */ + void SetBeta(Scalar beta) { SetComponents(beta); } + + /** + The beta vector for this boost + */ + typedef DisplacementVector3D, DefaultCoordinateSystemTag > XYZVector; + XYZVector BetaVector() const; + + /** + Get elements of internal 4x4 symmetric representation, into a data + array suitable for direct use as the components of a LorentzRotation + Note -- 16 Scalars will be written into the array; if the array is not + that large, then this will lead to undefined behavior. + */ + void + GetLorentzRotation (Scalar r[]) const; + + // =========== operations ============== + + /** + Lorentz transformation operation on a Minkowski ('Cartesian') + LorentzVector + */ + LorentzVector< PxPyPzE4D > + operator() (const LorentzVector< PxPyPzE4D > & v) const; + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return LorentzVector ( r_xyzt ); + } + + /** + Lorentz transformation operation on an arbitrary 4-vector v. + Preconditions: v must implement methods x(), y(), z(), and t() + and the arbitrary vector type must have a constructor taking (x,y,z,t) + */ + template + Foreign4Vector + operator() (const Foreign4Vector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return Foreign4Vector ( r_xyzt.X(), r_xyzt.Y(), r_xyzt.Z(), r_xyzt.T() ); + } + + /** + Overload operator * for operation on a vector + */ + template + inline + A4Vector operator* (const A4Vector & v) const + { + return operator()(v); + } + + /** + Invert a BoostX in place + */ + void Invert(); + + /** + Return inverse of a boost + */ + BoostX Inverse() const; + + /** + Equality/inequality operators + */ + bool operator == (const BoostX & rhs) const { + if( fBeta != rhs.fBeta ) return false; + if( fGamma != rhs.fGamma ) return false; + return true; + } + + bool operator != (const BoostX & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fBeta; // boost beta X + Scalar fGamma; // boost gamma + +}; // BoostX + +// ============ Class BoostX ends here ============ + + +/** + Stream Output and Input +*/ +// TODO - I/O should be put in the manipulator form +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +std::ostream & operator<< (std::ostream & os, const BoostX & b); + +#endif + +} //namespace Math +} //namespace ROOT + + + + + + + +#endif /* ROOT_MathX_GenVectorX_BoostX */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostXfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostXfwd.h new file mode 100644 index 0000000000000..1c0884b2bbb6f --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostXfwd.h @@ -0,0 +1,23 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_BoostXfwd +#define ROOT_MathX_GenVectorX_BoostXfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a pure Lorentz Boost along the X axis + */ + +class BoostX; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_BoostXfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostY.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostY.h new file mode 100644 index 0000000000000..25b499a99a5f9 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostY.h @@ -0,0 +1,221 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for BoostY +// +// Created by: Mark Fischler Mon Nov 1 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_BoostY +#define ROOT_MathX_GenVectorX_BoostY 1 + +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + Class representing a Lorentz Boost along the Y axis, by beta. + For efficiency, gamma is held as well. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class BoostY { + +public: + + typedef double Scalar; + + enum ELorentzRotationMatrixIndex { + kLXX = 0, kLXY = 1, kLXZ = 2, kLXT = 3 + , kLYX = 4, kLYY = 5, kLYZ = 6, kLYT = 7 + , kLZX = 8, kLZY = 9, kLZZ = 10, kLZT = 11 + , kLTX = 12, kLTY = 13, kLTZ = 14, kLTT = 15 + }; + + enum EBoostMatrixIndex { + kXX = 0, kXY = 1, kXZ = 2, kXT = 3 + , kYY = 4, kYZ = 5, kYT = 6 + , kZZ = 7, kZT = 8 + , kTT = 9 + }; + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity transformation) + */ + BoostY(); + + /** + Construct given a Scalar beta_y + */ + explicit BoostY(Scalar beta_y) { SetComponents(beta_y); } + + + // The compiler-generated copy ctor, copy assignment, and dtor are OK. + + /** + Re-adjust components to eliminate small deviations from a perfect + orthosyplectic matrix. + */ + void Rectify(); + + // ======== Components ============== + + /** + Set components from a Scalar beta_y + */ + void + SetComponents (Scalar beta_y); + + /** + Get components into a Scalar beta_y + */ + void + GetComponents (Scalar& beta_y) const; + + + /** + Retrieve the beta of the Boost + */ + Scalar Beta() const { return fBeta; } + + /** + Retrieve the gamma of the Boost + */ + Scalar Gamma() const { return fGamma; } + + /** + Set the given beta of the Boost + */ + void SetBeta(Scalar beta) { SetComponents(beta); } + + /** + The beta vector for this boost + */ + typedef DisplacementVector3D, DefaultCoordinateSystemTag > XYZVector; + XYZVector BetaVector() const; + + /** + Get elements of internal 4x4 symmetric representation, into a data + array suitable for direct use as the components of a LorentzRotation + Note -- 16 Scalars will be written into the array; if the array is not + that large, then this will lead to undefined behavior. + */ + void + GetLorentzRotation (Scalar r[]) const; + + // =========== operations ============== + + /** + Lorentz transformation operation on a Minkowski ('Cartesian') + LorentzVector + */ + LorentzVector< PxPyPzE4D > + operator() (const LorentzVector< PxPyPzE4D > & v) const; + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return LorentzVector ( r_xyzt ); + } + + /** + Lorentz transformation operation on an arbitrary 4-vector v. + Preconditions: v must implement methods x(), y(), z(), and t() + and the arbitrary vector type must have a constructor taking (x,y,z,t) + */ + template + Foreign4Vector + operator() (const Foreign4Vector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return Foreign4Vector ( r_xyzt.X(), r_xyzt.Y(), r_xyzt.Z(), r_xyzt.T() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + A4Vector operator* (const A4Vector & v) const + { + return operator()(v); + } + + /** + Invert a BoostY in place + */ + void Invert(); + + /** + Return inverse of a rotation + */ + BoostY Inverse() const; + + /** + Equality/inequality operators + */ + bool operator == (const BoostY & rhs) const { + if( fBeta != rhs.fBeta ) return false; + if( fGamma != rhs.fGamma ) return false; + return true; + } + bool operator != (const BoostY & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fBeta; // beta Y of the Boost + Scalar fGamma; // gamma of the Boost + +}; // BoostY + +// ============ Class BoostY ends here ============ + +/** + Stream Output and Input +*/ + // TODO - I/O should be put in the manipulator form +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + std::ostream & operator<< (std::ostream & os, const BoostY & b); +#endif + +} //namespace Math +} //namespace ROOT + + + + + + + +#endif /* ROOT_MathX_GenVectorX_BoostY */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostYfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostYfwd.h new file mode 100644 index 0000000000000..80a6600b379d9 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostYfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_BoostYfwd +#define ROOT_MathX_GenVectorX_BoostYfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a pure Lorentz Boost along the Y axis + */ + +class BoostY; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_BoostYfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostZ.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostZ.h new file mode 100644 index 0000000000000..ca8162aeea9ff --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostZ.h @@ -0,0 +1,221 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for BoostZ +// +// Created by: Mark Fischler Mon Nov 1 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_BoostZ +#define ROOT_MathX_GenVectorX_BoostZ 1 + +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + Class representing a Lorentz Boost along the Z axis, by beta. + For efficiency, gamma is held as well. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class BoostZ { + +public: + + typedef double Scalar; + + enum ELorentzRotationMatrixIndex { + kLXX = 0, kLXY = 1, kLXZ = 2, kLXT = 3 + , kLYX = 4, kLYY = 5, kLYZ = 6, kLYT = 7 + , kLZX = 8, kLZY = 9, kLZZ = 10, kLZT = 11 + , kLTX = 12, kLTY = 13, kLTZ = 14, kLTT = 15 + }; + + enum EBoostMatrixIndex { + kXX = 0, kXY = 1, kXZ = 2, kXT = 3 + , kYY = 4, kYZ = 5, kYT = 6 + , kZZ = 7, kZT = 8 + , kTT = 9 + }; + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity transformation) + */ + BoostZ(); + + /** + Construct given a Scalar beta_z + */ + explicit BoostZ(Scalar beta_z) { SetComponents(beta_z); } + + + // The compiler-generated copy ctor, copy assignment, and dtor are OK. + + /** + Re-adjust components to eliminate small deviations from a perfect + orthosyplectic matrix. + */ + void Rectify(); + + // ======== Components ============== + + /** + Set components from a Scalar beta_z + */ + void + SetComponents (Scalar beta_z); + + /** + Get components into a Scalar beta_z + */ + void + GetComponents (Scalar& beta_z) const; + + + /** + Retrieve the beta of the Boost + */ + Scalar Beta() const { return fBeta; } + + /** + Retrieve the gamma of the Boost + */ + Scalar Gamma() const { return fGamma; } + + /** + Set the given beta of the Boost + */ + void SetBeta(Scalar beta) { SetComponents(beta); } + + /** + The beta vector for this boost + */ + typedef DisplacementVector3D, DefaultCoordinateSystemTag > XYZVector; + XYZVector BetaVector() const; + + /** + Get elements of internal 4x4 symmetric representation, into a data + array suitable for direct use as the components of a LorentzRotation + Note -- 16 Scalars will be written into the array; if the array is not + that large, then this will lead to undefined behavior. + */ + void + GetLorentzRotation (Scalar r[]) const; + + // =========== operations ============== + + /** + Lorentz transformation operation on a Minkowski ('Cartesian') + LorentzVector + */ + LorentzVector< PxPyPzE4D > + operator() (const LorentzVector< PxPyPzE4D > & v) const; + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return LorentzVector ( r_xyzt ); + } + + /** + Lorentz transformation operation on an arbitrary 4-vector v. + Preconditions: v must implement methods x(), y(), z(), and t() + and the arbitrary vector type must have a constructor taking (x,y,z,t) + */ + template + Foreign4Vector + operator() (const Foreign4Vector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return Foreign4Vector ( r_xyzt.X(), r_xyzt.Y(), r_xyzt.Z(), r_xyzt.T() ); + } + + /** + Overload operator * for boost on a vector + */ + template + inline + A4Vector operator* (const A4Vector & v) const + { + return operator()(v); + } + + /** + Invert a BoostZ in place + */ + void Invert(); + + /** + Return inverse of a BoostZ + */ + BoostZ Inverse() const; + + /** + Equality/inequality operators + */ + bool operator == (const BoostZ & rhs) const { + if( fBeta != rhs.fBeta ) return false; + if( fGamma != rhs.fGamma ) return false; + return true; + } + bool operator != (const BoostZ & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fBeta; // boost beta z + Scalar fGamma; // boost gamma + +}; // BoostZ + +// ============ Class BoostZ ends here ============ + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +std::ostream & operator<< (std::ostream & os, const BoostZ & b); +#endif + +} //namespace Math +} //namespace ROOT + + + + + + + +#endif /* ROOT_MathX_GenVectorX_BoostZ */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostZfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostZfwd.h new file mode 100644 index 0000000000000..332ee46a63d75 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostZfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_BoostZfwd +#define ROOT_MathX_GenVectorX_BoostZfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a pure Lorentz Boost along the Z axis + */ + +class BoostZ; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_BoostZfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Boostfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Boostfwd.h new file mode 100644 index 0000000000000..ee7caa860b187 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Boostfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: M. Fischler 2005 + +#ifndef ROOT_MathX_GenVectorX_Boostfwd +#define ROOT_MathX_GenVectorX_Boostfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a pure boost in some direction + */ + +class Boost; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_Boostfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian2D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian2D.h new file mode 100644 index 0000000000000..c9160e6c09fa2 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian2D.h @@ -0,0 +1,260 @@ +// @(#)root/mathcore:$Id: b12794c790afad19142e34a401af6c233aba446b $ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * & FNAL LCG ROOT Mathlib Team * + * * + * * + **********************************************************************/ + +// Header file for class Cartesian2D +// +// Created by: Lorenzo Moneta at Mon 16 Apr 2007 +// +#ifndef ROOT_MathX_GenVectorX_Cartesian2D +#define ROOT_MathX_GenVectorX_Cartesian2D 1 + +#include "MathX/GenVectorX/Polar2Dfwd.h" + +#include "Math/Math.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + Class describing a 2D cartesian coordinate system + (x, y coordinates) + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +template +class Cartesian2D { + +public : + + typedef T Scalar; + + /** + Default constructor with x=y=0 + */ + Cartesian2D() : fX(0.0), fY(0.0) { } + + /** + Constructor from x,y coordinates + */ + Cartesian2D(Scalar xx, Scalar yy) : fX(xx), fY(yy) { } + + /** + Construct from any Vector or coordinate system implementing + X() and Y() + */ + template + explicit Cartesian2D(const CoordSystem & v) + : fX(v.X()), fY(v.Y()) { } + + + // 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 + */ + Cartesian2D(const Cartesian2D & v) : + fX(v.X()), fY(v.Y()) { } + + /** + assignment operator + */ + Cartesian2D & operator= (const Cartesian2D & v) { + fX = v.X(); + fY = v.Y(); + return *this; + } + + /** + Set internal data based on 2 Scalar numbers + */ + void SetCoordinates(Scalar xx, Scalar yy) { fX=xx; fY=yy; } + + /** + get internal data into 2 Scalar numbers + */ + void GetCoordinates(Scalar& xx, Scalar& yy ) const {xx=fX; yy=fY; } + + Scalar X() const { return fX;} + Scalar Y() const { return fY;} + Scalar Mag2() const { return fX*fX + fY*fY; } + Scalar R() const { return math_sqrt(Mag2()); } + Scalar Phi() const { return (fX == Scalar(0) && fY == Scalar(0)) ? Scalar(0) : math_atan2(fY, fX); } + + /** + set the x coordinate value keeping y constant + */ + void SetX(Scalar a) { fX = a; } + + /** + set the y coordinate value keeping x constant + */ + void SetY(Scalar a) { fY = a; } + + /** + set all values using cartesian coordinates + */ + void SetXY(Scalar xx, Scalar yy ) { + fX=xx; + fY=yy; + } + + /** + scale the vector by a scalar quantity a + */ + void Scale(Scalar a) { fX *= a; fY *= a; } + + /** + negate the vector + */ + void Negate() { fX = -fX; fY = -fY; } + + /** + rotate by an angle + */ + void Rotate(Scalar angle) { + const Scalar s = math_sin(angle); + const Scalar c = math_cos(angle); + SetCoordinates(c * fX - s * fY, s * fX + c * fY); + } + + /** + Assignment from any class implementing x(),y() + (can assign from any coordinate system) + */ + template + Cartesian2D & operator = (const CoordSystem & v) { + fX = v.x(); + fY = v.y(); + return *this; + } + + /** + Exact equality + */ + bool operator == (const Cartesian2D & rhs) const { + return fX == rhs.fX && fY == rhs.fY; + } + bool operator != (const Cartesian2D & 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 + Scalar x() const { return X();} + Scalar y() const { return Y();} + + // ============= Overloads for improved speed ================== + + template + explicit Cartesian2D( const Polar2D & v ) + { + const Scalar r = v.R(); // re-using this instead of calling v.X() and v.Y() + // is the speed improvement + fX = r * math_cos(v.Phi()); + fY = r * math_sin(v.Phi()); + } + // Technical note: This works even though only Polar2Dfwd.h is + // included (and in fact, including Polar2D.h would cause circularity + // problems). It works because any program **using** this ctor must itself + // be including Polar2D.h. + + template + Cartesian2D & operator = (const Polar2D & v) + { + const Scalar r = v.R(); + fX = r * math_cos(v.Phi()); + fY = r * math_sin(v.Phi()); + return *this; + } + + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) + + // ====== Set member functions for coordinates in other systems ======= + + void SetR(Scalar r); + + void SetPhi(Scalar phi); + +#endif + + +private: + + /** + (Contiguous) data containing the coordinates values x and y + */ + T fX; + T fY; + +}; + + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// need to put here setter methods to resolve nasty cyclical dependencies +// I need to include other coordinate systems only when Cartesian is already defined +// since they depend on it + +#include "MathX/GenVectorX/GenVector_exception.h" +#include "MathX/GenVectorX/Polar2D.h" + +// ====== Set member functions for coordinates in other systems ======= + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + template + void Cartesian2D::SetR(Scalar r) { + GenVector_exception e("Cartesian2D::SetR() is not supposed to be called"); + throw e; + Polar2D v(*this); v.SetR(r); *this = Cartesian2D(v); + } + + + template + void Cartesian2D::SetPhi(Scalar phi) { + GenVector_exception e("Cartesian2D::SetPhi() is not supposed to be called"); + throw e; + Polar2D v(*this); v.SetPhi(phi); *this = Cartesian2D(v); + } + + + + } // end namespace Math + +} // end namespace ROOT + +#endif +#endif + + + +#endif /* ROOT_MathX_GenVectorX_Cartesian2D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian2Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian2Dfwd.h new file mode 100644 index 0000000000000..406b76a806567 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian2Dfwd.h @@ -0,0 +1,21 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_Cartesian2Dfwd +#define ROOT_MathX_GenVectorX_Cartesian2Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + template + class Cartesian2D; + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_Cartesian2Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian3D.h new file mode 100644 index 0000000000000..d8dcdb72bdcb1 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian3D.h @@ -0,0 +1,320 @@ +// @(#)root/mathcore:$Id: 2fd203872f434b1e4e74933903abb3429494ea6f $ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * & FNAL LCG ROOT Mathlib Team * + * * + * * + **********************************************************************/ + +// Header file for class Cartesian3D +// +// Created by: Lorenzo Moneta at Mon May 30 11:16:56 2005 +// Major revamp: M. FIschler at Wed Jun 8 2005 +// +// Last update: $ID: $ +// +#ifndef ROOT_MathX_GenVectorX_Cartesian3D +#define ROOT_MathX_GenVectorX_Cartesian3D 1 + +#include "MathX/GenVectorX/Polar3Dfwd.h" + +#include "Math/Math.h" + +#include "MathX/GenVectorX/eta.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include +#include + + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + Class describing a 3D cartesian coordinate system + (x, y, z coordinates) + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +template +class Cartesian3D { + +public : + + typedef T Scalar; + + /** + Default constructor with x=y=z=0 + */ + Cartesian3D() : fX(0.0), fY(0.0), fZ(0.0) { } + + /** + Constructor from x,y,z coordinates + */ + Cartesian3D(Scalar xx, Scalar yy, Scalar zz) : fX(xx), fY(yy), fZ(zz) { } + + /** + Construct from any Vector or coordinate system implementing + X(), Y() and Z() + */ + template + explicit Cartesian3D(const CoordSystem & v) + : fX(v.X()), fY(v.Y()), fZ(v.Z()) { } + + // 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 + */ + Cartesian3D(const Cartesian3D & v) : + fX(v.X()), fY(v.Y()), fZ(v.Z()) { } + + /** + assignment operator + */ + Cartesian3D & operator= (const Cartesian3D & v) { + fX = v.x(); + fY = v.y(); + fZ = v.z(); + return *this; + } + + /** + Set internal data based on an array of 3 Scalar numbers + */ + void SetCoordinates( const Scalar src[] ) { fX=src[0]; fY=src[1]; fZ=src[2]; } + + /** + get internal data into an array of 3 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { dest[0] = fX; dest[1] = fY; dest[2] = fZ; } + + /** + Set internal data based on 3 Scalar numbers + */ + void SetCoordinates(Scalar xx, Scalar yy, Scalar zz) { fX=xx; fY=yy; fZ=zz; } + + /** + get internal data into 3 Scalar numbers + */ + void GetCoordinates(Scalar& xx, Scalar& yy, Scalar& zz) const {xx=fX; yy=fY; zz=fZ;} + + Scalar X() const { return fX;} + Scalar Y() const { return fY;} + Scalar Z() const { return fZ;} + Scalar Mag2() const { return fX*fX + fY*fY + fZ*fZ;} + Scalar Perp2() const { return fX*fX + fY*fY ;} + Scalar Rho() const { return math_sqrt(Perp2()); } + Scalar R() const { return math_sqrt(Mag2()); } + Scalar Theta() const { return math_atan2(Rho(), Z()); } + Scalar Phi() const { return math_atan2(fY, fX); } + + // pseudorapidity + Scalar Eta() const { + return Impl::Eta_FromRhoZ( Rho(), fZ ); + } + + /** + set the x coordinate value keeping y and z constant + */ + void SetX(Scalar xx) { fX = xx; } + + /** + set the y coordinate value keeping x and z constant + */ + void SetY(Scalar yy) { fY = yy; } + + /** + set the z coordinate value keeping x and y constant + */ + void SetZ(Scalar zz) { fZ = zz; } + + /** + set all values using cartesian coordinates + */ + void SetXYZ(Scalar xx, Scalar yy, Scalar zz) { + fX=xx; + fY=yy; + fZ=zz; + } + + /** + scale the vector by a scalar quantity a + */ + void Scale(Scalar a) + { + fX *= a; + fY *= a; + fZ *= a; + } + + /** + negate the vector + */ + void Negate() { fX = -fX; fY = -fY; fZ = -fZ; } + + /** + Assignment from any class implementing x(),y() and z() + (can assign from any coordinate system) + */ + template + Cartesian3D & operator = (const CoordSystem & v) { + fX = v.x(); + fY = v.y(); + fZ = v.z(); + return *this; + } + + /** + Exact equality + */ + bool operator == (const Cartesian3D & rhs) const { + return fX == rhs.fX && fY == rhs.fY && fZ == rhs.fZ; + } + bool operator != (const Cartesian3D & 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(); } + + // ============= Overloads for improved speed ================== + + template + explicit Cartesian3D( const Polar3D & v ) : fZ (v.Z()) + { + const T rho = v.Rho(); + // re-using this instead of calling v.X() and v.Y() + // is the speed improvement + fX = rho * math_cos(v.Phi()); + fY = rho * math_sin(v.Phi()); + } + // Technical note: This works even though only Polar3Dfwd.h is + // included (and in fact, including Polar3D.h would cause circularity + // problems). It works because any program **using** this ctor must itself + // be including Polar3D.h. + + template + Cartesian3D & operator = (const Polar3D & v) + { + const T rho = v.Rho(); + fX = rho * math_cos(v.Phi()); + fY = rho * math_sin(v.Phi()); + fZ = v.Z(); + return *this; + } + + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) + + // ====== Set member functions for coordinates in other systems ======= + + void SetR(Scalar r); + + void SetTheta(Scalar theta); + + void SetPhi(Scalar phi); + + void SetRho(Scalar rho); + + void SetEta(Scalar eta); + +#endif + + +private: + + T fX; // x coordinate + T fY; // y coordinate + T fZ; // z coordinate +}; + + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// need to put here setter methods to resolve nasty cyclical dependencies +// I need to include other coordinate systems only when Cartesian is already defined +// since they depend on it +#include "MathX/GenVectorX/GenVector_exception.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#include "MathX/GenVectorX/Polar3D.h" + + // ====== Set member functions for coordinates in other systems ======= + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +void Cartesian3D::SetR(Scalar r) { + GenVector_exception e("Cartesian3D::SetR() is not supposed to be called"); + throw e; + Polar3D v(*this); v.SetR(r); *this = Cartesian3D(v); +} + +template +void Cartesian3D::SetTheta(Scalar theta) { + GenVector_exception e("Cartesian3D::SetTheta() is not supposed to be called"); + throw e; + Polar3D v(*this); v.SetTheta(theta); *this = Cartesian3D(v); +} + +template +void Cartesian3D::SetPhi(Scalar phi) { + GenVector_exception e("Cartesian3D::SetPhi() is not supposed to be called"); + throw e; + Polar3D v(*this); v.SetPhi(phi); *this = Cartesian3D(v); +} + +template +void Cartesian3D::SetRho(Scalar rho) { + GenVector_exception e("Cartesian3D::SetRho() is not supposed to be called"); + throw e; + CylindricalEta3D v(*this); v.SetRho(rho); + *this = Cartesian3D(v); +} + +template +void Cartesian3D::SetEta(Scalar eta) { + GenVector_exception e("Cartesian3D::SetEta() is not supposed to be called"); + throw e; + CylindricalEta3D v(*this); v.SetEta(eta); + *this = Cartesian3D(v); +} + + + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + +#endif +#endif + + + +#endif /* ROOT_MathX_GenVectorX_Cartesian3D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian3Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian3Dfwd.h new file mode 100644 index 0000000000000..a1022ce9fc6ed --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian3Dfwd.h @@ -0,0 +1,21 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_Cartesian3Dfwd +#define ROOT_MathX_GenVectorX_Cartesian3Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT_MATH_ARCH { + + namespace Math { + +template +class Cartesian3D; + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_Cartesian3Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/CoordinateSystemTags.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/CoordinateSystemTags.h new file mode 100644 index 0000000000000..05c6d0914a391 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/CoordinateSystemTags.h @@ -0,0 +1,69 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team and * + * FNAL LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header source file for CoordinateSystemTag's classes +// +// Created by: Lorenzo Moneta at Wed Apr 05 2006 +// +// + +#ifndef ROOT_MathX_GenVectorX_CoordinateSystemTags +#define ROOT_MathX_GenVectorX_CoordinateSystemTags 1 + +#include "MathX/GenVectorX/AccHeaders.h" + + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + DefaultCoordinateSystemTag + Default tag for identifying any coordinate system + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + + class DefaultCoordinateSystemTag {}; + + +//__________________________________________________________________________________________ + /** + Tag for identifying vectors based on a global coordinate system + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + class GlobalCoordinateSystemTag {}; + +//__________________________________________________________________________________________ + /** + Tag for identifying vectors based on a local coordinate system + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + class LocalCoordinateSystemTag {}; + + +} // namespace Math + +} // namespace ROOT + + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Cylindrical3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cylindrical3D.h new file mode 100644 index 0000000000000..c724731f3f958 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cylindrical3D.h @@ -0,0 +1,325 @@ +// @(#)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_MathX_GenVectorX_Cylindrical3D +#define ROOT_MathX_GenVectorX_Cylindrical3D 1 + +#include "Math/Math.h" + +#include "MathX/GenVectorX/eta.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include +#include + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + 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 + + @sa Overview of the @ref GenVector "physics vector library" + */ + +template +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 + 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 Scalar(M_PI); } + inline void Restrict() + { + if (fPhi <= -pi() || fPhi > pi()) fPhi = fPhi - math_floor(fPhi / (2 * pi()) + .5) * 2 * pi(); + } +public: + + // accessors + + Scalar Rho() const { return fRho; } + Scalar Z() const { return fZ; } + Scalar Phi() const { return fPhi; } + Scalar X() const { return fRho * math_cos(fPhi); } + Scalar Y() const { return fRho * math_sin(fPhi); } + + Scalar Mag2() const { return fRho*fRho + fZ*fZ; } + Scalar R() const { return math_sqrt(Mag2()); } + Scalar Perp2() const { return fRho*fRho; } + Scalar Theta() const { return (fRho == Scalar(0) && fZ == Scalar(0)) ? Scalar(0) : math_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 + 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 ROOT_MATH_ARCH + +} // end namespace ROOT + +// move implementations here to avoid circle dependencies + +#include "MathX/GenVectorX/Cartesian3D.h" + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#include "MathX/GenVectorX/GenVector_exception.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#include "MathX/GenVectorX/Polar3D.h" +#endif + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +void Cylindrical3D::SetXYZ(Scalar xx, Scalar yy, Scalar zz) { + *this = Cartesian3D(xx, yy, zz); +} + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + + + // ====== Set member functions for coordinates in other systems ======= + + + +template +void Cylindrical3D::SetX(Scalar xx) { + GenVector_exception e("Cylindrical3D::SetX() is not supposed to be called"); + throw e; + Cartesian3D v(*this); v.SetX(xx); *this = Cylindrical3D(v); +} +template +void Cylindrical3D::SetY(Scalar yy) { + GenVector_exception e("Cylindrical3D::SetY() is not supposed to be called"); + throw e; + Cartesian3D v(*this); v.SetY(yy); *this = Cylindrical3D(v); +} +template +void Cylindrical3D::SetR(Scalar r) { + GenVector_exception e("Cylindrical3D::SetR() is not supposed to be called"); + throw e; + Polar3D v(*this); v.SetR(r); + *this = Cylindrical3D(v); +} +template +void Cylindrical3D::SetTheta(Scalar theta) { + GenVector_exception e("Cylindrical3D::SetTheta() is not supposed to be called"); + throw e; + Polar3D v(*this); v.SetTheta(theta); + *this = Cylindrical3D(v); +} +template +void Cylindrical3D::SetEta(Scalar eta) { + GenVector_exception e("Cylindrical3D::SetEta() is not supposed to be called"); + throw e; + CylindricalEta3D v(*this); v.SetEta(eta); + *this = Cylindrical3D(v); +} + +#endif +#endif + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_Cylindrical3D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Cylindrical3Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cylindrical3Dfwd.h new file mode 100644 index 0000000000000..343f21b7fe105 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cylindrical3Dfwd.h @@ -0,0 +1,24 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_Cylindrical3Dfwd +#define ROOT_MathX_GenVectorX_Cylindrical3Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a 3D Cylindrical Eta coordinate system + (rho, z, phi coordinates) + */ + +template +class Cylindrical3D; + +} +} + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/CylindricalEta3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/CylindricalEta3D.h new file mode 100644 index 0000000000000..38174e4988efd --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/CylindricalEta3D.h @@ -0,0 +1,357 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team and * + * FNAL LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class CylindricalEta3D +// +// Created by: Lorenzo Moneta at Mon May 30 11:58:46 2005 +// Major revamp: M. Fischler at Fri Jun 10 2005 +// +// Last update: $Id$ + +// +#ifndef ROOT_MathX_GenVectorX_CylindricalEta3D +#define ROOT_MathX_GenVectorX_CylindricalEta3D 1 + +#include "Math/Math.h" + +#include "MathX/GenVectorX/etaMax.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include +#include + + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + Class describing a cylindrical coordinate system based on eta (pseudorapidity) instead of z. + The base coordinates are rho (transverse component) , eta and phi + Phi is restricted to be in the range [-PI,PI) + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +template +class CylindricalEta3D { + +public : + + typedef T Scalar; + + /** + Default constructor with rho=eta=phi=0 + */ + CylindricalEta3D() : fRho(0), fEta(0), fPhi(0) { } + + /** + Construct from rho eta and phi values + */ + CylindricalEta3D(Scalar rho, Scalar eta, Scalar phi) : + fRho(rho), fEta(eta), fPhi(phi) { Restrict(); } + + /** + Construct from any Vector or coordinate system implementing + Rho(), Eta() and Phi() + */ + template + explicit CylindricalEta3D( const CoordSystem & v ) : + fRho(v.Rho() ), fEta(v.Eta() ), fPhi(v.Phi() ) + { + static Scalar bigEta = Scalar(-0.3) * math_log(std::numeric_limits::epsilon()); + if (math_fabs(fEta) > bigEta) { + // This gives a small absolute adjustment in rho, + // which, for large eta, results in a significant + // improvement in the faithfullness of reproducing z. + fRho *= v.Z() / Z(); + } + } + + // 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 + */ + CylindricalEta3D(const CylindricalEta3D & v) : + fRho(v.Rho() ), fEta(v.Eta() ), fPhi(v.Phi() ) { } + + /** + assignment operator + */ + CylindricalEta3D & operator= (const CylindricalEta3D & v) { + fRho = v.Rho(); + fEta = v.Eta(); + fPhi = v.Phi(); + return *this; + } + + /** + Set internal data based on an array of 3 Scalar numbers + */ + void SetCoordinates( const Scalar src[] ) + { fRho=src[0]; fEta=src[1]; fPhi=src[2]; Restrict(); } + + /** + get internal data into an array of 3 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { dest[0] = fRho; dest[1] = fEta; dest[2] = fPhi; } + + /** + Set internal data based on 3 Scalar numbers + */ + void SetCoordinates(Scalar rho, Scalar eta, Scalar phi) + { fRho=rho; fEta=eta; fPhi=phi; Restrict(); } + + /** + get internal data into 3 Scalar numbers + */ + void GetCoordinates(Scalar& rho, Scalar& eta, Scalar& phi) const + {rho=fRho; eta=fEta; phi=fPhi;} + +private: + inline static Scalar pi() { return M_PI; } + inline void Restrict() { + if (fPhi <= -pi() || fPhi > pi()) fPhi = fPhi - math_floor(fPhi / (2 * pi()) + .5) * 2 * pi(); + return; + } +public: + + // accessors + + T Rho() const { return fRho; } + T Eta() const { return fEta; } + T Phi() const { return fPhi; } + T X() const { return fRho * math_cos(fPhi); } + T Y() const { return fRho * math_sin(fPhi); } + T Z() const + { + return fRho > 0 ? fRho * math_sinh(fEta) : fEta == 0 ? 0 : fEta > 0 ? fEta - etaMax() : fEta + etaMax(); + } + T R() const + { + return fRho > 0 ? fRho * math_cosh(fEta) + : fEta > etaMax() ? fEta - etaMax() : fEta < -etaMax() ? -fEta - etaMax() : 0; + } + T Mag2() const + { + const Scalar r = R(); + return r * r; + } + T Perp2() const { return fRho*fRho; } + T Theta() const { return fRho > 0 ? 2 * math_atan(exp(-fEta)) : (fEta >= 0 ? 0 : pi()); } + + // setters (only for data members) + + + /** + set the rho coordinate value keeping eta and phi constant + */ + void SetRho(T rho) { + fRho = rho; + } + + /** + set the eta coordinate value keeping rho and phi constant + */ + void SetEta(T eta) { + fEta = eta; + } + + /** + set the phi coordinate value keeping rho and eta 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 eta coords, as long as a >= 0, only rho changes! + */ + void Scale (T a) { + if (a < 0) { + Negate(); + a = -a; + } + // angles do not change when scaling by a positive quantity + if (fRho > 0) { + fRho *= a; + } else if ( fEta > etaMax() ) { + fEta = ( fEta-etaMax())*a + etaMax(); + } else if ( fEta < -etaMax() ) { + fEta = ( fEta+etaMax())*a - etaMax(); + } // when rho==0 and eta is not above etaMax, vector represents 0 + // and remains unchanged + } + + /** + negate the vector + */ + void Negate ( ) { + fPhi = ( fPhi > 0 ? fPhi - pi() : fPhi + pi() ); + fEta = -fEta; + } + + // assignment operators + /** + generic assignment operator from any coordinate system + */ + template + CylindricalEta3D & operator= ( const CoordSystem & c ) { + fRho = c.Rho(); + fEta = c.Eta(); + fPhi = c.Phi(); + return *this; + } + + /** + Exact component-by-component equality + Note: Peculiar representations of the zero vector such as (0,1,0) will + not test as equal to one another. + */ + bool operator==(const CylindricalEta3D & rhs) const { + return fRho == rhs.fRho && fEta == rhs.fEta && fPhi == rhs.fPhi; + } + bool operator!= (const CylindricalEta3D & 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 SetZ(Scalar z); + + void SetR(Scalar r); + + void SetTheta(Scalar theta); + + +#endif + + +private: + T fRho; + T fEta; + T fPhi; + +}; + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + +// move implementations here to avoid circle dependencies + +#include "MathX/GenVectorX/Cartesian3D.h" + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#include "MathX/GenVectorX/GenVector_exception.h" +#include "MathX/GenVectorX/Polar3D.h" +#endif + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +void CylindricalEta3D::SetXYZ(Scalar xx, Scalar yy, Scalar zz) { + *this = Cartesian3D(xx, yy, zz); +} + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + + // ====== Set member functions for coordinates in other systems ======= + + +template +void CylindricalEta3D::SetX(Scalar xx) { + GenVector_exception e("CylindricalEta3D::SetX() is not supposed to be called"); + throw e; + Cartesian3D v(*this); v.SetX(xx); + *this = CylindricalEta3D(v); +} +template +void CylindricalEta3D::SetY(Scalar yy) { + GenVector_exception e("CylindricalEta3D::SetY() is not supposed to be called"); + throw e; + Cartesian3D v(*this); v.SetY(yy); + *this = CylindricalEta3D(v); +} +template +void CylindricalEta3D::SetZ(Scalar zz) { + GenVector_exception e("CylindricalEta3D::SetZ() is not supposed to be called"); + throw e; + Cartesian3D v(*this); v.SetZ(zz); + *this = CylindricalEta3D(v); +} +template +void CylindricalEta3D::SetR(Scalar r) { + GenVector_exception e("CylindricalEta3D::SetR() is not supposed to be called"); + throw e; + Polar3D v(*this); v.SetR(r); + *this = CylindricalEta3D(v); +} +template +void CylindricalEta3D::SetTheta(Scalar theta) { + GenVector_exception e("CylindricalEta3D::SetTheta() is not supposed to be called"); + throw e; + Polar3D v(*this); v.SetTheta(theta); + *this = CylindricalEta3D(v); +} + +#endif +#endif + + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + + +#endif /* ROOT_MathX_GenVectorX_CylindricalEta3D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/CylindricalEta3Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/CylindricalEta3Dfwd.h new file mode 100644 index 0000000000000..4132d04afb226 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/CylindricalEta3Dfwd.h @@ -0,0 +1,24 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_CylindricalEta3Dfwd +#define ROOT_MathX_GenVectorX_CylindricalEta3Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a 3D Cylindrical Eta coordinate system + (rho, eta, phi coordinates) + */ + +template +class CylindricalEta3D; + +} +} + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector2D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector2D.h new file mode 100644 index 0000000000000..11edcc8fef8d0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector2D.h @@ -0,0 +1,549 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team and * + * FNAL LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header source file for class DisplacementVector2D +// +// Created by: Lorenzo Moneta at Mon Apr 16 2007 +// + +#ifndef ROOT_MathX_GenVectorX_DisplacementVector2D +#define ROOT_MathX_GenVectorX_DisplacementVector2D 1 + +#include "MathX/GenVectorX/Cartesian2D.h" + +#include "MathX/GenVectorX/PositionVector2Dfwd.h" + +#include "MathX/GenVectorX/GenVectorIO.h" + +#include "MathX/GenVectorX/BitReproducible.h" + +#include "MathX/GenVectorX/CoordinateSystemTags.h" + +//#include "MathX/GenVectorX/Expression2D.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + + +//__________________________________________________________________________________________ + /** + Class describing a generic displacement vector in 2 dimensions. + This class is templated on the type of Coordinate system. + One example is the XYVector which is a vector based on + double precision x,y data members by using the + ROOT::Math::Cartesian2D Coordinate system. + The class is having also an extra template parameter, the coordinate system tag, + to be able to identify (tag) vector described in different reference coordinate system, + like global or local coordinate systems. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + + template + class DisplacementVector2D { + + public: + + typedef typename CoordSystem::Scalar Scalar; + typedef CoordSystem CoordinateType; + typedef Tag CoordinateSystemTag; + + // ------ ctors ------ + + /** + Default constructor. Construct an empty object with zero values + */ + DisplacementVector2D ( ) : fCoordinates() { } + + + /** + Construct from three values of type Scalar. + In the case of a XYVector the values are x,y + In the case of a polar vector they are r, phi + */ + DisplacementVector2D(Scalar a, Scalar b) : + fCoordinates ( a , b ) { } + + /** + Construct from a displacement vector expressed in different + coordinates, or using a different Scalar type, but with same coordinate system tag + */ + template + explicit DisplacementVector2D( const DisplacementVector2D & v) : + fCoordinates ( v.Coordinates() ) { } + + + /** + Construct from a position vector expressed in different coordinates + but with the same coordinate system tag + */ + template + explicit DisplacementVector2D( const PositionVector2D & p) : + fCoordinates ( p.Coordinates() ) { } + + + /** + Construct from a foreign 2D vector type, for example, Hep2Vector + Precondition: v must implement methods x() and y() + */ + template + explicit DisplacementVector2D( const ForeignVector & v) : + fCoordinates ( Cartesian2D( v.x(), v.y() ) ) { } + + + + // compiler-generated copy ctor and dtor are fine. + + // ------ assignment ------ + + /** + Assignment operator from a displacement vector of arbitrary type + */ + template + DisplacementVector2D & operator= + ( const DisplacementVector2D & v) { + fCoordinates = v.Coordinates(); + return *this; + } + + /** + Assignment operator from a position vector + (not necessarily efficient unless one or the other is Cartesian) + */ + template + DisplacementVector2D & operator= + ( const PositionVector2D & rhs) { + SetXY(rhs.x(), rhs.y() ); + return *this; + } + + + /** + Assignment from a foreign 2D vector type, for example, Hep2Vector + Precondition: v must implement methods x() and y() + */ + template + DisplacementVector2D & operator= ( const ForeignVector & v) { + SetXY( v.x(), v.y() ); + return *this; + } + + + // ------ Set, Get, and access coordinate data ------ + + /** + Retrieve a copy of the coordinates object + */ + CoordSystem Coordinates() const { + return fCoordinates; + } + + /** + Set internal data based on 2 Scalar numbers. + These are for example (x,y) for a cartesian vector or (r,phi) for a polar vector + */ + DisplacementVector2D& SetCoordinates( Scalar a, Scalar b) { + fCoordinates.SetCoordinates(a, b); + return *this; + } + + + /** + get internal data into 2 Scalar numbers. + These are for example (x,y) for a cartesian vector or (r,phi) for a polar vector + */ + void GetCoordinates( Scalar& a, Scalar& b) const + { fCoordinates.GetCoordinates(a, b); } + + + /** + set the values of the vector from the cartesian components (x,y) + (if the vector is held in polar coordinates, + then (x, y) are converted to that form) + */ + DisplacementVector2D& SetXY (Scalar a, Scalar b) { + fCoordinates.SetXY(a,b); + return *this; + } + + // ------------------- Equality ----------------- + + /** + Exact equality + */ + bool operator==(const DisplacementVector2D & rhs) const { + return fCoordinates==rhs.fCoordinates; + } + bool operator!= (const DisplacementVector2D & rhs) const { + return !(operator==(rhs)); + } + + // ------ Individual element access, in various coordinate systems ------ + + /** + Cartesian X, converting if necessary from internal coordinate system. + */ + Scalar X() const { return fCoordinates.X(); } + + /** + Cartesian Y, converting if necessary from internal coordinate system. + */ + Scalar Y() const { return fCoordinates.Y(); } + + + /** + Polar R, converting if necessary from internal coordinate system. + */ + Scalar R() const { return fCoordinates.R(); } + + + /** + Polar phi, converting if necessary from internal coordinate system. + */ + Scalar Phi() const { return fCoordinates.Phi(); } + + + // ----- Other fundamental properties ----- + + /** + Magnitute squared ( r^2 in spherical coordinate) + */ + Scalar Mag2() const { return fCoordinates.Mag2();} + + + /** + return unit vector parallel to this + */ + DisplacementVector2D Unit() const { + Scalar tot = R(); + return tot == 0 ? *this : DisplacementVector2D(*this) / tot; + } + + // ------ Setting individual elements present in coordinate system ------ + + /** + Change X - Cartesian2D coordinates only + */ + DisplacementVector2D& SetX (Scalar a) { + fCoordinates.SetX(a); + return *this; + } + + /** + Change Y - Cartesian2D coordinates only + */ + DisplacementVector2D& SetY (Scalar a) { + fCoordinates.SetY(a); + return *this; + } + + + /** + Change R - Polar2D coordinates only + */ + DisplacementVector2D& SetR (Scalar a) { + fCoordinates.SetR(a); + return *this; + } + + + /** + Change Phi - Polar2D coordinates + */ + DisplacementVector2D& SetPhi (Scalar ang) { + fCoordinates.SetPhi(ang); + return *this; + } + + + + // ------ Operations combining two vectors ------ + // -- need to have the specialized version in order to avoid + + /** + Return the scalar (dot) product of two displacement vectors. + It is possible to perform the product for any type of vector coordinates, + but they must have the same coordinate system tag + */ + template< class OtherCoords > + Scalar Dot( const DisplacementVector2D & v) const { + return X()*v.X() + Y()*v.Y(); + } + /** + Return the scalar (dot) product of two vectors. + It is possible to perform the product for any classes + implementing x() and y() member functions + */ + template< class OtherVector > + Scalar Dot( const OtherVector & v) const { + return X()*v.x() + Y()*v.y(); + } + + + + /** + Self Addition with a displacement vector. + */ + template + DisplacementVector2D & operator+= + (const DisplacementVector2D & v) { + SetXY( X() + v.X(), Y() + v.Y() ); + return *this; + } + + /** + Self Difference with a displacement vector. + */ + template + DisplacementVector2D & operator-= + (const DisplacementVector2D & v) { + SetXY( x() - v.x(), y() - v.y() ); + return *this; + } + + + /** + multiply this vector by a scalar quantity + */ + DisplacementVector2D & operator*= (Scalar a) { + fCoordinates.Scale(a); + return *this; + } + + /** + divide this vector by a scalar quantity + */ + DisplacementVector2D & operator/= (Scalar a) { + fCoordinates.Scale(1/a); + return *this; + } + + // -- The following methods (v*a and v/a) could instead be free functions. + // -- They were moved into the class to solve a problem on AIX. + + /** + Multiply a vector by a real number + */ + DisplacementVector2D operator * ( Scalar a ) const { + DisplacementVector2D tmp(*this); + tmp *= a; + return tmp; + } + + /** + Negative of the vector + */ + DisplacementVector2D operator - ( ) const { + return operator*( Scalar(-1) ); + } + + /** + Positive of the vector, return itself + */ + DisplacementVector2D operator + ( ) const {return *this;} + + /** + Division of a vector with a real number + */ + DisplacementVector2D operator/ (Scalar a) const { + DisplacementVector2D tmp(*this); + tmp /= a; + return tmp; + } + + /** + Rotate by an angle + */ + void Rotate( Scalar angle) { + return fCoordinates.Rotate(angle); + } + + + // Methods providing Limited backward name compatibility with CLHEP + + Scalar x() const { return fCoordinates.X(); } + Scalar y() const { return fCoordinates.Y(); } + Scalar r() const { return fCoordinates.R(); } + Scalar phi() const { return fCoordinates.Phi(); } + Scalar mag2() const { return fCoordinates.Mag2(); } + DisplacementVector2D unit() const {return Unit();} + + + private: + + CoordSystem fCoordinates; // internal coordinate system + + + // the following methods should not compile + + // this should not compile (if from a vector or points with different tag + template + explicit DisplacementVector2D( const DisplacementVector2D & ) {} + + template + explicit DisplacementVector2D( const PositionVector2D & ) {} + + template + DisplacementVector2D & operator=( const DisplacementVector2D & ); + + + template + DisplacementVector2D & operator=( const PositionVector2D & ); + + template + DisplacementVector2D & operator+=(const DisplacementVector2D & ); + + template + DisplacementVector2D & operator-=(const DisplacementVector2D & ); + + template + Scalar Dot( const DisplacementVector2D & ) const; + + template + DisplacementVector2D Cross( const DisplacementVector2D & ) const; + + + }; + +// ---------- DisplacementVector2D class template ends here ------------ +// --------------------------------------------------------------------- + + + /** + Addition of DisplacementVector2D vectors. + The (coordinate system) type of the returned vector is defined to + be identical to that of the first vector, which is passed by value + */ + template + inline + DisplacementVector2D + operator+( DisplacementVector2D v1, + const DisplacementVector2D & v2) { + return v1 += v2; + } + + /** + Difference between two DisplacementVector2D vectors. + The (coordinate system) type of the returned vector is defined to + be identical to that of the first vector. + */ + template + inline + DisplacementVector2D + operator-( DisplacementVector2D v1, + DisplacementVector2D const & v2) { + return v1 -= v2; + } + + + + + + /** + Multiplication of a displacement vector by real number a*v + */ + template + inline + DisplacementVector2D + operator * ( typename DisplacementVector2D::Scalar a, + DisplacementVector2D v) { + return v *= a; + // Note - passing v by value and using operator *= may save one + // copy relative to passing v by const ref and creating a temporary. + } + + + // v1*v2 notation for Cross product of two vectors is omitted, + // since it is always confusing as to whether dot product is meant. + + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + + // ------------- I/O to/from streams ------------- + + template< class char_t, class traits_t, class T, class U > + inline + std::basic_ostream & + operator << ( std::basic_ostream & os + , DisplacementVector2D const & v + ) + { + if( !os ) return os; + + typename T::Scalar a, b; + v.GetCoordinates(a, b); + + if( detail::get_manip( os, detail::bitforbit ) ) { + detail::set_manip( os, detail::bitforbit, '\00' ); + typedef GenVector_detail::BitReproducible BR; + BR::Output(os, a); + BR::Output(os, b); + } + else { + os << detail::get_manip( os, detail::open ) << a + << detail::get_manip( os, detail::sep ) << b + << detail::get_manip( os, detail::close ); + } + + return os; + + } // op<< <>() + + + template< class char_t, class traits_t, class T, class U > + inline + std::basic_istream & + operator >> ( std::basic_istream & is + , DisplacementVector2D & v + ) + { + if( !is ) return is; + + typename T::Scalar a, b; + + if( detail::get_manip( is, detail::bitforbit ) ) { + detail::set_manip( is, detail::bitforbit, '\00' ); + typedef GenVector_detail::BitReproducible BR; + BR::Input(is, a); + BR::Input(is, b); + } + else { + detail::require_delim( is, detail::open ); is >> a; + detail::require_delim( is, detail::sep ); is >> b; + detail::require_delim( is, detail::close ); + } + + if( is ) + v.SetCoordinates(a, b); + return is; + + } // op>> <>() + +#endif + + } // namespace ROOT_MATH_ARCH + +} // namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_DisplacementVector2D */ + diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector2Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector2Dfwd.h new file mode 100644 index 0000000000000..5193acd90dd8d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector2Dfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_DisplacementVector2Dfwd +#define ROOT_MathX_GenVectorX_DisplacementVector2Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + namespace ROOT_MATH_ARCH { + + /** + Class template describing a 2D displacement vector + */ + template< class CoordSystem, class Tag > + class DisplacementVector2D; + + } // namespace Math +} // namespace ROOT + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector3D.h new file mode 100644 index 0000000000000..0a0049a11be8d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector3D.h @@ -0,0 +1,709 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team and * + * FNAL LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header source file for class DisplacementVector3D +// +// Created by: Lorenzo Moneta at Mon May 30 12:21:43 2005 +// Major rewrite: M. FIschler at Wed Jun 8 2005 +// +// Last update: $Id$ +// + +#ifndef ROOT_MathX_GenVectorX_DisplacementVector3D +#define ROOT_MathX_GenVectorX_DisplacementVector3D 1 + +#include "MathX/GenVectorX/Cartesian3D.h" + +#include "MathX/GenVectorX/PositionVector3Dfwd.h" + +#include "MathX/GenVectorX/GenVectorIO.h" + +#include "MathX/GenVectorX/BitReproducible.h" + +#include "MathX/GenVectorX/CoordinateSystemTags.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include + + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Class describing a generic displacement vector in 3 dimensions. + This class is templated on the type of Coordinate system. + One example is the XYZVector which is a vector based on + double precision x,y,z data members by using the + ROOT::Math::Cartesian3D Coordinate system. + The class is having also an extra template parameter, the coordinate system tag, + to be able to identify (tag) vector described in different reference coordinate system, + like global or local coordinate systems. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + + template + class DisplacementVector3D { + + public: + + typedef typename CoordSystem::Scalar Scalar; + typedef CoordSystem CoordinateType; + typedef Tag CoordinateSystemTag; + + // ------ ctors ------ + + /** + Default constructor. Construct an empty object with zero values + */ + DisplacementVector3D ( ) : fCoordinates() { } + + + /** + Construct from three values of type Scalar. + In the case of a XYZVector the values are x,y,z + In the case of a polar vector they are r,theta, phi + */ + DisplacementVector3D(Scalar a, Scalar b, Scalar c) : + fCoordinates ( a , b, c ) { } + + /** + Construct from a displacement vector expressed in different + coordinates, or using a different Scalar type, but with same coordinate system tag + */ + template + explicit DisplacementVector3D( const DisplacementVector3D & v) : + fCoordinates ( v.Coordinates() ) { } + + + /** + Construct from a position vector expressed in different coordinates + but with the same coordinate system tag + */ + template + explicit DisplacementVector3D( const PositionVector3D & p) : + fCoordinates ( p.Coordinates() ) { } + + + /** + Construct from a foreign 3D vector type, for example, Hep3Vector + Precondition: v must implement methods x(), y() and z() + */ + template + explicit DisplacementVector3D( const ForeignVector & v) : + fCoordinates ( Cartesian3D( v.x(), v.y(), v.z() ) ) { } + + +#ifdef LATER + /** + construct from a generic linear algebra vector of at least size 3 + implementing operator []. + \par v LAVector + \par index0 index where coordinates starts (typically zero) + It works for all Coordinates types, + ( x= v[index0] for Cartesian and r=v[index0] for Polar ) + */ + template + DisplacementVector3D(const LAVector & v, size_t index0 ) { + fCoordinates = CoordSystem ( v[index0], v[index0+1], v[index0+2] ); + } +#endif + + // compiler-generated copy ctor and dtor are fine. + + // ------ assignment ------ + + /** + Assignment operator from a displacement vector of arbitrary type + */ + template + DisplacementVector3D & operator= + ( const DisplacementVector3D & v) { + fCoordinates = v.Coordinates(); + return *this; + } + + /** + Assignment operator from a position vector + (not necessarily efficient unless one or the other is Cartesian) + */ + template + DisplacementVector3D & operator= + ( const PositionVector3D & rhs) { + SetXYZ(rhs.x(), rhs.y(), rhs.z()); + return *this; + } + + + /** + Assignment from a foreign 3D vector type, for example, Hep3Vector + Precondition: v must implement methods x(), y() and z() + */ + template + DisplacementVector3D & operator= ( const ForeignVector & v) { + SetXYZ( v.x(), v.y(), v.z() ); + return *this; + } + + +#ifdef LATER + /** + assign from a generic linear algebra vector of at least size 3 + implementing operator []. This could be also a C array + \par v LAVector + \par index0 index where coordinates starts (typically zero) + It works for all Coordinates types, + ( x= v[index0] for Cartesian and r=v[index0] for Polar ) + */ + template + DisplacementVector3D & assignFrom(const LAVector & v, size_t index0 = 0) { + fCoordinates = CoordSystem ( v[index0], v[index0+1], v[index0+2] ); + return *this; + } +#endif + + // ------ Set, Get, and access coordinate data ------ + + /** + Retrieve a copy of the coordinates object + */ + CoordSystem Coordinates() const { + return fCoordinates; + } + + /** + Set internal data based on a C-style array of 3 Scalar numbers + */ + DisplacementVector3D& SetCoordinates( const Scalar src[] ) + { fCoordinates.SetCoordinates(src); return *this; } + + /** + Set internal data based on 3 Scalar numbers + */ + DisplacementVector3D& SetCoordinates( Scalar a, Scalar b, Scalar c ) + { fCoordinates.SetCoordinates(a, b, c); return *this; } + + /** + Set internal data based on 3 Scalars at *begin to *end + */ + template + DisplacementVector3D& SetCoordinates( IT begin, IT end ) + { IT a = begin; IT b = ++begin; IT c = ++begin; + (void)end; + assert (++begin==end); + SetCoordinates (*a,*b,*c); + return *this; + } + + /** + get internal data into 3 Scalar numbers + */ + void GetCoordinates( Scalar& a, Scalar& b, Scalar& c ) const + { fCoordinates.GetCoordinates(a, b, c); } + + /** + get internal data into a C-style array of 3 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { fCoordinates.GetCoordinates(dest); } + + /** + get internal data into 3 Scalars at *begin to *end (3 past begin) + */ + template + void GetCoordinates( IT begin, IT end ) const + { IT a = begin; IT b = ++begin; IT c = ++begin; + (void)end; + assert (++begin==end); + GetCoordinates (*a,*b,*c); + } + /** + get internal data into 3 Scalars starting at *begin + */ + template + void GetCoordinates( IT begin) const { + Scalar a = Scalar(0); + Scalar b = Scalar(0); + Scalar c = Scalar(0); + GetCoordinates(a, b, c); + *begin++ = a; + *begin++ = b; + *begin = c; + } + + /** + set the values of the vector from the cartesian components (x,y,z) + (if the vector is held in polar or cylindrical eta coordinates, + then (x, y, z) are converted to that form) + */ + DisplacementVector3D& SetXYZ (Scalar a, Scalar b, Scalar c) { + fCoordinates.SetXYZ(a, b, c); + return *this; + } + + // ------------------- Equality ----------------- + + /** + Exact equality + */ + bool operator==(const DisplacementVector3D & rhs) const { + return fCoordinates==rhs.fCoordinates; + } + bool operator!= (const DisplacementVector3D & rhs) const { + return !(operator==(rhs)); + } + + // ------ Individual element access, in various coordinate systems ------ + + /** + Cartesian X, converting if necessary from internal coordinate system. + */ + Scalar X() const { return fCoordinates.X(); } + + /** + Cartesian Y, converting if necessary from internal coordinate system. + */ + Scalar Y() const { return fCoordinates.Y(); } + + /** + Cartesian Z, converting if necessary from internal coordinate system. + */ + Scalar Z() const { return fCoordinates.Z(); } + + /** + Polar R, converting if necessary from internal coordinate system. + */ + Scalar R() const { return fCoordinates.R(); } + + /** + Polar theta, converting if necessary from internal coordinate system. + */ + Scalar Theta() const { return fCoordinates.Theta(); } + + /** + Polar phi, converting if necessary from internal coordinate system. + */ + Scalar Phi() const { return fCoordinates.Phi(); } + + /** + Polar eta, converting if necessary from internal coordinate system. + */ + Scalar Eta() const { return fCoordinates.Eta(); } + + /** + Cylindrical transverse component rho + */ + Scalar Rho() const { return fCoordinates.Rho(); } + + // ----- Other fundamental properties ----- + + /** + Magnitute squared ( r^2 in spherical coordinate) + */ + Scalar Mag2() const { return fCoordinates.Mag2();} + + /** + Transverse component squared (rho^2 in cylindrical coordinates. + */ + Scalar Perp2() const { return fCoordinates.Perp2();} + + /** + return unit vector parallel to this (scalar) + */ + template ::value>::type * = nullptr> + DisplacementVector3D Unit() const + { + const auto tot = R(); + return tot == 0 ? *this : DisplacementVector3D(*this) / tot; + } + + /** + return unit vector parallel to this (vector) + */ + template ::value>::type * = nullptr> + DisplacementVector3D Unit() const + { + SCALAR tot = R(); + tot(tot == SCALAR(0)) = SCALAR(1); + return DisplacementVector3D(*this) / tot; + } + + // ------ Setting of individual elements present in coordinate system ------ + + /** + Change X - Cartesian3D coordinates only + */ + DisplacementVector3D& SetX (Scalar xx) { fCoordinates.SetX(xx); return *this;} + + /** + Change Y - Cartesian3D coordinates only + */ + DisplacementVector3D& SetY (Scalar yy) { fCoordinates.SetY(yy); return *this;} + + /** + Change Z - Cartesian3D coordinates only + */ + DisplacementVector3D& SetZ (Scalar zz) { fCoordinates.SetZ(zz); return *this;} + + /** + Change R - Polar3D coordinates only + */ + DisplacementVector3D& SetR (Scalar rr) { fCoordinates.SetR(rr); return *this;} + + /** + Change Theta - Polar3D coordinates only + */ + DisplacementVector3D& SetTheta (Scalar ang) { fCoordinates.SetTheta(ang); return *this;} + + /** + Change Phi - Polar3D or CylindricalEta3D coordinates + */ + DisplacementVector3D& SetPhi (Scalar ang) { fCoordinates.SetPhi(ang); return *this;} + + /** + Change Rho - CylindricalEta3D coordinates only + */ + DisplacementVector3D& SetRho (Scalar rr) { fCoordinates.SetRho(rr); return *this;} + + /** + Change Eta - CylindricalEta3D coordinates only + */ + DisplacementVector3D& SetEta (Scalar etaval) { fCoordinates.SetEta(etaval); return *this;} + + + // ------ Operations combining two vectors ------ + // -- need to have the specialized version in order to avoid + + /** + Return the scalar (dot) product of two displacement vectors. + It is possible to perform the product for any type of vector coordinates, + but they must have the same coordinate system tag + */ + template< class OtherCoords > + Scalar Dot( const DisplacementVector3D & v) const { + return X()*v.X() + Y()*v.Y() + Z()*v.Z(); + } + /** + Return the scalar (dot) product of two vectors. + It is possible to perform the product for any classes + implementing x(), y() and z() member functions + */ + template< class OtherVector > + Scalar Dot( const OtherVector & v) const { + return X()*v.x() + Y()*v.y() + Z()*v.z(); + } + + /** + Return vector (cross) product of two displacement vectors, + as a vector in the coordinate system of this class. + It is possible to perform the product for any type of vector coordinates, + but they must have the same coordinate system tag + */ + template + DisplacementVector3D Cross( const DisplacementVector3D & v) const { + DisplacementVector3D result; + result.SetXYZ ( Y()*v.Z() - v.Y()*Z(), + Z()*v.X() - v.Z()*X(), + X()*v.Y() - v.X()*Y() ); + return result; + } + /** + Return vector (cross) product of two vectors, + as a vector in the coordinate system of this class. + It is possible to perform the product for any classes + implementing X(), Y() and Z() member functions + */ + template + DisplacementVector3D Cross( const OtherVector & v) const { + DisplacementVector3D result; + result.SetXYZ ( Y()*v.z() - v.y()*Z(), + Z()*v.x() - v.z()*X(), + X()*v.y() - v.x()*Y() ); + return result; + } + + + + /** + Self Addition with a displacement vector. + */ + template + DisplacementVector3D & operator+= + (const DisplacementVector3D & v) { + SetXYZ( X() + v.X(), Y() + v.Y(), Z() + v.Z() ); + return *this; + } + + /** + Self Difference with a displacement vector. + */ + template + DisplacementVector3D & operator-= + (const DisplacementVector3D & v) { + SetXYZ( x() - v.x(), y() - v.y(), z() - v.z() ); + return *this; + } + + + /** + multiply this vector by a scalar quantity + */ + DisplacementVector3D & operator*= (Scalar a) { + fCoordinates.Scale(a); + return *this; + } + + /** + divide this vector by a scalar quantity + */ + DisplacementVector3D & operator/= (Scalar a) { + fCoordinates.Scale(1/a); + return *this; + } + + // The following methods (v*a and v/a) could instead be free functions. + // They were moved into the class to solve a problem on AIX. + + /** + Multiply a vector by a real number + */ + DisplacementVector3D operator * ( Scalar a ) const { + DisplacementVector3D tmp(*this); + tmp *= a; + return tmp; + } + + /** + Negative of the vector + */ + DisplacementVector3D operator - ( ) const { + return operator*( Scalar(-1) ); + } + + /** + Positive of the vector, return itself + */ + DisplacementVector3D operator + ( ) const {return *this;} + + /** + Division of a vector with a real number + */ + DisplacementVector3D operator/ (Scalar a) const { + DisplacementVector3D tmp(*this); + tmp /= a; + return tmp; + } + + + // Methods providing limited backward name compatibility with CLHEP + + Scalar x() const { return fCoordinates.X(); } + Scalar y() const { return fCoordinates.Y(); } + Scalar z() const { return fCoordinates.Z(); } + Scalar r() const { return fCoordinates.R(); } + Scalar theta() const { return fCoordinates.Theta(); } + Scalar phi() const { return fCoordinates.Phi(); } + Scalar eta() const { return fCoordinates.Eta(); } + Scalar rho() const { return fCoordinates.Rho(); } + Scalar mag2() const { return fCoordinates.Mag2(); } + Scalar perp2() const { return fCoordinates.Perp2(); } + DisplacementVector3D unit() const {return Unit();} + + + private: + + CoordSystem fCoordinates; // internal coordinate system + +#ifdef NOT_SURE_THIS_SHOULD_BE_FORBIDDEN + /** + Cross product involving a position vector is inappropriate + */ + template + DisplacementVector3D Cross( const PositionVector3D & ) const; +#endif + + // the following methods should not compile + + // this should not compile (if from a vector or points with different tag + template + explicit DisplacementVector3D( const DisplacementVector3D & ) {} + + template + explicit DisplacementVector3D( const PositionVector3D & ) {} + + template + DisplacementVector3D & operator=( const DisplacementVector3D & ); + + + template + DisplacementVector3D & operator=( const PositionVector3D & ); + + template + DisplacementVector3D & operator+=(const DisplacementVector3D & ); + + template + DisplacementVector3D & operator-=(const DisplacementVector3D & ); + + template + Scalar Dot( const DisplacementVector3D & ) const; + + template + DisplacementVector3D Cross( const DisplacementVector3D & ) const; + + + }; + +// ---------- DisplacementVector3D class template ends here ------------ +// --------------------------------------------------------------------- + + + + /** + Addition of DisplacementVector3D vectors. + The (coordinate system) type of the returned vector is defined to + be identical to that of the first vector, which is passed by value + */ + template + inline + DisplacementVector3D + operator+( DisplacementVector3D v1, + const DisplacementVector3D & v2) { + return v1 += v2; + } + + /** + Difference between two DisplacementVector3D vectors. + The (coordinate system) type of the returned vector is defined to + be identical to that of the first vector. + */ + template + inline + DisplacementVector3D + operator-( DisplacementVector3D v1, + DisplacementVector3D const & v2) { + return v1 -= v2; + } + + //#endif // not __CINT__ + + /** + Multiplication of a displacement vector by real number a*v + */ + template + inline + DisplacementVector3D + operator * ( typename DisplacementVector3D::Scalar a, + DisplacementVector3D v) { + return v *= a; + // Note - passing v by value and using operator *= may save one + // copy relative to passing v by const ref and creating a temporary. + } + + + // v1*v2 notation for Cross product of two vectors is omitted, + // since it is always confusing as to whether dot product is meant. + + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + // ------------- I/O to/from streams ------------- + + template ::Scalar>::value>::type * = + nullptr> + std::basic_ostream &operator<<(std::basic_ostream &os, + DisplacementVector3D const &v) + { + if (os) { + + typename T::Scalar a, b, c; + v.GetCoordinates(a, b, c); + + if (detail::get_manip(os, detail::bitforbit)) { + detail::set_manip(os, detail::bitforbit, '\00'); + typedef GenVector_detail::BitReproducible BR; + BR::Output(os, a); + BR::Output(os, b); + BR::Output(os, c); + } else { + os << detail::get_manip(os, detail::open) << a << detail::get_manip(os, detail::sep) << b + << detail::get_manip(os, detail::sep) << c << detail::get_manip(os, detail::close); + } + } + return os; + } // op<< <>() + + template ::Scalar>::value>::type * = + nullptr> + std::basic_ostream &operator<<(std::basic_ostream &os, + DisplacementVector3D const &v) + { + if (os) { + os << "{ "; + for (std::size_t i = 0; i < PositionVector3D::Scalar::Size; ++i) { + os << "(" << v.x()[i] << "," << v.y()[i] << "," << v.z()[i] << ") "; + } + os << "}"; + } + return os; + } // op<< <>() + + template< class char_t, class traits_t, class T, class U > + inline + std::basic_istream & + operator >> ( std::basic_istream & is + , DisplacementVector3D & v + ) + { + if( !is ) return is; + + typename T::Scalar a, b, c; + + if( detail::get_manip( is, detail::bitforbit ) ) { + detail::set_manip( is, detail::bitforbit, '\00' ); + typedef GenVector_detail::BitReproducible BR; + BR::Input(is, a); + BR::Input(is, b); + BR::Input(is, c); + } + else { + detail::require_delim( is, detail::open ); is >> a; + detail::require_delim( is, detail::sep ); is >> b; + detail::require_delim( is, detail::sep ); is >> c; + detail::require_delim( is, detail::close ); + } + + if( is ) + v.SetCoordinates(a, b, c); + return is; + + } // op>> <>() + +#endif + + + } // namespace ROOT_MATH_ARCH + +} // namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_DisplacementVector3D */ + diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector3Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector3Dfwd.h new file mode 100644 index 0000000000000..7c6481dc1e70b --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector3Dfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_DisplacementVector3Dfwd +#define ROOT_MathX_GenVectorX_DisplacementVector3Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + namespace ROOT_MATH_ARCH { + + /** + Class template describing a 3D displacement vector + */ + template< class CoordSystem, class Tag > + class DisplacementVector3D; + + } // namespace Math +} // namespace ROOT + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/EulerAngles.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/EulerAngles.h new file mode 100644 index 0000000000000..25f92ae5c9263 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/EulerAngles.h @@ -0,0 +1,387 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class EulerAngles +// +// Created by: Lorenzo Moneta at Tue May 10 17:55:10 2005 +// +// Last update: Tue May 10 17:55:10 2005 +// +#ifndef ROOT_MathX_GenVectorX_EulerAngles +#define ROOT_MathX_GenVectorX_EulerAngles 1 + +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/3DConversions.h" +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + EulerAngles class describing rotation as three angles (Euler Angles). + The Euler angles definition matches that of Classical Mechanics (Goldstein). + It is also the same convention defined in + mathworld + and used in Mathematica and CLHEP. Note that the ROOT class TRotation defines + a slightly different convention. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ +class EulerAngles { + +public: + + typedef double Scalar; + + /** + Default constructor + */ + EulerAngles() : fPhi(0.0), fTheta(0.0), fPsi(0.0) { } + + /** + Constructor from phi, theta and psi + */ + EulerAngles( Scalar phi, Scalar theta, Scalar psi ) : + fPhi(phi), fTheta(theta), fPsi(psi) + {Rectify();} // Added 27 Jan. 06 JMM + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of three Scalars, to be treated as + the angles phi, theta and psi. + */ + template + EulerAngles(IT begin, IT end) { SetComponents(begin,end); } + + // The compiler-generated copy ctor, copy assignment, and dtor are OK. + + /** + Re-adjust components place angles in canonical ranges + */ + void Rectify(); + + + // ======== Construction and assignment from any other rotation ================== + + /** + Create from any other supported rotation (see gv_detail::convert ) + */ + template + explicit EulerAngles(const OtherRotation & r) {gv_detail::convert(r,*this);} + + /** + Assign from any other rotation (see gv_detail::convert ) + */ + template + EulerAngles & operator=( OtherRotation const & r ) { + gv_detail::convert(r,*this); + return *this; + } + +#ifdef OLD + explicit EulerAngles(const Rotation3D & r) {gv_detail::convert(r,*this);} + + /** + Construct from a rotation matrix + */ + explicit EulerAngles(const Rotation3D & r) {gv_detail::convert(r,*this);} + + /** + Construct from a rotation represented by a Quaternion + */ + explicit EulerAngles(const Quaternion & q) {gv_detail::convert(q,*this);} + + /** + Construct from an AxisAngle + */ + explicit EulerAngles(const AxisAngle & a ) { gv_detail::convert(a, *this); } + + /** + Construct from an axial rotation + */ + explicit EulerAngles( RotationZ const & r ) { gv_detail::convert(r, *this); } + explicit EulerAngles( RotationY const & r ) { gv_detail::convert(r, *this); } + explicit EulerAngles( RotationX const & r ) { gv_detail::convert(r, *this); } + + + /** + Assign from an AxisAngle + */ + EulerAngles & + operator=( AxisAngle const & a ) { return operator=(EulerAngles(a)); } + + /** + Assign from a Quaternion + */ + EulerAngles & + operator=( Quaternion const & q ) {return operator=(EulerAngles(q)); } + + /** + Assign from an axial rotation + */ + EulerAngles & + operator=( RotationZ const & r ) { return operator=(EulerAngles(r)); } + EulerAngles & + operator=( RotationY const & r ) { return operator=(EulerAngles(r)); } + EulerAngles & + operator=( RotationX const & r ) { return operator=(EulerAngles(r)); } + +#endif + + // ======== Components ============== + + /** + Set the three Euler angles given a pair of pointers or iterators + defining the beginning and end of an array of three Scalars. + */ + template + void SetComponents(IT begin, IT end) { + fPhi = *begin++; + fTheta = *begin++; + fPsi = *begin++; + (void)end; + assert(begin == end); + Rectify(); // Added 27 Jan. 06 JMM + } + + /** + Get the axis and then the angle into data specified by an iterator begin + and another to the end of the desired data (4 past start). + */ + template + void GetComponents(IT begin, IT end) const { + *begin++ = fPhi; + *begin++ = fTheta; + *begin++ = fPsi; + (void)end; + assert(begin == end); + } + + /** + Get the axis and then the angle into data specified by an iterator begin + */ + template + void GetComponents(IT begin) const { + *begin++ = fPhi; + *begin++ = fTheta; + *begin = fPsi; + } + + /** + Set the components phi, theta, psi based on three Scalars. + */ + void SetComponents(Scalar phi, Scalar theta, Scalar psi) { + fPhi=phi; fTheta=theta; fPsi=psi; + Rectify(); // Added 27 Jan. 06 JMM + } + + /** + Get the components phi, theta, psi into three Scalars. + */ + void GetComponents(Scalar & phi, Scalar & theta, Scalar & psi) const { + phi=fPhi; theta=fTheta; psi=fPsi; + } + + /** + Set Phi Euler angle // JMM 30 Jan. 2006 + */ + void SetPhi(Scalar phi) { fPhi=phi; Rectify(); } + + /** + Return Phi Euler angle + */ + Scalar Phi() const { return fPhi; } + + /** + Set Theta Euler angle // JMM 30 Jan. 2006 + */ + void SetTheta(Scalar theta) { fTheta=theta; Rectify(); } + + /** + Return Theta Euler angle + */ + Scalar Theta() const { return fTheta; } + + /** + Set Psi Euler angle // JMM 30 Jan. 2006 + */ + void SetPsi(Scalar psi) { fPsi=psi; Rectify(); } + + /** + Return Psi Euler angle + */ + Scalar Psi() const { return fPsi; } + + // =========== operations ============== + + + /** + Rotation operation on a displacement vector in any coordinate system and tag + */ + template + DisplacementVector3D + operator() (const DisplacementVector3D & v) const { + return Rotation3D(*this) ( v ); + } + + /** + Rotation operation on a position vector in any coordinate system + */ + template + PositionVector3D + operator() (const PositionVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz(v); + DisplacementVector3D< Cartesian3D,U > rxyz = operator()(xyz); + return PositionVector3D ( rxyz ); + } + + /** + Rotation operation on a Lorentz vector in any 4D coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector< PxPyPzE4D > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E()); + return LorentzVector ( xyzt ); + } + + /** + Rotation operation on an arbitrary vector v. + Preconditions: v must implement methods x(), y(), and z() + and the arbitrary vector type must have a constructor taking (x,y,z) + */ + template + ForeignVector + operator() (const ForeignVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + AVector operator* (const AVector & v) const + { + return operator()(v); + } + + /** + Invert a rotation in place + */ + // theta stays the same and negative rotation in Theta is done via a rotation + // of + PI in phi and Psi + void Invert() { + Scalar tmp = -fPhi; + fPhi = -fPsi + Pi(); + fPsi=tmp + Pi(); + } + + /** + Return inverse of a rotation + */ + EulerAngles Inverse() const { return EulerAngles(-fPsi + Pi(), fTheta, -fPhi + Pi()); } + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) two rotations + */ + EulerAngles operator * (const Rotation3D & r) const; + EulerAngles operator * (const AxisAngle & a) const; + EulerAngles operator * (const EulerAngles & e) const; + EulerAngles operator * (const Quaternion & q) const; + EulerAngles operator * (const RotationX & rx) const; + EulerAngles operator * (const RotationY & ry) const; + EulerAngles operator * (const RotationZ & rz) const; + + /** + Post-Multiply (on right) by another rotation : T = T*R + */ + template + EulerAngles & operator *= (const R & r) { return *this = (*this)*r; } + + /** + Distance between two rotations + */ + template + Scalar Distance ( const R & r ) const {return gv_detail::dist(*this,r);} + + /** + Equality/inequality operators + */ + bool operator == (const EulerAngles & rhs) const { + if( fPhi != rhs.fPhi ) return false; + if( fTheta != rhs.fTheta ) return false; + if( fPsi != rhs.fPsi ) return false; + return true; + } + bool operator != (const EulerAngles & rhs) const { + return ! operator==(rhs); + } + +private: + + double fPhi; // Z rotation angle (first) defined in [-PI,PI] + double fTheta; // X rotation angle (second) defined only [0,PI] + double fPsi; // Z rotation angle (third) defined in [-PI,PI] + + static double Pi() { return M_PI; } + +}; // EulerAngles + +/** + Distance between two rotations + */ +template +inline +typename EulerAngles::Scalar +Distance ( const EulerAngles& r1, const R & r2) {return gv_detail::dist(r1,r2);} + +/** + Multiplication of an axial rotation by an AxisAngle + */ +EulerAngles operator* (RotationX const & r1, EulerAngles const & r2); +EulerAngles operator* (RotationY const & r1, EulerAngles const & r2); +EulerAngles operator* (RotationZ const & r1, EulerAngles const & r2); + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +std::ostream & operator<< (std::ostream & os, const EulerAngles & e); + +#endif + +} // namespace Math +} // namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_EulerAngles */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/EulerAnglesfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/EulerAnglesfwd.h new file mode 100644 index 0000000000000..7ae55726f10fb --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/EulerAnglesfwd.h @@ -0,0 +1,23 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_EulerAnglesfwd +#define ROOT_MathX_GenVectorX_EulerAnglesfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a rotation represented + by Euler angles phi, theta, psi + */ + +class EulerAngles; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_EulerAnglesfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/GenVectorIO.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/GenVectorIO.h new file mode 100644 index 0000000000000..79ee0d790954c --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/GenVectorIO.h @@ -0,0 +1,225 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team (FNAL component) * + * * + * * + **********************************************************************/ + +// Support templates (class and function) for stream i/o of vectors +// This is a utuility to allow for control, via manipulators, of the +// form of +// +// Created by: W. E. Brown and M. Fischler at Tue Jun 21 2005 +// +// Last update: Tue Jun 21 2005 +// +#ifndef ROOT_MathX_GenVectorX_GenVectorIO +#define ROOT_MathX_GenVectorX_GenVectorIO 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +#include +#include + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +namespace ROOT { +namespace ROOT_MATH_ARCH { + +namespace detail { + + +// -------- Manipulator support ---------- + + +enum manip_t { open, sep, close, bitforbit }; + + +inline int + ios_data( int k ) +{ + static int const ios_data[4] = { std::ios::xalloc() // open + , std::ios::xalloc() // sep + , std::ios::xalloc() // close + , std::ios::xalloc() // bitforbit + }; + + return ios_data[k]; + +} // ios_data() + + +template< class char_t, class traits_t > + inline char_t + get_manip( std::basic_ios & ios + , manip_t m + ) +{ + char_t ch = static_cast( ios.iword( ios_data(m) ) ); + if( ch ) return ch; + + switch( m ) + { default : return ios.widen( '?' ); + case open : return ios.widen( '(' ); + case close : return ios.widen( ')' ); + case sep : return ios.widen( ',' ); + case bitforbit : return ch; + } + +} // get_manip<>() + + +template< class char_t, class traits_t > + inline void + set_manip( std::basic_ios & ios + , manip_t m + , char_t ch + ) +{ + ios.iword( ios_data(m) ) = static_cast(ch); + +} // set_manip<>() + + +template< class char_t > + class manipulator +{ +public: + explicit + manipulator( manip_t m + , char_t ch = 0 + ) + : fMan(m) + , fChar(ch) + { } + + template< class traits_t > + void + set( std::basic_ios & ios ) const + { + set_manip( ios, fMan, fChar ); + } + +private: + manip_t fMan; + char_t fChar; + +}; // manipulator<> + + +template< class char_t, class traits_t > + inline + std::basic_istream & + require_delim( std::basic_istream & is + , manip_t m + ) +{ + char_t delim = get_manip( is, m ); + if( std::isspace(delim) ) return is; + + char_t ch; + is >> ch; + if( ch != delim ) + is.setstate( std::ios::failbit ); + + return is; + +} // require_delim<>() + + +template< class char_t, class traits_t > + inline + std::basic_ostream & + operator << ( std::basic_ostream & os + , detail::manipulator const & manip + ) + +{ + manip.set(os); + return os; + +} // op<< <>() + + +template< class char_t, class traits_t > + inline + std::basic_istream & + operator >> ( std::basic_istream & is + , detail::manipulator const & manip + ) + +{ + manip.set(is); + return is; + +} // op>> <>() + +} // namespace detail + + +// --------- Functions that allow a user to control vector I/O ---------- + + + +template< class char_t > + inline + detail::manipulator + set_open( char_t ch ) +{ + return detail::manipulator( detail::open, ch ); + +} // set_open<>() + + +template< class char_t > + inline + detail::manipulator + set_separator( char_t ch ) +{ + return detail::manipulator( detail::sep, ch ); + +} // set_separator<>() + + +template< class char_t > + inline + detail::manipulator + set_close( char_t ch ) +{ + return detail::manipulator( detail::close, ch ); + +} // set_close<>() + + +template< class char_t, class traits_t > + inline + std::basic_ios & + human_readable( std::basic_ios & ios ) +{ + ios.iword( ios_data(detail::bitforbit) ) = 0L; + return ios; + +} // human_readable<>() + + +template< class char_t, class traits_t > + inline + std::basic_ios & + machine_readable( std::basic_ios & ios ) +{ + ios.iword( ios_data(detail::bitforbit) ) = 1L; + return ios; + +} // machine_readable<>() + + + +} // namespace ROOT +} // namespace Math + +#endif + +#endif // ROOT_MathX_GenVectorX_GenVectorIO diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/GenVector_exception.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/GenVector_exception.h new file mode 100644 index 0000000000000..156dc3a6bd382 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/GenVector_exception.h @@ -0,0 +1,98 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_GenVector_exception +#define ROOT_MathX_GenVectorX_GenVector_exception 1 + +// ====================================================================== +// $Id $ +// +// Define the exception type used throughout this package. +// ====================================================================== + +// ---------------------------------------------------------------------- +// Prolog + +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +namespace ROOT { +namespace ROOT_MATH_ARCH { + +class GenVector_exception; +inline void Throw(GenVector_exception &e); +namespace GenVector { +inline void Throw(const char *); +} + +// ---------------------------------------------------------------------- +// GenVector_exception class definition +// +// This class needs to be entirely contained in this header, otherwise +// the interactive usage of entities such as ROOT::Math::PtEtaPhiMVector +// is not possible because of missing symbols. +// This is due to the fact that the Throw function is used in the inline +// code bu this function is implemented in the Genvector library. +class GenVector_exception : public std::runtime_error { +public: + GenVector_exception(const std::string &s) : runtime_error(s) {} + + // Compiler-generated copy ctor, copy assignment, dtor are fine + // Inherited what() from runtime_error is fine + + static bool EnableThrow() + { + bool tmp = GenVector_exception::IsOn(); + IsOn() = true; + return tmp; + } + static bool DisableThrow() + { + bool tmp = GenVector_exception::IsOn(); + IsOn() = false; + return tmp; + } + +private: + friend void Throw(GenVector_exception &); + friend void GenVector::Throw(const char *); + + static bool &IsOn() + { + static bool isOn = false; + return isOn; + }; + +}; // GenVector_exception + +// ---------------------------------------------------------------------- +// Epilog + +/// throw explicitly GenVector exceptions +inline void Throw(GenVector_exception &e) +{ + if (GenVector_exception::IsOn()) + throw e; +} + +namespace GenVector { +/// function throwing exception, by creating internally a GenVector_exception only when needed +inline void Throw(const char *s) +{ + if (!GenVector_exception::IsOn()) + return; + GenVector_exception e(s); + throw e; +} +} // namespace GenVector + +} // namespace Math +} // namespace ROOT + +#endif + +#endif // GENVECTOR_EXCEPTION_H diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzRotation.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzRotation.h new file mode 100644 index 0000000000000..1e9152dd965b8 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzRotation.h @@ -0,0 +1,499 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for LorentzRotation +// +// Created by: Mark Fischler Mon Aug 8 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_LorentzRotation +#define ROOT_MathX_GenVectorX_LorentzRotation 1 + +#include "MathX/GenVectorX/LorentzRotationfwd.h" + +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" + +#include "MathX/GenVectorX/Rotation3Dfwd.h" +#include "MathX/GenVectorX/AxisAnglefwd.h" +#include "MathX/GenVectorX/EulerAnglesfwd.h" +#include "MathX/GenVectorX/Quaternionfwd.h" +#include "MathX/GenVectorX/RotationXfwd.h" +#include "MathX/GenVectorX/RotationYfwd.h" +#include "MathX/GenVectorX/RotationZfwd.h" +#include "MathX/GenVectorX/Boost.h" +#include "MathX/GenVectorX/BoostX.h" +#include "MathX/GenVectorX/BoostY.h" +#include "MathX/GenVectorX/BoostZ.h" + +#include "MathX/GenVectorX/AccHeaders.h" + + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ + /** + Lorentz transformation class with the (4D) transformation represented by + a 4x4 orthosymplectic matrix. + See also Boost, BoostX, BoostY and BoostZ for classes representing + specialized Lorentz transformations. + Also, the 3-D rotation classes can be considered to be special Lorentz + transformations which do not mix space and time components. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class LorentzRotation { + +public: + + typedef double Scalar; + + enum ELorentzRotationMatrixIndex { + kXX = 0, kXY = 1, kXZ = 2, kXT = 3 + , kYX = 4, kYY = 5, kYZ = 6, kYT = 7 + , kZX = 8, kZY = 9, kZZ = 10, kZT = 11 + , kTX = 12, kTY = 13, kTZ = 14, kTT = 15 + }; + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity transformation) + */ + LorentzRotation(); + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of sixteen Scalars + */ + template + LorentzRotation(IT begin, IT end) { SetComponents(begin,end); } + + // The compiler-generated and dtor are OK but we have implementwd the copy-ctor and + // assignment operators since we have a template assignment + + /** + Copy constructor + */ + LorentzRotation( LorentzRotation const & r ) { + *this = r; + } + + /** + Construct from a pure boost + */ + explicit LorentzRotation( Boost const & b ) { b.GetLorentzRotation( fM+0 ); } + explicit LorentzRotation( BoostX const & bx ) { bx.GetLorentzRotation( fM+0 ); } + explicit LorentzRotation( BoostY const & by ) { by.GetLorentzRotation( fM+0 ); } + explicit LorentzRotation( BoostZ const & bz ) { bz.GetLorentzRotation( fM+0 ); } + + /** + Construct from a 3-D rotation (no space-time mixing) + */ + explicit LorentzRotation( Rotation3D const & r ); + explicit LorentzRotation( AxisAngle const & a ); + explicit LorentzRotation( EulerAngles const & e ); + explicit LorentzRotation( Quaternion const & q ); + explicit LorentzRotation( RotationX const & r ); + explicit LorentzRotation( RotationY const & r ); + explicit LorentzRotation( RotationZ const & r ); + + /** + Construct from a linear algebra matrix of size at least 4x4, + which must support operator()(i,j) to obtain elements (0,3) thru (3,3). + Precondition: The matrix is assumed to be orthosymplectic. NO checking + or re-adjusting is performed. + Note: (0,0) refers to the XX component; (3,3) refers to the TT component. + */ + template + explicit LorentzRotation(const ForeignMatrix & m) { SetComponents(m); } + + /** + Construct from four orthosymplectic vectors (which must have methods + x(), y(), z() and t()) which will be used as the columns of the Lorentz + rotation matrix. The orthosymplectic conditions will be checked, and + values adjusted so that the result will always be a good Lorentz rotation + matrix. + */ + template + LorentzRotation(const Foreign4Vector& v1, + const Foreign4Vector& v2, + const Foreign4Vector& v3, + const Foreign4Vector& v4 ) { SetComponents(v1, v2, v3, v4); } + + + /** + Raw constructor from sixteen Scalar components (without any checking) + */ + LorentzRotation(Scalar xx, Scalar xy, Scalar xz, Scalar xt, + Scalar yx, Scalar yy, Scalar yz, Scalar yt, + Scalar zx, Scalar zy, Scalar zz, Scalar zt, + Scalar tx, Scalar ty, Scalar tz, Scalar tt) + { + SetComponents (xx, xy, xz, xt, + yx, yy, yz, yt, + zx, zy, zz, zt, + tx, ty, tz, tt); + } + + /** + Assign from another LorentzRotation + */ + LorentzRotation & + operator=( LorentzRotation const & rhs ) { + SetComponents( rhs.fM[0], rhs.fM[1], rhs.fM[2], rhs.fM[3], + rhs.fM[4], rhs.fM[5], rhs.fM[6], rhs.fM[7], + rhs.fM[8], rhs.fM[9], rhs.fM[10], rhs.fM[11], + rhs.fM[12], rhs.fM[13], rhs.fM[14], rhs.fM[15] ); + return *this; + } + + /** + Assign from a pure boost + */ + LorentzRotation & + operator=( Boost const & b ) { return operator=(LorentzRotation(b)); } + LorentzRotation & + operator=( BoostX const & b ) { return operator=(LorentzRotation(b)); } + LorentzRotation & + operator=( BoostY const & b ) { return operator=(LorentzRotation(b)); } + LorentzRotation & + operator=( BoostZ const & b ) { return operator=(LorentzRotation(b)); } + + /** + Assign from a 3-D rotation + */ + LorentzRotation & + operator=( Rotation3D const & r ) { return operator=(LorentzRotation(r)); } + LorentzRotation & + operator=( AxisAngle const & a ) { return operator=(LorentzRotation(a)); } + LorentzRotation & + operator=( EulerAngles const & e ) { return operator=(LorentzRotation(e)); } + LorentzRotation & + operator=( Quaternion const & q ) { return operator=(LorentzRotation(q)); } + LorentzRotation & + operator=( RotationZ const & r ) { return operator=(LorentzRotation(r)); } + LorentzRotation & + operator=( RotationY const & r ) { return operator=(LorentzRotation(r)); } + LorentzRotation & + operator=( RotationX const & r ) { return operator=(LorentzRotation(r)); } + + /** + Assign from a linear algebra matrix of size at least 4x4, + which must support operator()(i,j) to obtain elements (0,3) thru (3,3). + Precondition: The matrix is assumed to be orthosymplectic. NO checking + or re-adjusting is performed. + */ + template + LorentzRotation & + operator=(const ForeignMatrix & m) { + SetComponents( m(0,0), m(0,1), m(0,2), m(0,3), + m(1,0), m(1,1), m(1,2), m(1,3), + m(2,0), m(2,1), m(2,2), m(2,3), + m(3,0), m(3,1), m(3,2), m(3,3) ); + return *this; + } + + /** + Re-adjust components to eliminate small deviations from a perfect + orthosyplectic matrix. + */ + void Rectify(); + + // ======== Components ============== + + /** + Set components from four orthosymplectic vectors (which must have methods + x(), y(), z(), and t()) which will be used as the columns of the + Lorentz rotation matrix. The values will be adjusted + so that the result will always be a good Lorentz rotation matrix. + */ + template + void + SetComponents (const Foreign4Vector& v1, + const Foreign4Vector& v2, + const Foreign4Vector& v3, + const Foreign4Vector& v4 ) { + fM[kXX]=v1.x(); fM[kXY]=v2.x(); fM[kXZ]=v3.x(); fM[kXT]=v4.x(); + fM[kYX]=v1.y(); fM[kYY]=v2.y(); fM[kYZ]=v3.y(); fM[kYT]=v4.y(); + fM[kZX]=v1.z(); fM[kZY]=v2.z(); fM[kZZ]=v3.z(); fM[kZT]=v4.z(); + fM[kTX]=v1.t(); fM[kTY]=v2.t(); fM[kTZ]=v3.t(); fM[kTT]=v4.t(); + Rectify(); + } + + /** + Get components into four 4-vectors which will be the (orthosymplectic) + columns of the rotation matrix. (The 4-vector class must have a + constructor from 4 Scalars used as x, y, z, t) + */ + template + void + GetComponents ( Foreign4Vector& v1, + Foreign4Vector& v2, + Foreign4Vector& v3, + Foreign4Vector& v4 ) const { + v1 = Foreign4Vector ( fM[kXX], fM[kYX], fM[kZX], fM[kTX] ); + v2 = Foreign4Vector ( fM[kXY], fM[kYY], fM[kZY], fM[kTY] ); + v3 = Foreign4Vector ( fM[kXZ], fM[kYZ], fM[kZZ], fM[kTZ] ); + v4 = Foreign4Vector ( fM[kXT], fM[kYT], fM[kZT], fM[kTT] ); + } + + /** + Set the 16 matrix components given an iterator to the start of + the desired data, and another to the end (16 past start). + */ + template + void SetComponents(IT begin, IT end) { + for (int i = 0; i <16; ++i) { + fM[i] = *begin; + ++begin; + } + (void)end; + assert (end==begin); + } + + /** + Get the 16 matrix components into data specified by an iterator begin + and another to the end of the desired data (16 past start). + */ + template + void GetComponents(IT begin, IT end) const { + for (int i = 0; i <16; ++i) { + *begin = fM[i]; + ++begin; + } + (void)end; + assert (end==begin); + } + + /** + Get the 16 matrix components into data specified by an iterator begin + */ + template + void GetComponents(IT begin) const { + std::copy ( fM+0, fM+16, begin ); + } + + /** + Set components from a linear algebra matrix of size at least 4x4, + which must support operator()(i,j) to obtain elements (0,0) thru (3,3). + Precondition: The matrix is assumed to be orthosymplectic. NO checking + or re-adjusting is performed. + */ + template + void + SetRotationMatrix (const ForeignMatrix & m) { + fM[kXX]=m(0,0); fM[kXY]=m(0,1); fM[kXZ]=m(0,2); fM[kXT]=m(0,3); + fM[kYX]=m(1,0); fM[kYY]=m(1,1); fM[kYZ]=m(1,2); fM[kYT]=m(1,3); + fM[kZX]=m(2,0); fM[kZY]=m(2,1); fM[kZZ]=m(2,2); fM[kZT]=m(2,3); + fM[kTX]=m(3,0); fM[kTY]=m(3,1); fM[kTZ]=m(3,2); fM[kTT]=m(3,3); + } + + /** + Get components into a linear algebra matrix of size at least 4x4, + which must support operator()(i,j) for write access to elements + (0,0) thru (3,3). + */ + template + void + GetRotationMatrix (ForeignMatrix & m) const { + m(0,0)=fM[kXX]; m(0,1)=fM[kXY]; m(0,2)=fM[kXZ]; m(0,3)=fM[kXT]; + m(1,0)=fM[kYX]; m(1,1)=fM[kYY]; m(1,2)=fM[kYZ]; m(1,3)=fM[kYT]; + m(2,0)=fM[kZX]; m(2,1)=fM[kZY]; m(2,2)=fM[kZZ]; m(2,3)=fM[kZT]; + m(3,0)=fM[kTX]; m(3,1)=fM[kTY]; m(3,2)=fM[kTZ]; m(3,3)=fM[kTT]; + } + + /** + Set the components from sixteen scalars -- UNCHECKED for orthosymplectic + */ + void + SetComponents (Scalar xx, Scalar xy, Scalar xz, Scalar xt, + Scalar yx, Scalar yy, Scalar yz, Scalar yt, + Scalar zx, Scalar zy, Scalar zz, Scalar zt, + Scalar tx, Scalar ty, Scalar tz, Scalar tt) { + fM[kXX]=xx; fM[kXY]=xy; fM[kXZ]=xz; fM[kXT]=xt; + fM[kYX]=yx; fM[kYY]=yy; fM[kYZ]=yz; fM[kYT]=yt; + fM[kZX]=zx; fM[kZY]=zy; fM[kZZ]=zz; fM[kZT]=zt; + fM[kTX]=tx; fM[kTY]=ty; fM[kTZ]=tz; fM[kTT]=tt; + } + + /** + Get the sixteen components into sixteen scalars + */ + void + GetComponents (Scalar &xx, Scalar &xy, Scalar &xz, Scalar &xt, + Scalar &yx, Scalar &yy, Scalar &yz, Scalar &yt, + Scalar &zx, Scalar &zy, Scalar &zz, Scalar &zt, + Scalar &tx, Scalar &ty, Scalar &tz, Scalar &tt) const { + xx=fM[kXX]; xy=fM[kXY]; xz=fM[kXZ]; xt=fM[kXT]; + yx=fM[kYX]; yy=fM[kYY]; yz=fM[kYZ]; yt=fM[kYT]; + zx=fM[kZX]; zy=fM[kZY]; zz=fM[kZZ]; zt=fM[kZT]; + tx=fM[kTX]; ty=fM[kTY]; tz=fM[kTZ]; tt=fM[kTT]; + } + + // =========== operations ============== + + /** + Lorentz transformation operation on a Minkowski ('Cartesian') + LorentzVector + */ + LorentzVector< PxPyPzE4D > + operator() (const LorentzVector< PxPyPzE4D > & v) const { + Scalar x = v.Px(); + Scalar y = v.Py(); + Scalar z = v.Pz(); + Scalar t = v.E(); + return LorentzVector< PxPyPzE4D > + ( fM[kXX]*x + fM[kXY]*y + fM[kXZ]*z + fM[kXT]*t + , fM[kYX]*x + fM[kYY]*y + fM[kYZ]*z + fM[kYT]*t + , fM[kZX]*x + fM[kZY]*y + fM[kZZ]*z + fM[kZT]*t + , fM[kTX]*x + fM[kTY]*y + fM[kTZ]*z + fM[kTT]*t ); + } + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return LorentzVector ( r_xyzt ); + } + + /** + Lorentz transformation operation on an arbitrary 4-vector v. + Preconditions: v must implement methods x(), y(), z(), and t() + and the arbitrary vector type must have a constructor taking (x,y,z,t) + */ + template + Foreign4Vector + operator() (const Foreign4Vector & v) const { + LorentzVector< PxPyPzE4D > xyzt(v); + LorentzVector< PxPyPzE4D > r_xyzt = operator()(xyzt); + return Foreign4Vector ( r_xyzt.X(), r_xyzt.Y(), r_xyzt.Z(), r_xyzt.T() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + A4Vector operator* (const A4Vector & v) const + { + return operator()(v); + } + + /** + Invert a Lorentz rotation in place + */ + void Invert(); + + /** + Return inverse of a rotation + */ + LorentzRotation Inverse() const; + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) this Lorentz rotation by another LorentzRotation + */ + LorentzRotation operator * (const LorentzRotation & r) const; + + //#ifdef TODO_LATER + /** + Multiply (combine) this Lorentz rotation by a pure Lorentz boost + */ + //TODO: implement directly in a more efficient way. Now are implemented + // going through another LorentzRotation + LorentzRotation operator * (const Boost & b) const { LorentzRotation tmp(b); return (*this)*tmp; } + LorentzRotation operator * (const BoostX & b) const { LorentzRotation tmp(b); return (*this)*tmp; } + LorentzRotation operator * (const BoostY & b) const { LorentzRotation tmp(b); return (*this)*tmp; } + LorentzRotation operator * (const BoostZ & b) const { LorentzRotation tmp(b); return (*this)*tmp; } + + /** + Multiply (combine) this Lorentz rotation by a 3-D Rotation + */ + LorentzRotation operator * (const Rotation3D & r) const { LorentzRotation tmp(r); return (*this)*tmp; } + LorentzRotation operator * (const AxisAngle & a) const { LorentzRotation tmp(a); return (*this)*tmp; } + LorentzRotation operator * (const EulerAngles & e) const { LorentzRotation tmp(e); return (*this)*tmp; } + LorentzRotation operator * (const Quaternion & q) const { LorentzRotation tmp(q); return (*this)*tmp; } + LorentzRotation operator * (const RotationX & rx) const { LorentzRotation tmp(rx); return (*this)*tmp; } + LorentzRotation operator * (const RotationY & ry) const { LorentzRotation tmp(ry); return (*this)*tmp; } + LorentzRotation operator * (const RotationZ & rz) const { LorentzRotation tmp(rz); return (*this)*tmp; } + //#endif + + /** + Post-Multiply (on right) by another LorentzRotation, Boost, or + rotation : T = T*R + */ + template + LorentzRotation & operator *= (const R & r) { return *this = (*this)*r; } + + /** + Equality/inequality operators + */ + bool operator == (const LorentzRotation & rhs) const { + for (unsigned int i=0; i < 16; ++i) { + if( fM[i] != rhs.fM[i] ) return false; + } + return true; + } + bool operator != (const LorentzRotation & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fM[16]; + +}; // LorentzRotation + +// ============ Class LorentzRotation ends here ============ + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form +std::ostream & operator<< (std::ostream & os, const LorentzRotation & r); + +// ============================================ vetted to here ============ + +#ifdef NOTYET +/** + Distance between two Lorentz rotations + */ +template +inline +typename Rotation3D::Scalar +Distance ( const Rotation3D& r1, const R & r2) {return gv_detail::dist(r1,r2);} +#endif + +#endif + +} //namespace Math +} //namespace ROOT + + + + + + + +#endif /* ROOT_MathX_GenVectorX_LorentzRotation */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzRotationfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzRotationfwd.h new file mode 100644 index 0000000000000..02d0067586e79 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzRotationfwd.h @@ -0,0 +1,30 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 ROOT CERN / FNAL MATHLIB Group * + * * + * * + **********************************************************************/ + +// Header file defining forward declarations for LorentzVector classes +// +// Created by: Lorenzo Moneta at Thu May 12 11:19:02 2005 +// Major revamp by: M. Fischler at Tue Aug 9 2005 +// +// Last update: Tue Aug 9 2005 +// +#ifndef ROOT_MathX_GenVectorX_LorentzRotationfwd +#define ROOT_MathX_GenVectorX_LorentzRotationfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + namespace ROOT_MATH_ARCH { + class LoretzRotation; + } // end namespace Math +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_LorentzRotationfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzVector.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzVector.h new file mode 100644 index 0000000000000..cbb73b83f12e0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzVector.h @@ -0,0 +1,795 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class LorentzVector +// +// Created by: moneta at Tue May 31 17:06:09 2005 +// Major mods by: fischler at Wed Jul 20 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_LorentzVector +#define ROOT_MathX_GenVectorX_LorentzVector 1 + +#include "MathX/GenVectorX/PxPyPzE4D.h" + +#include "MathX/GenVectorX/DisplacementVector3D.h" + +#include "MathX/GenVectorX/GenVectorIO.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include +#include + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ +/** @ingroup GenVector + +Class describing a generic LorentzVector in the 4D space-time, +using the specified coordinate system for the spatial vector part. +The metric used for the LorentzVector is (-,-,-,+). +In the case of LorentzVector we don't distinguish the concepts +of points and displacement vectors as in the 3D case, +since the main use case for 4D Vectors is to describe the kinematics of +relativistic particles. A LorentzVector behaves like a +DisplacementVector in 4D. The Minkowski components could be viewed as +v and t, or for kinematic 4-vectors, as p and E. + +ROOT provides specialisations and aliases to them of the ROOT::ROOT_MATH_ARCH::LorentzVector template: +- ROOT::ROOT_MATH_ARCH::PtEtaPhiMVector based on pt (rho),eta,phi and M (t) coordinates in double precision +- ROOT::ROOT_MATH_ARCH::PtEtaPhiEVector based on pt (rho),eta,phi and E (t) coordinates in double precision +- ROOT::ROOT_MATH_ARCH::PxPyPzMVector based on px,py,pz and M (mass) coordinates in double precision +- ROOT::ROOT_MATH_ARCH::PxPyPzEVector based on px,py,pz and E (energy) coordinates in double precision +- ROOT::ROOT_MATH_ARCH::XYZTVector based on x,y,z,t coordinates (cartesian) in double precision (same as PxPyPzEVector) +- ROOT::ROOT_MATH_ARCH::XYZTVectorF based on x,y,z,t coordinates (cartesian) in float precision (same as PxPyPzEVector but float) + +@sa Overview of the @ref GenVector "physics vector library" +*/ + + template< class CoordSystem > + class LorentzVector { + + public: + + // ------ ctors ------ + + typedef typename CoordSystem::Scalar Scalar; + typedef CoordSystem CoordinateType; + + /** + default constructor of an empty vector (Px = Py = Pz = E = 0 ) + */ + LorentzVector ( ) : fCoordinates() { } + + /** + generic constructors from four scalar values. + The association between values and coordinate depends on the + coordinate system. For PxPyPzE4D, + \param a scalar value (Px) + \param b scalar value (Py) + \param c scalar value (Pz) + \param d scalar value (E) + */ + LorentzVector(const Scalar & a, + const Scalar & b, + const Scalar & c, + const Scalar & d) : + fCoordinates(a , b, c, d) { } + + /** + constructor from a LorentzVector expressed in different + coordinates, or using a different Scalar type + */ + template< class Coords > + explicit LorentzVector(const LorentzVector & v ) : + fCoordinates( v.Coordinates() ) { } + + /** + Construct from a foreign 4D vector type, for example, HepLorentzVector + Precondition: v must implement methods x(), y(), z(), and t() + */ + template().x() + + std::declval().y() + + std::declval().z() + + std::declval().t())> + explicit LorentzVector( const ForeignLorentzVector & v) : + fCoordinates(PxPyPzE4D( v.x(), v.y(), v.z(), v.t() ) ) { } + +#ifdef LATER + /** + construct from a generic linear algebra vector implementing operator [] + and with a size of at least 4. This could be also a C array + In this case v[0] is the first data member + ( Px for a PxPyPzE4D base) + \param v LA vector + \param index0 index of first vector element (Px) + */ + template< class LAVector > + explicit LorentzVector(const LAVector & v, size_t index0 ) { + fCoordinates = CoordSystem ( v[index0], v[index0+1], v[index0+2], v[index0+3] ); + } +#endif + + + // ------ assignment ------ + + /** + Assignment operator from a lorentz vector of arbitrary type + */ + template< class OtherCoords > + LorentzVector & operator= ( const LorentzVector & v) { + fCoordinates = v.Coordinates(); + return *this; + } + + /** + assignment from any other Lorentz vector implementing + x(), y(), z() and t() + */ + template().x() + + std::declval().y() + + std::declval().z() + + std::declval().t())> + LorentzVector & operator = ( const ForeignLorentzVector & v) { + SetXYZT( v.x(), v.y(), v.z(), v.t() ); + return *this; + } + +#ifdef LATER + /** + assign from a generic linear algebra vector implementing operator [] + and with a size of at least 4 + In this case v[0] is the first data member + ( Px for a PxPyPzE4D base) + \param v LA vector + \param index0 index of first vector element (Px) + */ + template< class LAVector > + LorentzVector & AssignFrom(const LAVector & v, size_t index0=0 ) { + fCoordinates.SetCoordinates( v[index0], v[index0+1], v[index0+2], v[index0+3] ); + return *this; + } +#endif + + // ------ Set, Get, and access coordinate data ------ + + /** + Retrieve a const reference to the coordinates object + */ + const CoordSystem & Coordinates() const { + return fCoordinates; + } + + /** + Set internal data based on an array of 4 Scalar numbers + */ + LorentzVector& SetCoordinates( const Scalar src[] ) { + fCoordinates.SetCoordinates(src); + return *this; + } + + /** + Set internal data based on 4 Scalar numbers + */ + LorentzVector& SetCoordinates( Scalar a, Scalar b, Scalar c, Scalar d ) { + fCoordinates.SetCoordinates(a, b, c, d); + return *this; + } + + /** + Set internal data based on 4 Scalars at *begin to *end + */ + template< class IT > + LorentzVector& SetCoordinates( IT begin, IT end ) { + IT a = begin; IT b = ++begin; IT c = ++begin; IT d = ++begin; + (void)end; + assert (++begin==end); + SetCoordinates (*a,*b,*c,*d); + return *this; + } + + /** + get internal data into 4 Scalar numbers + */ + void GetCoordinates( Scalar& a, Scalar& b, Scalar& c, Scalar & d ) const + { fCoordinates.GetCoordinates(a, b, c, d); } + + /** + get internal data into an array of 4 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { fCoordinates.GetCoordinates(dest); } + + /** + get internal data into 4 Scalars at *begin to *end + */ + template + void GetCoordinates( IT begin, IT end ) const + { IT a = begin; IT b = ++begin; IT c = ++begin; IT d = ++begin; + (void)end; + assert (++begin==end); + GetCoordinates (*a,*b,*c,*d); + } + + /** + get internal data into 4 Scalars at *begin + */ + template + void GetCoordinates( IT begin ) const { + Scalar a,b,c,d = 0; + GetCoordinates (a,b,c,d); + *begin++ = a; + *begin++ = b; + *begin++ = c; + *begin = d; + } + + /** + set the values of the vector from the cartesian components (x,y,z,t) + (if the vector is held in another coordinates, like (Pt,eta,phi,m) + then (x, y, z, t) are converted to that form) + */ + LorentzVector& SetXYZT (Scalar xx, Scalar yy, Scalar zz, Scalar tt) { + fCoordinates.SetPxPyPzE(xx,yy,zz,tt); + return *this; + } + LorentzVector& SetPxPyPzE (Scalar xx, Scalar yy, Scalar zz, Scalar ee) { + fCoordinates.SetPxPyPzE(xx,yy,zz,ee); + return *this; + } + + // ------------------- Equality ----------------- + + /** + Exact equality + */ + bool operator==(const LorentzVector & rhs) const { + return fCoordinates==rhs.fCoordinates; + } + bool operator!= (const LorentzVector & rhs) const { + return !(operator==(rhs)); + } + + // ------ Individual element access, in various coordinate systems ------ + + // individual coordinate accessors in various coordinate systems + + /** + spatial X component + */ + Scalar Px() const { return fCoordinates.Px(); } + Scalar X() const { return fCoordinates.Px(); } + /** + spatial Y component + */ + Scalar Py() const { return fCoordinates.Py(); } + Scalar Y() const { return fCoordinates.Py(); } + /** + spatial Z component + */ + Scalar Pz() const { return fCoordinates.Pz(); } + Scalar Z() const { return fCoordinates.Pz(); } + /** + return 4-th component (time, or energy for a 4-momentum vector) + */ + Scalar E() const { return fCoordinates.E(); } + Scalar T() const { return fCoordinates.E(); } + /** + return magnitude (mass) squared M2 = T**2 - X**2 - Y**2 - Z**2 + (we use -,-,-,+ metric) + */ + Scalar M2() const { return fCoordinates.M2(); } + /** + return magnitude (mass) using the (-,-,-,+) metric. + If M2 is negative (space-like vector) a GenVector_exception + is suggested and if continuing, - sqrt( -M2) is returned + */ + Scalar M() const { return fCoordinates.M();} + /** + return the spatial (3D) magnitude ( sqrt(X**2 + Y**2 + Z**2) ) + */ + Scalar R() const { return fCoordinates.R(); } + Scalar P() const { return fCoordinates.R(); } + /** + return the square of the spatial (3D) magnitude ( X**2 + Y**2 + Z**2 ) + */ + Scalar P2() const { return P() * P(); } + /** + return the square of the transverse spatial component ( X**2 + Y**2 ) + */ + Scalar Perp2( ) const { return fCoordinates.Perp2();} + + /** + return the transverse spatial component sqrt ( X**2 + Y**2 ) + */ + Scalar Pt() const { return fCoordinates.Pt(); } + Scalar Rho() const { return fCoordinates.Pt(); } + + /** + return the transverse mass squared + \f[ m_t^2 = E^2 - p{_z}^2 \f] + */ + Scalar Mt2() const { return fCoordinates.Mt2(); } + + /** + return the transverse mass + \f[ \sqrt{ m_t^2 = E^2 - p{_z}^2} X sign(E^ - p{_z}^2) \f] + */ + Scalar Mt() const { return fCoordinates.Mt(); } + + /** + return the transverse energy squared + \f[ e_t = \frac{E^2 p_{\perp}^2 }{ |p|^2 } \f] + */ + Scalar Et2() const { return fCoordinates.Et2(); } + + /** + return the transverse energy + \f[ e_t = \sqrt{ \frac{E^2 p_{\perp}^2 }{ |p|^2 } } X sign(E) \f] + */ + Scalar Et() const { return fCoordinates.Et(); } + + /** + azimuthal Angle + */ + Scalar Phi() const { return fCoordinates.Phi();} + + /** + polar Angle + */ + Scalar Theta() const { return fCoordinates.Theta(); } + + /** + pseudorapidity + \f[ \eta = - \ln { \tan { \frac { \theta} {2} } } \f] + */ + Scalar Eta() const { return fCoordinates.Eta(); } + + /** + get the spatial components of the Vector in a + DisplacementVector based on Cartesian Coordinates + */ + DisplacementVector3D > Vect() const { + return DisplacementVector3D >( X(), Y(), Z() ); + } + + // ------ Operations combining two Lorentz vectors ------ + + /** + scalar (Dot) product of two LorentzVector vectors (metric is -,-,-,+) + Enable the product using any other LorentzVector implementing + the x(), y() , y() and t() member functions + \param q any LorentzVector implementing the x(), y() , z() and t() + member functions + \return the result of v.q of type according to the base scalar type of v + */ + + template< class OtherLorentzVector > + Scalar Dot(const OtherLorentzVector & q) const { + return t()*q.t() - x()*q.x() - y()*q.y() - z()*q.z(); + } + + /** + Self addition with another Vector ( v+= q ) + Enable the addition with any other LorentzVector + \param q any LorentzVector implementing the x(), y() , z() and t() + member functions + */ + template< class OtherLorentzVector > + inline LorentzVector & operator += ( const OtherLorentzVector & q) + { + SetXYZT( x() + q.x(), y() + q.y(), z() + q.z(), t() + q.t() ); + return *this; + } + + /** + Self subtraction of another Vector from this ( v-= q ) + Enable the addition with any other LorentzVector + \param q any LorentzVector implementing the x(), y() , z() and t() + member functions + */ + template< class OtherLorentzVector > + LorentzVector & operator -= ( const OtherLorentzVector & q) { + SetXYZT( x() - q.x(), y() - q.y(), z() - q.z(), t() - q.t() ); + return *this; + } + + /** + addition of two LorentzVectors (v3 = v1 + v2) + Enable the addition with any other LorentzVector + \param v2 any LorentzVector implementing the x(), y() , z() and t() + member functions + \return a new LorentzVector of the same type as v1 + */ + template + LorentzVector operator + ( const OtherLorentzVector & v2) const + { + LorentzVector v3(*this); + v3 += v2; + return v3; + } + + /** + subtraction of two LorentzVectors (v3 = v1 - v2) + Enable the subtraction of any other LorentzVector + \param v2 any LorentzVector implementing the x(), y() , z() and t() + member functions + \return a new LorentzVector of the same type as v1 + */ + template + LorentzVector operator - ( const OtherLorentzVector & v2) const { + LorentzVector v3(*this); + v3 -= v2; + return v3; + } + + //--- scaling operations ------ + + /** + multiplication by a scalar quantity v *= a + */ + LorentzVector & operator *= (Scalar a) { + fCoordinates.Scale(a); + return *this; + } + + /** + division by a scalar quantity v /= a + */ + LorentzVector & operator /= (Scalar a) { + fCoordinates.Scale(1/a); + return *this; + } + + /** + product of a LorentzVector by a scalar quantity + \param a scalar quantity of type a + \return a new mathcoreLorentzVector q = v * a same type as v + */ + LorentzVector operator * ( const Scalar & a) const { + LorentzVector tmp(*this); + tmp *= a; + return tmp; + } + + /** + Divide a LorentzVector by a scalar quantity + \param a scalar quantity of type a + \return a new mathcoreLorentzVector q = v / a same type as v + */ + LorentzVector operator / ( const Scalar & a) const { + LorentzVector tmp(*this); + tmp /= a; + return tmp; + } + + /** + Negative of a LorentzVector (q = - v ) + \return a new LorentzVector with opposite direction and time + */ + LorentzVector operator - () const { + //LorentzVector v(*this); + //v.Negate(); + return operator*( Scalar(-1) ); + } + LorentzVector operator + () const { + return *this; + } + + // ---- Relativistic Properties ---- + + /** + Rapidity relative to the Z axis: .5 log [(E+Pz)/(E-Pz)] + */ + Scalar Rapidity() const { + // TODO - It would be good to check that E > Pz and use the Throw() + // mechanism or at least load a NAN if not. + // We should then move the code to a .cpp file. + const Scalar ee = E(); + const Scalar ppz = Pz(); + return Scalar(0.5) * math_log((ee + ppz) / (ee - ppz)); + } + + /** + Rapidity in the direction of travel: atanh (|P|/E)=.5 log[(E+P)/(E-P)] + */ + Scalar ColinearRapidity() const { + // TODO - It would be good to check that E > P and use the Throw() + // mechanism or at least load a NAN if not. + const Scalar ee = E(); + const Scalar pp = P(); + return Scalar(0.5) * math_log((ee + pp) / (ee - pp)); + } + + /** + Determine if momentum-energy can represent a physical massive particle + */ + bool isTimelike( ) const { + Scalar ee = E(); Scalar pp = P(); return ee*ee > pp*pp; + } + + /** + Determine if momentum-energy can represent a massless particle + */ + bool isLightlike( Scalar tolerance + = 100*std::numeric_limits::epsilon() ) const { + Scalar ee = E(); Scalar pp = P(); Scalar delta = ee-pp; + if ( ee==0 ) return pp==0; + return delta*delta < tolerance * ee*ee; + } + + /** + Determine if momentum-energy is spacelike, and represents a tachyon + */ + bool isSpacelike( ) const { + Scalar ee = E(); Scalar pp = P(); return ee*ee < pp*pp; + } + + typedef DisplacementVector3D< Cartesian3D > BetaVector; + + /** + The beta vector for the boost that would bring this vector into + its center of mass frame (zero momentum) + */ + BetaVector BoostToCM( ) const { + if (E() == 0) { + if (P() == 0) { + return BetaVector(); + } else { + // TODO - should attempt to Throw with msg about + // boostVector computed for LorentzVector with t=0 + return -Vect()/E(); + } + } + if (M2() <= 0) { + // TODO - should attempt to Throw with msg about + // boostVector computed for a non-timelike LorentzVector + } + return -Vect()/E(); + } + + /** + The beta vector for the boost that would bring this vector into + its center of mass frame (zero momentum) + */ + template + BetaVector BoostToCM(const Other4Vector& v ) const { + Scalar eSum = E() + v.E(); + DisplacementVector3D< Cartesian3D > vecSum = Vect() + v.Vect(); + if (eSum == 0) { + if (vecSum.Mag2() == 0) { + return BetaVector(); + } else { + // TODO - should attempt to Throw with msg about + // boostToCM computed for two 4-vectors with combined t=0 + return BetaVector(vecSum/eSum); + } + // TODO - should attempt to Throw with msg about + // boostToCM computed for two 4-vectors with combined e=0 + } + return BetaVector (vecSum * (-1./eSum)); + } + + //beta and gamma + + /** + Return beta scalar value + */ + Scalar Beta() const { + if ( E() == 0 ) { + if ( P2() == 0) + // to avoid Nan + return 0; + else { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("LorentzVector::Beta() - beta computed for LorentzVector with t = 0. Return an Infinite result"); +#endif + return 1./E(); + } + } + if ( M2() <= 0 ) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("LorentzVector::Beta() - beta computed for non-timelike LorentzVector . Result is physically meaningless" ); +#endif + } + return P() / E(); + } + /** + Return Gamma scalar value + */ + Scalar Gamma() const { + const Scalar v2 = P2(); + const Scalar t2 = E() * E(); + if (E() == 0) { + if ( P2() == 0) { + return 1; + } else { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("LorentzVector::Gamma() - gamma computed for LorentzVector with t = 0. Return a zero result"); +#endif + } + } + if ( t2 < v2 ) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("LorentzVector::Gamma() - gamma computed for a spacelike LorentzVector. Imaginary result"); +#endif + return 0; + } + else if ( t2 == v2 ) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("LorentzVector::Gamma() - gamma computed for a lightlike LorentzVector. Infinite result"); +#endif + } + return Scalar(1) / math_sqrt(Scalar(1) - v2 / t2); + } /* gamma */ + + + // Method providing limited backward name compatibility with CLHEP ---- + + Scalar x() const { return fCoordinates.Px(); } + Scalar y() const { return fCoordinates.Py(); } + Scalar z() const { return fCoordinates.Pz(); } + Scalar t() const { return fCoordinates.E(); } + Scalar px() const { return fCoordinates.Px(); } + Scalar py() const { return fCoordinates.Py(); } + Scalar pz() const { return fCoordinates.Pz(); } + Scalar e() const { return fCoordinates.E(); } + Scalar r() const { return fCoordinates.R(); } + Scalar theta() const { return fCoordinates.Theta(); } + Scalar phi() const { return fCoordinates.Phi(); } + Scalar rho() const { return fCoordinates.Rho(); } + Scalar eta() const { return fCoordinates.Eta(); } + Scalar pt() const { return fCoordinates.Pt(); } + Scalar perp2() const { return fCoordinates.Perp2(); } + Scalar mag2() const { return fCoordinates.M2(); } + Scalar mag() const { return fCoordinates.M(); } + Scalar mt() const { return fCoordinates.Mt(); } + Scalar mt2() const { return fCoordinates.Mt2(); } + + + // Methods requested by CMS --- + Scalar energy() const { return fCoordinates.E(); } + Scalar mass() const { return fCoordinates.M(); } + Scalar mass2() const { return fCoordinates.M2(); } + + + /** + Methods setting a Single-component + Work only if the component is one of which the vector is represented. + For example SetE will work for a PxPyPzE Vector but not for a PxPyPzM Vector. + */ + LorentzVector& SetE ( Scalar a ) { fCoordinates.SetE (a); return *this; } + LorentzVector& SetEta( Scalar a ) { fCoordinates.SetEta(a); return *this; } + LorentzVector& SetM ( Scalar a ) { fCoordinates.SetM (a); return *this; } + LorentzVector& SetPhi( Scalar a ) { fCoordinates.SetPhi(a); return *this; } + LorentzVector& SetPt ( Scalar a ) { fCoordinates.SetPt (a); return *this; } + LorentzVector& SetPx ( Scalar a ) { fCoordinates.SetPx (a); return *this; } + LorentzVector& SetPy ( Scalar a ) { fCoordinates.SetPy (a); return *this; } + LorentzVector& SetPz ( Scalar a ) { fCoordinates.SetPz (a); return *this; } + + private: + + CoordSystem fCoordinates; // internal coordinate system + + + }; // LorentzVector<> + + + + // global methods + + /** + Scale of a LorentzVector with a scalar quantity a + \param a scalar quantity of type a + \param v mathcore::LorentzVector based on any coordinate system + \return a new mathcoreLorentzVector q = v * a same type as v + */ + template< class CoordSystem > + inline LorentzVector operator * + ( const typename LorentzVector::Scalar & a, + const LorentzVector& v) { + LorentzVector tmp(v); + tmp *= a; + return tmp; + } + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + // ------------- I/O to/from streams ------------- + + template< class char_t, class traits_t, class Coords > + inline + std::basic_ostream & + operator << ( std::basic_ostream & os + , LorentzVector const & v + ) + { + if( !os ) return os; + + typename Coords::Scalar a, b, c, d; + v.GetCoordinates(a, b, c, d); + + if( detail::get_manip( os, detail::bitforbit ) ) { + detail::set_manip( os, detail::bitforbit, '\00' ); + // TODO: call MF's bitwise-accurate functions on each of a, b, c, d + } + else { + os << detail::get_manip( os, detail::open ) << a + << detail::get_manip( os, detail::sep ) << b + << detail::get_manip( os, detail::sep ) << c + << detail::get_manip( os, detail::sep ) << d + << detail::get_manip( os, detail::close ); + } + + return os; + + } // op<< <>() + + + template< class char_t, class traits_t, class Coords > + inline + std::basic_istream & + operator >> ( std::basic_istream & is + , LorentzVector & v + ) + { + if( !is ) return is; + + typename Coords::Scalar a, b, c, d; + + if( detail::get_manip( is, detail::bitforbit ) ) { + detail::set_manip( is, detail::bitforbit, '\00' ); + // TODO: call MF's bitwise-accurate functions on each of a, b, c + } + else { + detail::require_delim( is, detail::open ); is >> a; + detail::require_delim( is, detail::sep ); is >> b; + detail::require_delim( is, detail::sep ); is >> c; + detail::require_delim( is, detail::sep ); is >> d; + detail::require_delim( is, detail::close ); + } + + if( is ) + v.SetCoordinates(a, b, c, d); + return is; + + } // op>> <>() +#endif + + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + +#include +namespace cling +{ +template +std::string printValue(const LorentzVector *v) +{ + std::stringstream s; + s << *v; + return s.str(); +} + +} // end namespace cling + +#endif + +//#include "MathX/GenVectorX/LorentzVectorOperations.h" diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzVectorfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzVectorfwd.h new file mode 100644 index 0000000000000..859388f5fefe1 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzVectorfwd.h @@ -0,0 +1,37 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class LorentzVectorfwd +// +// Created by: moneta at Tue May 31 21:06:43 2005 +// +// Last update: Tue May 31 21:06:43 2005 +// +#ifndef ROOT_MathX_GenVectorX_LorentzVectorfwd +#define ROOT_MathX_GenVectorX_LorentzVectorfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + + // forward declaretions of Lorentz Vectors and type defs definitions + + template class LorentzVector; + + + } // end namespace Math + +} // end namespace ROOT + +#endif + diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/MathHeaders.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/MathHeaders.h new file mode 100644 index 0000000000000..940daf67ff4c6 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/MathHeaders.h @@ -0,0 +1,466 @@ +/* + * Project: Math + * Authors: + * Monica Dessole, CERN, 2024 + * + * Copyright (c) 2024, CERN + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted according to the terms + * listed in LICENSE (http://roofit.sourceforge.net/license.txt) + */ + +#ifndef ROOT_MathHeaders_H +#define ROOT_MathHeaders_H + + +#include "MathX/GenVectorX/AccHeaders.h" + +#include + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +#if defined(ROOT_MATH_SYCL) +template +inline Scalar math_sin(Scalar x) +{ + return sycl::sin(x); +} + +template +inline Scalar math_cos(Scalar x) +{ + return sycl::cos(x); +} + +template +inline Scalar math_asin(Scalar x) +{ + return sycl::asin(x); +} + +template +inline Scalar math_acos(Scalar x) +{ + return sycl::acos(x); +} + +template +inline Scalar math_sinh(Scalar x) +{ + return sycl::sinh(x); +} + +template +inline Scalar math_cosh(Scalar x) +{ + return sycl::cosh(x); +} + +template +inline Scalar math_atan2(Scalar x, Scalar y) +{ + return sycl::atan2(x, y); +} + +template +inline Scalar math_atan(Scalar x) +{ + return sycl::atan(x); +} + +template +inline Scalar math_sqrt(Scalar x) +{ + return sycl::sqrt(x); +} + +template +inline Scalar math_floor(Scalar x) +{ + return sycl::floor(x); +} + +template +inline Scalar math_exp(Scalar x) +{ + return sycl::exp(x); +} + +template +inline Scalar math_log(Scalar x) +{ + return sycl::log(x); +} + +inline long double math_log(long double x) +{ + double castx = x; + double castres = sycl::log(castx); + return (long double) castres; +} + +template +inline Scalar math_tan(Scalar x) +{ + return sycl::tan(x); +} + +template +inline Scalar math_fabs(Scalar x) +{ + return sycl::fabs(x); +} + +template +inline Scalar math_pow(Scalar x, Scalar y) +{ + return sycl::pow(x, y); +} + +// template +// T etaMax2() +// { +// return static_cast(22756.0); +// } + +// template +// inline Scalar Eta_FromRhoZ(Scalar rho, Scalar z) +// { +// if (rho > 0) { +// // value to control Taylor expansion of sqrt +// // static const Scalar +// Scalar epsilon = static_cast(2e-16); +// const Scalar big_z_scaled = sycl::pow(epsilon, static_cast(-.25)); + +// Scalar z_scaled = z / rho; +// if (sycl::fabs(z_scaled) < big_z_scaled) { +// return sycl::log(z_scaled + sycl::sqrt(z_scaled * z_scaled + 1.0)); +// } else { +// // apply correction using first order Taylor expansion of sqrt +// return z > 0 ? sycl::log(2.0 * z_scaled + 0.5 / z_scaled) : -sycl::log(-2.0 * z_scaled); +// } +// return z_scaled; +// } +// // case vector has rho = 0 +// else if (z == 0) { +// return 0; +// } else if (z > 0) { +// return z + etaMax2(); +// } else { +// return z - etaMax2(); +// } +// } + +// /** +// Implementation of eta from -log(tan(theta/2)). +// This is convenient when theta is already known (for example in a polar +// coorindate system) +// */ +// template +// inline Scalar Eta_FromTheta(Scalar theta, Scalar r) +// { +// Scalar tanThetaOver2 = tan(theta / 2.); +// if (tanThetaOver2 == 0) { +// return r + etaMax2(); +// } else if (tanThetaOver2 > std::numeric_limits::max()) { +// return -r - etaMax2(); +// } else { +// return -log(tanThetaOver2); +// } +// } + +#elif defined(ROOT_MATH_CUDA) +template +__roohost__ __roodevice__ inline Scalar math_sin(Scalar x) +{ + return std::sin(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_cos(Scalar x) +{ + return std::cos(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_asin(Scalar x) +{ + return std::asin(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_acos(Scalar x) +{ + return std::acos(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_sinh(Scalar x) +{ + return std::sinh(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_cosh(Scalar x) +{ + return std::cosh(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_atan2(Scalar x, Scalar y) +{ + return std::atan2(x, y); +} + +template +__roohost__ __roodevice__ inline Scalar math_atan(Scalar x) +{ + return std::atan(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_sqrt(Scalar x) +{ + return std::sqrt(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_floor(Scalar x) +{ + return std::floor(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_exp(Scalar x) +{ + return std::exp(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_log(Scalar x) +{ + return std::log(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_tan(Scalar x) +{ + return std::tan(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_fabs(Scalar x) +{ + return std::fabs(x); +} + +template +__roohost__ __roodevice__ inline Scalar math_pow(Scalar x, Scalar y) +{ + return std::pow(x, y); +} + +template +__roohost__ __roodevice__ inline T etaMax2() +{ + return static_cast(22756.0); +} + +template +__roohost__ __roodevice__ inline Scalar Eta_FromRhoZ(Scalar rho, Scalar z) +{ + if (rho > 0) { + // value to control Taylor expansion of sqrt + // static const Scalar + Scalar epsilon = static_cast(2e-16); + const Scalar big_z_scaled = pow(epsilon, static_cast(-.25)); + + Scalar z_scaled = z / rho; + if (fabs(z_scaled) < big_z_scaled) { + return log(z_scaled + sqrt(z_scaled * z_scaled + 1.0)); + } else { + // apply correction using first order Taylor expansion of sqrt + return z > 0 ? log(2.0 * z_scaled + 0.5 / z_scaled) : log(-2.0 * z_scaled); + } + return z_scaled; + } + // case vector has rho = 0 + else if (z == 0) { + return 0; + } else if (z > 0) { + return z + etaMax2(); + } else { + return z - etaMax2(); + } +} + +/** + Implementation of eta from -log(tan(theta/2)). + This is convenient when theta is already known (for example in a polar + coorindate system) +*/ +template +__roohost__ __roodevice__ inline Scalar Eta_FromTheta(Scalar theta, Scalar r) +{ + Scalar tanThetaOver2 = tan(theta / 2.); + if (tanThetaOver2 == 0) { + return r + etaMax2(); + } else if (tanThetaOver2 > std::numeric_limits::max()) { + return -r - etaMax2(); + } else { + return -log(tanThetaOver2); + } +} + +#else + +template +inline Scalar math_sin(Scalar x) +{ + return std::sin(x); +} + +template +inline Scalar math_cos(Scalar x) +{ + return std::cos(x); +} + +template +inline Scalar math_asin(Scalar x) +{ + return std::asin(x); +} + +template +inline Scalar math_acos(Scalar x) +{ + return std::acos(x); +} + +template +inline Scalar math_sinh(Scalar x) +{ + return std::sinh(x); +} + +template +inline Scalar math_cosh(Scalar x) +{ + return std::cosh(x); +} + +template +inline Scalar math_atan2(Scalar x, Scalar y) +{ + return std::atan2(x, y); +} + +template +inline Scalar math_atan(Scalar x) +{ + return std::atan(x); +} + +template +inline Scalar math_sqrt(Scalar x) +{ + return std::sqrt(x); +} + +template +inline Scalar math_floor(Scalar x) +{ + return std::floor(x); +} + +template +inline Scalar math_exp(Scalar x) +{ + return std::exp(x); +} + +template +inline Scalar math_log(Scalar x) +{ + return std::log(x); +} + +template +inline Scalar math_tan(Scalar x) +{ + return std::tan(x); +} + +template +inline Scalar math_fabs(Scalar x) +{ + return std::fabs(x); +} + +template +inline Scalar math_pow(Scalar x, Scalar y) +{ + return std::pow(x, y); +} + +template +inline T etaMax2() +{ + return static_cast(22756.0); +} + +template +inline Scalar Eta_FromRhoZ(Scalar rho, Scalar z) +{ + if (rho > 0) { + + // value to control Taylor expansion of sqrt + static const Scalar big_z_scaled = pow(std::numeric_limits::epsilon(), static_cast(-.25)); + + Scalar z_scaled = z / rho; + if (fabs(z_scaled) < big_z_scaled) { + return log(z_scaled + sqrt(z_scaled * z_scaled + 1.0)); + } else { + // apply correction using first order Taylor expansion of sqrt + return z > 0 ? log(2.0 * z_scaled + 0.5 / z_scaled) : -log(-2.0 * z_scaled); + } + } + // case vector has rho = 0 + else if (z == 0) { + return 0; + } else if (z > 0) { + return z + etaMax2(); + } else { + return z - etaMax2(); + } +} + +/** + Implementation of eta from -log(tan(theta/2)). + This is convenient when theta is already known (for example in a polar + coorindate system) +*/ +template +inline Scalar Eta_FromTheta(Scalar theta, Scalar r) +{ + Scalar tanThetaOver2 = tan(theta / 2.); + if (tanThetaOver2 == 0) { + return r + etaMax2(); + } else if (tanThetaOver2 > std::numeric_limits::max()) { + return -r - etaMax2(); + } else { + return -log(tanThetaOver2); + } +} + +#endif + +} // namespace ROOT_MATH_ARCH + +} // end namespace ROOT + +#endif \ No newline at end of file diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Plane3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Plane3D.h new file mode 100644 index 0000000000000..5bff64dfbfbb8 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Plane3D.h @@ -0,0 +1,314 @@ +// @(#)root/mathcore:$Id$ +// Authors: L. Moneta 12/2005 + +/********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class LorentzVector +// +// Created by: moneta at Fri Dec 02 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_Plane3D +#define ROOT_MathX_GenVectorX_Plane3D 1 + +#include + +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" + + + +namespace ROOT { + +namespace Math { + +namespace Impl { + +//_______________________________________________________________________________ +/** + Class describing a geometrical plane in 3 dimensions. + A Plane3D is a 2 dimensional surface spanned by two linearly independent vectors. + The plane is described by the equation + \f$ a*x + b*y + c*z + d = 0 \f$ where (a,b,c) are the components of the + normal vector to the plane \f$ n = (a,b,c) \f$ and \f$ d = - n \dot x \f$, where x is any point + belonging to plane. + More information on the mathematics describing a plane in 3D is available on + MathWord. + The Plane3D class contains the 4 scalar values in T which represent the + four coefficients, fA, fB, fC, fD. fA, fB, fC are the normal components normalized to 1, + i.e. fA**2 + fB**2 + fC**2 = 1 + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" +*/ + +template +class Plane3D { + +public: + // ------ ctors ------ + + typedef T Scalar; + + typedef DisplacementVector3D, DefaultCoordinateSystemTag> Vector; + typedef PositionVector3D, DefaultCoordinateSystemTag> Point; + + /** + default constructor create plane z = 0 + */ + Plane3D() : fA(0), fB(0), fC(1), fD(0) {} + + /** + generic constructors from the four scalar values describing the plane + according to the equation ax + by + cz + d = 0 + \param a scalar value + \param b scalar value + \param c scalar value + \param d sxcalar value + */ + Plane3D(const Scalar &a, const Scalar &b, const Scalar &c, const Scalar &d) : fA(a), fB(b), fC(c), fD(d) + { + // renormalize a,b,c to unit + Normalize(); + } + + /** + constructor a Plane3D from a normal vector and a point coplanar to the plane + \param n normal expressed as a ROOT::Math::DisplacementVector3D > + \param p point expressed as a ROOT::Math::PositionVector3D > + */ + Plane3D(const Vector &n, const Point &p) { BuildFromVecAndPoint(n, p); } + + /** + Construct from a generic DisplacementVector3D (normal vector) and PositionVector3D (point coplanar to + the plane) + \param n normal expressed as a generic ROOT::Math::DisplacementVector3D + \param p point expressed as a generic ROOT::Math::PositionVector3D + */ + template + Plane3D(const DisplacementVector3D &n, const PositionVector3D &p) + { + BuildFromVecAndPoint(Vector(n), Point(p)); + } + + /** + constructor from three Cartesian point belonging to the plane + \param p1 point1 expressed as a generic ROOT::Math::PositionVector3D + \param p2 point2 expressed as a generic ROOT::Math::PositionVector3D + \param p3 point3 expressed as a generic ROOT::Math::PositionVector3D + */ + Plane3D(const Point &p1, const Point &p2, const Point &p3) { BuildFrom3Points(p1, p2, p3); } + + /** + constructor from three generic point belonging to the plane + \param p1 point1 expressed as ROOT::Math::DisplacementVector3D > + \param p2 point2 expressed as ROOT::Math::DisplacementVector3D > + \param p3 point3 expressed as ROOT::Math::DisplacementVector3D > + */ + template + Plane3D(const PositionVector3D &p1, const PositionVector3D &p2, const PositionVector3D &p3) + { + BuildFrom3Points(Point(p1.X(), p1.Y(), p1.Z()), Point(p2.X(), p2.Y(), p2.Z()), Point(p3.X(), p3.Y(), p3.Z())); + } + + // compiler-generated copy ctor and dtor are fine. + Plane3D(const Plane3D &) = default; + + // ------ assignment ------ + + /** + Assignment operator from other Plane3D class + */ + Plane3D &operator=(const Plane3D &) = default; + + /** + Return the a coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the + x-component of the vector perpendicular to the plane. + */ + Scalar A() const { return fA; } + + /** + Return the b coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the + y-component of the vector perpendicular to the plane + */ + Scalar B() const { return fB; } + + /** + Return the c coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the + z-component of the vector perpendicular to the plane + */ + Scalar C() const { return fC; } + + /** + Return the d coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also + the distance from the origin (HesseDistance) + */ + Scalar D() const { return fD; } + + /** + Return normal vector to the plane as Cartesian DisplacementVector + */ + Vector Normal() const { return Vector(fA, fB, fC); } + + /** + Return the Hesse Distance (distance from the origin) of the plane or + the d coefficient expressed in normalize form + */ + Scalar HesseDistance() const { return fD; } + + /** + Return the signed distance to a Point. + The distance is signed positive if the Point is in the same side of the + normal vector to the plane. + \param p Point expressed in Cartesian Coordinates + */ + Scalar Distance(const Point &p) const { return fA * p.X() + fB * p.Y() + fC * p.Z() + fD; } + + /** + Return the distance to a Point described with generic coordinates + \param p Point expressed as generic ROOT::Math::PositionVector3D + */ + template + Scalar Distance(const PositionVector3D &p) const + { + return Distance(Point(p.X(), p.Y(), p.Z())); + } + + /** + Return the projection of a Cartesian point to a plane + \param p Point expressed as PositionVector3D > + */ + Point ProjectOntoPlane(const Point &p) const + { + const Scalar d = Distance(p); + return XYZPoint(p.X() - fA * d, p.Y() - fB * d, p.Z() - fC * d); + } + + /** + Return the projection of a point to a plane + \param p Point expressed as generic ROOT::Math::PositionVector3D + */ + template + PositionVector3D ProjectOntoPlane(const PositionVector3D &p) const + { + const Point pxyz = ProjectOntoPlane(Point(p.X(), p.Y(), p.Z())); + return PositionVector3D(pxyz.X(), pxyz.Y(), pxyz.Z()); + } + + // ------------------- Equality ----------------- + + /** + Exact equality + */ + bool operator==(const Plane3D &rhs) const { return (fA == rhs.fA && fB == rhs.fB && fC == rhs.fC && fD == rhs.fD); } + bool operator!=(const Plane3D &rhs) const { return !(operator==(rhs)); } + +protected: + /** + Normalize the normal (a,b,c) plane components + */ + template ::value>::type * = nullptr> + void Normalize() + { + // normalize the plane + using std::sqrt; + const SCALAR s = sqrt(fA * fA + fB * fB + fC * fC); + // what to do if s = 0 ? + if (s == SCALAR(0)) { + fD = SCALAR(0); + } else { + const SCALAR w = Scalar(1) / s; + fA *= w; + fB *= w; + fC *= w; + fD *= w; + } + } + + /** + Normalize the normal (a,b,c) plane components + */ + template ::value>::type * = nullptr> + void Normalize() + { + // normalize the plane + using std::sqrt; + SCALAR s = sqrt(fA * fA + fB * fB + fC * fC); + // what to do if s = 0 ? + const auto m = (s == SCALAR(0)); + // set zero entries to 1 in the vector to avoid /0 later on + s(m) = SCALAR(1); + fD(m) = SCALAR(0); + const SCALAR w = SCALAR(1) / s; + fA *= w; + fB *= w; + fC *= w; + fD *= w; + } + +private: + // internal method to construct class from a vector and a point + void BuildFromVecAndPoint(const Vector &n, const Point &p) + { + // build from a normal vector and a point + fA = n.X(); + fB = n.Y(); + fC = n.Z(); + fD = -n.Dot(p); + Normalize(); + } + + // internal method to construct class from 3 points + void BuildFrom3Points(const Point &p1, const Point &p2, const Point &p3) + { + // plane from three points + // normal is (x3-x1) cross (x2 -x1) + const Vector n = (p2 - p1).Cross(p3 - p1); + fA = n.X(); + fB = n.Y(); + fC = n.Z(); + fD = -n.Dot(p1); + Normalize(); + } + + // plane data members the four scalar which satisfies fA*x + fB*y + fC*z + fD = 0 + // for every point (x,y,z) belonging to the plane. + // fA**2 + fB**2 + fC** =1 plane is stored in normalized form + Scalar fA; + Scalar fB; + Scalar fC; + Scalar fD; + + }; // Plane3D<> + + /** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form + template + std::ostream &operator<<(std::ostream &os, const Plane3D &p) + { + os << "\n" + << p.Normal().X() << " " << p.Normal().Y() << " " << p.Normal().Z() << " " << p.HesseDistance() << "\n"; + return os; + } + + } // end namespace Impl + + // typedefs for double and float versions + typedef Impl::Plane3D Plane3D; + typedef Impl::Plane3D Plane3DF; + +} // end namespace Math + +} // end namespace ROOT + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar2D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar2D.h new file mode 100644 index 0000000000000..426b1be5890f6 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar2D.h @@ -0,0 +1,272 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team and * + * FNAL LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Polar2D +// +// Created by: Lorenzo Moneta at Mon May 30 11:40:03 2005 +// Major revamp: M. Fischler at Wed Jun 8 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_Polar2D +#define ROOT_MathX_GenVectorX_Polar2D 1 + +#include "Math/Math.h" + +#include "MathX/GenVectorX/etaMax.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Class describing a polar 2D coordinate system based on r and phi + Phi is restricted to be in the range [-PI,PI) + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + + +template +class Polar2D { + +public : + + typedef T Scalar; + + /** + Default constructor with r=1,phi=0 + */ + Polar2D() : fR(1.), fPhi(0) { } + + /** + Construct from the polar coordinates: r and phi + */ + Polar2D(T r,T phi) : fR(r), fPhi(phi) { Restrict(); } + + /** + Construct from any Vector or coordinate system implementing + R() and Phi() + */ + template + explicit Polar2D( const CoordSystem & v ) : + fR(v.R() ), 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 + */ + Polar2D(const Polar2D & v) : + fR(v.R() ), fPhi(v.Phi() ) { } + + /** + assignment operator + */ + Polar2D & operator= (const Polar2D & v) { + fR = v.R(); + fPhi = v.Phi(); + return *this; + } + + + /** + Set internal data based on 2 Scalar numbers + */ + void SetCoordinates(Scalar r, Scalar phi) + { fR=r; fPhi=phi; Restrict(); } + + /** + get internal data into 2 Scalar numbers + */ + void GetCoordinates(Scalar& r, Scalar& phi) const {r=fR; phi=fPhi;} + + + Scalar R() const { return fR;} + Scalar Phi() const { return fPhi; } + Scalar X() const { return fR * math_cos(fPhi); } + Scalar Y() const { return fR * math_sin(fPhi); } + Scalar Mag2() const { return fR*fR;} + + + // setters (only for data members) + + + /** + set the r coordinate value keeping phi constant + */ + void SetR(const T & r) { + fR = r; + } + + + /** + set the phi coordinate value keeping r constant + */ + void SetPhi(const T & phi) { + fPhi = phi; + Restrict(); + } + + /** + set all values using cartesian coordinates + */ + void SetXY(Scalar a, Scalar b); + + +private: + inline static double pi() { return M_PI; } + + /** + restrict abgle hi to be between -PI and PI + */ + inline void Restrict() { + if (fPhi <= -pi() || fPhi > pi()) fPhi = fPhi - math_floor(fPhi / (2 * pi()) + .5) * 2 * pi(); + } + +public: + + /** + scale by a scalar quantity - for polar coordinates r changes + */ + void Scale (T a) { + if (a < 0) { + Negate(); + a = -a; + } + // angles do not change when scaling by a positive quantity + fR *= a; + } + + /** + negate the vector + */ + void Negate ( ) { + fPhi = ( fPhi > 0 ? fPhi - pi() : fPhi + pi() ); + } + + /** + rotate the vector + */ + void Rotate(T angle) { + fPhi += angle; + Restrict(); + } + + // assignment operators + /** + generic assignment operator from any coordinate system + */ + template + Polar2D & operator= ( const CoordSystem & c ) { + fR = c.R(); + fPhi = c.Phi(); + return *this; + } + + /** + Exact equality + */ + bool operator==(const Polar2D & rhs) const { + return fR == rhs.fR && fPhi == rhs.fPhi; + } + bool operator!= (const Polar2D & 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();} + + // ============= Specializations for improved speed ================== + + // (none) + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) + + // ====== Set member functions for coordinates in other systems ======= + + void SetX(Scalar a); + + void SetY(Scalar a); + +#endif + +private: + T fR; + T fPhi; +}; + + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + +// move implementations here to avoid circle dependencies + +#include "MathX/GenVectorX/Cartesian2D.h" + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#include "MathX/GenVectorX/GenVector_exception.h" +#endif + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +void Polar2D::SetXY(Scalar a, Scalar b) { + *this = Cartesian2D(a, b); +} + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +// ====== Set member functions for coordinates in other systems ======= + + template + void Polar2D::SetX(Scalar a) { + GenVector_exception e("Polar2D::SetX() is not supposed to be called"); + throw e; + Cartesian2D v(*this); v.SetX(a); *this = Polar2D(v); + } + template + void Polar2D::SetY(Scalar a) { + GenVector_exception e("Polar2D::SetY() is not supposed to be called"); + throw e; + Cartesian2D v(*this); v.SetY(a); *this = Polar2D(v); + } + +#endif +#endif + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + + +#endif /* ROOT_MathX_GenVectorX_Polar2D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar2Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar2Dfwd.h new file mode 100644 index 0000000000000..f2246e0c64d77 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar2Dfwd.h @@ -0,0 +1,24 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_Polar2Dfwd +#define ROOT_MathX_GenVectorX_Polar2Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a 2D Polar coordinate system + (r, phi coordinates) + */ + + template + class Polar2D; + + } +} + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar3D.h new file mode 100644 index 0000000000000..16ad7357e278e --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar3D.h @@ -0,0 +1,320 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team and * + * FNAL LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Polar3D +// +// Created by: Lorenzo Moneta at Mon May 30 11:40:03 2005 +// Major revamp: M. Fischler at Wed Jun 8 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_Polar3D +#define ROOT_MathX_GenVectorX_Polar3D 1 + +#include "Math/Math.h" + +#include "MathX/GenVectorX/eta.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Class describing a polar coordinate system based on r, theta and phi + Phi is restricted to be in the range [-PI,PI) + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + + +template +class Polar3D { + +public : + + typedef T Scalar; + + /** + Default constructor with r=theta=phi=0 + */ + Polar3D() : fR(0), fTheta(0), fPhi(0) { } + + /** + Construct from the polar coordinates: r, theta and phi + */ + Polar3D(T r,T theta,T phi) : fR(r), fTheta(theta), fPhi(phi) { Restrict(); } + + /** + Construct from any Vector or coordinate system implementing + R(), Theta() and Phi() + */ + template + explicit Polar3D( const CoordSystem & v ) : + fR(v.R() ), fTheta(v.Theta() ), 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 + */ + Polar3D(const Polar3D & v) : + fR(v.R() ), fTheta(v.Theta() ), fPhi(v.Phi() ) { } + + /** + assignment operator + */ + Polar3D & operator= (const Polar3D & v) { + fR = v.R(); + fTheta = v.Theta(); + fPhi = v.Phi(); + return *this; + } + + /** + Set internal data based on an array of 3 Scalar numbers + */ + void SetCoordinates( const Scalar src[] ) + { fR=src[0]; fTheta=src[1]; fPhi=src[2]; Restrict(); } + + /** + get internal data into an array of 3 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { dest[0] = fR; dest[1] = fTheta; dest[2] = fPhi; } + + /** + Set internal data based on 3 Scalar numbers + */ + void SetCoordinates(Scalar r, Scalar theta, Scalar phi) + { fR=r; fTheta=theta; fPhi=phi; Restrict(); } + + /** + get internal data into 3 Scalar numbers + */ + void GetCoordinates(Scalar& r, Scalar& theta, Scalar& phi) const {r=fR; theta=fTheta; phi=fPhi;} + + + Scalar R() const { return fR;} + Scalar Phi() const { return fPhi; } + Scalar Theta() const { return fTheta; } + Scalar Rho() const { return fR * math_sin(fTheta); } + Scalar X() const { return Rho() * math_cos(fPhi); } + Scalar Y() const { return Rho() * math_sin(fPhi); } + Scalar Z() const { return fR * math_cos(fTheta); } + Scalar Mag2() const { return fR*fR;} + Scalar Perp2() const { return Rho() * Rho(); } + + // pseudorapidity + Scalar Eta() const + { + return Impl::Eta_FromTheta(fTheta, fR); + } + + // setters (only for data members) + + + /** + set the r coordinate value keeping theta and phi constant + */ + void SetR(const T & r) { + fR = r; + } + + /** + set the theta coordinate value keeping r and phi constant + */ + void SetTheta(const T & theta) { + fTheta = theta; + } + + /** + set the phi coordinate value keeping r and theta constant + */ + void SetPhi(const T & phi) { + fPhi = phi; + Restrict(); + } + + /** + set all values using cartesian coordinates + */ + void SetXYZ(Scalar x, Scalar y, Scalar z); + + +private: + inline static Scalar pi() { return M_PI; } + inline void Restrict() { + if (fPhi <= -pi() || fPhi > pi()) fPhi = fPhi - math_floor(fPhi / (2 * pi()) + .5) * 2 * pi(); + } + +public: + + /** + scale by a scalar quantity - for polar coordinates r changes + */ + void Scale (T a) { + if (a < 0) { + Negate(); + a = -a; + } + // angles do not change when scaling by a positive quantity + fR *= a; + } + + /** + negate the vector + */ + void Negate ( ) { + fPhi = ( fPhi > 0 ? fPhi - pi() : fPhi + pi() ); + fTheta = pi() - fTheta; + } + + // assignment operators + /** + generic assignment operator from any coordinate system + */ + template + Polar3D & operator= ( const CoordSystem & c ) { + fR = c.R(); + fTheta = c.Theta(); + fPhi = c.Phi(); + return *this; + } + + /** + Exact equality + */ + bool operator==(const Polar3D & rhs) const { + return fR == rhs.fR && fTheta == rhs.fTheta && fPhi == rhs.fPhi; + } + bool operator!= (const Polar3D & 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 SetZ(Scalar z); + + void SetRho(Scalar rho); + + void SetEta(Scalar eta); + +#endif + +private: + T fR; + T fTheta; + T fPhi; +}; + + + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + +// move implementations here to avoid circle dependencies + +#include "MathX/GenVectorX/Cartesian3D.h" + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#include "MathX/GenVectorX/GenVector_exception.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#endif + + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +void Polar3D::SetXYZ(Scalar xx, Scalar yy, Scalar zz) { + *this = Cartesian3D(xx, yy, zz); +} + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + // ====== Set member functions for coordinates in other systems ======= + + +template +void Polar3D::SetX(Scalar xx) { + GenVector_exception e("Polar3D::SetX() is not supposed to be called"); + throw e; + Cartesian3D v(*this); v.SetX(xx); *this = Polar3D(v); +} +template +void Polar3D::SetY(Scalar yy) { + GenVector_exception e("Polar3D::SetY() is not supposed to be called"); + throw e; + Cartesian3D v(*this); v.SetY(yy); *this = Polar3D(v); +} +template +void Polar3D::SetZ(Scalar zz) { + GenVector_exception e("Polar3D::SetZ() is not supposed to be called"); + throw e; + Cartesian3D v(*this); v.SetZ(zz); *this = Polar3D(v); +} +template +void Polar3D::SetRho(Scalar rho) { + GenVector_exception e("Polar3D::SetRho() is not supposed to be called"); + throw e; + CylindricalEta3D v(*this); v.SetRho(rho); + *this = Polar3D(v); +} +template +void Polar3D::SetEta(Scalar eta) { + GenVector_exception e("Polar3D::SetEta() is not supposed to be called"); + throw e; + CylindricalEta3D v(*this); v.SetEta(eta); + *this = Polar3D(v); +} + +#endif +#endif + + } // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + + +#endif /* ROOT_MathX_GenVectorX_Polar3D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar3Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar3Dfwd.h new file mode 100644 index 0000000000000..154110fb3547d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar3Dfwd.h @@ -0,0 +1,24 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_Polar3Dfwd +#define ROOT_MathX_GenVectorX_Polar3Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a 3D Polar coordinate system + (r, theta, phi coordinates) + */ + +template +class Polar3D; + +} +} + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector2D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector2D.h new file mode 100644 index 0000000000000..c2ff166c37993 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector2D.h @@ -0,0 +1,517 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class PositionVector2D +// +// Created by: Lorenzo Moneta at Mon Apr 16 2007 +// +// +#ifndef ROOT_MathX_GenVectorX_PositionVector2D +#define ROOT_MathX_GenVectorX_PositionVector2D 1 + +#include "MathX/GenVectorX/DisplacementVector2D.h" + +#include "MathX/GenVectorX/GenVectorIO.h" + +#include "MathX/GenVectorX/BitReproducible.h" + +#include "MathX/GenVectorX/CoordinateSystemTags.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Class describing a generic position vector (point) in 2 dimensions. + This class is templated on the type of Coordinate system. + One example is the XYPoint which is a vector based on + double precision x,y data members by using the + ROOT::Math::Cartesian2D Coordinate system. + The class is having also an extra template parameter, the coordinate system tag, + to be able to identify (tag) vector described in different reference coordinate system, + like global or local coordinate systems. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + + template + class PositionVector2D { + + public: + + typedef typename CoordSystem::Scalar Scalar; + typedef CoordSystem CoordinateType; + typedef Tag CoordinateSystemTag; + + // ------ ctors ------ + + /** + Default constructor. Construct an empty object with zero values + */ + + PositionVector2D() : fCoordinates() { } + + /** + Construct from three values of type Scalar. + In the case of a XYPoint the values are x,y + In the case of a polar vector they are r,phi + */ + PositionVector2D(const Scalar & a, const Scalar & b) : + fCoordinates ( a , b) { } + + /** + Construct from a position vector expressed in different + coordinates, or using a different Scalar type + */ + template + explicit PositionVector2D( const PositionVector2D & v) : + fCoordinates ( v.Coordinates() ) { } + + /** + Construct from an arbitrary displacement vector + */ + template + explicit PositionVector2D( const DisplacementVector2D & p) : + fCoordinates ( p.Coordinates() ) { } + + /** + Construct from a foreign 2D vector type, for example, Hep2Vector + Precondition: v must implement methods x() and y() + */ + template + explicit PositionVector2D( const ForeignVector & v) : + fCoordinates ( Cartesian2D( v.x(), v.y() ) ) { } + + // compiler-generated copy ctor and dtor are fine. + + // ------ assignment ------ + + /** + Assignment operator from a position vector of arbitrary type + */ + template + PositionVector2D & operator= + ( const PositionVector2D & v) { + fCoordinates = v.Coordinates(); + return *this; + } + + /** + Assignment operator from a displacement vector of arbitrary type + */ + template + PositionVector2D & operator= + ( const DisplacementVector2D & v) { + fCoordinates = v.Coordinates(); + return *this; + } + + /** + Assignment from a foreign 2D vector type, for example, Hep2Vector + Precondition: v must implement methods x() and y() + */ + template + PositionVector2D & operator= ( const ForeignVector & v) { + SetXY( v.x(), v.y() ); + return *this; + } + + /** + Retrieve a copy of the coordinates object + */ + const CoordSystem & Coordinates() const { + return fCoordinates; + } + + /** + Set internal data based on 2 Scalar numbers. + These are for example (x,y) for a cartesian vector or (r,phi) for a polar vector + */ + PositionVector2D& SetCoordinates( Scalar a, Scalar b) { + fCoordinates.SetCoordinates(a, b); + return *this; + } + + + /** + get internal data into 2 Scalar numbers. + These are for example (x,y) for a cartesian vector or (r,phi) for a polar vector + */ + void GetCoordinates( Scalar& a, Scalar& b) const + { fCoordinates.GetCoordinates(a, b); } + + + /** + set the values of the vector from the cartesian components (x,y) + (if the vector is held in polar coordinates, + then (x, y) are converted to that form) + */ + PositionVector2D& SetXY (Scalar a, Scalar b) { + fCoordinates.SetXY (a,b); + return *this; + } + + // ------------------- Equality ----------------- + + /** + Exact equality + */ + bool operator==(const PositionVector2D & rhs) const { + return fCoordinates==rhs.fCoordinates; + } + bool operator!= (const PositionVector2D & rhs) const { + return !(operator==(rhs)); + } + + // ------ Individual element access, in various coordinate systems ------ + + /** + Cartesian X, converting if necessary from internal coordinate system. + */ + Scalar X() const { return fCoordinates.X(); } + + /** + Cartesian Y, converting if necessary from internal coordinate system. + */ + Scalar Y() const { return fCoordinates.Y(); } + + /** + Polar R, converting if necessary from internal coordinate system. + */ + Scalar R() const { return fCoordinates.R(); } + + /** + Polar phi, converting if necessary from internal coordinate system. + */ + Scalar Phi() const { return fCoordinates.Phi(); } + + /** + Magnitute squared ( r^2 in spherical coordinate) + */ + Scalar Mag2() const { return fCoordinates.Mag2();} + + + // It is physically meaningless to speak of the unit vector corresponding + // to a point. + + // ------ Setting individual elements present in coordinate system ------ + + /** + Change X - Cartesian2D coordinates only + */ + PositionVector2D& SetX (Scalar a) { + fCoordinates.SetX(a); + return *this; + } + + /** + Change Y - Cartesian2D coordinates only + */ + PositionVector2D& SetY (Scalar a) { + fCoordinates.SetY(a); + return *this; + } + + + /** + Change R - Polar2D coordinates only + */ + PositionVector2D& SetR (Scalar a) { + fCoordinates.SetR(a); + return *this; + } + + /** + Change Phi - Polar2D coordinates + */ + PositionVector2D& SetPhi (Scalar ang) { + fCoordinates.SetPhi(ang); + return *this; + } + + + // ------ Operations combining two vectors ------ + // need to specialize to exclude those with a different tags + + /** + Return the scalar (Dot) product of this with a displacement vector in + any coordinate system, but with the same tag + */ + template< class OtherCoords > + Scalar Dot( const DisplacementVector2D & v) const { + return X()*v.x() + Y()*v.y(); + } + + + // The Dot product of a pair of point vectors are physically + // meaningless concepts and thus are defined as private methods + + + /** + Self Addition with a displacement vector. + */ + template + PositionVector2D & operator+= (const DisplacementVector2D & v) + { + SetXY( X() + v.X(), Y() + v.Y() ); + return *this; + } + + /** + Self Difference with a displacement vector. + */ + template + PositionVector2D & operator-= (const DisplacementVector2D & v) + { + SetXY( X() - v.X(), Y() - v.Y() ); + return *this; + } + + /** + multiply this vector by a scalar quantity + */ + PositionVector2D & operator *= (Scalar a) { + fCoordinates.Scale(a); + return *this; + } + + /** + divide this vector by a scalar quantity + */ + PositionVector2D & operator /= (Scalar a) { + fCoordinates.Scale(1/a); + return *this; + } + + // The following methods (v*a and v/a) could instead be free functions. + // They were moved into the class to solve a problem on AIX. + /** + Multiply a vector by a real number + */ + PositionVector2D operator * ( Scalar a ) const { + PositionVector2D tmp(*this); + tmp *= a; + return tmp; + } + + /** + Division of a vector with a real number + */ + PositionVector2D operator / (Scalar a) const { + PositionVector2D tmp(*this); + tmp /= a; + return tmp; + } + + /** + Rotate by an angle + */ + void Rotate( Scalar angle) { + return fCoordinates.Rotate(angle); + } + + // Limited backward name compatibility with CLHEP + + Scalar x() const { return fCoordinates.X(); } + Scalar y() const { return fCoordinates.Y(); } + Scalar r() const { return fCoordinates.R(); } + Scalar phi() const { return fCoordinates.Phi(); } + Scalar mag2() const { return fCoordinates.Mag2(); } + + private: + + CoordSystem fCoordinates; + + // Prohibited methods + + // this should not compile (if from a vector or points with different tag + + template + explicit PositionVector2D( const PositionVector2D & ); + + template + explicit PositionVector2D( const DisplacementVector2D & ); + + template + PositionVector2D & operator=( const PositionVector2D & ); + + template + PositionVector2D & operator=( const DisplacementVector2D & ); + + template + PositionVector2D & operator+=(const DisplacementVector2D & ); + + template + PositionVector2D & operator-=(const DisplacementVector2D & ); + +// /** +// Dot product of two position vectors is inappropriate +// */ +// template +// PositionVector2D Dot( const PositionVector2D & v) const; + + + + }; + +// ---------- PositionVector2D class template ends here ---------------- +// --------------------------------------------------------------------- + + /** + Multiplication of a position vector by real number a*v + */ + template + inline + PositionVector2D + operator * ( typename PositionVector2D::Scalar a, + PositionVector2D v) { + return v *= a; + // Note - passing v by value and using operator *= may save one + // copy relative to passing v by const ref and creating a temporary. + } + + /** + Difference between two PositionVector2D vectors. + The result is a DisplacementVector2D. + The (coordinate system) type of the returned vector is defined to + be identical to that of the first position vector. + */ + + template + inline + DisplacementVector2D + operator-( const PositionVector2D & v1, + const PositionVector2D & v2) { + return DisplacementVector2D( Cartesian2D( + v1.X()-v2.X(), v1.Y()-v2.Y() ) + ); + } + + /** + Addition of a PositionVector2D and a DisplacementVector2D. + The return type is a PositionVector2D, + of the same (coordinate system) type as the input PositionVector2D. + */ + template + inline + PositionVector2D + operator+( PositionVector2D p1, + const DisplacementVector2D & v2) { + return p1 += v2; + } + + /** + Addition of a DisplacementVector2D and a PositionVector2D. + The return type is a PositionVector2D, + of the same (coordinate system) type as the input PositionVector2D. + */ + template + inline + PositionVector2D + operator+( DisplacementVector2D const & v1, + PositionVector2D p2) { + return p2 += v1; + } + + /** + Subtraction of a DisplacementVector2D from a PositionVector2D. + The return type is a PositionVector2D, + of the same (coordinate system) type as the input PositionVector2D. + */ + template + inline + PositionVector2D + operator-( PositionVector2D p1, + DisplacementVector2D const & v2) { + return p1 -= v2; + } + + // Scaling of a position vector with a real number is not physically meaningful + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + // ------------- I/O to/from streams ------------- + + template< class char_t, class traits_t, class T, class U > + inline + std::basic_ostream & + operator << ( std::basic_ostream & os + , PositionVector2D const & v + ) + { + if( !os ) return os; + + typename T::Scalar a, b; + v.GetCoordinates(a, b); + + if( detail::get_manip( os, detail::bitforbit ) ) { + detail::set_manip( os, detail::bitforbit, '\00' ); + typedef GenVector_detail::BitReproducible BR; + BR::Output(os, a); + BR::Output(os, b); + } + else { + os << detail::get_manip( os, detail::open ) << a + << detail::get_manip( os, detail::sep ) << b + << detail::get_manip( os, detail::close ); + } + + return os; + + } // op<< <>() + + + template< class char_t, class traits_t, class T, class U > + inline + std::basic_istream & + operator >> ( std::basic_istream & is + , PositionVector2D & v + ) + { + if( !is ) return is; + + typename T::Scalar a, b; + + if( detail::get_manip( is, detail::bitforbit ) ) { + detail::set_manip( is, detail::bitforbit, '\00' ); + typedef GenVector_detail::BitReproducible BR; + BR::Input(is, a); + BR::Input(is, b); + } + else { + detail::require_delim( is, detail::open ); is >> a; + detail::require_delim( is, detail::sep ); is >> b; + detail::require_delim( is, detail::close ); + } + + if( is ) + v.SetCoordinates(a, b); + return is; + + } // op>> <>() +#endif + + + + } // namespace ROOT_MATH_ARCH + +} // namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_PositionVector2D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector2Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector2Dfwd.h new file mode 100644 index 0000000000000..b6656e155b004 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector2Dfwd.h @@ -0,0 +1,24 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_PositionVector2Dfwd +#define ROOT_MathX_GenVectorX_PositionVector2Dfwd 1 + + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a 2D Position vector + */ + + template + class PositionVector2D; + + } +} + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector3D.h new file mode 100644 index 0000000000000..f6f2eb0bb589f --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector3D.h @@ -0,0 +1,664 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class PositionVector3D +// +// Created by: Lorenzo Moneta at Mon May 30 15:25:04 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_PositionVector3D +#define ROOT_MathX_GenVectorX_PositionVector3D 1 + +#include "MathX/GenVectorX/DisplacementVector3Dfwd.h" + +#include "MathX/GenVectorX/Cartesian3D.h" + +#include "MathX/GenVectorX/GenVectorIO.h" + +#include "MathX/GenVectorX/BitReproducible.h" + +#include "MathX/GenVectorX/CoordinateSystemTags.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Class describing a generic position vector (point) in 3 dimensions. + This class is templated on the type of Coordinate system. + One example is the XYZPoint which is a vector based on + double precision x,y,z data members by using the + ROOT::Math::Cartesian3D Coordinate system. + The class is having also an extra template parameter, the coordinate system tag, + to be able to identify (tag) vector described in different reference coordinate system, + like global or local coordinate systems. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + + template + class PositionVector3D { + + public: + + typedef typename CoordSystem::Scalar Scalar; + typedef CoordSystem CoordinateType; + typedef Tag CoordinateSystemTag; + + // ------ ctors ------ + + /** + Default constructor. Construct an empty object with zero values + */ + + PositionVector3D() : fCoordinates() { } + + /** + Construct from three values of type Scalar. + In the case of a XYZPoint the values are x,y,z + In the case of a polar vector they are r,theta,phi + */ + PositionVector3D(const Scalar & a, const Scalar & b, const Scalar & c) : + fCoordinates ( a , b, c) { } + + /** + Construct from a position vector expressed in different + coordinates, or using a different Scalar type + */ + template + explicit PositionVector3D( const PositionVector3D & v) : + fCoordinates ( v.Coordinates() ) { } + + /** + Construct from an arbitrary displacement vector + */ + template + explicit PositionVector3D( const DisplacementVector3D & p) : + fCoordinates ( p.Coordinates() ) { } + + /** + Construct from a foreign 3D vector type, for example, Hep3Vector + Precondition: v must implement methods x(), y() and z() + */ + template + explicit PositionVector3D( const ForeignVector & v) : + fCoordinates ( Cartesian3D( v.x(), v.y(), v.z() ) ) { } + +#ifdef LATER + /** + construct from a generic linear algebra vector of at least size 3 + implementing operator []. This could be also a C array + \par v LAVector + \par index0 index where coordinates starts (typically zero) + It works for all Coordinates types, + ( x= v[index0] for Cartesian and r=v[index0] for Polar ) + */ + template + PositionVector3D(const LAVector & v, size_t index0 ) { + fCoordinates = CoordSystem ( v[index0], v[index0+1], v[index0+2] ); + } +#endif + + // compiler-generated copy ctor and dtor are fine. + + // ------ assignment ------ + + /** + Assignment operator from a position vector of arbitrary type + */ + template + PositionVector3D & operator= + ( const PositionVector3D & v) { + fCoordinates = v.Coordinates(); + return *this; + } + + /** + Assignment operator from a displacement vector of arbitrary type + */ + template + PositionVector3D & operator= + ( const DisplacementVector3D & v) { + fCoordinates = v.Coordinates(); + return *this; + } + + /** + Assignment from a foreign 3D vector type, for example, Hep3Vector + Precondition: v must implement methods x(), y() and z() + */ + template + PositionVector3D & operator= ( const ForeignVector & v) { + SetXYZ( v.x(), v.y(), v.z() ); + return *this; + } + +#ifdef LATER + /** + assign from a generic linear algebra vector of at least size 3 + implementing operator []. + \par v LAVector + \par index0 index where coordinates starts (typically zero) + It works for all Coordinates types, + ( x= v[index0] for Cartesian and r=v[index0] for Polar ) + */ + template + PositionVector3D & assignFrom(const LAVector & v, size_t index0 = 0) { + fCoordinates = CoordSystem ( v[index0], v[index0+1], v[index0+2] ); + return *this; + } +#endif + + /** + Retrieve a copy of the coordinates object + */ + const CoordSystem & Coordinates() const { + return fCoordinates; + } + + /** + Set internal data based on a C-style array of 3 Scalar numbers + */ + PositionVector3D& SetCoordinates( const Scalar src[] ) + { fCoordinates.SetCoordinates(src); return *this; } + + /** + Set internal data based on 3 Scalar numbers + */ + PositionVector3D& SetCoordinates( Scalar a, Scalar b, Scalar c ) + { fCoordinates.SetCoordinates(a, b, c); return *this; } + + /** + Set internal data based on 3 Scalars at *begin to *end + */ + template + PositionVector3D& SetCoordinates( IT begin, IT end ) + { IT a = begin; IT b = ++begin; IT c = ++begin; + (void)end; + assert (++begin==end); + SetCoordinates (*a,*b,*c); + return *this; + } + + /** + get internal data into 3 Scalar numbers + */ + void GetCoordinates( Scalar& a, Scalar& b, Scalar& c ) const + { fCoordinates.GetCoordinates(a, b, c); } + + /** + get internal data into a C-style array of 3 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { fCoordinates.GetCoordinates(dest); } + + /** + get internal data into 3 Scalars at *begin to *end (3 past begin) + */ + template + void GetCoordinates( IT begin, IT end ) const + { IT a = begin; IT b = ++begin; IT c = ++begin; + (void)end; + assert (++begin==end); + GetCoordinates (*a,*b,*c); + } + + /** + get internal data into 3 Scalars at *begin + */ + template + void GetCoordinates( IT begin ) const { + Scalar a = Scalar(0); + Scalar b = Scalar(0); + Scalar c = Scalar(0); + GetCoordinates(a, b, c); + *begin++ = a; + *begin++ = b; + *begin = c; + } + + /** + set the values of the vector from the cartesian components (x,y,z) + (if the vector is held in polar or cylindrical eta coordinates, + then (x, y, z) are converted to that form) + */ + PositionVector3D& SetXYZ (Scalar a, Scalar b, Scalar c) { + fCoordinates.SetXYZ(a,b,c); + return *this; + } + + // ------------------- Equality ----------------- + + /** + Exact equality + */ + bool operator==(const PositionVector3D & rhs) const { + return fCoordinates==rhs.fCoordinates; + } + bool operator!= (const PositionVector3D & rhs) const { + return !(operator==(rhs)); + } + + // ------ Individual element access, in various coordinate systems ------ + + /** + Cartesian X, converting if necessary from internal coordinate system. + */ + Scalar X() const { return fCoordinates.X(); } + + /** + Cartesian Y, converting if necessary from internal coordinate system. + */ + Scalar Y() const { return fCoordinates.Y(); } + + /** + Cartesian Z, converting if necessary from internal coordinate system. + */ + Scalar Z() const { return fCoordinates.Z(); } + + /** + Polar R, converting if necessary from internal coordinate system. + */ + Scalar R() const { return fCoordinates.R(); } + + /** + Polar theta, converting if necessary from internal coordinate system. + */ + Scalar Theta() const { return fCoordinates.Theta(); } + + /** + Polar phi, converting if necessary from internal coordinate system. + */ + Scalar Phi() const { return fCoordinates.Phi(); } + + /** + Polar eta, converting if necessary from internal coordinate system. + */ + Scalar Eta() const { return fCoordinates.Eta(); } + + /** + Cylindrical transverse component rho + */ + Scalar Rho() const { return fCoordinates.Rho(); } + + // ----- Other fundamental properties ----- + + /** + Magnitute squared ( r^2 in spherical coordinate) + */ + Scalar Mag2() const { return fCoordinates.Mag2();} + + /** + Transverse component squared (rho^2 in cylindrical coordinates. + */ + Scalar Perp2() const { return fCoordinates.Perp2();} + + // It is physically meaningless to speak of the unit vector corresponding + // to a point. + + // ------ Setting individual elements present in coordinate system ------ + + /** + Change X - Cartesian3D coordinates only + */ + PositionVector3D& SetX (Scalar xx) { fCoordinates.SetX(xx); return *this;} + + /** + Change Y - Cartesian3D coordinates only + */ + PositionVector3D& SetY (Scalar yy) { fCoordinates.SetY(yy); return *this;} + + /** + Change Z - Cartesian3D coordinates only + */ + PositionVector3D& SetZ (Scalar zz) { fCoordinates.SetZ(zz); return *this;} + + /** + Change R - Polar3D coordinates only + */ + PositionVector3D& SetR (Scalar rr) { fCoordinates.SetR(rr); return *this;} + + /** + Change Theta - Polar3D coordinates only + */ + PositionVector3D& SetTheta (Scalar ang) { fCoordinates.SetTheta(ang); return *this;} + + /** + Change Phi - Polar3D or CylindricalEta3D coordinates + */ + PositionVector3D& SetPhi (Scalar ang) { fCoordinates.SetPhi(ang); return *this;} + + /** + Change Rho - CylindricalEta3D coordinates only + */ + PositionVector3D& SetRho (Scalar rr) { fCoordinates.SetRho(rr); return *this;} + + /** + Change Eta - CylindricalEta3D coordinates only + */ + PositionVector3D& SetEta (Scalar etaval) { fCoordinates.SetEta(etaval); return *this;} + + // ------ Operations combining two vectors ------ + // need to specialize to exclude those with a different tags + + /** + Return the scalar (Dot) product of this with a displacement vector in + any coordinate system, but with the same tag + */ + template< class OtherCoords > + Scalar Dot( const DisplacementVector3D & v) const { + return X()*v.x() + Y()*v.y() + Z()*v.z(); + } + + + /** + Return vector (Cross) product of this point with a displacement, as a + point vector in this coordinate system of the first. + */ + template< class OtherCoords > + PositionVector3D Cross( const DisplacementVector3D & v) const { + PositionVector3D result; + result.SetXYZ ( Y()*v.z() - v.y()*Z(), + Z()*v.x() - v.z()*X(), + X()*v.y() - v.x()*Y() ); + return result; + } + + // The Dot and Cross products of a pair of point vectors are physically + // meaningless concepts and thus are defined as private methods + + // It is physically meaningless to speak of the Unit vector corresponding + // to a point. + + + /** + Self Addition with a displacement vector. + */ + template + PositionVector3D & operator+= (const DisplacementVector3D & v) + { + SetXYZ( X() + v.X(), Y() + v.Y(), Z() + v.Z() ); + return *this; + } + + /** + Self Difference with a displacement vector. + */ + template + PositionVector3D & operator-= (const DisplacementVector3D & v) + { + SetXYZ( X() - v.X(), Y() - v.Y(), Z() - v.Z() ); + return *this; + } + + /** + multiply this vector by a scalar quantity + */ + PositionVector3D & operator *= (Scalar a) { + fCoordinates.Scale(a); + return *this; + } + + /** + divide this vector by a scalar quantity + */ + PositionVector3D & operator /= (Scalar a) { + fCoordinates.Scale(1/a); + return *this; + } + + // The following methods (v*a and v/a) could instead be free functions. + // They were moved into the class to solve a problem on AIX. + /** + Multiply a vector by a real number + */ + PositionVector3D operator * ( Scalar a ) const { + PositionVector3D tmp(*this); + tmp *= a; + return tmp; + } + + /** + Division of a vector with a real number + */ + PositionVector3D operator / (Scalar a) const { + PositionVector3D tmp(*this); + tmp /= a; + return tmp; + } + + // Limited backward name compatibility with CLHEP + + Scalar x() const { return fCoordinates.X(); } + Scalar y() const { return fCoordinates.Y(); } + Scalar z() const { return fCoordinates.Z(); } + Scalar r() const { return fCoordinates.R(); } + Scalar theta() const { return fCoordinates.Theta(); } + Scalar phi() const { return fCoordinates.Phi(); } + Scalar eta() const { return fCoordinates.Eta(); } + Scalar rho() const { return fCoordinates.Rho(); } + Scalar mag2() const { return fCoordinates.Mag2(); } + Scalar perp2() const { return fCoordinates.Perp2(); } + + private: + + CoordSystem fCoordinates; + + // Prohibited methods + + // this should not compile (if from a vector or points with different tag + + template + explicit PositionVector3D( const PositionVector3D & ); + + template + explicit PositionVector3D( const DisplacementVector3D & ); + + template + PositionVector3D & operator=( const PositionVector3D & ); + + template + PositionVector3D & operator=( const DisplacementVector3D & ); + + template + PositionVector3D & operator+=(const DisplacementVector3D & ); + + template + PositionVector3D & operator-=(const DisplacementVector3D & ); + +// /** +// Dot product of two position vectors is inappropriate +// */ +// template +// PositionVector3D Dot( const PositionVector3D & v) const; + +// /** +// Cross product of two position vectors is inappropriate +// */ +// template +// PositionVector3D Cross( const PositionVector3D & v) const; + + + + }; + +// ---------- PositionVector3D class template ends here ---------------- +// --------------------------------------------------------------------- + + /** + Multiplication of a position vector by real number a*v + */ + template + inline + PositionVector3D + operator * ( typename PositionVector3D::Scalar a, + PositionVector3D v) { + return v *= a; + // Note - passing v by value and using operator *= may save one + // copy relative to passing v by const ref and creating a temporary. + } + + /** + Difference between two PositionVector3D vectors. + The result is a DisplacementVector3D. + The (coordinate system) type of the returned vector is defined to + be identical to that of the first position vector. + */ + + template + inline + DisplacementVector3D + operator-( const PositionVector3D & v1, + const PositionVector3D & v2) { + return DisplacementVector3D( Cartesian3D( + v1.X()-v2.X(), v1.Y()-v2.Y(),v1.Z()-v2.Z() ) + ); + } + + /** + Addition of a PositionVector3D and a DisplacementVector3D. + The return type is a PositionVector3D, + of the same (coordinate system) type as the input PositionVector3D. + */ + template + inline + PositionVector3D + operator+( PositionVector3D p1, + const DisplacementVector3D & v2) { + return p1 += v2; + } + + /** + Addition of a DisplacementVector3D and a PositionVector3D. + The return type is a PositionVector3D, + of the same (coordinate system) type as the input PositionVector3D. + */ + template + inline + PositionVector3D + operator+( DisplacementVector3D const & v1, + PositionVector3D p2) { + return p2 += v1; + } + + /** + Subtraction of a DisplacementVector3D from a PositionVector3D. + The return type is a PositionVector3D, + of the same (coordinate system) type as the input PositionVector3D. + */ + template + inline + PositionVector3D + operator-( PositionVector3D p1, + DisplacementVector3D const & v2) { + return p1 -= v2; + } + + // Scaling of a position vector with a real number is not physically meaningful + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + // ------------- I/O to/from streams ------------- + + template < + class char_t, class traits_t, class T, class U, + typename std::enable_if::Scalar>::value>::type * = nullptr> + std::basic_ostream &operator<<(std::basic_ostream &os, + PositionVector3D const &v) + { + if (os) { + + typename T::Scalar a = 0; + typename T::Scalar b = 0; + typename T::Scalar c = 0; + v.GetCoordinates(a, b, c); + + if (detail::get_manip(os, detail::bitforbit)) { + detail::set_manip(os, detail::bitforbit, '\00'); + typedef GenVector_detail::BitReproducible BR; + BR::Output(os, a); + BR::Output(os, b); + BR::Output(os, c); + } else { + os << detail::get_manip(os, detail::open) << a << detail::get_manip(os, detail::sep) << b + << detail::get_manip(os, detail::sep) << c << detail::get_manip(os, detail::close); + } + } + return os; + } // op<< <>() + + template < + class char_t, class traits_t, class T, class U, + typename std::enable_if::Scalar>::value>::type * = nullptr> + std::basic_ostream &operator<<(std::basic_ostream &os, + PositionVector3D const &v) + { + if (os) { + os << "{ "; + for (std::size_t i = 0; i < PositionVector3D::Scalar::Size; ++i) { + os << "(" << v.x()[i] << "," << v.y()[i] << "," << v.z()[i] << ") "; + } + os << "}"; + } + return os; + } // op<< <>() + + template< class char_t, class traits_t, class T, class U > + inline + std::basic_istream & + operator >> ( std::basic_istream & is + , PositionVector3D & v + ) + { + if( !is ) return is; + + typename T::Scalar a, b, c; + + if( detail::get_manip( is, detail::bitforbit ) ) { + detail::set_manip( is, detail::bitforbit, '\00' ); + typedef GenVector_detail::BitReproducible BR; + BR::Input(is, a); + BR::Input(is, b); + BR::Input(is, c); + } + else { + detail::require_delim( is, detail::open ); is >> a; + detail::require_delim( is, detail::sep ); is >> b; + detail::require_delim( is, detail::sep ); is >> c; + detail::require_delim( is, detail::close ); + } + + if( is ) + v.SetCoordinates(a, b, c); + return is; + + } // op>> <>() +#endif + + + + } // namespace ROOT_MATH_ARCH + +} // namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_PositionVector3D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector3Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector3Dfwd.h new file mode 100644 index 0000000000000..4901253da3613 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector3Dfwd.h @@ -0,0 +1,24 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_PositionVector3Dfwd +#define ROOT_MathX_GenVectorX_PositionVector3Dfwd 1 + + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a 3D Position vector + */ + + template + class PositionVector3D; + + } +} + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiE4D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiE4D.h new file mode 100644 index 0000000000000..5099e63e922bb --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiE4D.h @@ -0,0 +1,435 @@ + +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** +* * +* Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * +* * +* * +**********************************************************************/ + +// Header file for class PtEtaPhiE4D +// +// Created by: fischler at Wed Jul 20 2005 +// based on CylindricalEta4D by moneta +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_PtEtaPhiE4D +#define ROOT_MathX_GenVectorX_PtEtaPhiE4D 1 + +#include "Math/Math.h" + +#include "MathX/GenVectorX/etaMax.h" + +#include "MathX/GenVectorX/GenVector_exception.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +//#define TRACE_CE +#ifdef TRACE_CE +#include +#endif + +#include + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ +/** + Class describing a 4D cylindrical coordinate system + using Pt , Phi, Eta and E (or rho, phi, eta , T) + The metric used is (-,-,-,+). + Phi is restricted to be in the range [-PI,PI) + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" +*/ + +template +class PtEtaPhiE4D { + +public : + + typedef ScalarType Scalar; + + // --------- Constructors --------------- + + /** + Default constructor gives zero 4-vector + */ + PtEtaPhiE4D() : fPt(0), fEta(0), fPhi(0), fE(0) { } + + /** + Constructor from pt, eta, phi, e values + */ + PtEtaPhiE4D(Scalar pt, Scalar eta, Scalar phi, Scalar e) : + fPt(pt), fEta(eta), fPhi(phi), fE(e) { Restrict(); } + + /** + Generic constructor from any 4D coordinate system implementing + Pt(), Eta(), Phi() and E() + */ + template + explicit PtEtaPhiE4D(const CoordSystem & c) : + fPt(c.Pt()), fEta(c.Eta()), fPhi(c.Phi()), fE(c.E()) { } + + // for g++ 3.2 and 3.4 on 32 bits found that the compiler generated copy ctor and assignment are much slower + // so we decided to re-implement them ( there is no no need to have them with g++4) + + /** + copy constructor + */ + PtEtaPhiE4D(const PtEtaPhiE4D & v) : + fPt(v.fPt), fEta(v.fEta), fPhi(v.fPhi), fE(v.fE) { } + + /** + assignment operator + */ + PtEtaPhiE4D & operator = (const PtEtaPhiE4D & v) { + fPt = v.fPt; + fEta = v.fEta; + fPhi = v.fPhi; + fE = v.fE; + return *this; + } + + + /** + Set internal data based on an array of 4 Scalar numbers + */ + void SetCoordinates( const Scalar src[] ) + { fPt=src[0]; fEta=src[1]; fPhi=src[2]; fE=src[3]; Restrict(); } + + /** + get internal data into an array of 4 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { dest[0] = fPt; dest[1] = fEta; dest[2] = fPhi; dest[3] = fE; } + + /** + Set internal data based on 4 Scalar numbers + */ + void SetCoordinates(Scalar pt, Scalar eta, Scalar phi, Scalar e) + { fPt=pt; fEta = eta; fPhi = phi; fE = e; Restrict(); } + + /** + get internal data into 4 Scalar numbers + */ + void + GetCoordinates(Scalar& pt, Scalar & eta, Scalar & phi, Scalar& e) const + { pt=fPt; eta=fEta; phi = fPhi; e = fE; } + + // --------- Coordinates and Coordinate-like Scalar properties ------------- + + // 4-D Cylindrical eta coordinate accessors + + Scalar Pt() const { return fPt; } + Scalar Eta() const { return fEta; } + Scalar Phi() const { return fPhi; } + Scalar E() const { return fE; } + + Scalar Perp()const { return Pt(); } + Scalar Rho() const { return Pt(); } + Scalar T() const { return E(); } + + // other coordinate representation + + Scalar Px() const { return fPt * math_cos(fPhi); } + Scalar X () const { return Px(); } + Scalar Py() const { return fPt * math_sin(fPhi); } + Scalar Y () const { return Py(); } + Scalar Pz() const { + return fPt > 0 ? fPt * math_sinh(fEta) : fEta == 0 ? 0 : fEta > 0 ? fEta - etaMax() : fEta + etaMax(); + } + Scalar Z () const { return Pz(); } + + /** + magnitude of momentum + */ + Scalar P() const { + return fPt > 0 ? fPt * math_cosh(fEta) + : fEta > etaMax() ? fEta - etaMax() + : fEta < -etaMax() ? -fEta - etaMax() : 0; + } + Scalar R() const { return P(); } + + /** + squared magnitude of spatial components (momentum squared) + */ + Scalar P2() const + { + const Scalar p = P(); + return p * p; + } + + /** + vector magnitude squared (or mass squared) + */ + Scalar M2() const + { + const Scalar p = P(); + return fE * fE - p * p; + } + Scalar Mag2() const { return M2(); } + + /** + invariant mass + */ + Scalar M() const { + const Scalar mm = M2(); + if (mm >= 0) { + return math_sqrt(mm); + } else { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("PtEtaPhiE4D::M() - Tachyonic:\n" + " Pt and Eta give P such that P^2 > E^2, so the mass would be imaginary"); +#endif + return -math_sqrt(-mm); + } + } + Scalar Mag() const { return M(); } + + /** + transverse spatial component squared + */ + Scalar Pt2() const { return fPt*fPt;} + Scalar Perp2() const { return Pt2(); } + + /** + transverse mass squared + */ + Scalar Mt2() const { Scalar pz = Pz(); return fE*fE - pz*pz; } + + /** + transverse mass + */ + Scalar Mt() const { + const Scalar mm = Mt2(); + if (mm >= 0) { + return math_sqrt(mm); + } else { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("PtEtaPhiE4D::Mt() - Tachyonic:\n" + " Pt and Eta give Pz such that Pz^2 > E^2, so the mass would be imaginary"); +#endif + return -math_sqrt(-mm); + } + } + + /** + transverse energy + */ + /** + transverse energy + */ + Scalar Et() const { + return fE / math_cosh(fEta); // faster using eta + } + + /** + transverse energy squared + */ + Scalar Et2() const + { + const Scalar et = Et(); + return et * et; + } + +private: + inline static Scalar pi() { return M_PI; } + inline void Restrict() { + if (fPhi <= -pi() || fPhi > pi()) fPhi = fPhi - math_floor(fPhi / (2 * pi()) + .5) * 2 * pi(); + } +public: + + /** + polar angle + */ + Scalar Theta() const { return (fPt > 0 ? Scalar(2) * math_atan(math_exp(-fEta)) : fEta >= 0 ? 0 : pi()); } + + // --------- Set Coordinates of this system --------------- + + /** + set Pt value + */ + void SetPt( Scalar pt) { + fPt = pt; + } + /** + set eta value + */ + void SetEta( Scalar eta) { + fEta = eta; + } + /** + set phi value + */ + void SetPhi( Scalar phi) { + fPhi = phi; + Restrict(); + } + /** + set E value + */ + void SetE( Scalar e) { + fE = e; + } + + /** + set values using cartesian coordinate system + */ + void SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e); + + + // ------ Manipulations ------------- + + /** + negate the 4-vector + */ + void Negate( ) { + fPhi = ( fPhi > 0 ? fPhi - pi() : fPhi + pi() ); + fEta = - fEta; + fE = - fE; + } + + /** + Scale coordinate values by a scalar quantity a + */ + void Scale( Scalar a) { + if (a < 0) { + Negate(); a = -a; + } + fPt *= a; + fE *= a; + } + + /** + Assignment from a generic coordinate system implementing + Pt(), Eta(), Phi() and E() + */ + template + PtEtaPhiE4D & operator = (const CoordSystem & c) { + fPt = c.Pt(); + fEta = c.Eta(); + fPhi = c.Phi(); + fE = c.E(); + return *this; + } + + /** + Exact equality + */ + bool operator == (const PtEtaPhiE4D & rhs) const { + return fPt == rhs.fPt && fEta == rhs.fEta + && fPhi == rhs.fPhi && fE == rhs.fE; + } + bool operator != (const PtEtaPhiE4D & 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 + Scalar x() const { return X(); } + Scalar y() const { return Y(); } + Scalar z() const { return Z(); } + Scalar t() const { return E(); } + + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) + + // ====== Set member functions for coordinates in other systems ======= + + void SetPx(Scalar px); + + void SetPy(Scalar py); + + void SetPz(Scalar pz); + + void SetM(Scalar m); + + +#endif + +private: + + ScalarType fPt; + ScalarType fEta; + ScalarType fPhi; + ScalarType fE; + +}; + + +} // end namespace ROOT_MATH_ARCH +} // end namespace ROOT + + + +// move implementations here to avoid circle dependencies +#include "MathX/GenVectorX/PxPyPzE4D.h" +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#include "MathX/GenVectorX/PtEtaPhiM4D.h" +#endif + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +template +inline void PtEtaPhiE4D::SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e) { + *this = PxPyPzE4D (px, py, pz, e); +} + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + + // ====== Set member functions for coordinates in other systems ======= + +template +inline void PtEtaPhiE4D::SetPx(Scalar px) { + GenVector_exception e("PtEtaPhiE4D::SetPx() is not supposed to be called"); + throw e; + PxPyPzE4D v(*this); v.SetPx(px); *this = PtEtaPhiE4D(v); +} +template +inline void PtEtaPhiE4D::SetPy(Scalar py) { + GenVector_exception e("PtEtaPhiE4D::SetPx() is not supposed to be called"); + throw e; + PxPyPzE4D v(*this); v.SetPy(py); *this = PtEtaPhiE4D(v); +} +template +inline void PtEtaPhiE4D::SetPz(Scalar pz) { + GenVector_exception e("PtEtaPhiE4D::SetPx() is not supposed to be called"); + throw e; + PxPyPzE4D v(*this); v.SetPz(pz); *this = PtEtaPhiE4D(v); +} +template +inline void PtEtaPhiE4D::SetM(Scalar m) { + GenVector_exception e("PtEtaPhiE4D::SetM() is not supposed to be called"); + throw e; + PtEtaPhiM4D v(*this); v.SetM(m); + *this = PtEtaPhiE4D(v); +} + +#endif // endif __MAKE__CINT || G__DICTIONARY +#endif + +} // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + + + +#endif // ROOT_MathX_GenVectorX_PtEtaPhiE4D diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiE4Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiE4Dfwd.h new file mode 100644 index 0000000000000..b9630232da01f --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiE4Dfwd.h @@ -0,0 +1,21 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_PtEtaPhiE4Dfwd +#define ROOT_MathX_GenVectorX_PtEtaPhiE4Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +class PtEtaPhiE4D; + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_PtEtaPhiE4Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiM4D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiM4D.h new file mode 100644 index 0000000000000..ff217d50d8807 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiM4D.h @@ -0,0 +1,454 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** +* * +* Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * +* * +* * +**********************************************************************/ + +// Header file for class PtEtaPhiM4D +// +// Created by: fischler at Wed Jul 21 2005 +// Similar to PtEtaPhiMSystem by moneta +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_PtEtaPhiM4D +#define ROOT_MathX_GenVectorX_PtEtaPhiM4D 1 + +#include "Math/Math.h" + +#include "MathX/GenVectorX/etaMax.h" + +#include "MathX/GenVectorX/GenVector_exception.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +//#define TRACE_CE +#ifdef TRACE_CE +#include +#endif + +#include + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ +/** + Class describing a 4D cylindrical coordinate system + using Pt , Phi, Eta and M (mass) + The metric used is (-,-,-,+). + Spacelike particles (M2 < 0) are described with negative mass values, + but in this case m2 must always be less than P2 to preserve a positive value of E2 + Phi is restricted to be in the range [-PI,PI) + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" +*/ + +template +class PtEtaPhiM4D { + +public : + + typedef ScalarType Scalar; + + // --------- Constructors --------------- + + /** + Default constructor gives zero 4-vector (with zero mass) + */ + PtEtaPhiM4D() : fPt(0), fEta(0), fPhi(0), fM(0) { } + + /** + Constructor from pt, eta, phi, mass values + */ + PtEtaPhiM4D(Scalar pt, Scalar eta, Scalar phi, Scalar mass) : + fPt(pt), fEta(eta), fPhi(phi), fM(mass) { + RestrictPhi(); + if (fM < 0) RestrictNegMass(); + } + + /** + Generic constructor from any 4D coordinate system implementing + Pt(), Eta(), Phi() and M() + */ + template + explicit PtEtaPhiM4D(const CoordSystem & c) : + fPt(c.Pt()), fEta(c.Eta()), fPhi(c.Phi()), fM(c.M()) { RestrictPhi(); } + + // for g++ 3.2 and 3.4 on 32 bits found that the compiler generated copy ctor and assignment are much slower + // so we decided to re-implement them ( there is no no need to have them with g++4) + + /** + copy constructor + */ + PtEtaPhiM4D(const PtEtaPhiM4D & v) : + fPt(v.fPt), fEta(v.fEta), fPhi(v.fPhi), fM(v.fM) { } + + /** + assignment operator + */ + PtEtaPhiM4D & operator = (const PtEtaPhiM4D & v) { + fPt = v.fPt; + fEta = v.fEta; + fPhi = v.fPhi; + fM = v.fM; + return *this; + } + + + /** + Set internal data based on an array of 4 Scalar numbers + */ + void SetCoordinates( const Scalar src[] ) { + fPt=src[0]; fEta=src[1]; fPhi=src[2]; fM=src[3]; + RestrictPhi(); + if (fM <0) RestrictNegMass(); + } + + /** + get internal data into an array of 4 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { dest[0] = fPt; dest[1] = fEta; dest[2] = fPhi; dest[3] = fM; } + + /** + Set internal data based on 4 Scalar numbers + */ + void SetCoordinates(Scalar pt, Scalar eta, Scalar phi, Scalar mass) { + fPt=pt; fEta = eta; fPhi = phi; fM = mass; + RestrictPhi(); + if (fM <0) RestrictNegMass(); + } + + /** + get internal data into 4 Scalar numbers + */ + void + GetCoordinates(Scalar& pt, Scalar & eta, Scalar & phi, Scalar& mass) const + { pt=fPt; eta=fEta; phi = fPhi; mass = fM; } + + // --------- Coordinates and Coordinate-like Scalar properties ------------- + + // 4-D Cylindrical eta coordinate accessors + + Scalar Pt() const { return fPt; } + Scalar Eta() const { return fEta; } + Scalar Phi() const { return fPhi; } + /** + M() is the invariant mass; + in this coordinate system it can be negagative if set that way. + */ + Scalar M() const { return fM; } + Scalar Mag() const { return M(); } + + Scalar Perp()const { return Pt(); } + Scalar Rho() const { return Pt(); } + + // other coordinate representation + + Scalar Px() const { return fPt * math_cos(fPhi); } + Scalar X () const { return Px(); } + Scalar Py() const { return fPt * math_sin(fPhi); } + Scalar Y () const { return Py(); } + Scalar Pz() const { + return fPt > 0 ? fPt * math_sinh(fEta) : fEta == 0 ? 0 : fEta > 0 ? fEta - etaMax() : fEta + etaMax(); + } + Scalar Z () const { return Pz(); } + + /** + magnitude of momentum + */ + Scalar P() const { + return fPt > 0 ? fPt * math_cosh(fEta) + : fEta > etaMax() ? fEta - etaMax() + : fEta < -etaMax() ? -fEta - etaMax() : 0; + } + Scalar R() const { return P(); } + + /** + squared magnitude of spatial components (momentum squared) + */ + Scalar P2() const + { + const Scalar p = P(); + return p * p; + } + + /** + energy squared + */ + Scalar E2() const { + Scalar e2 = P2() + M2(); + // avoid rounding error which can make E2 negative when M2 is negative + return e2 > 0 ? e2 : 0; + } + + /** + Energy (timelike component of momentum-energy 4-vector) + */ + Scalar E() const { return math_sqrt(E2()); } + + Scalar T() const { return E(); } + + /** + vector magnitude squared (or mass squared) + In case of negative mass (spacelike particles return negative values) + */ + Scalar M2() const { + return ( fM >= 0 ) ? fM*fM : -fM*fM; + } + Scalar Mag2() const { return M2(); } + + /** + transverse spatial component squared + */ + Scalar Pt2() const { return fPt*fPt;} + Scalar Perp2() const { return Pt2(); } + + /** + transverse mass squared + */ + Scalar Mt2() const { return M2() + fPt*fPt; } + + /** + transverse mass - will be negative if Mt2() is negative + */ + Scalar Mt() const { + const Scalar mm = Mt2(); + if (mm >= 0) { + return math_sqrt(mm); + } else { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("PtEtaPhiM4D::Mt() - Tachyonic:\n" + " Pz^2 > E^2 so the transverse mass would be imaginary"); +#endif + return -math_sqrt(-mm); + } + } + + /** + transverse energy squared + */ + Scalar Et2() const { + // a bit faster than et * et + return 2. * E2() / (math_cosh(2 * fEta) + 1); + } + + /** + transverse energy + */ + Scalar Et() const { return E() / math_cosh(fEta); } + +private: + inline static Scalar pi() { return M_PI; } + inline void RestrictPhi() { + if (fPhi <= -pi() || fPhi > pi()) fPhi = fPhi - math_floor(fPhi / (2 * pi()) + .5) * 2 * pi(); + } + // restrict the value of negative mass to avoid unphysical negative E2 values + // M2 must be less than P2 for the tachionic particles - otherwise use positive values + inline void RestrictNegMass() { + if (fM < 0) { + if (P2() - fM * fM < 0) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw("PtEtaPhiM4D::unphysical value of mass, set to closest physical value"); +#endif + fM = -P(); + } + } + } + +public: + + /** + polar angle + */ + Scalar Theta() const { return (fPt > 0 ? Scalar(2) * math_atan(math_exp(-fEta)) : fEta >= 0 ? 0 : pi()); } + + // --------- Set Coordinates of this system --------------- + + /** + set Pt value + */ + void SetPt( Scalar pt) { + fPt = pt; + } + /** + set eta value + */ + void SetEta( Scalar eta) { + fEta = eta; + } + /** + set phi value + */ + void SetPhi( Scalar phi) { + fPhi = phi; + RestrictPhi(); + } + /** + set M value + */ + void SetM( Scalar mass) { + fM = mass; + if (fM <0) RestrictNegMass(); + } + + /** + set values using cartesian coordinate system + */ + void SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e); + + + // ------ Manipulations ------------- + + /** + negate the 4-vector -- Note that the energy cannot be negate (would need an additional data member) + therefore negate will work only on the spatial components + One would need to use negate only with vectors having the energy as data members + */ + void Negate( ) { + fPhi = ( (fPhi > 0) ? fPhi - pi() : fPhi + pi() ); + fEta = - fEta; +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("PtEtaPhiM4D::Negate - cannot negate the energy - can negate only the spatial components"); +#endif + } + + /** + Scale coordinate values by a scalar quantity a + */ + void Scale( Scalar a) { + if (a < 0) { + Negate(); a = -a; + } + fPt *= a; + fM *= a; + } + + /** + Assignment from a generic coordinate system implementing + Pt(), Eta(), Phi() and M() + */ + template + PtEtaPhiM4D & operator = (const CoordSystem & c) { + fPt = c.Pt(); + fEta = c.Eta(); + fPhi = c.Phi(); + fM = c.M(); + return *this; + } + + /** + Exact equality + */ + bool operator == (const PtEtaPhiM4D & rhs) const { + return fPt == rhs.fPt && fEta == rhs.fEta + && fPhi == rhs.fPhi && fM == rhs.fM; + } + bool operator != (const PtEtaPhiM4D & 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 + Scalar x() const { return X(); } + Scalar y() const { return Y(); } + Scalar z() const { return Z(); } + Scalar t() const { return E(); } + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) + + // ====== Set member functions for coordinates in other systems ======= + + void SetPx(Scalar px); + + void SetPy(Scalar py); + + void SetPz(Scalar pz); + + void SetE(Scalar t); + +#endif + +private: + + ScalarType fPt; + ScalarType fEta; + ScalarType fPhi; + ScalarType fM; + +}; + + +} // end namespace ROOT_MATH_ARCH +} // end namespace ROOT + + +// move implementations here to avoid circle dependencies +#include "MathX/GenVectorX/PxPyPzE4D.h" + + + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + +template +inline void PtEtaPhiM4D::SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e) { + *this = PxPyPzE4D (px, py, pz, e); +} + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + + // ====== Set member functions for coordinates in other systems ======= + +template +void PtEtaPhiM4D::SetPx(Scalar px) { + GenVector_exception e("PtEtaPhiM4D::SetPx() is not supposed to be called"); + throw e; + PxPyPzE4D v(*this); v.SetPx(px); *this = PtEtaPhiM4D(v); +} +template +void PtEtaPhiM4D::SetPy(Scalar py) { + GenVector_exception e("PtEtaPhiM4D::SetPx() is not supposed to be called"); + throw e; + PxPyPzE4D v(*this); v.SetPy(py); *this = PtEtaPhiM4D(v); +} +template +void PtEtaPhiM4D::SetPz(Scalar pz) { + GenVector_exception e("PtEtaPhiM4D::SetPx() is not supposed to be called"); + throw e; + PxPyPzE4D v(*this); v.SetPz(pz); *this = PtEtaPhiM4D(v); +} +template +void PtEtaPhiM4D::SetE(Scalar energy) { + GenVector_exception e("PtEtaPhiM4D::SetE() is not supposed to be called"); + throw e; + PxPyPzE4D v(*this); v.SetE(energy); *this = PtEtaPhiM4D(v); +} + +#endif // endif __MAKE__CINT || G__DICTIONARY +#endif + +} // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + + +#endif // ROOT_MathX_GenVectorX_PtEtaPhiM4D diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiM4Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiM4Dfwd.h new file mode 100644 index 0000000000000..9be7c1fd623df --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiM4Dfwd.h @@ -0,0 +1,21 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_PtEtaPhiM4Dfwd +#define ROOT_MathX_GenVectorX_PtEtaPhiM4Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +class PtEtaPhiM4D; + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_PtEtaPhiM4Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzE4D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzE4D.h new file mode 100644 index 0000000000000..8d05f365eea6b --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzE4D.h @@ -0,0 +1,414 @@ +// @(#)root/mathcore:$Id: 04c6d98020d7178ed5f0884f9466bca32b031565 $ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** +* * +* Copyright (c) 2005 , LCG ROOT MathLib Team * +* * +* * +**********************************************************************/ + +// Header file for class PxPyPzE4D +// +// Created by: fischler at Wed Jul 20 2005 +// (starting from PxPyPzE4D by moneta) +// +// Last update: $Id: 04c6d98020d7178ed5f0884f9466bca32b031565 $ +// +#ifndef ROOT_MathX_GenVectorX_PxPyPzE4D +#define ROOT_MathX_GenVectorX_PxPyPzE4D 1 + +#include "MathX/GenVectorX/eta.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include "MathX/GenVectorX/GenVector_exception.h" + + +#include + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ +/** + Class describing a 4D cartesian coordinate system (x, y, z, t coordinates) + or momentum-energy vectors stored as (Px, Py, Pz, E). + The metric used is (-,-,-,+) + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" +*/ + +template +class PxPyPzE4D { + +public : + + typedef ScalarType Scalar; + + // --------- Constructors --------------- + + /** + Default constructor with x=y=z=t=0 + */ + PxPyPzE4D() : fX(0.0), fY(0.0), fZ(0.0), fT(0.0) { } + + + /** + Constructor from x, y , z , t values + */ + PxPyPzE4D(Scalar px, Scalar py, Scalar pz, Scalar e) : + fX(px), fY(py), fZ(pz), fT(e) { } + + + /** + construct from any vector or coordinate system class + implementing x(), y() and z() and t() + */ + template + explicit PxPyPzE4D(const CoordSystem & v) : + fX( v.x() ), fY( v.y() ), fZ( v.z() ), fT( v.t() ) { } + + // for g++ 3.2 and 3.4 on 32 bits found that the compiler generated copy ctor and assignment are much slower + // so we decided to re-implement them ( there is no no need to have them with g++4) + /** + copy constructor + */ + PxPyPzE4D(const PxPyPzE4D & v) : + fX(v.fX), fY(v.fY), fZ(v.fZ), fT(v.fT) { } + + /** + assignment operator + */ + PxPyPzE4D & operator = (const PxPyPzE4D & v) { + fX = v.fX; + fY = v.fY; + fZ = v.fZ; + fT = v.fT; + return *this; + } + + /** + Set internal data based on an array of 4 Scalar numbers + */ + void SetCoordinates( const Scalar src[] ) + { fX=src[0]; fY=src[1]; fZ=src[2]; fT=src[3]; } + + /** + get internal data into an array of 4 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { dest[0] = fX; dest[1] = fY; dest[2] = fZ; dest[3] = fT; } + + /** + Set internal data based on 4 Scalar numbers + */ + void SetCoordinates(Scalar px, Scalar py, Scalar pz, Scalar e) + { fX=px; fY=py; fZ=pz; fT=e;} + + /** + get internal data into 4 Scalar numbers + */ + void GetCoordinates(Scalar& px, Scalar& py, Scalar& pz, Scalar& e) const + { px=fX; py=fY; pz=fZ; e=fT;} + + // --------- Coordinates and Coordinate-like Scalar properties ------------- + + // cartesian (Minkowski)coordinate accessors + + Scalar Px() const { return fX;} + Scalar Py() const { return fY;} + Scalar Pz() const { return fZ;} + Scalar E() const { return fT;} + + Scalar X() const { return fX;} + Scalar Y() const { return fY;} + Scalar Z() const { return fZ;} + Scalar T() const { return fT;} + + // other coordinate representation + + /** + squared magnitude of spatial components + */ + Scalar P2() const { return fX*fX + fY*fY + fZ*fZ; } + + /** + magnitude of spatial components (magnitude of 3-momentum) + */ + Scalar P() const { return math_sqrt(P2()); } + Scalar R() const { return P(); } + + /** + vector magnitude squared (or mass squared) + */ + Scalar M2() const { return fT*fT - fX*fX - fY*fY - fZ*fZ;} + Scalar Mag2() const { return M2(); } + + /** + invariant mass + */ + Scalar M() const + { + const Scalar mm = M2(); + if (mm >= 0) { + return math_sqrt(mm); + } else { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("PxPyPzE4D::M() - Tachyonic:\n" + " P^2 > E^2 so the mass would be imaginary"); +#endif + return -math_sqrt(-mm); + } + } + Scalar Mag() const { return M(); } + + /** + transverse spatial component squared + */ + Scalar Pt2() const { return fX*fX + fY*fY;} + Scalar Perp2() const { return Pt2();} + + /** + Transverse spatial component (P_perp or rho) + */ + Scalar Pt() const { return math_sqrt(Perp2()); } + Scalar Perp() const { return Pt();} + Scalar Rho() const { return Pt();} + + /** + transverse mass squared + */ + Scalar Mt2() const { return fT*fT - fZ*fZ; } + + /** + transverse mass + */ + Scalar Mt() const { + const Scalar mm = Mt2(); + if (mm >= 0) { + return math_sqrt(mm); + } else { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("PxPyPzE4D::Mt() - Tachyonic:\n" + " Pz^2 > E^2 so the transverse mass would be imaginary"); +#endif + return -math_sqrt(-mm); + } + } + + /** + transverse energy squared + */ + Scalar Et2() const { // is (E^2 * pt ^2) / p^2 + // but it is faster to form p^2 from pt^2 + Scalar pt2 = Pt2(); + return pt2 == 0 ? 0 : fT*fT * pt2/( pt2 + fZ*fZ ); + } + + /** + transverse energy + */ + Scalar Et() const { + const Scalar etet = Et2(); + return fT < 0.0 ? -math_sqrt(etet) : math_sqrt(etet); + } + + /** + azimuthal angle + */ + Scalar Phi() const { return (fX == 0.0 && fY == 0.0) ? 0 : math_atan2(fY, fX); } + + /** + polar angle + */ + Scalar Theta() const { return (fX == 0.0 && fY == 0.0 && fZ == 0.0) ? 0 : math_atan2(Pt(), fZ); } + + /** + pseudorapidity + */ + Scalar Eta() const { + return Impl::Eta_FromRhoZ ( Pt(), fZ); + } + + // --------- Set Coordinates of this system --------------- + + + /** + set X value + */ + void SetPx( Scalar px) { + fX = px; + } + /** + set Y value + */ + void SetPy( Scalar py) { + fY = py; + } + /** + set Z value + */ + void SetPz( Scalar pz) { + fZ = pz; + } + /** + set T value + */ + void SetE( Scalar e) { + fT = e; + } + + /** + set all values using cartesian coordinates + */ + void SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e) { + fX=px; + fY=py; + fZ=pz; + fT=e; + } + + + + // ------ Manipulations ------------- + + /** + negate the 4-vector + */ + void Negate( ) { fX = -fX; fY = -fY; fZ = -fZ; fT = -fT;} + + /** + scale coordinate values by a scalar quantity a + */ + void Scale( const Scalar & a) { + fX *= a; + fY *= a; + fZ *= a; + fT *= a; + } + + /** + Assignment from a generic coordinate system implementing + x(), y(), z() and t() + */ + template + PxPyPzE4D & operator = (const AnyCoordSystem & v) { + fX = v.x(); + fY = v.y(); + fZ = v.z(); + fT = v.t(); + return *this; + } + + /** + Exact equality + */ + bool operator == (const PxPyPzE4D & rhs) const { + return fX == rhs.fX && fY == rhs.fY && fZ == rhs.fZ && fT == rhs.fT; + } + bool operator != (const PxPyPzE4D & 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 + Scalar x() const { return fX; } + Scalar y() const { return fY; } + Scalar z() const { return fZ; } + Scalar t() const { return fT; } + + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) + + // ====== Set member functions for coordinates in other systems ======= + + void SetPt(Scalar pt); + + void SetEta(Scalar eta); + + void SetPhi(Scalar phi); + + void SetM(Scalar m); + +#endif + +private: + + /** + (contiguous) data containing the coordinate values x,y,z,t + */ + + ScalarType fX; + ScalarType fY; + ScalarType fZ; + ScalarType fT; + +}; + +} // end namespace ROOT_MATH_ARCH +} // end namespace ROOT + + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// move implementations here to avoid circle dependencies + +#include "MathX/GenVectorX/PtEtaPhiE4D.h" +#include "MathX/GenVectorX/PtEtaPhiM4D.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + + // ====== Set member functions for coordinates in other systems ======= + // throw always exceptions in this case + +template +void PxPyPzE4D::SetPt(Scalar pt) { + GenVector_exception e("PxPyPzE4D::SetPt() is not supposed to be called"); + throw e; + PtEtaPhiE4D v(*this); v.SetPt(pt); *this = PxPyPzE4D(v); +} +template +void PxPyPzE4D::SetEta(Scalar eta) { + GenVector_exception e("PxPyPzE4D::SetEta() is not supposed to be called"); + throw e; + PtEtaPhiE4D v(*this); v.SetEta(eta); *this = PxPyPzE4D(v); +} +template +void PxPyPzE4D::SetPhi(Scalar phi) { + GenVector_exception e("PxPyPzE4D::SetPhi() is not supposed to be called"); + throw e; + PtEtaPhiE4D v(*this); v.SetPhi(phi); *this = PxPyPzE4D(v); +} + +template +void PxPyPzE4D::SetM(Scalar m) { + GenVector_exception e("PxPyPzE4D::SetM() is not supposed to be called"); + throw e; + PtEtaPhiM4D v(*this); v.SetM(m); + *this = PxPyPzE4D(v); +} + + +} // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + +#endif // endif __MAKE__CINT || G__DICTIONARY +#endif + + +#endif // ROOT_MathX_GenVectorX_PxPyPzE4D diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzE4Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzE4Dfwd.h new file mode 100644 index 0000000000000..82d1537232a46 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzE4Dfwd.h @@ -0,0 +1,21 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_PxPyPzE4Dfwd +#define ROOT_MathX_GenVectorX_PxPyPzE4Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +class PxPyPzE4D; + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_PxPyPzE4Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzM4D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzM4D.h new file mode 100644 index 0000000000000..df1422d713b4e --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzM4D.h @@ -0,0 +1,451 @@ +// @(#)root/mathcore:$Id: 464c29f33a8bbd8462a3e15b7e4c30c6f5b74a30 $ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** +* * +* Copyright (c) 2005 , LCG ROOT MathLib Team * +* * +* * +**********************************************************************/ + +// Header file for class PxPyPzM4D +// +// Created by: fischler at Wed Jul 20 2005 +// (starting from PxPyPzM4D by moneta) +// +// Last update: $Id: 464c29f33a8bbd8462a3e15b7e4c30c6f5b74a30 $ +// +#ifndef ROOT_MathX_GenVectorX_PxPyPzM4D +#define ROOT_MathX_GenVectorX_PxPyPzM4D 1 + +#include "MathX/GenVectorX/eta.h" + +#include "MathX/GenVectorX/GenVector_exception.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +//__________________________________________________________________________________________ +/** + Class describing a 4D coordinate system + or momentum-energy vectors stored as (Px, Py, Pz, M). + This system is useful to describe ultra-relativistic particles + (like electrons at LHC) to avoid numerical errors evaluating the mass + when E >>> m + The metric used is (-,-,-,+) + Spacelike particles (M2 < 0) are described with negative mass values, + but in this case m2 must always be less than P2 to preserve a positive value of E2 + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" +*/ + +template +class PxPyPzM4D { + +public : + + typedef ScalarType Scalar; + + // --------- Constructors --------------- + + /** + Default constructor with x=y=z=m=0 + */ + PxPyPzM4D() : fX(0.0), fY(0.0), fZ(0.0), fM(0.0) { } + + + /** + Constructor from x, y , z , m values + */ + PxPyPzM4D(Scalar px, Scalar py, Scalar pz, Scalar m) : + fX(px), fY(py), fZ(pz), fM(m) { + + if (fM < 0) RestrictNegMass(); + } + + /** + construct from any 4D coordinate system class + implementing X(), Y(), X() and M() + */ + template + explicit PxPyPzM4D(const CoordSystem & v) : + fX( v.X() ), fY( v.Y() ), fZ( v.Z() ), fM( v.M() ) + { } + + // for g++ 3.2 and 3.4 on 32 bits found that the compiler generated copy ctor and assignment are much slower + // so we decided to re-implement them ( there is no no need to have them with g++4) + /** + copy constructor + */ + PxPyPzM4D(const PxPyPzM4D & v) : + fX(v.fX), fY(v.fY), fZ(v.fZ), fM(v.fM) { } + + /** + assignment operator + */ + PxPyPzM4D & operator = (const PxPyPzM4D & v) { + fX = v.fX; + fY = v.fY; + fZ = v.fZ; + fM = v.fM; + return *this; + } + + + /** + construct from any 4D coordinate system class + implementing X(), Y(), X() and M() + */ + template + PxPyPzM4D & operator = (const AnyCoordSystem & v) { + fX = v.X(); + fY = v.Y(); + fZ = v.Z(); + fM = v.M(); + return *this; + } + + /** + Set internal data based on an array of 4 Scalar numbers + */ + void SetCoordinates( const Scalar src[] ) { + fX=src[0]; fY=src[1]; fZ=src[2]; fM=src[3]; + if (fM < 0) RestrictNegMass(); + } + + /** + get internal data into an array of 4 Scalar numbers + */ + void GetCoordinates( Scalar dest[] ) const + { dest[0] = fX; dest[1] = fY; dest[2] = fZ; dest[3] = fM; } + + /** + Set internal data based on 4 Scalar numbers + */ + void SetCoordinates(Scalar px, Scalar py, Scalar pz, Scalar m) { + fX=px; fY=py; fZ=pz; fM=m; + if (fM < 0) RestrictNegMass(); + } + + /** + get internal data into 4 Scalar numbers + */ + void GetCoordinates(Scalar& px, Scalar& py, Scalar& pz, Scalar& m) const + { px=fX; py=fY; pz=fZ; m=fM;} + + // --------- Coordinates and Coordinate-like Scalar properties ------------- + + // cartesian (Minkowski)coordinate accessors + + Scalar Px() const { return fX;} + Scalar Py() const { return fY;} + Scalar Pz() const { return fZ;} + Scalar M() const { return fM; } + + Scalar X() const { return fX;} + Scalar Y() const { return fY;} + Scalar Z() const { return fZ;} + + // other coordinate representation + /** + Energy + */ + Scalar E() const { return math_sqrt(E2()); } + + Scalar T() const { return E();} + + /** + squared magnitude of spatial components + */ + Scalar P2() const { return fX*fX + fY*fY + fZ*fZ; } + + /** + magnitude of spatial components (magnitude of 3-momentum) + */ + Scalar P() const { return math_sqrt(P2()); } + Scalar R() const { return P(); } + + /** + vector magnitude squared (or mass squared) + In case of negative mass (spacelike particles return negative values) + */ + Scalar M2() const { + return ( fM >= 0 ) ? fM*fM : -fM*fM; + } + Scalar Mag2() const { return M2(); } + + Scalar Mag() const { return M(); } + + /** + energy squared + */ + Scalar E2() const { + Scalar e2 = P2() + M2(); + // protect against numerical errors when M2() is negative + return e2 > 0 ? e2 : 0; + } + + /** + transverse spatial component squared + */ + Scalar Pt2() const { return fX*fX + fY*fY;} + Scalar Perp2() const { return Pt2();} + + /** + Transverse spatial component (P_perp or rho) + */ + Scalar Pt() const { return math_sqrt(Perp2()); } + Scalar Perp() const { return Pt();} + Scalar Rho() const { return Pt();} + + /** + transverse mass squared + */ + Scalar Mt2() const { return E2() - fZ*fZ; } + + /** + transverse mass + */ + Scalar Mt() const { + const Scalar mm = Mt2(); + if (mm >= 0) { + return math_sqrt(mm); + } else { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("PxPyPzM4D::Mt() - Tachyonic:\n" + " Pz^2 > E^2 so the transverse mass would be imaginary"); +#endif + return -math_sqrt(-mm); + } + } + + /** + transverse energy squared + */ + Scalar Et2() const { // is (E^2 * pt ^2) / p^2 + // but it is faster to form p^2 from pt^2 + Scalar pt2 = Pt2(); + return pt2 == 0 ? 0 : E2() * pt2/( pt2 + fZ*fZ ); + } + + /** + transverse energy + */ + Scalar Et() const { + const Scalar etet = Et2(); + return math_sqrt(etet); + } + + /** + azimuthal angle + */ + Scalar Phi() const { return (fX == 0.0 && fY == 0.0) ? 0.0 : math_atan2(fY, fX); } + + /** + polar angle + */ + Scalar Theta() const { return (fX == 0.0 && fY == 0.0 && fZ == 0.0) ? 0 : math_atan2(Pt(), fZ); } + + /** + pseudorapidity + */ + Scalar Eta() const { + return Impl::Eta_FromRhoZ ( Pt(), fZ); + } + + // --------- Set Coordinates of this system --------------- + + + /** + set X value + */ + void SetPx( Scalar px) { + fX = px; + } + /** + set Y value + */ + void SetPy( Scalar py) { + fY = py; + } + /** + set Z value + */ + void SetPz( Scalar pz) { + fZ = pz; + } + /** + set T value + */ + void SetM( Scalar m) { + fM = m; + if (fM < 0) RestrictNegMass(); + } + + /** + set all values + */ + void SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e); + + // ------ Manipulations ------------- + + /** + negate the 4-vector - Note that the energy cannot be negate (would need an additional data member) + therefore negate will work only on the spatial components. + One would need to use negate only with vectors having the energy as data members + */ + void Negate( ) { + fX = -fX; + fY = -fY; + fZ = -fZ; +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("PxPyPzM4D::Negate - cannot negate the energy - can negate only the spatial components"); +#endif + } + + /** + scale coordinate values by a scalar quantity a + */ + void Scale( const Scalar & a) { + fX *= a; + fY *= a; + fZ *= a; + fM *= a; + } + + + /** + Exact equality + */ + bool operator == (const PxPyPzM4D & rhs) const { + return fX == rhs.fX && fY == rhs.fY && fZ == rhs.fZ && fM == rhs.fM; + } + bool operator != (const PxPyPzM4D & 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 + Scalar x() const { return X(); } + Scalar y() const { return Y(); } + Scalar z() const { return Z(); } + Scalar t() const { return E(); } + + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) + + // ====== Set member functions for coordinates in other systems ======= + + void SetPt(Scalar pt); + + void SetEta(Scalar eta); + + void SetPhi(Scalar phi); + + void SetE(Scalar t); + +#endif + +private: + + // restrict the value of negative mass to avoid unphysical negative E2 values + // M2 must be less than P2 for the tachionic particles - otherwise use positive values + inline void RestrictNegMass() { + if ( fM >=0 ) return; + if ( P2() - fM*fM < 0 ) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw("PxPyPzM4D::unphysical value of mass, set to closest physical value"); +#endif + fM = - P(); + } + return; + } + + + /** + (contiguous) data containing the coordinate values x,y,z,t + */ + + ScalarType fX; + ScalarType fY; + ScalarType fZ; + ScalarType fM; + +}; + +} // end namespace ROOT_MATH_ARCH +} // end namespace ROOT + + +// move implementations here to avoid circle dependencies + +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/PtEtaPhiM4D.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +template +inline void PxPyPzM4D::SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e) { + *this = PxPyPzE4D (px, py, pz, e); +} + + +#if defined(__MAKECINT__) || defined(G__DICTIONARY) +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + + // ====== Set member functions for coordinates in other systems ======= + + // ====== Set member functions for coordinates in other systems ======= + +template +inline void PxPyPzM4D::SetPt(ScalarType pt) { + GenVector_exception e("PxPyPzM4D::SetPt() is not supposed to be called"); + throw e; + PtEtaPhiE4D v(*this); v.SetPt(pt); *this = PxPyPzM4D(v); +} +template +inline void PxPyPzM4D::SetEta(ScalarType eta) { + GenVector_exception e("PxPyPzM4D::SetEta() is not supposed to be called"); + throw e; + PtEtaPhiE4D v(*this); v.SetEta(eta); *this = PxPyPzM4D(v); +} +template +inline void PxPyPzM4D::SetPhi(ScalarType phi) { + GenVector_exception e("PxPyPzM4D::SetPhi() is not supposed to be called"); + throw e; + PtEtaPhiE4D v(*this); v.SetPhi(phi); *this = PxPyPzM4D(v); +} +template +inline void PxPyPzM4D::SetE(ScalarType energy) { + GenVector_exception e("PxPyPzM4D::SetE() is not supposed to be called"); + throw e; + PxPyPzE4D v(*this); v.SetE(energy); + *this = PxPyPzM4D(v); +} + + +#endif // endif __MAKE__CINT || G__DICTIONARY +#endif + +} // end namespace ROOT_MATH_ARCH + +} // end namespace ROOT + + + +#endif // ROOT_MathX_GenVectorX_PxPyPzM4D diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzM4Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzM4Dfwd.h new file mode 100644 index 0000000000000..6c556cd2ea2ef --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzM4Dfwd.h @@ -0,0 +1,21 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_PxPyPzM4Dfwd +#define ROOT_MathX_GenVectorX_PxPyPzM4Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + +template +class PxPyPzM4D; + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_PxPyPzM4Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Quaternion.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Quaternion.h new file mode 100644 index 0000000000000..e79839a05a066 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Quaternion.h @@ -0,0 +1,357 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for rotation in 3 dimensions, represented by a quaternion +// Created by: Mark Fischler Thurs June 9 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_Quaternion +#define ROOT_MathX_GenVectorX_Quaternion 1 + + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/3DConversions.h" +#include "MathX/GenVectorX/3DDistances.h" + +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Rotation class with the (3D) rotation represented by + a unit quaternion (u, i, j, k). + This is the optimal representation for multiplication of multiple + rotations, and for computation of group-manifold-invariant distance + between two rotations. + See also ROOT::Math::AxisAngle, ROOT::Math::EulerAngles, and ROOT::Math::Rotation3D. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class Quaternion { + +public: + + typedef double Scalar; + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity rotation) + */ + Quaternion() + : fU(1.0) + , fI(0.0) + , fJ(0.0) + , fK(0.0) + { } + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of four Scalars + */ + template + Quaternion(IT begin, IT end) { SetComponents(begin,end); } + + // ======== Construction From other Rotation Forms ================== + + /** + Construct from another supported rotation type (see gv_detail::convert ) + */ + template + explicit Quaternion(const OtherRotation & r) {gv_detail::convert(r,*this);} + + + /** + Construct from four Scalars representing the coefficients of u, i, j, k + */ + Quaternion(Scalar u, Scalar i, Scalar j, Scalar k) : + fU(u), fI(i), fJ(j), fK(k) { } + + // The compiler-generated copy ctor, copy assignment, and dtor are OK. + + /** + Re-adjust components to eliminate small deviations from |Q| = 1 + orthonormality. + */ + void Rectify(); + + /** + Assign from another supported rotation type (see gv_detail::convert ) + */ + template + Quaternion & operator=( OtherRotation const & r ) { + gv_detail::convert(r,*this); + return *this; + } + + // ======== Components ============== + + /** + Set the four components given an iterator to the start of + the desired data, and another to the end (4 past start). + */ + template + void SetComponents(IT begin, IT end) { + fU = *begin++; + fI = *begin++; + fJ = *begin++; + fK = *begin++; + (void)end; + assert (end==begin); + } + + /** + Get the components into data specified by an iterator begin + and another to the end of the desired data (4 past start). + */ + template + void GetComponents(IT begin, IT end) const { + *begin++ = fU; + *begin++ = fI; + *begin++ = fJ; + *begin++ = fK; + (void)end; + assert (end==begin); + } + + /** + Get the components into data specified by an iterator begin + */ + template + void GetComponents(IT begin ) const { + *begin++ = fU; + *begin++ = fI; + *begin++ = fJ; + *begin = fK; + } + + /** + Set the components based on four Scalars. The sum of the squares of + these Scalars should be 1; no checking is done. + */ + void SetComponents(Scalar u, Scalar i, Scalar j, Scalar k) { + fU=u; fI=i; fJ=j; fK=k; + } + + /** + Get the components into four Scalars. + */ + void GetComponents(Scalar & u, Scalar & i, Scalar & j, Scalar & k) const { + u=fU; i=fI; j=fJ; k=fK; + } + + /** + Access to the four quaternion components: + U() is the coefficient of the identity Pauli matrix, + I(), J() and K() are the coefficients of sigma_x, sigma_y, sigma_z + */ + Scalar U() const { return fU; } + Scalar I() const { return fI; } + Scalar J() const { return fJ; } + Scalar K() const { return fK; } + + // =========== operations ============== + + /** + Rotation operation on a cartesian vector + */ + typedef DisplacementVector3D, DefaultCoordinateSystemTag > XYZVector; + XYZVector operator() (const XYZVector & v) const { + + const Scalar alpha = fU*fU - fI*fI - fJ*fJ - fK*fK; + const Scalar twoQv = 2*(fI*v.X() + fJ*v.Y() + fK*v.Z()); + const Scalar twoU = 2 * fU; + return XYZVector ( alpha * v.X() + twoU * (fJ*v.Z() - fK*v.Y()) + twoQv * fI , + alpha * v.Y() + twoU * (fK*v.X() - fI*v.Z()) + twoQv * fJ , + alpha * v.Z() + twoU * (fI*v.Y() - fJ*v.X()) + twoQv * fK ); + } + + /** + Rotation operation on a displacement vector in any coordinate system + */ + template + DisplacementVector3D + operator() (const DisplacementVector3D & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.X(), v.Y(), v.Z()); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + DisplacementVector3D< CoordSystem,Tag > vNew; + vNew.SetXYZ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + return vNew; + } + + /** + Rotation operation on a position vector in any coordinate system + */ + template + PositionVector3D + operator() (const PositionVector3D & p) const { + DisplacementVector3D< Cartesian3D,Tag > xyz(p); + DisplacementVector3D< Cartesian3D,Tag > rxyz = operator()(xyz); + return PositionVector3D ( rxyz ); + } + + /** + Rotation operation on a Lorentz vector in any 4D coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector< PxPyPzE4D > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E()); + return LorentzVector ( xyzt ); + } + + /** + Rotation operation on an arbitrary vector v. + Preconditions: v must implement methods x(), y(), and z() + and the arbitrary vector type must have a constructor taking (x,y,z) + */ + template + ForeignVector + operator() (const ForeignVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + AVector operator* (const AVector & v) const + { + return operator()(v); + } + + /** + Invert a rotation in place + */ + void Invert() { fI = -fI; fJ = -fJ; fK = -fK; } + + /** + Return inverse of a rotation + */ + Quaternion Inverse() const { return Quaternion(fU, -fI, -fJ, -fK); } + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) two rotations + */ + /** + Multiply (combine) two rotations + */ + Quaternion operator * (const Quaternion & q) const { + return Quaternion ( fU*q.fU - fI*q.fI - fJ*q.fJ - fK*q.fK , + fU*q.fI + fI*q.fU + fJ*q.fK - fK*q.fJ , + fU*q.fJ - fI*q.fK + fJ*q.fU + fK*q.fI , + fU*q.fK + fI*q.fJ - fJ*q.fI + fK*q.fU ); + } + + Quaternion operator * (const Rotation3D & r) const; + Quaternion operator * (const AxisAngle & a) const; + Quaternion operator * (const EulerAngles & e) const; + Quaternion operator * (const RotationZYX & r) const; + Quaternion operator * (const RotationX & rx) const; + Quaternion operator * (const RotationY & ry) const; + Quaternion operator * (const RotationZ & rz) const; + + /** + Post-Multiply (on right) by another rotation : T = T*R + */ + template + Quaternion & operator *= (const R & r) { return *this = (*this)*r; } + + + /** + Distance between two rotations in Quaternion form + Note: The rotation group is isomorphic to a 3-sphere + with diametrically opposite points identified. + The (rotation group-invariant) is the smaller + of the two possible angles between the images of + the two totations on that sphere. Thus the distance + is never greater than pi/2. + */ + + Scalar Distance(const Quaternion & q) const ; + + /** + Equality/inequality operators + */ + bool operator == (const Quaternion & rhs) const { + if( fU != rhs.fU ) return false; + if( fI != rhs.fI ) return false; + if( fJ != rhs.fJ ) return false; + if( fK != rhs.fK ) return false; + return true; + } + bool operator != (const Quaternion & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fU; + Scalar fI; + Scalar fJ; + Scalar fK; + +}; // Quaternion + +// ============ Class Quaternion ends here ============ + +/** + Distance between two rotations + */ +template +inline +typename Quaternion::Scalar +Distance ( const Quaternion& r1, const R & r2) {return gv_detail::dist(r1,r2);} + +/** + Multiplication of an axial rotation by an AxisAngle + */ +Quaternion operator* (RotationX const & r1, Quaternion const & r2); +Quaternion operator* (RotationY const & r1, Quaternion const & r2); +Quaternion operator* (RotationZ const & r1, Quaternion const & r2); + + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form + +std::ostream & operator<< (std::ostream & os, const Quaternion & q); +#endif + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_Quaternion diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Quaternionfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Quaternionfwd.h new file mode 100644 index 0000000000000..b26b0f624cbab --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Quaternionfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_Quaternionfwd +#define ROOT_MathX_GenVectorX_Quaternionfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a rotation represented by a quaternion + */ + +class Quaternion; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_Quaternionfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Rotation3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Rotation3D.h new file mode 100644 index 0000000000000..dd024a7c93259 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Rotation3D.h @@ -0,0 +1,531 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Rotation in 3 dimensions, represented by 3x3 matrix +// +// Created by: Mark Fischler Thurs June 9 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_Rotation3D +#define ROOT_MathX_GenVectorX_Rotation3D 1 + + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/3DConversions.h" +#include "MathX/GenVectorX/3DDistances.h" + +#include "MathX/GenVectorX/Rotation3Dfwd.h" +#include "MathX/GenVectorX/AxisAnglefwd.h" +#include "MathX/GenVectorX/EulerAnglesfwd.h" +#include "MathX/GenVectorX/Quaternionfwd.h" +#include "MathX/GenVectorX/RotationXfwd.h" +#include "MathX/GenVectorX/RotationYfwd.h" +#include "MathX/GenVectorX/RotationZfwd.h" + + +#include +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Rotation class with the (3D) rotation represented by + a 3x3 orthogonal matrix. + This is the optimal representation for application to vectors. + See also ROOT::Math::AxisAngle, ROOT::Math::EulerAngles, and ROOT::Math::Quaternion for + classes which have conversion operators to Rotation3D. + + All Rotations types (not only Rotation3D) can be applied to all 3D Vector classes + (like ROOT::Math::DisplacementVector3D and ROOT::Math::PositionVector3D) + and also to the 4D Vectors (ROOT::Math::LorentzVector classes), acting on the 3D components. + A rotation operation is applied by using the operator() or the operator *. + With the operator * is possible also to combine rotations. + Note that the operator is NOT commutative, the order how the rotations are applied is relevant. + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class Rotation3D { + +public: + + typedef double Scalar; + + enum ERotation3DMatrixIndex { + kXX = 0, kXY = 1, kXZ = 2 + , kYX = 3, kYY = 4, kYZ = 5 + , kZX = 6, kZY = 7, kZZ = 8 + }; + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity rotation) + */ + Rotation3D(); + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of nine Scalars + */ + template + Rotation3D(IT begin, IT end) { SetComponents(begin,end); } + + /** + copy constructor + */ + Rotation3D ( Rotation3D const & r ) { + *this = r; + } + + /** + Construct from an AxisAngle + */ + explicit Rotation3D( AxisAngle const & a ) { gv_detail::convert(a, *this); } + + /** + Construct from EulerAngles + */ + explicit Rotation3D( EulerAngles const & e ) { gv_detail::convert(e, *this); } + + /** + Construct from RotationZYX + */ + explicit Rotation3D( RotationZYX const & e ) { gv_detail::convert(e, *this); } + + /** + Construct from a Quaternion + */ + explicit Rotation3D( Quaternion const & q ) { gv_detail::convert(q, *this); } + + /** + Construct from an axial rotation + */ + explicit Rotation3D( RotationZ const & r ) { gv_detail::convert(r, *this); } + explicit Rotation3D( RotationY const & r ) { gv_detail::convert(r, *this); } + explicit Rotation3D( RotationX const & r ) { gv_detail::convert(r, *this); } + + /** + Construct from a linear algebra matrix of size at least 3x3, + which must support operator()(i,j) to obtain elements (0,0) thru (2,2). + Precondition: The matrix is assumed to be orthonormal. No checking + or re-adjusting is performed. + */ + template + explicit Rotation3D(const ForeignMatrix & m) { SetComponents(m); } + + /** + Construct from three orthonormal vectors (which must have methods + x(), y() and z()) which will be used as the columns of the rotation + matrix. The orthonormality will be checked, and values adjusted + so that the result will always be a good rotation matrix. + */ + template + Rotation3D(const ForeignVector& v1, + const ForeignVector& v2, + const ForeignVector& v3 ) { SetComponents(v1, v2, v3); } + + // compiler generated destruuctor is ok + + /** + Raw constructor from nine Scalar components (without any checking) + */ + Rotation3D(Scalar xx, Scalar xy, Scalar xz, + Scalar yx, Scalar yy, Scalar yz, + Scalar zx, Scalar zy, Scalar zz) + { + SetComponents (xx, xy, xz, yx, yy, yz, zx, zy, zz); + } + + // need to implement assignment operator to avoid using the templated one + + /** + Assignment operator + */ + Rotation3D & + operator=( Rotation3D const & rhs ) { + SetComponents( rhs.fM[0], rhs.fM[1], rhs.fM[2], + rhs.fM[3], rhs.fM[4], rhs.fM[5], + rhs.fM[6], rhs.fM[7], rhs.fM[8] ); + return *this; + } + + /** + Assign from an AxisAngle + */ + Rotation3D & + operator=( AxisAngle const & a ) { return operator=(Rotation3D(a)); } + + /** + Assign from EulerAngles + */ + Rotation3D & + operator=( EulerAngles const & e ) { return operator=(Rotation3D(e)); } + + /** + Assign from RotationZYX + */ + Rotation3D & + operator=( RotationZYX const & r ) { return operator=(Rotation3D(r)); } + + /** + Assign from a Quaternion + */ + Rotation3D & + operator=( Quaternion const & q ) {return operator=(Rotation3D(q)); } + + /** + Assign from an axial rotation + */ + Rotation3D & + operator=( RotationZ const & r ) { return operator=(Rotation3D(r)); } + Rotation3D & + operator=( RotationY const & r ) { return operator=(Rotation3D(r)); } + Rotation3D & + operator=( RotationX const & r ) { return operator=(Rotation3D(r)); } + + /** + Assign from an orthonormal linear algebra matrix of size 3x3, + which must support operator()(i,j) to obtain elements (0,0) thru (2,2). + */ + template + Rotation3D & + operator=(const ForeignMatrix & m) { + SetComponents( m(0,0), m(0,1), m(0,2), + m(1,0), m(1,1), m(1,2), + m(2,0), m(2,1), m(2,2) ); + return *this; + } + + /** + Re-adjust components to eliminate small deviations from perfect + orthonormality. + */ + void Rectify(); + + // ======== Components ============== + + /** + Set components from three orthonormal vectors (which must have methods + x(), y() and z()) which will be used as the columns of the rotation + matrix. The orthonormality will be checked, and values adjusted + so that the result will always be a good rotation matrix. + */ + template + void + SetComponents (const ForeignVector& v1, + const ForeignVector& v2, + const ForeignVector& v3 ) { + fM[kXX]=v1.x(); fM[kXY]=v2.x(); fM[kXZ]=v3.x(); + fM[kYX]=v1.y(); fM[kYY]=v2.y(); fM[kYZ]=v3.y(); + fM[kZX]=v1.z(); fM[kZY]=v2.z(); fM[kZZ]=v3.z(); + Rectify(); + } + + /** + Get components into three vectors which will be the (orthonormal) + columns of the rotation matrix. (The vector class must have a + constructor from 3 Scalars.) + */ + template + void + GetComponents ( ForeignVector& v1, + ForeignVector& v2, + ForeignVector& v3 ) const { + v1 = ForeignVector ( fM[kXX], fM[kYX], fM[kZX] ); + v2 = ForeignVector ( fM[kXY], fM[kYY], fM[kZY] ); + v3 = ForeignVector ( fM[kXZ], fM[kYZ], fM[kZZ] ); + } + + /** + Set the 9 matrix components given an iterator to the start of + the desired data, and another to the end (9 past start). + */ + template + void SetComponents(IT begin, IT end) { + for (int i = 0; i <9; ++i) { + fM[i] = *begin; + ++begin; + } + (void)end; + assert (end==begin); + } + + /** + Get the 9 matrix components into data specified by an iterator begin + and another to the end of the desired data (9 past start). + */ + template + void GetComponents(IT begin, IT end) const { + for (int i = 0; i <9; ++i) { + *begin = fM[i]; + ++begin; + } + (void)end; + assert (end==begin); + } + + /** + Get the 9 matrix components into data specified by an iterator begin + */ + template + void GetComponents(IT begin) const { + std::copy ( fM, fM+9, begin ); + } + + /** + Set components from a linear algebra matrix of size at least 3x3, + which must support operator()(i,j) to obtain elements (0,0) thru (2,2). + Precondition: The matrix is assumed to be orthonormal. NO checking + or re-adjusting is performed. + */ + template + void + SetRotationMatrix (const ForeignMatrix & m) { + fM[kXX]=m(0,0); fM[kXY]=m(0,1); fM[kXZ]=m(0,2); + fM[kYX]=m(1,0); fM[kYY]=m(1,1); fM[kYZ]=m(1,2); + fM[kZX]=m(2,0); fM[kZY]=m(2,1); fM[kZZ]=m(2,2); + } + + /** + Get components into a linear algebra matrix of size at least 3x3, + which must support operator()(i,j) for write access to elements + (0,0) thru (2,2). + */ + template + void + GetRotationMatrix (ForeignMatrix & m) const { + m(0,0)=fM[kXX]; m(0,1)=fM[kXY]; m(0,2)=fM[kXZ]; + m(1,0)=fM[kYX]; m(1,1)=fM[kYY]; m(1,2)=fM[kYZ]; + m(2,0)=fM[kZX]; m(2,1)=fM[kZY]; m(2,2)=fM[kZZ]; + } + + /** + Set the components from nine scalars -- UNCHECKED for orthonormaility + */ + void + SetComponents (Scalar xx, Scalar xy, Scalar xz, + Scalar yx, Scalar yy, Scalar yz, + Scalar zx, Scalar zy, Scalar zz) { + fM[kXX]=xx; fM[kXY]=xy; fM[kXZ]=xz; + fM[kYX]=yx; fM[kYY]=yy; fM[kYZ]=yz; + fM[kZX]=zx; fM[kZY]=zy; fM[kZZ]=zz; + } + + /** + Get the nine components into nine scalars + */ + void + GetComponents (Scalar &xx, Scalar &xy, Scalar &xz, + Scalar &yx, Scalar &yy, Scalar &yz, + Scalar &zx, Scalar &zy, Scalar &zz) const { + xx=fM[kXX]; xy=fM[kXY]; xz=fM[kXZ]; + yx=fM[kYX]; yy=fM[kYY]; yz=fM[kYZ]; + zx=fM[kZX]; zy=fM[kZY]; zz=fM[kZZ]; + } + + // =========== operations ============== + + + /** + Rotation operation on a displacement vector in any coordinate system + */ + template + DisplacementVector3D + operator() (const DisplacementVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz; + xyz.SetXYZ( fM[kXX] * v.X() + fM[kXY] * v.Y() + fM[kXZ] * v.Z() , + fM[kYX] * v.X() + fM[kYY] * v.Y() + fM[kYZ] * v.Z() , + fM[kZX] * v.X() + fM[kZY] * v.Y() + fM[kZZ] * v.Z() ); + return DisplacementVector3D( xyz ); + } + + /** + Rotation operation on a position vector in any coordinate system + */ + template + PositionVector3D + operator() (const PositionVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz(v); + DisplacementVector3D< Cartesian3D,U > rxyz = operator()(xyz); + return PositionVector3D ( rxyz ); + } + + /** + Rotation operation on a Lorentz vector in any spatial coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector< PxPyPzE4D > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E()); + return LorentzVector ( xyzt ); + } + + /** + Rotation operation on an arbitrary vector v. + Preconditions: v must implement methods x(), y(), and z() + and the arbitrary vector type must have a constructor taking (x,y,z) + */ + template + ForeignVector + operator() (const ForeignVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + AVector operator* (const AVector & v) const + { + return operator()(v); + } + + /** + Invert a rotation in place + */ + void Invert(); + + /** + Return inverse of a rotation + */ + Rotation3D Inverse() const { Rotation3D t(*this); t.Invert(); return t; } + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) two rotations + */ + Rotation3D operator * (const Rotation3D & r) const { + return Rotation3D + ( fM[kXX]*r.fM[kXX] + fM[kXY]*r.fM[kYX] + fM[kXZ]*r.fM[kZX] + , fM[kXX]*r.fM[kXY] + fM[kXY]*r.fM[kYY] + fM[kXZ]*r.fM[kZY] + , fM[kXX]*r.fM[kXZ] + fM[kXY]*r.fM[kYZ] + fM[kXZ]*r.fM[kZZ] + + , fM[kYX]*r.fM[kXX] + fM[kYY]*r.fM[kYX] + fM[kYZ]*r.fM[kZX] + , fM[kYX]*r.fM[kXY] + fM[kYY]*r.fM[kYY] + fM[kYZ]*r.fM[kZY] + , fM[kYX]*r.fM[kXZ] + fM[kYY]*r.fM[kYZ] + fM[kYZ]*r.fM[kZZ] + + , fM[kZX]*r.fM[kXX] + fM[kZY]*r.fM[kYX] + fM[kZZ]*r.fM[kZX] + , fM[kZX]*r.fM[kXY] + fM[kZY]*r.fM[kYY] + fM[kZZ]*r.fM[kZY] + , fM[kZX]*r.fM[kXZ] + fM[kZY]*r.fM[kYZ] + fM[kZZ]*r.fM[kZZ] ); + + } + + + /** + Multiplication with arbitrary rotations + */ + // note: cannot have a template method since it is ambiguous with the operator * on vectors + + Rotation3D operator * (const AxisAngle & a) const; + Rotation3D operator * (const EulerAngles & e) const; + Rotation3D operator * (const Quaternion & q) const; + Rotation3D operator * (const RotationZYX & r) const; + Rotation3D operator * (const RotationX & rx) const; + Rotation3D operator * (const RotationY & ry) const; + Rotation3D operator * (const RotationZ & rz) const; + + /** + Post-Multiply (on right) by another rotation : T = T*R + */ + template + Rotation3D & operator *= (const R & r) { return *this = (*this)*r; } + + /** + Equality/inequality operators + */ + bool operator == (const Rotation3D & rhs) const { + if( fM[0] != rhs.fM[0] ) return false; + if( fM[1] != rhs.fM[1] ) return false; + if( fM[2] != rhs.fM[2] ) return false; + if( fM[3] != rhs.fM[3] ) return false; + if( fM[4] != rhs.fM[4] ) return false; + if( fM[5] != rhs.fM[5] ) return false; + if( fM[6] != rhs.fM[6] ) return false; + if( fM[7] != rhs.fM[7] ) return false; + if( fM[8] != rhs.fM[8] ) return false; + return true; + } + bool operator != (const Rotation3D & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fM[9]; // 9 elements (3x3 matrix) representing the rotation + +}; // Rotation3D + +// ============ Class Rotation3D ends here ============ + +/** + Distance between two rotations + */ +template +inline +typename Rotation3D::Scalar +Distance ( const Rotation3D& r1, const R & r2) {return gv_detail::dist(r1,r2);} + +/** + Multiplication of an axial rotation by a Rotation3D + */ +Rotation3D operator* (RotationX const & r1, Rotation3D const & r2); +Rotation3D operator* (RotationY const & r1, Rotation3D const & r2); +Rotation3D operator* (RotationZ const & r1, Rotation3D const & r2); + +/** + Multiplication of an axial rotation by another axial Rotation + */ +Rotation3D operator* (RotationX const & r1, RotationY const & r2); +Rotation3D operator* (RotationX const & r1, RotationZ const & r2); + +Rotation3D operator* (RotationY const & r1, RotationX const & r2); +Rotation3D operator* (RotationY const & r1, RotationZ const & r2); + +Rotation3D operator* (RotationZ const & r1, RotationX const & r2); +Rotation3D operator* (RotationZ const & r1, RotationY const & r2); + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form + +std::ostream & operator<< (std::ostream & os, const Rotation3D & r); +#endif + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_Rotation3D diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Rotation3Dfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Rotation3Dfwd.h new file mode 100644 index 0000000000000..e59c2d4cc21b5 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Rotation3Dfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_Rotation3Dfwd +#define ROOT_MathX_GenVectorX_Rotation3Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a rotation represented by a 3x3 matrix + */ + +class Rotation3D; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_Rotation3Dfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationX.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationX.h new file mode 100644 index 0000000000000..b1b34e094bcbd --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationX.h @@ -0,0 +1,259 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class RotationZ representing a rotation about the Z axis +// +// Created by: Mark Fischler Mon July 18 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_RotationX +#define ROOT_MathX_GenVectorX_RotationX 1 + + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/3DDistances.h" + +#include "MathX/GenVectorX/RotationXfwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Rotation class representing a 3D rotation about the X axis by the angle of rotation. + For efficiency reason, in addition to the angle, the sine and cosine of the angle are held + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class RotationX { + +public: + + typedef double Scalar; + + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity rotation) + */ + RotationX() : fAngle(0), fSin(0), fCos(1) { } + + /** + Construct from an angle + */ + explicit RotationX( Scalar angle ) : fAngle(angle), + fSin(math_sin(angle)), + fCos(math_cos(angle)) + { + Rectify(); + } + + // The compiler-generated copy ctor, copy assignment, and destructor are OK. + + /** + Rectify makes sure the angle is in (-pi,pi] + */ + void Rectify() { + if ( math_fabs(fAngle) >= M_PI ) { + double x = fAngle / (2.0 * M_PI); + fAngle = (2.0 * M_PI) * ( x + math_floor(.5-x) ); + fSin = math_sin(fAngle); + fCos = math_cos(fAngle); + } + } + + // ======== Components ============== + + /** + Set given the angle. + */ + void SetAngle (Scalar angle) { + fSin=math_sin(angle); + fCos=math_cos(angle); + fAngle= angle; + Rectify(); + } + void SetComponents (Scalar angle) { SetAngle(angle); } + + /** + Get the angle + */ + void GetAngle(Scalar &angle) const { angle = math_atan2(fSin, fCos); } + void GetComponents ( Scalar & angle ) const { GetAngle(angle); } + + /** + Angle of rotation + */ + Scalar Angle() const { return math_atan2(fSin, fCos); } + + /** + Sine or Cosine of the rotation angle + */ + Scalar SinAngle () const { return fSin; } + Scalar CosAngle () const { return fCos; } + + // =========== operations ============== + + /** + Rotation operation on a cartesian vector + */ +// typedef DisplacementVector3D< Cartesian3D > XYZVector; +// XYZVector operator() (const XYZVector & v) const { +// return XYZVector ( v.x(), fCos*v.y()-fSin*v.z(), fCos*v.z()+fSin*v.y() ); +// } + + + /** + Rotation operation on a displacement vector in any coordinate system + */ + template + DisplacementVector3D + operator() (const DisplacementVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz; + xyz.SetXYZ( v.X(), fCos*v.Y()-fSin*v.Z(), fCos*v.Z()+fSin*v.Y() ); + return DisplacementVector3D(xyz); + } + + /** + Rotation operation on a position vector in any coordinate system + */ + template + PositionVector3D + operator() (const PositionVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz(v); + DisplacementVector3D< Cartesian3D,U > rxyz = operator()(xyz); + return PositionVector3D ( rxyz ); + } + + /** + Rotation operation on a Lorentz vector in any 4D coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector< PxPyPzE4D > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E()); + return LorentzVector ( xyzt ); + } + + /** + Rotation operation on an arbitrary vector v. + Preconditions: v must implement methods x(), y(), and z() + and the arbitrary vector type must have a constructor taking (x,y,z) + */ + template + ForeignVector + operator() (const ForeignVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + AVector operator* (const AVector & v) const + { + return operator()(v); + } + + /** + Invert a rotation in place + */ + void Invert() { fAngle = -fAngle; fSin = -fSin; } + + /** + Return inverse of a rotation + */ + RotationX Inverse() const { RotationX t(*this); t.Invert(); return t; } + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) two rotations + */ + RotationX operator * (const RotationX & r) const { + RotationX ans; + double x = (fAngle + r.fAngle) / (2.0 * M_PI); + ans.fAngle = (2.0 * M_PI) * ( x + math_floor(.5-x) ); + ans.fSin = fSin*r.fCos + fCos*r.fSin; + ans.fCos = fCos*r.fCos - fSin*r.fSin; + return ans; + } + + /** + Post-Multiply (on right) by another rotation : T = T*R + */ + RotationX & operator *= (const RotationX & r) { return *this = (*this)*r; } + + /** + Equality/inequality operators + */ + bool operator == (const RotationX & rhs) const { + if( fAngle != rhs.fAngle ) return false; + return true; + } + bool operator != (const RotationX & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fAngle; // rotation angle + Scalar fSin; // sine of the rotation angle + Scalar fCos; // cosine of the rotation angle + +}; // RotationX + +// ============ Class RotationX ends here ============ + +/** + Distance between two rotations + */ +template +inline +typename RotationX::Scalar +Distance ( const RotationX& r1, const R & r2) {return gv_detail::dist(r1,r2);} + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form + +inline +std::ostream & operator<< (std::ostream & os, const RotationX & r) { + os << " RotationX(" << r.Angle() << ") "; + return os; +} + +#endif + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_RotationX diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationXfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationXfwd.h new file mode 100644 index 0000000000000..1fd89f35ff830 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationXfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_RotationXfwd +#define ROOT_MathX_GenVectorX_RotationXfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a rotation about the X axis + */ + +class RotationX; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_RotationXfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationY.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationY.h new file mode 100644 index 0000000000000..fd049152908fc --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationY.h @@ -0,0 +1,258 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class RotationY representing a rotation about the Y axis +// +// Created by: Mark Fischler Mon July 18 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_RotationY +#define ROOT_MathX_GenVectorX_RotationY 1 + + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/3DDistances.h" + +#include "MathX/GenVectorX/RotationYfwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Rotation class representing a 3D rotation about the Y axis by the angle of rotation. + For efficiency reason, in addition to the angle, the sine and cosine of the angle are held + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class RotationY { + +public: + + typedef double Scalar; + + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity rotation) + */ + RotationY() : fAngle(0), fSin(0), fCos(1) { } + + /** + Construct from an angle + */ + explicit RotationY( Scalar angle ) : fAngle(angle), + fSin(math_sin(angle)), + fCos(math_cos(angle)) + { + Rectify(); + } + + // The compiler-generated copy ctor, copy assignment, and destructor are OK. + + /** + Rectify makes sure the angle is in (-pi,pi] + */ + void Rectify() { + if ( math_fabs(fAngle) >= M_PI ) { + double x = fAngle / (2.0 * M_PI); + fAngle = (2.0 * M_PI) * ( x + math_floor(.5-x) ); + fSin = math_sin(fAngle); + fCos = math_cos(fAngle); + } + } + + // ======== Components ============== + + /** + Set given the angle. + */ + void SetAngle (Scalar angle) { + fSin=math_sin(angle); + fCos=math_cos(angle); + fAngle= angle; + Rectify(); + } + void SetComponents (Scalar angle) { SetAngle(angle); } + + /** + Get the angle + */ + void GetAngle(Scalar &angle) const { angle = math_atan2(fSin, fCos); } + void GetComponents ( Scalar & angle ) const { GetAngle(angle); } + + /** + Angle of rotation + */ + Scalar Angle() const { return math_atan2(fSin, fCos); } + + /** + Sine or Cosine of the rotation angle + */ + Scalar SinAngle () const { return fSin; } + Scalar CosAngle () const { return fCos; } + + // =========== operations ============== + +// /** +// Rotation operation on a cartesian vector +// */ +// typedef DisplacementVector3D< Cartesian3D > XYZVector; +// XYZVector operator() (const XYZVector & v) const { +// return XYZVector +// ( fCos*v.x()+fSin*v.z(), v.y(), fCos*v.z()-fSin*v.x() ); +// } + + /** + Rotation operation on a displacement vector in any coordinate system + */ + template + DisplacementVector3D + operator() (const DisplacementVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz; + xyz.SetXYZ( fCos*v.x()+fSin*v.z(), v.y(), fCos*v.z()-fSin*v.x() ); + return DisplacementVector3D(xyz); + } + + /** + Rotation operation on a position vector in any coordinate system + */ + template + PositionVector3D + operator() (const PositionVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz(v); + DisplacementVector3D< Cartesian3D,U > rxyz = operator()(xyz); + return PositionVector3D ( rxyz ); + } + + /** + Rotation operation on a Lorentz vector in any 4D coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector< PxPyPzE4D > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E()); + return LorentzVector ( xyzt ); + } + + /** + Rotation operation on an arbitrary vector v. + Preconditions: v must implement methods x(), y(), and z() + and the arbitrary vector type must have a constructor taking (x,y,z) + */ + template + ForeignVector + operator() (const ForeignVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + AVector operator* (const AVector & v) const + { + return operator()(v); + } + + /** + Invert a rotation in place + */ + void Invert() { fAngle = -fAngle; fSin = -fSin; } + + /** + Return inverse of a rotation + */ + RotationY Inverse() const { RotationY t(*this); t.Invert(); return t; } + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) two rotations + */ + RotationY operator * (const RotationY & r) const { + RotationY ans; + double x = (fAngle + r.fAngle) / (2.0 * M_PI); + ans.fAngle = (2.0 * M_PI) * ( x + math_floor(.5-x) ); + ans.fSin = fSin*r.fCos + fCos*r.fSin; + ans.fCos = fCos*r.fCos - fSin*r.fSin; + return ans; + } + + /** + Post-Multiply (on right) by another rotation : T = T*R + */ + RotationY & operator *= (const RotationY & r) { return *this = (*this)*r; } + + /** + Equality/inequality operators + */ + bool operator == (const RotationY & rhs) const { + if( fAngle != rhs.fAngle ) return false; + return true; + } + bool operator != (const RotationY & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fAngle; // rotation angle + Scalar fSin; // sine of the rotation angle + Scalar fCos; // cosine of the rotation angle + +}; // RotationY + +// ============ Class RotationY ends here ============ + +/** + Distance between two rotations + */ +template +inline +typename RotationY::Scalar +Distance ( const RotationY& r1, const R & r2) {return gv_detail::dist(r1,r2);} + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +inline +std::ostream & operator<< (std::ostream & os, const RotationY & r) { + os << " RotationY(" << r.Angle() << ") "; + return os; +} +#endif + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_RotationY diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationYfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationYfwd.h new file mode 100644 index 0000000000000..d2295ba07a0dd --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationYfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_RotationYfwd +#define ROOT_MathX_GenVectorX_RotationYfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a rotation about the Y axis + */ + +class RotationY; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_RotationYfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZ.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZ.h new file mode 100644 index 0000000000000..613c15c8e6ff9 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZ.h @@ -0,0 +1,259 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class RotationZ representing a rotation about the Z axis +// +// Created by: Mark Fischler Mon July 18 2005 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_RotationZ +#define ROOT_MathX_GenVectorX_RotationZ 1 + + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/3DDistances.h" + +#include "MathX/GenVectorX/RotationZfwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Rotation class representing a 3D rotation about the Z axis by the angle of rotation. + For efficiency reason, in addition to the angle, the sine and cosine of the angle are held + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class RotationZ { + +public: + + typedef double Scalar; + + + // ========== Constructors and Assignment ===================== + + /** + Default constructor (identity rotation) + */ + RotationZ() : fAngle(0), fSin(0), fCos(1) { } + + /** + Construct from an angle + */ + explicit RotationZ( Scalar angle ) : fAngle(angle), + fSin(math_sin(angle)), + fCos(math_cos(angle)) + { + Rectify(); + } + + // The compiler-generated copy ctor, copy assignment, and destructor are OK. + + /** + Rectify makes sure the angle is in (-pi,pi] + */ + void Rectify() { + if ( math_fabs(fAngle) >= M_PI ) { + double x = fAngle / (2.0 * M_PI); + fAngle = (2.0 * M_PI) * ( x + math_floor(.5-x) ); + fSin = math_sin(fAngle); + fCos = math_cos(fAngle); + } + } + + // ======== Components ============== + + /** + Set given the angle. + */ + void SetAngle (Scalar angle) { + fSin=math_sin(angle); + fCos=math_cos(angle); + fAngle= angle; + Rectify(); + } + void SetComponents (Scalar angle) { SetAngle(angle); } + + /** + Get the angle + */ + void GetAngle(Scalar &angle) const { angle = math_atan2(fSin, fCos); } + void GetComponents ( Scalar & angle ) const { GetAngle(angle); } + + /** + Angle of rotation + */ + Scalar Angle() const { return math_atan2(fSin, fCos); } + + /** + Sine or Cosine of the rotation angle + */ + Scalar SinAngle () const { return fSin; } + Scalar CosAngle () const { return fCos; } + + // =========== operations ============== + +// /** +// Rotation operation on a cartesian vector +// */ +// typedef DisplacementVector3D< Cartesian3D > XYZVector; +// XYZVector operator() (const XYZVector & v) const { +// return XYZVector +// ( fCos*v.x()-fSin*v.y(), fCos*v.y()+fSin*v.x(), v.z() ); +// } + + /** + Rotation operation on a displacement vector in any coordinate system + */ + template + DisplacementVector3D + operator() (const DisplacementVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz; + xyz.SetXYZ( fCos*v.x()-fSin*v.y(), fCos*v.y()+fSin*v.x(), v.z() ); + return DisplacementVector3D(xyz); + } + + /** + Rotation operation on a position vector in any coordinate system + */ + template + PositionVector3D + operator() (const PositionVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz(v); + DisplacementVector3D< Cartesian3D,U > rxyz = operator()(xyz); + return PositionVector3D ( rxyz ); + } + + /** + Rotation operation on a Lorentz vector in any 4D coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector< PxPyPzE4D > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E()); + return LorentzVector ( xyzt ); + } + + /** + Rotation operation on an arbitrary vector v. + Preconditions: v must implement methods x(), y(), and z() + and the arbitrary vector type must have a constructor taking (x,y,z) + */ + template + ForeignVector + operator() (const ForeignVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + AVector operator* (const AVector & v) const + { + return operator()(v); + } + + /** + Invert a rotation in place + */ + void Invert() { fAngle = -fAngle; fSin = -fSin; } + + /** + Return inverse of a rotation + */ + RotationZ Inverse() const { RotationZ t(*this); t.Invert(); return t; } + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) two rotations + */ + RotationZ operator * (const RotationZ & r) const { + RotationZ ans; + double x = (fAngle + r.fAngle) / (2.0 * M_PI); + ans.fAngle = (2.0 * M_PI) * ( x + math_floor(.5-x) ); + ans.fSin = fSin*r.fCos + fCos*r.fSin; + ans.fCos = fCos*r.fCos - fSin*r.fSin; + return ans; + } + + /** + Post-Multiply (on right) by another rotation : T = T*R + */ + RotationZ & operator *= (const RotationZ & r) { return *this = (*this)*r; } + + /** + Equality/inequality operators + */ + bool operator == (const RotationZ & rhs) const { + if( fAngle != rhs.fAngle ) return false; + return true; + } + bool operator != (const RotationZ & rhs) const { + return ! operator==(rhs); + } + +private: + + Scalar fAngle; // rotation angle + Scalar fSin; // sine of the rotation angle + Scalar fCos; // cosine of the rotation angle + +}; // RotationZ + +// ============ Class RotationZ ends here ============ + +/** + Distance between two rotations + */ +template +inline +typename RotationZ::Scalar +Distance ( const RotationZ& r1, const R & r2) {return gv_detail::dist(r1,r2);} + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +inline +std::ostream & operator<< (std::ostream & os, const RotationZ & r) { + os << " RotationZ(" << r.Angle() << ") "; + return os; +} + +#endif + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_RotationZ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZYX.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZYX.h new file mode 100644 index 0000000000000..5b191b10ad040 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZYX.h @@ -0,0 +1,355 @@ +// @(#)root/mathcore:$Id$ +// Authors: J. Palacios, L. Moneta 2007 + + /********************************************************************** + * * + * Copyright (c) 2007 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Rotation in 3 dimensions, described by 3 Z-Y-X Euler angles +// representing a rotation along Z, Y and X +// +// Created by: Lorenzo Moneta, Wed. May 22, 2007 +// +// Last update: $Id$ +// +#ifndef ROOT_MathX_GenVectorX_RotationZYX +#define ROOT_MathX_GenVectorX_RotationZYX 1 + +#include "Math/Math.h" + +#include "MathX/GenVectorX/Rotation3D.h" + + +#include "MathX/GenVectorX/DisplacementVector3D.h" + +#include "MathX/GenVectorX/PositionVector3D.h" + +#include "MathX/GenVectorX/LorentzVector.h" + +#include "MathX/GenVectorX/3DConversions.h" + + +#include +#include +#include + + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { +namespace ROOT_MATH_ARCH { + + +//__________________________________________________________________________________________ + /** + Rotation class with the (3D) rotation represented by + angles describing first a rotation of + an angle phi (yaw) about the Z axis, + followed by a rotation of an angle theta (pitch) about the Y axis, + followed by a third rotation of an angle psi (roll) about the X axis. + Note that the rotations are extrinsic rotations happening around a fixed coordinate system. + This is different than the convention of the ROOT::Math::EulerAngles class, where the rotation are intrinsic. + Also it has not to be confused with the typical Goldstein definition of the Euler Angles + (Z-X-Z or 313 sequence) which is used by the ROOT::Math::EulerAngles class, while the sequence here is Z-Y-X or 321. + Applying a RotationZYX(phi, theta, psi) to a vector is then equal to applying RotationX(psi) * RotationY(theta) * RotationZ(phi) to the same vector. + + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + +class RotationZYX { + +public: + + typedef double Scalar; + + + // ========== Constructors and Assignment ===================== + + /** + Default constructor + */ + RotationZYX() : fPhi(0.0), fTheta(0.0), fPsi(0.0) { } + + /** + Constructor from phi, theta and psi + */ + RotationZYX( Scalar phi, Scalar theta, Scalar psi ) : + fPhi(phi), fTheta(theta), fPsi(psi) + {Rectify();} // Added 27 Jan. 06 JMM + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of three Scalars, to be treated as + the angles phi, theta and psi. + */ + template + RotationZYX(IT begin, IT end) { SetComponents(begin,end); } + + // The compiler-generated copy ctor, copy assignment, and dtor are OK. + + /** + Re-adjust components place angles in canonical ranges + */ + void Rectify(); + + + // ======== Construction and Assignment From other Rotation Forms ================== + + /** + Construct from another supported rotation type (see gv_detail::convert ) + */ + template + explicit RotationZYX(const OtherRotation & r) {gv_detail::convert(r,*this);} + + + /** + Assign from another supported rotation type (see gv_detail::convert ) + */ + template + RotationZYX & operator=( OtherRotation const & r ) { + gv_detail::convert(r,*this); + return *this; + } + + + // ======== Components ============== + + /** + Set the three Euler angles given a pair of pointers or iterators + defining the beginning and end of an array of three Scalars. + */ + template + void SetComponents(IT begin, IT end) { + fPhi = *begin++; + fTheta = *begin++; + fPsi = *begin++; + (void)end; + assert(begin == end); + Rectify(); + } + + /** + Get the axis and then the angle into data specified by an iterator begin + and another to the end of the desired data (4 past start). + */ + template + void GetComponents(IT begin, IT end) const { + *begin++ = fPhi; + *begin++ = fTheta; + *begin++ = fPsi; + (void)end; + assert(begin == end); + } + + /** + Get the axis and then the angle into data specified by an iterator begin + */ + template + void GetComponents(IT begin) const { + *begin++ = fPhi; + *begin++ = fTheta; + *begin = fPsi; + } + + /** + Set the components phi, theta, psi based on three Scalars. + */ + void SetComponents(Scalar phi, Scalar theta, Scalar psi) { + fPhi=phi; fTheta=theta; fPsi=psi; + Rectify(); + } + + /** + Get the components phi, theta, psi into three Scalars. + */ + void GetComponents(Scalar & phi, Scalar & theta, Scalar & psi) const { + phi=fPhi; theta=fTheta; psi=fPsi; + } + + /** + Set Phi angle (Z rotation angle) + */ + void SetPhi(Scalar phi) { fPhi=phi; Rectify(); } + + /** + Return Phi angle (Z rotation angle) + */ + Scalar Phi() const { return fPhi; } + + /** + Set Theta angle (Y' rotation angle) + */ + void SetTheta(Scalar theta) { fTheta=theta; Rectify(); } + + /** + Return Theta angle (Y' rotation angle) + */ + Scalar Theta() const { return fTheta; } + + /** + Set Psi angle (X'' rotation angle) + */ + void SetPsi(Scalar psi) { fPsi=psi; Rectify(); } + + /** + Return Psi angle (X'' rotation angle) + */ + Scalar Psi() const { return fPsi; } + + // =========== operations ============== + + + /** + Rotation operation on a displacement vector in any coordinate system and tag + */ + template + DisplacementVector3D + operator() (const DisplacementVector3D & v) const { + return Rotation3D(*this) ( v ); + } + + /** + Rotation operation on a position vector in any coordinate system + */ + template + PositionVector3D + operator() (const PositionVector3D & v) const { + DisplacementVector3D< Cartesian3D,U > xyz(v); + DisplacementVector3D< Cartesian3D,U > rxyz = operator()(xyz); + return PositionVector3D ( rxyz ); + } + + /** + Rotation operation on a Lorentz vector in any 4D coordinate system + */ + template + LorentzVector + operator() (const LorentzVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector< PxPyPzE4D > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E()); + return LorentzVector ( xyzt ); + } + + /** + Rotation operation on an arbitrary vector v. + Preconditions: v must implement methods x(), y(), and z() + and the arbitrary vector type must have a constructor taking (x,y,z) + */ + template + ForeignVector + operator() (const ForeignVector & v) const { + DisplacementVector3D< Cartesian3D > xyz(v); + DisplacementVector3D< Cartesian3D > rxyz = operator()(xyz); + return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() ); + } + + /** + Overload operator * for rotation on a vector + */ + template + inline + AVector operator* (const AVector & v) const + { + return operator()(v); + } + + /** + Invert a rotation in place + */ + void Invert(); + + /** + Return inverse of a rotation + */ + RotationZYX Inverse() const { + RotationZYX r(*this); + r.Invert(); + return r; + } + + + // ========= Multi-Rotation Operations =============== + + /** + Multiply (combine) two rotations + */ + RotationZYX operator * (const RotationZYX & e) const; + RotationZYX operator * (const Rotation3D & r) const; + RotationZYX operator * (const AxisAngle & a) const; + RotationZYX operator * (const Quaternion & q) const; + RotationZYX operator * (const EulerAngles & q) const; + RotationZYX operator * (const RotationX & rx) const; + RotationZYX operator * (const RotationY & ry) const; + RotationZYX operator * (const RotationZ & rz) const; + + /** + Post-Multiply (on right) by another rotation : T = T*R + */ + template + RotationZYX & operator *= (const R & r) { return *this = (*this)*r; } + + /** + Distance between two rotations + */ + template + Scalar Distance ( const R & r ) const {return gv_detail::dist(*this,r);} + + /** + Equality/inequality operators + */ + bool operator == (const RotationZYX & rhs) const { + if( fPhi != rhs.fPhi ) return false; + if( fTheta != rhs.fTheta ) return false; + if( fPsi != rhs.fPsi ) return false; + return true; + } + bool operator != (const RotationZYX & rhs) const { + return ! operator==(rhs); + } + +private: + + double fPhi; // Z rotation angle (yaw) defined in (-PI,PI] + double fTheta; // Y' rotation angle (pitch) defined in [-PI/2,PI/2] + double fPsi; // X'' rotation angle (roll) defined in (-PI,PI] + + static double Pi() { return M_PI; } + +}; // RotationZYX + +/** + Distance between two rotations + */ +template +inline +typename RotationZYX::Scalar +Distance ( const RotationZYX& r1, const R & r2) {return gv_detail::dist(r1,r2);} + +/** + Multiplication of an axial rotation by an AxisAngle + */ +RotationZYX operator* (RotationX const & r1, RotationZYX const & r2); +RotationZYX operator* (RotationY const & r1, RotationZYX const & r2); +RotationZYX operator* (RotationZ const & r1, RotationZYX const & r2); + +/** + Stream Output and Input + */ + // TODO - I/O should be put in the manipulator form +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +std::ostream & operator<< (std::ostream & os, const RotationZYX & e); +#endif + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_RotationZYX diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZYXfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZYXfwd.h new file mode 100644 index 0000000000000..e08d1f429b9c7 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZYXfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_RotationZYXfwd +#define ROOT_MathX_GenVectorX_RotationZYXfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a rotation represented by a 3-2-1 (Z-Y-X) Euler angles + */ + +class RotationZYX; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_Rotation3Dfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZfwd.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZfwd.h new file mode 100644 index 0000000000000..29cc6beeda827 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZfwd.h @@ -0,0 +1,22 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_GenVectorX_RotationZfwd +#define ROOT_MathX_GenVectorX_RotationZfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + /** + Class describing a rotation about the Z axis + */ + +class RotationZ; + +} // namespace Math +} // namespace ROOT + +#endif // ROOT_MathX_GenVectorX_RotationZfwd diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Transform3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Transform3D.h new file mode 100644 index 0000000000000..0189cdd23ddca --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Transform3D.h @@ -0,0 +1,1324 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Transform3D +// +// Created by: Lorenzo Moneta October 21 2005 +// +// +#ifndef ROOT_MathX_GenVectorX_Transform3D +#define ROOT_MathX_GenVectorX_Transform3D 1 + + + +#include "MathX/GenVectorX/DisplacementVector3D.h" + +#include "MathX/GenVectorX/PositionVector3D.h" + +#include "MathX/GenVectorX/Rotation3D.h" + +#include "MathX/GenVectorX/Translation3D.h" + + +#include "MathX/GenVectorX/AxisAnglefwd.h" +#include "MathX/GenVectorX/EulerAnglesfwd.h" +#include "MathX/GenVectorX/Quaternionfwd.h" +#include "MathX/GenVectorX/RotationZYXfwd.h" +#include "MathX/GenVectorX/RotationXfwd.h" +#include "MathX/GenVectorX/RotationYfwd.h" +#include "MathX/GenVectorX/RotationZfwd.h" + +#include +#include +#include + +//#include "MathX/Vector3Dfwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +namespace Impl { + +//_________________________________________________________________________________________ +/** + Basic 3D Transformation class describing a rotation and then a translation + The internal data are a 3D rotation data (represented as a 3x3 matrix) and a 3D vector data. + They are represented and held in this class like a 3x4 matrix (a simple array of 12 numbers). + + The class can be constructed from any 3D rotation object + (ROOT::Math::Rotation3D, ROOT::Math::AxisAngle, ROOT::Math::Quaternion, etc...) and/or + a 3D Vector (ROOT::Math::DislacementVector3D or via ROOT::Math::Translation ) representing a Translation. + The Transformation is defined by applying first the rotation and then the translation. + A transformation defined by applying first a translation and then a rotation is equivalent to the + transformation obtained applying first the rotation and then a translation equivalent to the rotated vector. + The operator * can be used to obtain directly such transformations, in addition to combine various + transformations. + Keep in mind that the operator * (like in the case of rotations ) is not commutative. + The operator * is used (in addition to operator() ) to apply a transformations on the vector + (DisplacementVector3D and LorentzVector classes) and point (PositionVector3D) classes. + In the case of Vector objects the transformation only rotates them and does not translate them. + Only Point objects are able to be both rotated and translated. + + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + +*/ + +template +class Transform3D { + +public: + typedef T Scalar; + + typedef DisplacementVector3D, DefaultCoordinateSystemTag> Vector; + typedef PositionVector3D, DefaultCoordinateSystemTag> Point; + + enum ETransform3DMatrixIndex { + kXX = 0, kXY = 1, kXZ = 2, kDX = 3, + kYX = 4, kYY = 5, kYZ = 6, kDY = 7, + kZX = 8, kZY = 9, kZZ =10, kDZ = 11 + }; + + + + /** + Default constructor (identy rotation) + zero translation + */ + Transform3D() + { + SetIdentity(); + } + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of 12 Scalars + */ + template + Transform3D(IT begin, IT end) + { + SetComponents(begin,end); + } + + /** + Construct from a rotation and then a translation described by a Vector + */ + Transform3D( const Rotation3D & r, const Vector & v) + { + AssignFrom( r, v ); + } + /** + Construct from a rotation and then a translation described by a Translation3D class + */ + Transform3D(const Rotation3D &r, const Translation3D &t) { AssignFrom(r, t.Vect()); } + + /** + Construct from a rotation (any rotation object) and then a translation + (represented by any DisplacementVector) + The requirements on the rotation and vector objects are that they can be transformed in a + Rotation3D class and in a Cartesian3D Vector + */ + template + Transform3D( const ARotation & r, const DisplacementVector3D & v) + { + AssignFrom( Rotation3D(r), Vector (v.X(),v.Y(),v.Z()) ); + } + + /** + Construct from a rotation (any rotation object) and then a translation + represented by a Translation3D class + The requirements on the rotation is that it can be transformed in a + Rotation3D class + */ + template + Transform3D(const ARotation &r, const Translation3D &t) + { + AssignFrom( Rotation3D(r), t.Vect() ); + } + + +#ifdef OLD_VERSION + /** + Construct from a translation and then a rotation (inverse assignment) + */ + Transform3D( const Vector & v, const Rotation3D & r) + { + // is equivalent from having first the rotation and then the translation vector rotated + AssignFrom( r, r(v) ); + } +#endif + + /** + Construct from a 3D Rotation only with zero translation + */ + explicit Transform3D( const Rotation3D & r) { + AssignFrom(r); + } + + // convenience methods for constructing a Transform3D from all the 3D rotations classes + // (cannot use templates for conflict with LA) + + explicit Transform3D( const AxisAngle & r) { + AssignFrom(Rotation3D(r)); + } + explicit Transform3D( const EulerAngles & r) { + AssignFrom(Rotation3D(r)); + } + explicit Transform3D( const Quaternion & r) { + AssignFrom(Rotation3D(r)); + } + explicit Transform3D( const RotationZYX & r) { + AssignFrom(Rotation3D(r)); + } + + // Constructors from axial rotations + // TO DO: implement direct methods for axial rotations without going through Rotation3D + explicit Transform3D( const RotationX & r) { + AssignFrom(Rotation3D(r)); + } + explicit Transform3D( const RotationY & r) { + AssignFrom(Rotation3D(r)); + } + explicit Transform3D( const RotationZ & r) { + AssignFrom(Rotation3D(r)); + } + + /** + Construct from a translation only, represented by any DisplacementVector3D + and with an identity rotation + */ + template + explicit Transform3D( const DisplacementVector3D & v) { + AssignFrom(Vector(v.X(),v.Y(),v.Z())); + } + /** + Construct from a translation only, represented by a Cartesian 3D Vector, + and with an identity rotation + */ + explicit Transform3D( const Vector & v) { + AssignFrom(v); + } + /** + Construct from a translation only, represented by a Translation3D class + and with an identity rotation + */ + explicit Transform3D(const Translation3D &t) { AssignFrom(t.Vect()); } + + //#if !defined(__MAKECINT__) && !defined(G__DICTIONARY) // this is ambiguous with double * , double * + + +#ifdef OLD_VERSION + /** + Construct from a translation (using any type of DisplacementVector ) + and then a rotation (any rotation object). + Requirement on the rotation and vector objects are that they can be transformed in a + Rotation3D class and in a Vector + */ + template + Transform3D(const DisplacementVector3D & v , const ARotation & r) + { + // is equivalent from having first the rotation and then the translation vector rotated + Rotation3D r3d(r); + AssignFrom( r3d, r3d( Vector(v.X(),v.Y(),v.Z()) ) ); + } +#endif + +public: + /** + Construct transformation from one coordinate system defined by three + points (origin + two axis) to + a new coordinate system defined by other three points (origin + axis) + Scalar version. + @param fr0 point defining origin of original reference system + @param fr1 point defining first axis of original reference system + @param fr2 point defining second axis of original reference system + @param to0 point defining origin of transformed reference system + @param to1 point defining first axis transformed reference system + @param to2 point defining second axis transformed reference system + */ + template ::value>::type * = nullptr> + Transform3D(const Point &fr0, const Point &fr1, const Point &fr2, const Point &to0, const Point &to1, + const Point &to2) + { + // takes impl. from CLHEP ( E.Chernyaev). To be checked + + Vector x1 = (fr1 - fr0).Unit(); + Vector y1 = (fr2 - fr0).Unit(); + Vector x2 = (to1 - to0).Unit(); + Vector y2 = (to2 - to0).Unit(); + + // C H E C K A N G L E S + + const T cos1 = x1.Dot(y1); + const T cos2 = x2.Dot(y2); + + if (std::fabs(T(1) - cos1) <= T(0.000001) || std::fabs(T(1) - cos2) <= T(0.000001)) { + std::cerr << "Transform3D: Error : zero angle between axes" << std::endl; + SetIdentity(); + } else { + if (std::fabs(cos1 - cos2) > T(0.000001)) { + std::cerr << "Transform3D: Warning: angles between axes are not equal" << std::endl; + } + + // F I N D R O T A T I O N M A T R I X + + Vector z1 = (x1.Cross(y1)).Unit(); + y1 = z1.Cross(x1); + + Vector z2 = (x2.Cross(y2)).Unit(); + y2 = z2.Cross(x2); + + T x1x = x1.x(); + T x1y = x1.y(); + T x1z = x1.z(); + T y1x = y1.x(); + T y1y = y1.y(); + T y1z = y1.z(); + T z1x = z1.x(); + T z1y = z1.y(); + T z1z = z1.z(); + + T x2x = x2.x(); + T x2y = x2.y(); + T x2z = x2.z(); + T y2x = y2.x(); + T y2y = y2.y(); + T y2z = y2.z(); + T z2x = z2.x(); + T z2y = z2.y(); + T z2z = z2.z(); + + T detxx = (y1y * z1z - z1y * y1z); + T detxy = -(y1x * z1z - z1x * y1z); + T detxz = (y1x * z1y - z1x * y1y); + T detyx = -(x1y * z1z - z1y * x1z); + T detyy = (x1x * z1z - z1x * x1z); + T detyz = -(x1x * z1y - z1x * x1y); + T detzx = (x1y * y1z - y1y * x1z); + T detzy = -(x1x * y1z - y1x * x1z); + T detzz = (x1x * y1y - y1x * x1y); + + T txx = x2x * detxx + y2x * detyx + z2x * detzx; + T txy = x2x * detxy + y2x * detyy + z2x * detzy; + T txz = x2x * detxz + y2x * detyz + z2x * detzz; + T tyx = x2y * detxx + y2y * detyx + z2y * detzx; + T tyy = x2y * detxy + y2y * detyy + z2y * detzy; + T tyz = x2y * detxz + y2y * detyz + z2y * detzz; + T tzx = x2z * detxx + y2z * detyx + z2z * detzx; + T tzy = x2z * detxy + y2z * detyy + z2z * detzy; + T tzz = x2z * detxz + y2z * detyz + z2z * detzz; + + // S E T T R A N S F O R M A T I O N + + T dx1 = fr0.x(), dy1 = fr0.y(), dz1 = fr0.z(); + T dx2 = to0.x(), dy2 = to0.y(), dz2 = to0.z(); + + SetComponents(txx, txy, txz, dx2 - txx * dx1 - txy * dy1 - txz * dz1, tyx, tyy, tyz, + dy2 - tyx * dx1 - tyy * dy1 - tyz * dz1, tzx, tzy, tzz, dz2 - tzx * dx1 - tzy * dy1 - tzz * dz1); + } + } + + /** + Construct transformation from one coordinate system defined by three + points (origin + two axis) to + a new coordinate system defined by other three points (origin + axis) + Vectorised version. + @param fr0 point defining origin of original reference system + @param fr1 point defining first axis of original reference system + @param fr2 point defining second axis of original reference system + @param to0 point defining origin of transformed reference system + @param to1 point defining first axis transformed reference system + @param to2 point defining second axis transformed reference system + */ + template ::value>::type * = nullptr> + Transform3D(const Point &fr0, const Point &fr1, const Point &fr2, const Point &to0, const Point &to1, + const Point &to2) + { + // takes impl. from CLHEP ( E.Chernyaev). To be checked + + Vector x1 = (fr1 - fr0).Unit(); + Vector y1 = (fr2 - fr0).Unit(); + Vector x2 = (to1 - to0).Unit(); + Vector y2 = (to2 - to0).Unit(); + + // C H E C K A N G L E S + + const T cos1 = x1.Dot(y1); + const T cos2 = x2.Dot(y2); + + const auto m1 = (abs(T(1) - cos1) <= T(0.000001) || abs(T(1) - cos2) <= T(0.000001)); + + const auto m2 = (abs(cos1 - cos2) > T(0.000001)); + if (any_of(m2)) { + std::cerr << "Transform3D: Warning: angles between axes are not equal" << std::endl; + } + + // F I N D R O T A T I O N M A T R I X + + Vector z1 = (x1.Cross(y1)).Unit(); + y1 = z1.Cross(x1); + + Vector z2 = (x2.Cross(y2)).Unit(); + y2 = z2.Cross(x2); + + T x1x = x1.x(); + T x1y = x1.y(); + T x1z = x1.z(); + T y1x = y1.x(); + T y1y = y1.y(); + T y1z = y1.z(); + T z1x = z1.x(); + T z1y = z1.y(); + T z1z = z1.z(); + + T x2x = x2.x(); + T x2y = x2.y(); + T x2z = x2.z(); + T y2x = y2.x(); + T y2y = y2.y(); + T y2z = y2.z(); + T z2x = z2.x(); + T z2y = z2.y(); + T z2z = z2.z(); + + T detxx = (y1y * z1z - z1y * y1z); + T detxy = -(y1x * z1z - z1x * y1z); + T detxz = (y1x * z1y - z1x * y1y); + T detyx = -(x1y * z1z - z1y * x1z); + T detyy = (x1x * z1z - z1x * x1z); + T detyz = -(x1x * z1y - z1x * x1y); + T detzx = (x1y * y1z - y1y * x1z); + T detzy = -(x1x * y1z - y1x * x1z); + T detzz = (x1x * y1y - y1x * x1y); + + T txx = x2x * detxx + y2x * detyx + z2x * detzx; + T txy = x2x * detxy + y2x * detyy + z2x * detzy; + T txz = x2x * detxz + y2x * detyz + z2x * detzz; + T tyx = x2y * detxx + y2y * detyx + z2y * detzx; + T tyy = x2y * detxy + y2y * detyy + z2y * detzy; + T tyz = x2y * detxz + y2y * detyz + z2y * detzz; + T tzx = x2z * detxx + y2z * detyx + z2z * detzx; + T tzy = x2z * detxy + y2z * detyy + z2z * detzy; + T tzz = x2z * detxz + y2z * detyz + z2z * detzz; + + // S E T T R A N S F O R M A T I O N + + T dx1 = fr0.x(), dy1 = fr0.y(), dz1 = fr0.z(); + T dx2 = to0.x(), dy2 = to0.y(), dz2 = to0.z(); + + SetComponents(txx, txy, txz, dx2 - txx * dx1 - txy * dy1 - txz * dz1, tyx, tyy, tyz, + dy2 - tyx * dx1 - tyy * dy1 - tyz * dz1, tzx, tzy, tzz, dz2 - tzx * dx1 - tzy * dy1 - tzz * dz1); + + if (any_of(m1)) { + std::cerr << "Transform3D: Error : zero angle between axes" << std::endl; + SetIdentity(m1); + } + } + + // use compiler generated copy ctor, copy assignment and destructor + + /** + Construct from a linear algebra matrix of size at least 3x4, + which must support operator()(i,j) to obtain elements (0,0) thru (2,3). + The 3x3 sub-block is assumed to be the rotation part and the translations vector + are described by the 4-th column + */ + template + explicit Transform3D(const ForeignMatrix & m) { + SetComponents(m); + } + + /** + Raw constructor from 12 Scalar components + */ + Transform3D(T xx, T xy, T xz, T dx, T yx, T yy, T yz, T dy, T zx, T zy, T zz, T dz) + { + SetComponents (xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz); + } + + + /** + Construct from a linear algebra matrix of size at least 3x4, + which must support operator()(i,j) to obtain elements (0,0) thru (2,3). + The 3x3 sub-block is assumed to be the rotation part and the translations vector + are described by the 4-th column + */ + template + Transform3D &operator=(const ForeignMatrix &m) + { + SetComponents(m); + return *this; + } + + + // ======== Components ============== + + + /** + Set the 12 matrix components given an iterator to the start of + the desired data, and another to the end (12 past start). + */ + template + void SetComponents(IT begin, IT end) { + for (int i = 0; i <12; ++i) { + fM[i] = *begin; + ++begin; + } + (void)end; + assert (end==begin); + } + + /** + Get the 12 matrix components into data specified by an iterator begin + and another to the end of the desired data (12 past start). + */ + template + void GetComponents(IT begin, IT end) const { + for (int i = 0; i <12; ++i) { + *begin = fM[i]; + ++begin; + } + (void)end; + assert (end==begin); + } + + /** + Get the 12 matrix components into data specified by an iterator begin + */ + template + void GetComponents(IT begin) const { + std::copy(fM, fM + 12, begin); + } + + /** + Set components from a linear algebra matrix of size at least 3x4, + which must support operator()(i,j) to obtain elements (0,0) thru (2,3). + The 3x3 sub-block is assumed to be the rotation part and the translations vector + are described by the 4-th column + */ + template + void + SetTransformMatrix (const ForeignMatrix & m) { + fM[kXX]=m(0,0); fM[kXY]=m(0,1); fM[kXZ]=m(0,2); fM[kDX]=m(0,3); + fM[kYX]=m(1,0); fM[kYY]=m(1,1); fM[kYZ]=m(1,2); fM[kDY]=m(1,3); + fM[kZX]=m(2,0); fM[kZY]=m(2,1); fM[kZZ]=m(2,2); fM[kDZ]=m(2,3); + } + + /** + Get components into a linear algebra matrix of size at least 3x4, + which must support operator()(i,j) for write access to elements + (0,0) thru (2,3). + */ + template + void + GetTransformMatrix (ForeignMatrix & m) const { + m(0,0)=fM[kXX]; m(0,1)=fM[kXY]; m(0,2)=fM[kXZ]; m(0,3)=fM[kDX]; + m(1,0)=fM[kYX]; m(1,1)=fM[kYY]; m(1,2)=fM[kYZ]; m(1,3)=fM[kDY]; + m(2,0)=fM[kZX]; m(2,1)=fM[kZY]; m(2,2)=fM[kZZ]; m(2,3)=fM[kDZ]; + } + + + /** + Set the components from 12 scalars + */ + void SetComponents(T xx, T xy, T xz, T dx, T yx, T yy, T yz, T dy, T zx, T zy, T zz, T dz) + { + fM[kXX]=xx; fM[kXY]=xy; fM[kXZ]=xz; fM[kDX]=dx; + fM[kYX]=yx; fM[kYY]=yy; fM[kYZ]=yz; fM[kDY]=dy; + fM[kZX]=zx; fM[kZY]=zy; fM[kZZ]=zz; fM[kDZ]=dz; + } + + /** + Get the components into 12 scalars + */ + void GetComponents(T &xx, T &xy, T &xz, T &dx, T &yx, T &yy, T &yz, T &dy, T &zx, T &zy, T &zz, T &dz) const + { + xx=fM[kXX]; xy=fM[kXY]; xz=fM[kXZ]; dx=fM[kDX]; + yx=fM[kYX]; yy=fM[kYY]; yz=fM[kYZ]; dy=fM[kDY]; + zx=fM[kZX]; zy=fM[kZY]; zz=fM[kZZ]; dz=fM[kDZ]; + } + + + /** + Get the rotation and translation vector representing the 3D transformation + in any rotation and any vector (the Translation class could also be used) + */ + template + void GetDecomposition(AnyRotation &r, V &v) const { + GetRotation(r); + GetTranslation(v); + } + + + /** + Get the rotation and translation vector representing the 3D transformation + */ + void GetDecomposition(Rotation3D &r, Vector &v) const { + GetRotation(r); + GetTranslation(v); + } + + /** + Get the 3D rotation representing the 3D transformation + */ + Rotation3D Rotation() const { + return Rotation3D( fM[kXX], fM[kXY], fM[kXZ], + fM[kYX], fM[kYY], fM[kYZ], + fM[kZX], fM[kZY], fM[kZZ] ); + } + + /** + Get the rotation representing the 3D transformation + */ + template + AnyRotation Rotation() const { + return AnyRotation(Rotation3D(fM[kXX], fM[kXY], fM[kXZ], fM[kYX], fM[kYY], fM[kYZ], fM[kZX], fM[kZY], fM[kZZ])); + } + + /** + Get the rotation (any type) representing the 3D transformation + */ + template + void GetRotation(AnyRotation &r) const { + r = Rotation(); + } + + /** + Get the translation representing the 3D transformation in a Cartesian vector + */ + Translation3D Translation() const { return Translation3D(fM[kDX], fM[kDY], fM[kDZ]); } + + /** + Get the translation representing the 3D transformation in any vector + which implements the SetXYZ method + */ + template + void GetTranslation(AnyVector &v) const { + v.SetXYZ(fM[kDX], fM[kDY], fM[kDZ]); + } + + + + // operations on points and vectors + + /** + Transformation operation for Position Vector in Cartesian coordinate + For a Position Vector first a rotation and then a translation is applied + */ + Point operator() (const Point & p) const { + return Point ( fM[kXX]*p.X() + fM[kXY]*p.Y() + fM[kXZ]*p.Z() + fM[kDX], + fM[kYX]*p.X() + fM[kYY]*p.Y() + fM[kYZ]*p.Z() + fM[kDY], + fM[kZX]*p.X() + fM[kZY]*p.Y() + fM[kZZ]*p.Z() + fM[kDZ] ); + } + + + /** + Transformation operation for Displacement Vectors in Cartesian coordinate + For the Displacement Vectors only the rotation applies - no translations + */ + Vector operator() (const Vector & v) const { + return Vector( fM[kXX]*v.X() + fM[kXY]*v.Y() + fM[kXZ]*v.Z() , + fM[kYX]*v.X() + fM[kYY]*v.Y() + fM[kYZ]*v.Z() , + fM[kZX]*v.X() + fM[kZY]*v.Y() + fM[kZZ]*v.Z() ); + } + + + /** + Transformation operation for Position Vector in any coordinate system + */ + template + PositionVector3D operator()(const PositionVector3D &p) const + { + return PositionVector3D(operator()(Point(p))); + } + /** + Transformation operation for Position Vector in any coordinate system + */ + template + PositionVector3D operator*(const PositionVector3D &v) const + { + return operator()(v); + } + + /** + Transformation operation for Displacement Vector in any coordinate system + */ + template + DisplacementVector3D operator() (const DisplacementVector3D & v) const { + return DisplacementVector3D(operator()(Vector(v))); + } + /** + Transformation operation for Displacement Vector in any coordinate system + */ + template + DisplacementVector3D operator*(const DisplacementVector3D &v) const + { + return operator()(v); + } + + /** + Directly apply the inverse affine transformation on vectors. + Avoids having to calculate the inverse as an intermediate result. + This is possible since the inverse of a rotation is its transpose. + */ + Vector ApplyInverse(const Vector &v) const + { + return Vector(fM[kXX] * v.X() + fM[kYX] * v.Y() + fM[kZX] * v.Z(), + fM[kXY] * v.X() + fM[kYY] * v.Y() + fM[kZY] * v.Z(), + fM[kXZ] * v.X() + fM[kYZ] * v.Y() + fM[kZZ] * v.Z()); + } + + /** + Directly apply the inverse affine transformation on points + (first inverse translation then inverse rotation). + Avoids having to calculate the inverse as an intermediate result. + This is possible since the inverse of a rotation is its transpose. + */ + Point ApplyInverse(const Point &p) const + { + Point tmp(p.X() - fM[kDX], p.Y() - fM[kDY], p.Z() - fM[kDZ]); + return Point(fM[kXX] * tmp.X() + fM[kYX] * tmp.Y() + fM[kZX] * tmp.Z(), + fM[kXY] * tmp.X() + fM[kYY] * tmp.Y() + fM[kZY] * tmp.Z(), + fM[kXZ] * tmp.X() + fM[kYZ] * tmp.Y() + fM[kZZ] * tmp.Z()); + } + + /** + Directly apply the inverse affine transformation on an arbitrary + coordinate-system point. + Involves casting to Point(p) type. + */ + template + PositionVector3D ApplyInverse(const PositionVector3D &p) const + { + return PositionVector3D(ApplyInverse(Point(p))); + } + + /** + Directly apply the inverse affine transformation on an arbitrary + coordinate-system vector. + Involves casting to Vector(p) type. + */ + template + DisplacementVector3D ApplyInverse(const DisplacementVector3D &p) const + { + return DisplacementVector3D(ApplyInverse(Vector(p))); + } + + /** + Transformation operation for points between different coordinate system tags + */ + template + void Transform(const PositionVector3D &p1, PositionVector3D &p2) const + { + const Point xyzNew = operator()(Point(p1.X(), p1.Y(), p1.Z())); + p2.SetXYZ( xyzNew.X(), xyzNew.Y(), xyzNew.Z() ); + } + + + /** + Transformation operation for Displacement Vector of different coordinate systems + */ + template + void Transform(const DisplacementVector3D &v1, DisplacementVector3D &v2) const + { + const Vector xyzNew = operator()(Vector(v1.X(), v1.Y(), v1.Z())); + v2.SetXYZ( xyzNew.X(), xyzNew.Y(), xyzNew.Z() ); + } + + /** + Transformation operation for a Lorentz Vector in any coordinate system + */ + template + LorentzVector operator() (const LorentzVector & q) const { + const Vector xyzNew = operator()(Vector(q.Vect())); + return LorentzVector(xyzNew.X(), xyzNew.Y(), xyzNew.Z(), q.E()); + } + /** + Transformation operation for a Lorentz Vector in any coordinate system + */ + template + LorentzVector operator*(const LorentzVector &q) const + { + return operator()(q); + } + + /** + Transformation on a 3D plane + */ + template + Plane3D operator()(const Plane3D &plane) const + { + // transformations on a 3D plane + const auto n = plane.Normal(); + // take a point on the plane. Use origin projection on the plane + // ( -ad, -bd, -cd) if (a**2 + b**2 + c**2 ) = 1 + const auto d = plane.HesseDistance(); + Point p(-d * n.X(), -d * n.Y(), -d * n.Z()); + return Plane3D(operator()(n), operator()(p)); + } + + /// Multiplication operator for 3D plane + template + Plane3D operator*(const Plane3D &plane) const + { + return operator()(plane); + } + + // skip transformation for arbitrary vectors - not really defined if point or displacement vectors + + /** + multiply (combine) with another transformation in place + */ + inline Transform3D &operator*=(const Transform3D &t); + + /** + multiply (combine) two transformations + */ + inline Transform3D operator*(const Transform3D &t) const; + + /** + Invert the transformation in place (scalar) + */ + template ::value>::type * = nullptr> + void Invert() + { + // + // Name: Transform3D::inverse Date: 24.09.96 + // Author: E.Chernyaev (IHEP/Protvino) Revised: + // + // Function: Find inverse affine transformation. + + T detxx = fM[kYY] * fM[kZZ] - fM[kYZ] * fM[kZY]; + T detxy = fM[kYX] * fM[kZZ] - fM[kYZ] * fM[kZX]; + T detxz = fM[kYX] * fM[kZY] - fM[kYY] * fM[kZX]; + T det = fM[kXX] * detxx - fM[kXY] * detxy + fM[kXZ] * detxz; + if (det == T(0)) { + std::cerr << "Transform3D::inverse error: zero determinant" << std::endl; + return; + } + det = T(1) / det; + detxx *= det; + detxy *= det; + detxz *= det; + T detyx = (fM[kXY] * fM[kZZ] - fM[kXZ] * fM[kZY]) * det; + T detyy = (fM[kXX] * fM[kZZ] - fM[kXZ] * fM[kZX]) * det; + T detyz = (fM[kXX] * fM[kZY] - fM[kXY] * fM[kZX]) * det; + T detzx = (fM[kXY] * fM[kYZ] - fM[kXZ] * fM[kYY]) * det; + T detzy = (fM[kXX] * fM[kYZ] - fM[kXZ] * fM[kYX]) * det; + T detzz = (fM[kXX] * fM[kYY] - fM[kXY] * fM[kYX]) * det; + SetComponents(detxx, -detyx, detzx, -detxx * fM[kDX] + detyx * fM[kDY] - detzx * fM[kDZ], -detxy, detyy, -detzy, + detxy * fM[kDX] - detyy * fM[kDY] + detzy * fM[kDZ], detxz, -detyz, detzz, + -detxz * fM[kDX] + detyz * fM[kDY] - detzz * fM[kDZ]); + } + + /** + Invert the transformation in place (vectorised) + */ + template ::value>::type * = nullptr> + void Invert() + { + // + // Name: Transform3D::inverse Date: 24.09.96 + // Author: E.Chernyaev (IHEP/Protvino) Revised: + // + // Function: Find inverse affine transformation. + + T detxx = fM[kYY] * fM[kZZ] - fM[kYZ] * fM[kZY]; + T detxy = fM[kYX] * fM[kZZ] - fM[kYZ] * fM[kZX]; + T detxz = fM[kYX] * fM[kZY] - fM[kYY] * fM[kZX]; + T det = fM[kXX] * detxx - fM[kXY] * detxy + fM[kXZ] * detxz; + const auto detZmask = (det == T(0)); + if (any_of(detZmask)) { + std::cerr << "Transform3D::inverse error: zero determinant" << std::endl; + det(detZmask) = T(1); + } + det = T(1) / det; + detxx *= det; + detxy *= det; + detxz *= det; + T detyx = (fM[kXY] * fM[kZZ] - fM[kXZ] * fM[kZY]) * det; + T detyy = (fM[kXX] * fM[kZZ] - fM[kXZ] * fM[kZX]) * det; + T detyz = (fM[kXX] * fM[kZY] - fM[kXY] * fM[kZX]) * det; + T detzx = (fM[kXY] * fM[kYZ] - fM[kXZ] * fM[kYY]) * det; + T detzy = (fM[kXX] * fM[kYZ] - fM[kXZ] * fM[kYX]) * det; + T detzz = (fM[kXX] * fM[kYY] - fM[kXY] * fM[kYX]) * det; + // Set det=0 cases to 0 + if (any_of(detZmask)) { + detxx(detZmask) = T(0); + detxy(detZmask) = T(0); + detxz(detZmask) = T(0); + detyx(detZmask) = T(0); + detyy(detZmask) = T(0); + detyz(detZmask) = T(0); + detzx(detZmask) = T(0); + detzy(detZmask) = T(0); + detzz(detZmask) = T(0); + } + // set final components + SetComponents(detxx, -detyx, detzx, -detxx * fM[kDX] + detyx * fM[kDY] - detzx * fM[kDZ], -detxy, detyy, -detzy, + detxy * fM[kDX] - detyy * fM[kDY] + detzy * fM[kDZ], detxz, -detyz, detzz, + -detxz * fM[kDX] + detyz * fM[kDY] - detzz * fM[kDZ]); + } + + /** + Return the inverse of the transformation. + */ + Transform3D Inverse() const + { + Transform3D t(*this); + t.Invert(); + return t; + } + + /** + Equality operator. Check equality for each element + To do: use T tolerance + */ + bool operator==(const Transform3D &rhs) const + { + return (fM[0] == rhs.fM[0] && fM[1] == rhs.fM[1] && fM[2] == rhs.fM[2] && fM[3] == rhs.fM[3] && + fM[4] == rhs.fM[4] && fM[5] == rhs.fM[5] && fM[6] == rhs.fM[6] && fM[7] == rhs.fM[7] && + fM[8] == rhs.fM[8] && fM[9] == rhs.fM[9] && fM[10] == rhs.fM[10] && fM[11] == rhs.fM[11]); + } + + /** + Inequality operator. Check equality for each element + To do: use T tolerance + */ + bool operator!=(const Transform3D &rhs) const { return !operator==(rhs); } + +protected: + + /** + make transformation from first a rotation then a translation + */ + void AssignFrom(const Rotation3D &r, const Vector &v) + { + // assignment from rotation + translation + + T rotData[9]; + r.GetComponents(rotData, rotData + 9); + // first raw + for (int i = 0; i < 3; ++i) fM[i] = rotData[i]; + // second raw + for (int i = 0; i < 3; ++i) fM[kYX + i] = rotData[3 + i]; + // third raw + for (int i = 0; i < 3; ++i) fM[kZX + i] = rotData[6 + i]; + + // translation data + T vecData[3]; + v.GetCoordinates(vecData, vecData + 3); + fM[kDX] = vecData[0]; + fM[kDY] = vecData[1]; + fM[kDZ] = vecData[2]; + } + + /** + make transformation from only rotations (zero translation) + */ + void AssignFrom(const Rotation3D &r) + { + // assign from only a rotation (null translation) + T rotData[9]; + r.GetComponents(rotData, rotData + 9); + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) fM[4 * i + j] = rotData[3 * i + j]; + // empty vector data + fM[4 * i + 3] = T(0); + } + } + + /** + make transformation from only translation (identity rotations) + */ + void AssignFrom(const Vector &v) + { + // assign from a translation only (identity rotations) + fM[kXX] = T(1); + fM[kXY] = T(0); + fM[kXZ] = T(0); + fM[kDX] = v.X(); + fM[kYX] = T(0); + fM[kYY] = T(1); + fM[kYZ] = T(0); + fM[kDY] = v.Y(); + fM[kZX] = T(0); + fM[kZY] = T(0); + fM[kZZ] = T(1); + fM[kDZ] = v.Z(); + } + + /** + Set identity transformation (identity rotation , zero translation) + */ + void SetIdentity() + { + // set identity ( identity rotation and zero translation) + fM[kXX] = T(1); + fM[kXY] = T(0); + fM[kXZ] = T(0); + fM[kDX] = T(0); + fM[kYX] = T(0); + fM[kYY] = T(1); + fM[kYZ] = T(0); + fM[kDY] = T(0); + fM[kZX] = T(0); + fM[kZY] = T(0); + fM[kZZ] = T(1); + fM[kDZ] = T(0); + } + + /** + Set identity transformation (identity rotation , zero translation) + vectorised version that sets using a mask + */ + template ::value>::type * = nullptr> + void SetIdentity(const typename SCALAR::mask_type m) + { + // set identity ( identity rotation and zero translation) + fM[kXX](m) = T(1); + fM[kXY](m) = T(0); + fM[kXZ](m) = T(0); + fM[kDX](m) = T(0); + fM[kYX](m) = T(0); + fM[kYY](m) = T(1); + fM[kYZ](m) = T(0); + fM[kDY](m) = T(0); + fM[kZX](m) = T(0); + fM[kZY](m) = T(0); + fM[kZZ](m) = T(1); + fM[kDZ](m) = T(0); + } + +private: + T fM[12]; // transformation elements (3x4 matrix) +}; + + + + +// inline functions (combination of transformations) + +template +inline Transform3D &Transform3D::operator*=(const Transform3D &t) +{ + // combination of transformations + + SetComponents(fM[kXX]*t.fM[kXX]+fM[kXY]*t.fM[kYX]+fM[kXZ]*t.fM[kZX], + fM[kXX]*t.fM[kXY]+fM[kXY]*t.fM[kYY]+fM[kXZ]*t.fM[kZY], + fM[kXX]*t.fM[kXZ]+fM[kXY]*t.fM[kYZ]+fM[kXZ]*t.fM[kZZ], + fM[kXX]*t.fM[kDX]+fM[kXY]*t.fM[kDY]+fM[kXZ]*t.fM[kDZ]+fM[kDX], + + fM[kYX]*t.fM[kXX]+fM[kYY]*t.fM[kYX]+fM[kYZ]*t.fM[kZX], + fM[kYX]*t.fM[kXY]+fM[kYY]*t.fM[kYY]+fM[kYZ]*t.fM[kZY], + fM[kYX]*t.fM[kXZ]+fM[kYY]*t.fM[kYZ]+fM[kYZ]*t.fM[kZZ], + fM[kYX]*t.fM[kDX]+fM[kYY]*t.fM[kDY]+fM[kYZ]*t.fM[kDZ]+fM[kDY], + + fM[kZX]*t.fM[kXX]+fM[kZY]*t.fM[kYX]+fM[kZZ]*t.fM[kZX], + fM[kZX]*t.fM[kXY]+fM[kZY]*t.fM[kYY]+fM[kZZ]*t.fM[kZY], + fM[kZX]*t.fM[kXZ]+fM[kZY]*t.fM[kYZ]+fM[kZZ]*t.fM[kZZ], + fM[kZX]*t.fM[kDX]+fM[kZY]*t.fM[kDY]+fM[kZZ]*t.fM[kDZ]+fM[kDZ]); + + return *this; +} + +template +inline Transform3D Transform3D::operator*(const Transform3D &t) const +{ + // combination of transformations + + return Transform3D(fM[kXX] * t.fM[kXX] + fM[kXY] * t.fM[kYX] + fM[kXZ] * t.fM[kZX], + fM[kXX] * t.fM[kXY] + fM[kXY] * t.fM[kYY] + fM[kXZ] * t.fM[kZY], + fM[kXX] * t.fM[kXZ] + fM[kXY] * t.fM[kYZ] + fM[kXZ] * t.fM[kZZ], + fM[kXX] * t.fM[kDX] + fM[kXY] * t.fM[kDY] + fM[kXZ] * t.fM[kDZ] + fM[kDX], + + fM[kYX] * t.fM[kXX] + fM[kYY] * t.fM[kYX] + fM[kYZ] * t.fM[kZX], + fM[kYX] * t.fM[kXY] + fM[kYY] * t.fM[kYY] + fM[kYZ] * t.fM[kZY], + fM[kYX] * t.fM[kXZ] + fM[kYY] * t.fM[kYZ] + fM[kYZ] * t.fM[kZZ], + fM[kYX] * t.fM[kDX] + fM[kYY] * t.fM[kDY] + fM[kYZ] * t.fM[kDZ] + fM[kDY], + + fM[kZX] * t.fM[kXX] + fM[kZY] * t.fM[kYX] + fM[kZZ] * t.fM[kZX], + fM[kZX] * t.fM[kXY] + fM[kZY] * t.fM[kYY] + fM[kZZ] * t.fM[kZY], + fM[kZX] * t.fM[kXZ] + fM[kZY] * t.fM[kYZ] + fM[kZZ] * t.fM[kZZ], + fM[kZX] * t.fM[kDX] + fM[kZY] * t.fM[kDY] + fM[kZZ] * t.fM[kDZ] + fM[kDZ]); +} + + + + +//--- global functions resulting in Transform3D ------- + + +// ------ combination of a translation (first) and a rotation ------ + + +/** + combine a translation and a rotation to give a transform3d + First the translation then the rotation + */ +template +inline Transform3D operator*(const Rotation3D &r, const Translation3D &t) +{ + return Transform3D(r, r(t.Vect())); +} +template +inline Transform3D operator*(const RotationX &r, const Translation3D &t) +{ + Rotation3D r3(r); + return Transform3D(r3, r3(t.Vect())); +} +template +inline Transform3D operator*(const RotationY &r, const Translation3D &t) +{ + Rotation3D r3(r); + return Transform3D(r3, r3(t.Vect())); +} +template +inline Transform3D operator*(const RotationZ &r, const Translation3D &t) +{ + Rotation3D r3(r); + return Transform3D(r3, r3(t.Vect())); +} +template +inline Transform3D operator*(const RotationZYX &r, const Translation3D &t) +{ + Rotation3D r3(r); + return Transform3D(r3, r3(t.Vect())); +} +template +inline Transform3D operator*(const AxisAngle &r, const Translation3D &t) +{ + Rotation3D r3(r); + return Transform3D(r3, r3(t.Vect())); +} +template +inline Transform3D operator*(const EulerAngles &r, const Translation3D &t) +{ + Rotation3D r3(r); + return Transform3D(r3, r3(t.Vect())); +} +template +inline Transform3D operator*(const Quaternion &r, const Translation3D &t) +{ + Rotation3D r3(r); + return Transform3D(r3, r3(t.Vect())); +} + +// ------ combination of a rotation (first) and then a translation ------ + +/** + combine a rotation and a translation to give a transform3d + First a rotation then the translation + */ +template +inline Transform3D operator*(const Translation3D &t, const Rotation3D &r) +{ + return Transform3D(r, t.Vect()); +} +template +inline Transform3D operator*(const Translation3D &t, const RotationX &r) +{ + return Transform3D(Rotation3D(r), t.Vect()); +} +template +inline Transform3D operator*(const Translation3D &t, const RotationY &r) +{ + return Transform3D(Rotation3D(r), t.Vect()); +} +template +inline Transform3D operator*(const Translation3D &t, const RotationZ &r) +{ + return Transform3D(Rotation3D(r), t.Vect()); +} +template +inline Transform3D operator*(const Translation3D &t, const RotationZYX &r) +{ + return Transform3D(Rotation3D(r), t.Vect()); +} +template +inline Transform3D operator*(const Translation3D &t, const EulerAngles &r) +{ + return Transform3D(Rotation3D(r), t.Vect()); +} +template +inline Transform3D operator*(const Translation3D &t, const Quaternion &r) +{ + return Transform3D(Rotation3D(r), t.Vect()); +} +template +inline Transform3D operator*(const Translation3D &t, const AxisAngle &r) +{ + return Transform3D(Rotation3D(r), t.Vect()); +} + +// ------ combination of a Transform3D and a pure translation------ + +/** + combine a transformation and a translation to give a transform3d + First the translation then the transform3D + */ +template +inline Transform3D operator*(const Transform3D &t, const Translation3D &d) +{ + Rotation3D r = t.Rotation(); + return Transform3D(r, r(d.Vect()) + t.Translation().Vect()); +} + +/** + combine a translation and a transformation to give a transform3d + First the transformation then the translation + */ +template +inline Transform3D operator*(const Translation3D &d, const Transform3D &t) +{ + return Transform3D(t.Rotation(), t.Translation().Vect() + d.Vect()); +} + +// ------ combination of a Transform3D and any rotation------ + + +/** + combine a transformation and a rotation to give a transform3d + First the rotation then the transform3D + */ +template +inline Transform3D operator*(const Transform3D &t, const Rotation3D &r) +{ + return Transform3D(t.Rotation() * r, t.Translation()); +} +template +inline Transform3D operator*(const Transform3D &t, const RotationX &r) +{ + return Transform3D(t.Rotation() * r, t.Translation()); +} +template +inline Transform3D operator*(const Transform3D &t, const RotationY &r) +{ + return Transform3D(t.Rotation() * r, t.Translation()); +} +template +inline Transform3D operator*(const Transform3D &t, const RotationZ &r) +{ + return Transform3D(t.Rotation() * r, t.Translation()); +} +template +inline Transform3D operator*(const Transform3D &t, const RotationZYX &r) +{ + return Transform3D(t.Rotation() * r, t.Translation()); +} +template +inline Transform3D operator*(const Transform3D &t, const EulerAngles &r) +{ + return Transform3D(t.Rotation() * r, t.Translation()); +} +template +inline Transform3D operator*(const Transform3D &t, const AxisAngle &r) +{ + return Transform3D(t.Rotation() * r, t.Translation()); +} +template +inline Transform3D operator*(const Transform3D &t, const Quaternion &r) +{ + return Transform3D(t.Rotation() * r, t.Translation()); +} + + + +/** + combine a rotation and a transformation to give a transform3d + First the transformation then the rotation + */ +template +inline Transform3D operator*(const Rotation3D &r, const Transform3D &t) +{ + return Transform3D(r * t.Rotation(), r * t.Translation().Vect()); +} +template +inline Transform3D operator*(const RotationX &r, const Transform3D &t) +{ + Rotation3D r3d(r); + return Transform3D(r3d * t.Rotation(), r3d * t.Translation().Vect()); +} +template +inline Transform3D operator*(const RotationY &r, const Transform3D &t) +{ + Rotation3D r3d(r); + return Transform3D(r3d * t.Rotation(), r3d * t.Translation().Vect()); +} +template +inline Transform3D operator*(const RotationZ &r, const Transform3D &t) +{ + Rotation3D r3d(r); + return Transform3D(r3d * t.Rotation(), r3d * t.Translation().Vect()); +} +template +inline Transform3D operator*(const RotationZYX &r, const Transform3D &t) +{ + Rotation3D r3d(r); + return Transform3D(r3d * t.Rotation(), r3d * t.Translation().Vect()); +} +template +inline Transform3D operator*(const EulerAngles &r, const Transform3D &t) +{ + Rotation3D r3d(r); + return Transform3D(r3d * t.Rotation(), r3d * t.Translation().Vect()); +} +template +inline Transform3D operator*(const AxisAngle &r, const Transform3D &t) +{ + Rotation3D r3d(r); + return Transform3D(r3d * t.Rotation(), r3d * t.Translation().Vect()); +} +template +inline Transform3D operator*(const Quaternion &r, const Transform3D &t) +{ + Rotation3D r3d(r); + return Transform3D(r3d * t.Rotation(), r3d * t.Translation().Vect()); +} + + +//---I/O functions +// TODO - I/O should be put in the manipulator form + +/** + print the 12 components of the Transform3D + */ +template +std::ostream &operator<<(std::ostream &os, const Transform3D &t) +{ + // TODO - this will need changing for machine-readable issues + // and even the human readable form needs formatting improvements + + T m[12]; + t.GetComponents(m, m + 12); + os << "\n" << m[0] << " " << m[1] << " " << m[2] << " " << m[3]; + os << "\n" << m[4] << " " << m[5] << " " << m[6] << " " << m[7]; + os << "\n" << m[8] << " " << m[9] << " " << m[10] << " " << m[11] << "\n"; + return os; +} + +} // end namespace Impl + +// typedefs for double and float versions +typedef Impl::Transform3D Transform3D; +typedef Impl::Transform3D Transform3DF; + +} // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_Transform3D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/Translation3D.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/Translation3D.h new file mode 100644 index 0000000000000..30316258217ec --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Translation3D.h @@ -0,0 +1,321 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +/********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Translation3D +// +// Created by: Lorenzo Moneta October 21 2005 +// +// +#ifndef ROOT_MathX_GenVectorX_Translation3D +#define ROOT_MathX_GenVectorX_Translation3D 1 + + +#include "MathX/GenVectorX/DisplacementVector3D.h" + +#include "MathX/GenVectorX/Plane3D.h" + +#include "MathX/GenVectorX/PositionVector3Dfwd.h" + +#include "MathX/GenVectorX/LorentzVectorfwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include +#include + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +namespace Impl { + +//____________________________________________________________________________________________________ +/** + Class describing a 3 dimensional translation. It can be combined (using the operator *) + with the ROOT::Math::Rotation3D classes and ROOT::Math::Transform3D to obtained combined + transformations and to operate on points and vectors. + Note that a the translation applied to a Vector object (DisplacementVector3D and LorentzVector classes) + performs a noop, i.e. it returns the same vector. A translation can be applied only to the Point objects + (PositionVector3D classes). + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + +*/ + +template +class Translation3D { + +public: + typedef T Scalar; + + typedef DisplacementVector3D, DefaultCoordinateSystemTag> Vector; + + /** + Default constructor ( zero translation ) + */ + Translation3D() {} + + /** + Construct given a pair of pointers or iterators defining the + beginning and end of an array of 3 Scalars representing the z,y,z of the translation vector + */ + template + Translation3D(IT begin, IT end) + { + fVect.SetCoordinates(begin,end); + } + + /** + Construct from x,y,z values representing the translation + */ + Translation3D(T dx, T dy, T dz) : fVect(Vector(dx, dy, dz)) {} + + /** + Construct from any Displacement vector in ant tag and coordinate system + */ + template + explicit Translation3D( const DisplacementVector3D & v) : + fVect(Vector(v.X(),v.Y(),v.Z())) + { } + + + /** + Construct transformation from one coordinate system defined one point (the origin) + to a new coordinate system defined by other point (origin ) + @param p1 point defining origin of original reference system + @param p2 point defining origin of transformed reference system + + */ + template + Translation3D(const PositionVector3D &p1, const PositionVector3D &p2) + : fVect(p2 - p1) + { } + + + // use compiler generated copy ctor, copy assignment and dtor + + + // ======== Components ============== + + /** + return a const reference to the underline vector representing the translation + */ + const Vector & Vect() const { return fVect; } + + /** + Set the 3 components given an iterator to the start of + the desired data, and another to the end (3 past start). + */ + template + void SetComponents(IT begin, IT end) { + fVect.SetCoordinates(begin,end); + } + + /** + Get the 3 components into data specified by an iterator begin + and another to the end of the desired data (12 past start). + */ + template + void GetComponents(IT begin, IT end) const { + fVect.GetCoordinates(begin,end); + } + + /** + Get the 3 matrix components into data specified by an iterator begin + */ + template + void GetComponents(IT begin) const { + fVect.GetCoordinates(begin); + } + + + /** + Set the components from 3 scalars + */ + void SetComponents(T dx, T dy, T dz) { fVect.SetCoordinates(dx, dy, dz); } + + /** + Get the components into 3 scalars + */ + void GetComponents(T &dx, T &dy, T &dz) const { fVect.GetCoordinates(dx, dy, dz); } + + /** + Set the XYZ vector components from 3 scalars + */ + void SetXYZ(T dx, T dy, T dz) { fVect.SetXYZ(dx, dy, dz); } + + // operations on points and vectors + + + /** + Transformation operation for Position Vector in any coordinate system and default tag + */ + template + PositionVector3D operator() (const PositionVector3D & p) const { + return PositionVector3D(p.X() + fVect.X(), p.Y() + fVect.Y(), p.Z() + fVect.Z()); + } + /** + Transformation operation + */ + template + PositionVector3D operator*(const PositionVector3D &v) const + { + return operator()(v); + } + + /** + Transformation operation for Displacement Vector in any coordinate system and default tag + For the Displacement Vectors no translation apply so return the vector itself + */ + template + DisplacementVector3D operator() (const DisplacementVector3D & v) const { + return v; + } + /** + Transformation operation + */ + template + DisplacementVector3D operator*(const DisplacementVector3D &v) const + { + return operator()(v); + } + + /** + Transformation operation for points between different coordinate system tags + */ + template + void Transform (const PositionVector3D & p1, PositionVector3D & p2 ) const { + PositionVector3D tmp; + tmp.SetXYZ( p1.X(), p1.Y(), p1.Z() ); + p2 = operator()(tmp); + } + + /** + Transformation operation for Displacement Vector of different coordinate systems + */ + template + void Transform(const DisplacementVector3D &v1, DisplacementVector3D &v2) const + { + // just copy v1 in v2 + v2.SetXYZ(v1.X(), v1.Y(), v1.Z()); + } + + /** + Transformation operation for a Lorentz Vector in any coordinate system + A LorentzVector contains a displacement vector so no translation applies as well + */ + template + LorentzVector operator()(const LorentzVector &q) const + { + return q; + } + /** + Transformation operation + */ + template + LorentzVector operator*(const LorentzVector &q) const + { + return operator()(q); + } + + /** + Transformation on a 3D plane + */ + Plane3D operator()(const Plane3D &plane) const + { + // transformations on a 3D plane + const Vector n = plane.Normal(); + // take a point on the plane. Use origin projection on the plane + // ( -ad, -bd, -cd) if (a**2 + b**2 + c**2 ) = 1 + const T d = plane.HesseDistance(); + PositionVector3D> p(-d * n.X(), -d * n.Y(), -d * n.Z()); + return PLANE(operator()(n), operator()(p)); + } + + /** + multiply (combine) with another transformation in place + */ + Translation3D &operator*=(const Translation3D &t) + { + fVect+= t.Vect(); + return *this; + } + + /** + multiply (combine) two transformations + */ + Translation3D operator*(const Translation3D &t) const { return Translation3D(fVect + t.Vect()); } + + /** + Invert the transformation in place + */ + void Invert() { + SetComponents( -fVect.X(), -fVect.Y(),-fVect.Z() ); + } + + /** + Return the inverse of the transformation. + */ + Translation3D Inverse() const { return Translation3D(-fVect.X(), -fVect.Y(), -fVect.Z()); } + + /** + Equality/inequality operators + */ + bool operator==(const Translation3D &rhs) const + { + if( fVect != rhs.fVect ) return false; + return true; + } + + bool operator!=(const Translation3D &rhs) const { return !operator==(rhs); } + +private: + + Vector fVect; // internal 3D vector representing the translation + +}; + + + + + +// global functions +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// TODO - I/O should be put in the manipulator form + +template +std::ostream &operator<<(std::ostream &os, const Translation3D &t) +{ + // TODO - this will need changing for machine-readable issues + // and even the human readable form needs formatting improvements + + T m[3]; + t.GetComponents(m, m + 3); + return os << "\n" << m[0] << " " << m[1] << " " << m[2] << "\n"; +} +#endif +// need a function Transform = Translation * Rotation ??? + +} // end namespace Impl + +// typedefs for double and float versions +typedef Impl::Translation3D Translation3D; +typedef Impl::Translation3D Translation3DF; + +} // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_Translation3D */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/VectorUtil.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/VectorUtil.h new file mode 100644 index 0000000000000..8d991a642e76a --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/VectorUtil.h @@ -0,0 +1,530 @@ +// @(#)root/mathcore:$Id: 9ef2a4a7bd1b62c1293920c2af2f64791c75bdd8 $ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + +/********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for Vector Utility functions +// +// Created by: moneta at Tue May 31 21:10:29 2005 +// +// Last update: Tue May 31 21:10:29 2005 +// +#ifndef ROOT_MathX_GenVectorX_VectorUtil +#define ROOT_MathX_GenVectorX_VectorUtil 1 + +#include "Math/Math.h" + +#include "MathX/GenVectorX/Boost.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + + // utility functions for vector classes + + + + /** + Global Helper functions for generic Vector classes. Any Vector classes implementing some defined member functions, + like Phi() or Eta() or mag() can use these functions. + The functions returning a scalar value, returns always double precision number even if the vector are + based on another precision type + + @ingroup GenVector + + @sa Overview of the @ref GenVector "physics vector library" + */ + + + namespace VectorUtil { + + + // methods for 3D vectors + + /** + Find aximutal Angle difference between two generic vectors ( v2.Phi() - v1.Phi() ) + The only requirements on the Vector classes is that they implement the Phi() method + \param v1 Vector of any type implementing the Phi() operator + \param v2 Vector of any type implementing the Phi() operator + \return Phi difference + \f[ \Delta \phi = \phi_2 - \phi_1 \f] + */ + template + inline typename Vector1::Scalar DeltaPhi( const Vector1 & v1, const Vector2 & v2) { + typename Vector1::Scalar dphi = v2.Phi() - v1.Phi(); + if ( dphi > M_PI ) { + dphi -= 2.0*M_PI; + } else if ( dphi <= -M_PI ) { + dphi += 2.0*M_PI; + } + return dphi; + } + + + + /** + Find square of the difference in pseudorapidity (Eta) and Phi between two generic vectors + The only requirements on the Vector classes is that they implement the Phi() and Eta() method + \param v1 Vector 1 + \param v2 Vector 2 + \return Angle between the two vectors + \f[ \Delta R2 = ( \Delta \phi )^2 + ( \Delta \eta )^2 \f] + */ + template + inline typename Vector1::Scalar DeltaR2( const Vector1 & v1, const Vector2 & v2) { + typename Vector1::Scalar dphi = DeltaPhi(v1,v2); + typename Vector1::Scalar deta = v2.Eta() - v1.Eta(); + return dphi*dphi + deta*deta; + } + + /** + Find square of the difference in true rapidity (y) and Phi between two generic vectors + The only requirements on the Vector classes is that they implement the Phi() and Rapidity() method + \param v1 Vector 1 + \param v2 Vector 2 + \return Angle between the two vectors + \f[ \Delta R2 = ( \Delta \phi )^2 + ( \Delta \y )^2 \f] + */ + template + inline typename Vector1::Scalar DeltaR2RapidityPhi( const Vector1 & v1, const Vector2 & v2) { + typename Vector1::Scalar dphi = DeltaPhi(v1,v2); + typename Vector1::Scalar drap = v2.Rapidity() - v1.Rapidity(); + return dphi*dphi + drap*drap; + } + + /** + Find difference in pseudorapidity (Eta) and Phi between two generic vectors + The only requirements on the Vector classes is that they implement the Phi() and Eta() method + \param v1 Vector 1 + \param v2 Vector 2 + \return Angle between the two vectors + \f[ \Delta R = \sqrt{ ( \Delta \phi )^2 + ( \Delta \eta )^2 } \f] + */ + template + inline typename Vector1::Scalar DeltaR( const Vector1 & v1, const Vector2 & v2) { + return math_sqrt( DeltaR2(v1,v2) ); + } + + /** + Find difference in Rapidity (y) and Phi between two generic vectors + The only requirements on the Vector classes is that they implement the Phi() and Rapidity() method + \param v1 Vector 1 + \param v2 Vector 2 + \return Angle between the two vectors + \f[ \Delta R = \sqrt{ ( \Delta \phi )^2 + ( \Delta y )^2 } \f], + */ + template + inline typename Vector1::Scalar DeltaRapidityPhi( const Vector1 & v1, const Vector2 & v2) { + return math_sqrt( DeltaR2RapidityPhi(v1,v2) ); + } + + /** + Find CosTheta Angle between two generic 3D vectors + pre-requisite: vectors implement the X(), Y() and Z() + \param v1 Vector v1 + \param v2 Vector v2 + \return cosine of Angle between the two vectors + \f[ \cos \theta = \frac { \vec{v1} \cdot \vec{v2} }{ | \vec{v1} | | \vec{v2} | } \f] + */ + // this cannot be made all generic since Mag2() for 2, 3 or 4 D is different + // need to have a specialization for polar Coordinates ?? + template + double CosTheta( const Vector1 & v1, const Vector2 & v2) { + double arg; + double v1_r2 = v1.X()*v1.X() + v1.Y()*v1.Y() + v1.Z()*v1.Z(); + double v2_r2 = v2.X()*v2.X() + v2.Y()*v2.Y() + v2.Z()*v2.Z(); + double ptot2 = v1_r2*v2_r2; + if(ptot2 <= 0) { + arg = 0.0; + }else{ + double pdot = v1.X()*v2.X() + v1.Y()*v2.Y() + v1.Z()*v2.Z(); + arg = pdot/math_sqrt(ptot2); + if(arg > 1.0) arg = 1.0; + if(arg < -1.0) arg = -1.0; + } + return arg; + } + + + /** + Find Angle between two vectors. + Use the CosTheta() function + \param v1 Vector v1 + \param v2 Vector v2 + \return Angle between the two vectors + \f[ \theta = \cos ^{-1} \frac { \vec{v1} \cdot \vec{v2} }{ | \vec{v1} | | \vec{v2} | } \f] + */ + template + inline double Angle( const Vector1 & v1, const Vector2 & v2) { + return math_acos( CosTheta(v1, v2) ); + } + + /** + Find the projection of v along the given direction u. + \param v Vector v for which the propjection is to be found + \param u Vector specifying the direction + \return Vector projection (same type of v) + \f[ \vec{proj} = \frac{ \vec{v} \cdot \vec{u} }{|\vec{u}|}\vec{u} \f] + Precondition is that Vector1 implements Dot function and Vector2 implements X(),Y() and Z() + */ + template + Vector1 ProjVector( const Vector1 & v, const Vector2 & u) { + double magU2 = u.X()*u.X() + u.Y()*u.Y() + u.Z()*u.Z(); + if (magU2 == 0) return Vector1(0,0,0); + double d = v.Dot(u)/magU2; + return Vector1( u.X() * d, u.Y() * d, u.Z() * d); + } + + /** + Find the vector component of v perpendicular to the given direction of u + \param v Vector v for which the perpendicular component is to be found + \param u Vector specifying the direction + \return Vector component of v which is perpendicular to u + \f[ \vec{perp} = \vec{v} - \frac{ \vec{v} \cdot \vec{u} }{|\vec{u}|}\vec{u} \f] + Precondition is that Vector1 implements Dot function and Vector2 implements X(),Y() and Z() + */ + template + inline Vector1 PerpVector( const Vector1 & v, const Vector2 & u) { + return v - ProjVector(v,u); + } + + /** + Find the magnitude square of the vector component of v perpendicular to the given direction of u + \param v Vector v for which the perpendicular component is to be found + \param u Vector specifying the direction + \return square value of the component of v which is perpendicular to u + \f[ perp = | \vec{v} - \frac{ \vec{v} \cdot \vec{u} }{|\vec{u}|}\vec{u} |^2 \f] + Precondition is that Vector1 implements Dot function and Vector2 implements X(),Y() and Z() + */ + template + inline double Perp2( const Vector1 & v, const Vector2 & u) { + double magU2 = u.X()*u.X() + u.Y()*u.Y() + u.Z()*u.Z(); + double prjvu = v.Dot(u); + double magV2 = v.Dot(v); + return magU2 > 0.0 ? magV2-prjvu*prjvu/magU2 : magV2; + } + + /** + Find the magnitude of the vector component of v perpendicular to the given direction of u + \param v Vector v for which the perpendicular component is to be found + \param u Vector specifying the direction + \return value of the component of v which is perpendicular to u + \f[ perp = | \vec{v} - \frac{ \vec{v} \cdot \vec{u} }{|\vec{u}|}\vec{u} | \f] + Precondition is that Vector1 implements Dot function and Vector2 implements X(),Y() and Z() + */ + template + inline double Perp( const Vector1 & v, const Vector2 & u) { + return math_sqrt(Perp2(v,u) ); + } + + + + // Lorentz Vector functions + + + /** + return the invariant mass of two LorentzVector + The only requirement on the LorentzVector is that they need to implement the + X() , Y(), Z() and E() methods. + \param v1 LorenzVector 1 + \param v2 LorenzVector 2 + \return invariant mass M + \f[ M_{12} = \sqrt{ (\vec{v1} + \vec{v2} ) \cdot (\vec{v1} + \vec{v2} ) } \f] + */ + template + inline typename Vector1::Scalar InvariantMass( const Vector1 & v1, const Vector2 & v2) { + typedef typename Vector1::Scalar Scalar; + Scalar ee = (v1.E() + v2.E() ); + Scalar xx = (v1.X() + v2.X() ); + Scalar yy = (v1.Y() + v2.Y() ); + Scalar zz = (v1.Z() + v2.Z() ); + Scalar mm2 = ee*ee - xx*xx - yy*yy - zz*zz; + return mm2 < 0.0 ? -math_sqrt(-mm2) : math_sqrt(mm2); + // PxPyPzE4D q(xx,yy,zz,ee); + // return q.M(); + //return ( v1 + v2).mag(); + } + + template + inline typename Vector1::Scalar InvariantMass2( const Vector1 & v1, const Vector2 & v2) { + typedef typename Vector1::Scalar Scalar; + Scalar ee = (v1.E() + v2.E() ); + Scalar xx = (v1.X() + v2.X() ); + Scalar yy = (v1.Y() + v2.Y() ); + Scalar zz = (v1.Z() + v2.Z() ); + Scalar mm2 = ee*ee - xx*xx - yy*yy - zz*zz; + return mm2 ; // < 0.0 ? -std::sqrt(-mm2) : std::sqrt(mm2); + // PxPyPzE4D q(xx,yy,zz,ee); + // return q.M(); + //return ( v1 + v2).mag(); + } + + // rotation and transformations + + +#ifndef __CINT__ + /** + rotation along X axis for a generic vector by an Angle alpha + returning a new vector. + The only pre requisite on the Vector is that it has to implement the X() , Y() and Z() + and SetXYZ methods. + */ + template + Vector RotateX(const Vector & v, double alpha) { + double sina = math_sin(alpha); + double cosa = math_cos(alpha); + double y2 = v.Y() * cosa - v.Z()*sina; + double z2 = v.Z() * cosa + v.Y() * sina; + Vector vrot; + vrot.SetXYZ(v.X(), y2, z2); + return vrot; + } + + /** + rotation along Y axis for a generic vector by an Angle alpha + returning a new vector. + The only pre requisite on the Vector is that it has to implement the X() , Y() and Z() + and SetXYZ methods. + */ + template + Vector RotateY(const Vector & v, double alpha) { + double sina = math_sin(alpha); + double cosa = math_cos(alpha); + double x2 = v.X() * cosa + v.Z() * sina; + double z2 = v.Z() * cosa - v.X() * sina; + Vector vrot; + vrot.SetXYZ(x2, v.Y(), z2); + return vrot; + } + + /** + rotation along Z axis for a generic vector by an Angle alpha + returning a new vector. + The only pre requisite on the Vector is that it has to implement the X() , Y() and Z() + and SetXYZ methods. + */ + template + Vector RotateZ(const Vector & v, double alpha) { + double sina = math_sin(alpha); + double cosa = math_cos(alpha); + double x2 = v.X() * cosa - v.Y() * sina; + double y2 = v.Y() * cosa + v.X() * sina; + Vector vrot; + vrot.SetXYZ(x2, y2, v.Z()); + return vrot; + } + + + /** + rotation on a generic vector using a generic rotation class. + The only requirement on the vector is that implements the + X(), Y(), Z() and SetXYZ methods. + The requirement on the rotation matrix is that need to implement the + (i,j) operator returning the matrix element with R(0,0) = xx element + */ + template + Vector Rotate(const Vector &v, const RotationMatrix & rot) { + double xX = v.X(); + double yY = v.Y(); + double zZ = v.Z(); + double x2 = rot(0,0)*xX + rot(0,1)*yY + rot(0,2)*zZ; + double y2 = rot(1,0)*xX + rot(1,1)*yY + rot(1,2)*zZ; + double z2 = rot(2,0)*xX + rot(2,1)*yY + rot(2,2)*zZ; + Vector vrot; + vrot.SetXYZ(x2,y2,z2); + return vrot; + } + + /** + Boost a generic Lorentz Vector class using a generic 3D Vector class describing the boost + The only requirement on the vector is that implements the + X(), Y(), Z(), T() and SetXYZT methods. + The requirement on the boost vector is that needs to implement the + X(), Y() , Z() retorning the vector elements describing the boost + The beta of the boost must be <= 1 or a nul Lorentz Vector will be returned + */ + template + LVector boost(const LVector & v, const BoostVector & b) { + double bx = b.X(); + double by = b.Y(); + double bz = b.Z(); + double b2 = bx*bx + by*by + bz*bz; + if (b2 >= 1) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( "Beta Vector supplied to set Boost represents speed >= c"); +#endif + return LVector(); + } + double gamma = 1.0 / math_sqrt(1.0 - b2); + double bp = bx*v.X() + by*v.Y() + bz*v.Z(); + double gamma2 = b2 > 0 ? (gamma - 1.0)/b2 : 0.0; + double x2 = v.X() + gamma2*bp*bx + gamma*bx*v.T(); + double y2 = v.Y() + gamma2*bp*by + gamma*by*v.T(); + double z2 = v.Z() + gamma2*bp*bz + gamma*bz*v.T(); + double t2 = gamma*(v.T() + bp); + LVector lv; + lv.SetXYZT(x2,y2,z2,t2); + return lv; + } + + + /** + Boost a generic Lorentz Vector class along the X direction with a factor beta + The only requirement on the vector is that implements the + X(), Y(), Z(), T() and SetXYZT methods. + The beta of the boost must be <= 1 or a nul Lorentz Vector will be returned + */ + template + LVector boostX(const LVector & v, T beta) { + if (beta >= 1) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("Beta Vector supplied to set Boost represents speed >= c"); +#endif + return LVector(); + } + T gamma = 1.0/ math_sqrt(1.0 - beta*beta); + typename LVector::Scalar x2 = gamma * v.X() + gamma * beta * v.T(); + typename LVector::Scalar t2 = gamma * beta * v.X() + gamma * v.T(); + + LVector lv; + lv.SetXYZT(x2,v.Y(),v.Z(),t2); + return lv; + } + + /** + Boost a generic Lorentz Vector class along the Y direction with a factor beta + The only requirement on the vector is that implements the + X(), Y(), Z(), T() methods and be constructed from x,y,z,t values + The beta of the boost must be <= 1 or a nul Lorentz Vector will be returned + */ + template + LVector boostY(const LVector & v, double beta) { + if (beta >= 1) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ("Beta Vector supplied to set Boost represents speed >= c"); +#endif + return LVector(); + } + double gamma = 1.0/ math_sqrt(1.0 - beta*beta); + double y2 = gamma * v.Y() + gamma * beta * v.T(); + double t2 = gamma * beta * v.Y() + gamma * v.T(); + LVector lv; + lv.SetXYZT(v.X(),y2,v.Z(),t2); + return lv; + } + + /** + Boost a generic Lorentz Vector class along the Z direction with a factor beta + The only requirement on the vector is that implements the + X(), Y(), Z(), T() methods and be constructed from x,y,z,t values + The beta of the boost must be <= 1 or a nul Lorentz Vector will be returned + */ + template + LVector boostZ(const LVector & v, double beta) { + if (beta >= 1) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( "Beta Vector supplied to set Boost represents speed >= c"); +#endif + return LVector(); + } + double gamma = 1.0/ math_sqrt(1.0 - beta*beta); + double z2 = gamma * v.Z() + gamma * beta * v.T(); + double t2 = gamma * beta * v.Z() + gamma * v.T(); + LVector lv; + lv.SetXYZT(v.X(),v.Y(),z2,t2); + return lv; + } + +#endif + + + + + // MATRIX VECTOR MULTIPLICATION + // cannot define an operator * otherwise conflicts with rotations + // operations like Rotation3D * vector use Mult + + /** + Multiplications of a generic matrices with a DisplacementVector3D of any coordinate system. + Assume that the matrix implements the operator( i,j) and that it has at least 3 columns and 3 rows. There is no check on the matrix size !! + */ + template + inline + DisplacementVector3D Mult (const Matrix & m, const DisplacementVector3D & v) { + DisplacementVector3D vret; + vret.SetXYZ( m(0,0) * v.x() + m(0,1) * v.y() + m(0,2) * v.z() , + m(1,0) * v.x() + m(1,1) * v.y() + m(1,2) * v.z() , + m(2,0) * v.x() + m(2,1) * v.y() + m(2,2) * v.z() ); + return vret; + } + + + /** + Multiplications of a generic matrices with a generic PositionVector + Assume that the matrix implements the operator( i,j) and that it has at least 3 columns and 3 rows. There is no check on the matrix size !! + */ + template + inline + PositionVector3D Mult (const Matrix & m, const PositionVector3D & p) { + DisplacementVector3D pret; + pret.SetXYZ( m(0,0) * p.x() + m(0,1) * p.y() + m(0,2) * p.z() , + m(1,0) * p.x() + m(1,1) * p.y() + m(1,2) * p.z() , + m(2,0) * p.x() + m(2,1) * p.y() + m(2,2) * p.z() ); + return pret; + } + + + /** + Multiplications of a generic matrices with a LorentzVector described + in any coordinate system. + Assume that the matrix implements the operator( i,j) and that it has at least 4 columns and 4 rows. There is no check on the matrix size !! + */ + // this will not be ambiguous with operator*(Scalar, LorentzVector) since that one // Scalar is passed by value + template + inline + LorentzVector Mult (const Matrix & m, const LorentzVector & v) { + LorentzVector vret; + vret.SetXYZT( m(0,0)*v.x() + m(0,1)*v.y() + m(0,2)*v.z() + m(0,3)* v.t() , + m(1,0)*v.x() + m(1,1)*v.y() + m(1,2)*v.z() + m(1,3)* v.t() , + m(2,0)*v.x() + m(2,1)*v.y() + m(2,2)*v.z() + m(2,3)* v.t() , + m(3,0)*v.x() + m(3,1)*v.y() + m(3,2)*v.z() + m(3,3)* v.t() ); + return vret; + } + + + + // non-template utility functions for all objects + + + /** + Return a phi angle in the interval (0,2*PI] + */ + double Phi_0_2pi(double phi); + /** + Returns phi angle in the interval (-PI,PI] + */ + double Phi_mpi_pi(double phi); + + + + } // end namespace Vector Util + + + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_VectorUtil */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/eta.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/eta.h new file mode 100644 index 0000000000000..043418a3a62b8 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/eta.h @@ -0,0 +1,108 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , FNAL MathLib Team * + * * + * * + **********************************************************************/ + + +// Header source file for function calculating eta +// +// Created by: Lorenzo Moneta at 14 Jun 2007 + + +#ifndef ROOT_MathX_GenVectorX_eta +#define ROOT_MathX_GenVectorX_eta 1 + +#include "MathX/GenVectorX/etaMax.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +using namespace ROOT::ROOT_MATH_ARCH; + +#include +#include + + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + namespace Impl { + + /** + Calculate eta given rho and zeta. + This formula is faster than the standard calculation (below) from log(tan(theta/2) + but one has to be careful when rho is much smaller than z (large eta values) + Formula is eta = log( zs + sqrt(zs^2 + 1) ) where zs = z/rho + + For large value of z_scaled (tan(theta) ) one can approximate the sqrt via a Taylor expansion + We do the approximation of the sqrt if the numerical error is of the same order of second term of + the sqrt.expansion: + eps > 1/zs^4 => zs > 1/(eps^0.25) + + When rho == 0 we use etaMax (see definition in etaMax.h) + + */ + template + inline Scalar Eta_FromRhoZ(Scalar rho, Scalar z) { + if (rho > 0) { + + // value to control Taylor expansion of sqrt + Scalar big_z_scaled = math_pow(std::numeric_limits::epsilon(), static_cast(-.25)); + + Scalar z_scaled = z/rho; + + if (math_fabs(z_scaled) < big_z_scaled) { + return math_log(z_scaled + math_sqrt(z_scaled * z_scaled + 1.0)); + } else { + // apply correction using first order Taylor expansion of sqrt + return z > 0 ? math_log(2.0 * z_scaled + 0.5 / z_scaled) : -math_log(-2.0 * z_scaled); + } + } + // case vector has rho = 0 + else if (z==0) { + return 0; + } + else if (z>0) { + return z + etaMax(); + } + else { + return z - etaMax(); + } + + } + + + /** + Implementation of eta from -log(tan(theta/2)). + This is convenient when theta is already known (for example in a polar coorindate system) + */ + template + inline Scalar Eta_FromTheta(Scalar theta, Scalar r) { + Scalar tanThetaOver2 = tan(theta / 2.); + if (tanThetaOver2 == 0) { + return r + etaMax(); + } + else if (tanThetaOver2 > std::numeric_limits::max()) { + return -r - etaMax(); + } + else { + return -math_log(tanThetaOver2); + } + + } + + } // end namespace Impl + + } // namespace ROOT_MATH_ARCH + +} // namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_etaMax */ diff --git a/math/experimental/genvectorx/inc/MathX/GenVectorX/etaMax.h b/math/experimental/genvectorx/inc/MathX/GenVectorX/etaMax.h new file mode 100644 index 0000000000000..b974a3f0b532a --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/etaMax.h @@ -0,0 +1,67 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , FNAL MathLib Team * + * * + * * + **********************************************************************/ + + +// Header source file for function etaMax +// +// Created by: Mark Fischler at Thu Jun 2 2005 + + +#ifndef ROOT_MathX_GenVectorX_etaMax +#define ROOT_MathX_GenVectorX_etaMax 1 + +#include "MathX/GenVectorX/MathHeaders.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include +#include + +// #if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// typedef long double d_type; +// #else +// typedef d_type double ; +// #endif + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +/** + The following function could be called to provide the maximum possible + value of pseudorapidity for a non-zero rho. This is log ( max/min ) + where max and min are the extrema of positive values for type + long double. + */ +__roohost__ __roodevice__ inline long double etaMax_impl() +{ + using std::log; + return math_log(std::numeric_limits::max() / 256.0l) - + math_log(std::numeric_limits::denorm_min() * 256.0l) + 16.0 * math_log(2.0); + // Actual usage of etaMax() simply returns the number 22756, which is + // the answer this would supply, rounded to a higher integer. +} + + /** + Function providing the maximum possible value of pseudorapidity for + a non-zero rho, in the Scalar type with the largest dynamic range. + */ + template + inline + T etaMax() { + return static_cast(22756.0); + } + + } // namespace ROOT_MATH_ARCH + +} // namespace ROOT + + +#endif /* ROOT_MathX_GenVectorX_etaMax */ diff --git a/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector.h b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector.h new file mode 100644 index 0000000000000..1cdedb97275f3 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector.h @@ -0,0 +1,722 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ nestedclass; +#pragma link C++ nestedtypedef; + +#pragma link C++ namespace ROOT; +#pragma link C++ namespace ROOT::Math; + + +#pragma link C++ class ROOT::Math::Cartesian2D+; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; + +#pragma link C++ class ROOT::Math::Polar2D+; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; + + + +#pragma link C++ class ROOT::Math::Cartesian3D+; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; + +#pragma link C++ class ROOT::Math::Polar3D+; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; + +#pragma link C++ class ROOT::Math::Cylindrical3D+; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; + +#pragma link C++ class ROOT::Math::CylindricalEta3D+; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; + + +#pragma link C++ class ROOT::Math::DefaultCoordinateSystemTag+; +#pragma link C++ class ROOT::Math::LocalCoordinateSystemTag+; +#pragma link C++ class ROOT::Math::GlobalCoordinateSystemTag+; + +#pragma link C++ class ROOT::Math::DisplacementVector2D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector2D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; + + +#pragma link C++ class ROOT::Math::PositionVector2D >+; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; + +#pragma link C++ class ROOT::Math::PositionVector2D >+; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; + + + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + + +#ifdef __CLING__ +// Work around CINT and autoloader deficiency with template default parameter +// Those requests are solely for rlibmap, they do no need to be seen by rootcint. +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#endif + +#pragma link C++ class ROOT::Math::PxPyPzE4D+; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; + +#pragma link C++ class ROOT::Math::PtEtaPhiE4D+; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; + +#pragma link C++ class ROOT::Math::PxPyPzM4D+; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; + +#pragma link C++ class ROOT::Math::PtEtaPhiM4D+; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; + +//#pragma link C++ class ROOT::Math::EEtaPhiMSystem+; +#pragma read sourceClass="ROOT::Math::EEtaPhiMSystem" \ + targetClass="ROOT::Math::EEtaPhiMSystem"; +#pragma read sourceClass="ROOT::Math::EEtaPhiMSystem" \ + targetClass="ROOT::Math::EEtaPhiMSystem"; +#pragma read sourceClass="ROOT::Math::EEtaPhiMSystem" \ + targetClass="ROOT::Math::EEtaPhiMSystem"; + +//#pragma link C++ class ROOT::Math::PtEtaPhiMSystem+; +#pragma read sourceClass="ROOT::Math::PtEtaPhiMSystem" \ + targetClass="ROOT::Math::PtEtaPhiMSystem"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiMSystem" \ + targetClass="ROOT::Math::PtEtaPhiMSystem"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiMSystem" \ + targetClass="ROOT::Math::PtEtaPhiMSystem"; + + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + + +//// Floating types + +#pragma link C++ class ROOT::Math::Cartesian2D+; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; + +#pragma link C++ class ROOT::Math::Polar2D+; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; + + +#pragma link C++ class ROOT::Math::Cartesian3D+; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; + +#pragma link C++ class ROOT::Math::Polar3D+; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; + +#pragma link C++ class ROOT::Math::Cylindrical3D+; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; + +#pragma link C++ class ROOT::Math::CylindricalEta3D+; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; + + +#pragma link C++ class ROOT::Math::DefaultCoordinateSystemTag+; +#pragma link C++ class ROOT::Math::LocalCoordinateSystemTag+; +#pragma link C++ class ROOT::Math::GlobalCoordinateSystemTag+; + +#pragma link C++ class ROOT::Math::DisplacementVector2D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector2D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; + + +#pragma link C++ class ROOT::Math::PositionVector2D >+; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; + +#pragma link C++ class ROOT::Math::PositionVector2D >+; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; +#pragma read sourceClass="ROOT::Math::PositionVector2D >" \ + targetClass="ROOT::Math::PositionVector2D >"; + + + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + + +#ifdef __CLING__ +// Work around CINT and autoloader deficiency with template default parameter +// Those requests are solely for rlibmap, they do no need to be seen by rootcint. +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#endif + +#pragma link C++ class ROOT::Math::PxPyPzE4D+; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; + +#pragma link C++ class ROOT::Math::PtEtaPhiE4D+; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; + +#pragma link C++ class ROOT::Math::PxPyPzM4D+; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; + +#pragma link C++ class ROOT::Math::PtEtaPhiM4D+; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; + +//#pragma link C++ class ROOT::Math::EEtaPhiMSystem+; +#pragma read sourceClass="ROOT::Math::EEtaPhiMSystem" \ + targetClass="ROOT::Math::EEtaPhiMSystem"; +#pragma read sourceClass="ROOT::Math::EEtaPhiMSystem" \ + targetClass="ROOT::Math::EEtaPhiMSystem"; +#pragma read sourceClass="ROOT::Math::EEtaPhiMSystem" \ + targetClass="ROOT::Math::EEtaPhiMSystem"; + +//#pragma link C++ class ROOT::Math::PtEtaPhiMSystem+; +#pragma read sourceClass="ROOT::Math::PtEtaPhiMSystem" \ + targetClass="ROOT::Math::PtEtaPhiMSystem"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiMSystem" \ + targetClass="ROOT::Math::PtEtaPhiMSystem"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiMSystem" \ + targetClass="ROOT::Math::PtEtaPhiMSystem"; + + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + + + + +// rotations +//#ifdef LATER + +#pragma link C++ class ROOT::Math::Rotation3D+; +#pragma link C++ class ROOT::Math::AxisAngle+; +#pragma link C++ class ROOT::Math::EulerAngles+; +#pragma link C++ class ROOT::Math::Quaternion+; +#pragma link C++ class ROOT::Math::RotationZYX+; +#pragma link C++ class ROOT::Math::RotationX+; +#pragma link C++ class ROOT::Math::RotationY+; +#pragma link C++ class ROOT::Math::RotationZ+; +#pragma link C++ class ROOT::Math::LorentzRotation+; +#pragma link C++ class ROOT::Math::Boost+; +#pragma link C++ class ROOT::Math::BoostX+; +#pragma link C++ class ROOT::Math::BoostY+; +#pragma link C++ class ROOT::Math::BoostZ+; + + +#pragma link C++ class ROOT::Math::Plane3D+; +#pragma link C++ class ROOT::Math::Transform3D+; +#pragma link C++ class ROOT::Math::Translation3D+; + +//#endif + +// typedef's + + +#pragma link C++ typedef ROOT::Math::XYVector; +#pragma link C++ typedef ROOT::Math::Polar2DVector; + +#pragma link C++ typedef ROOT::Math::XYPoint; +#pragma link C++ typedef ROOT::Math::Polar2DPoint; + +#pragma link C++ typedef ROOT::Math::XYZVector; +#pragma link C++ typedef ROOT::Math::RhoEtaPhiVector; +#pragma link C++ typedef ROOT::Math::Polar3DVector; + +#pragma link C++ typedef ROOT::Math::XYZPoint; +#pragma link C++ typedef ROOT::Math::RhoEtaPhiPoint; +#pragma link C++ typedef ROOT::Math::Polar3DPoint; + +#pragma link C++ typedef ROOT::Math::XYZTVector; +#pragma link C++ typedef ROOT::Math::PtEtaPhiEVector; +#pragma link C++ typedef ROOT::Math::PxPyPzMVector; +#pragma link C++ typedef ROOT::Math::PtEtaPhiMVector; + +#pragma link C++ typedef ROOT::Math::RhoZPhiVector; +#pragma link C++ typedef ROOT::Math::PxPyPzEVector; + +// tyoedef for floating types + +#pragma link C++ typedef ROOT::Math::XYVectorF; +#pragma link C++ typedef ROOT::Math::Polar2DVectorF; + +#pragma link C++ typedef ROOT::Math::XYPointF; +#pragma link C++ typedef ROOT::Math::Polar2DPointF; + +#pragma link C++ typedef ROOT::Math::XYZVectorF; +#pragma link C++ typedef ROOT::Math::RhoEtaPhiVectorF; +#pragma link C++ typedef ROOT::Math::Polar3DVectorF; + +#pragma link C++ typedef ROOT::Math::XYZPointF; +#pragma link C++ typedef ROOT::Math::RhoEtaPhiPointF; +#pragma link C++ typedef ROOT::Math::Polar3DPointF; + +#pragma link C++ typedef ROOT::Math::XYZTVectorF; + +// dictionary for points and vectors functions +// not needed with Cling +//#include "LinkDef_Vector3D.h" +//#include "LinkDef_Point3D.h" +//#include "LinkDef_Vector4D.h" +//#include "LinkDef_Rotation.h" + +// for std::vector of genvectors +#include "LinkDef_GenVector2.h" + + +// utility functions + +#pragma link C++ namespace ROOT::Math::VectorUtil; + + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector2.h b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector2.h new file mode 100644 index 0000000000000..40827719c2223 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector2.h @@ -0,0 +1,25 @@ +// dictionary for std::vector of genvector objects +// problem on Windows: CINT cannot deal with too long class name +// generated by an std::vector + +#pragma extra_include "vector"; +#include + +// conflict on solaris between template class T from std::vector and T(). +#ifndef __sun +#pragma link C++ class std::vector+; +#pragma link C++ class std::vector+; +#endif + +#pragma link C++ class std::vector+; +#pragma link C++ class std::vector+; + +#pragma link C++ class std::vector+; +#pragma link C++ class std::vector+; + +// for floating types + +#pragma link C++ class std::vector+; +#pragma link C++ class std::vector+; +#pragma link C++ class std::vector+; + diff --git a/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector32.h b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector32.h new file mode 100644 index 0000000000000..67963c77b0f43 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector32.h @@ -0,0 +1,339 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +// Linkdef for Doublr32_t types + + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + + +#pragma link C++ class ROOT::Math::Cartesian2D+; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; +#pragma read sourceClass="ROOT::Math::Cartesian2D" \ + targetClass="ROOT::Math::Cartesian2D"; + +#pragma link C++ class ROOT::Math::Polar2D+; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; +#pragma read sourceClass="ROOT::Math::Polar2D" \ + targetClass="ROOT::Math::Polar2D"; + + +#pragma link C++ class ROOT::Math::DisplacementVector2D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector2D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector2D >" \ + targetClass="ROOT::Math::DisplacementVector2D >"; + + + +#pragma link C++ class ROOT::Math::Cartesian3D+; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; +#pragma read sourceClass="ROOT::Math::Cartesian3D" \ + targetClass="ROOT::Math::Cartesian3D"; + +#pragma link C++ class ROOT::Math::CylindricalEta3D+; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; +#pragma read sourceClass="ROOT::Math::CylindricalEta3D" \ + targetClass="ROOT::Math::CylindricalEta3D"; + +#pragma link C++ class ROOT::Math::Polar3D+; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; +#pragma read sourceClass="ROOT::Math::Polar3D" \ + targetClass="ROOT::Math::Polar3D"; + +#pragma link C++ class ROOT::Math::Cylindrical3D+; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; +#pragma read sourceClass="ROOT::Math::Cylindrical3D" \ + targetClass="ROOT::Math::Cylindrical3D"; + + + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D >" \ + targetClass="ROOT::Math::DisplacementVector3D >"; + + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + +#pragma link C++ class ROOT::Math::PositionVector3D >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D >" \ + targetClass="ROOT::Math::PositionVector3D >"; + + +// using a tag (only cartesian and cylindrical eta) + +#ifdef __CLING__ +// Work around CINT and autoloader deficiency with template default parameter +// Those requests as solely for rlibmap, they do no need to be seen by rootcint +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::DefaultCoordinateSystemTag >"; + +#endif + +#pragma link C++ class ROOT::Math::DisplacementVector3D, ROOT::Math::LocalCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D, ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D, ROOT::Math::LocalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D, ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D, ROOT::Math::LocalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D, ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D, ROOT::Math::LocalCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::LocalCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::LocalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::LocalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::LocalCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D, ROOT::Math::GlobalCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D, ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D, ROOT::Math::GlobalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D, ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D, ROOT::Math::GlobalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D, ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D, ROOT::Math::GlobalCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::DisplacementVector3D,ROOT::Math::GlobalCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::DisplacementVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::DisplacementVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; + + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::LocalCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; + +#pragma link C++ class ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >+; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; +#pragma read sourceClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >" \ + targetClass="ROOT::Math::PositionVector3D,ROOT::Math::GlobalCoordinateSystemTag >"; + + + +#pragma link C++ class ROOT::Math::PxPyPzE4D+; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzE4D" \ + targetClass="ROOT::Math::PxPyPzE4D"; + +#pragma link C++ class ROOT::Math::PtEtaPhiE4D+; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiE4D" \ + targetClass="ROOT::Math::PtEtaPhiE4D"; + +#pragma link C++ class ROOT::Math::PxPyPzM4D+; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; +#pragma read sourceClass="ROOT::Math::PxPyPzM4D" \ + targetClass="ROOT::Math::PxPyPzM4D"; + +#pragma link C++ class ROOT::Math::PtEtaPhiM4D+; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; +#pragma read sourceClass="ROOT::Math::PtEtaPhiM4D" \ + targetClass="ROOT::Math::PtEtaPhiM4D"; + + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + +#pragma link C++ class ROOT::Math::LorentzVector >+; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; +#pragma read sourceClass="ROOT::Math::LorentzVector >" \ + targetClass="ROOT::Math::LorentzVector >"; + + + + +// #pragma link C++ typedef ROOT::Math::XYZVectorD32; +// #pragma link C++ typedef ROOT::Math::RhoEtaPhiVectorD32; +// #pragma link C++ typedef ROOT::Math::Polar3DVectorD32; + +// #pragma link C++ typedef ROOT::Math::XYZPointD32; +// #pragma link C++ typedef ROOT::Math::RhoEtaPhiPointD32; +// #pragma link C++ typedef ROOT::Math::Polar3DPointD32; + +// #pragma link C++ typedef ROOT::Math::XYZTVectorD32; +// #pragma link C++ typedef ROOT::Math::PtEtaPhiEVectorD32; +// #pragma link C++ typedef ROOT::Math::PxPyPzMVectorD32; +// #pragma link C++ typedef ROOT::Math::PtEtaPhiMVectorD32; + + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/LinkDef_GenVectorAll.h b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVectorAll.h new file mode 100644 index 0000000000000..ec39e203c5d58 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVectorAll.h @@ -0,0 +1,3 @@ +#include "LinkDef_GenVector32.h" +#include "LinkDef_GenVector.h" + diff --git a/math/experimental/genvectorx/inc/MathX/LorentzRotation.h b/math/experimental/genvectorx/inc/MathX/LorentzRotation.h new file mode 100644 index 0000000000000..028a1592ec883 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LorentzRotation.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_LorentzRotation +#define ROOT_MathX_LorentzRotation + + +#include "MathX/GenVectorX/LorentzRotation.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/LorentzVector.h b/math/experimental/genvectorx/inc/MathX/LorentzVector.h new file mode 100644 index 0000000000000..e243932874edb --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LorentzVector.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_LorentzVector +#define ROOT_MathX_LorentzVector + + +#include "MathX/GenVectorX/LorentzVector.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Plane3D.h b/math/experimental/genvectorx/inc/MathX/Plane3D.h new file mode 100644 index 0000000000000..32202db59db6f --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Plane3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Plane3D +#define ROOT_MathX_Plane3D + + +#include "MathX/GenVectorX/Plane3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Point2D.h b/math/experimental/genvectorx/inc/MathX/Point2D.h new file mode 100644 index 0000000000000..00aaa399795aa --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Point2D.h @@ -0,0 +1,19 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Point2D +#define ROOT_MathX_Point2D + +// defines typedefs to specific vectors and forward declarations +#include "MathX/Point2Dfwd.h" + +// coordinate system types +#include "MathX/GenVectorX/Cartesian2D.h" +#include "MathX/GenVectorX/Polar2D.h" + +// generic Point2D class definition +#include "MathX/GenVectorX/PositionVector2D.h" + + +#endif + diff --git a/math/experimental/genvectorx/inc/MathX/Point2Dfwd.h b/math/experimental/genvectorx/inc/MathX/Point2Dfwd.h new file mode 100644 index 0000000000000..6e46ae96b8af4 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Point2Dfwd.h @@ -0,0 +1,66 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file Point2Dfwd +// +// Created by: Lorenzo Moneta at Mon Apr 16 2007 +// + +#ifndef ROOT_MathX_Point2Dfwd +#define ROOT_MathX_Point2Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +// forward declareations of position vectors (Points) and type defs definitions + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + template class PositionVector2D; + + template class Cartesian2D; + template class Polar2D; + + class DefaultCoordinateSystemTag; + + /** + 2D Point based on the cartesian coordinates x,y,z in double precision + */ + typedef PositionVector2D< Cartesian2D, DefaultCoordinateSystemTag > XYPoint; + typedef XYPoint XYPointD; + + /** + 2D Point based on the cartesian coordinates x,y,z in single precision + */ + typedef PositionVector2D< Cartesian2D, DefaultCoordinateSystemTag > XYPointF; + + + /** + 2D Point based on the polar coordinates rho, theta, phi in double precision. + */ + typedef PositionVector2D< Polar2D, DefaultCoordinateSystemTag > Polar2DPoint; + typedef Polar2DPoint Polar2DPointD; + + /** + 2D Point based on the polar coordinates rho, theta, phi in single precision. + */ + typedef PositionVector2D< Polar2D, DefaultCoordinateSystemTag > Polar2DPointF; + + + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_Point2Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/Point3D.h b/math/experimental/genvectorx/inc/MathX/Point3D.h new file mode 100644 index 0000000000000..71b5e3942a2a2 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Point3D.h @@ -0,0 +1,21 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Point3D +#define ROOT_MathX_Point3D + +// defines typedefs to specific vectors and forward declarations +#include "MathX/Point3Dfwd.h" + +// coordinate system types +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#include "MathX/GenVectorX/Polar3D.h" +#include "MathX/GenVectorX/Cylindrical3D.h" + +// generic Point3D class definition +#include "MathX/GenVectorX/PositionVector3D.h" + + +#endif + diff --git a/math/experimental/genvectorx/inc/MathX/Point3Dfwd.h b/math/experimental/genvectorx/inc/MathX/Point3Dfwd.h new file mode 100644 index 0000000000000..67068f183b1a0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Point3Dfwd.h @@ -0,0 +1,84 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file Point3Dfwd +// +// Created by: Lorenzo Moneta at Mon May 30 18:12:14 2005 +// +// Last update: Mon May 30 18:12:14 2005 +// +#ifndef ROOT_MathX_Point3Dfwd +#define ROOT_MathX_Point3Dfwd 1 + +// forward declareations of position vectors (Points) and type defs definitions + +#include "MathX/GenVectorX/AccHeaders.h" + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + template class PositionVector3D; + + template class Cartesian3D; + template class Cylindrical3D; + template class CylindricalEta3D; + template class Polar3D; + + class DefaultCoordinateSystemTag; + + /** + 3D Point based on the cartesian coordinates x,y,z in double precision + */ + typedef PositionVector3D< Cartesian3D, DefaultCoordinateSystemTag > XYZPoint; + + /** + 3D Point based on the cartesian coordinates x,y,z in single precision + */ + typedef PositionVector3D< Cartesian3D, DefaultCoordinateSystemTag > XYZPointF; + typedef XYZPoint XYZPointD; + + /** + 3D Point based on the eta based cylindrical coordinates rho, eta, phi in double precision. + */ + typedef PositionVector3D< CylindricalEta3D, DefaultCoordinateSystemTag > RhoEtaPhiPoint; + /** + 3D Point based on the eta based cylindrical coordinates rho, eta, phi in single precision. + */ + typedef PositionVector3D< CylindricalEta3D, DefaultCoordinateSystemTag > RhoEtaPhiPointF; + typedef RhoEtaPhiPoint RhoEtaPhiPointD; + + /** + 3D Point based on the polar coordinates rho, theta, phi in double precision. + */ + typedef PositionVector3D< Polar3D, DefaultCoordinateSystemTag > Polar3DPoint; + /** + 3D Point based on the polar coordinates rho, theta, phi in single precision. + */ + typedef PositionVector3D< Polar3D, DefaultCoordinateSystemTag > Polar3DPointF; + typedef Polar3DPoint Polar3DPointD; + + /** + 3D Point based on the cylindrical coordinates rho, z, phi in double precision. + */ + typedef PositionVector3D< Cylindrical3D, DefaultCoordinateSystemTag > RhoZPhiPoint; + /** + 3D Point based on the cylindrical coordinates rho, z, phi in single precision. + */ + typedef PositionVector3D< Cylindrical3D, DefaultCoordinateSystemTag > RhoZPhiPointF; + typedef RhoZPhiPoint RhoZPhiPointD; + + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_Point3Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/Polar2D.h b/math/experimental/genvectorx/inc/MathX/Polar2D.h new file mode 100644 index 0000000000000..9c6249d797232 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Polar2D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Polar2D +#define ROOT_MathX_Polar2D + + +#include "MathX/GenVectorX/Polar2D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Polar3D.h b/math/experimental/genvectorx/inc/MathX/Polar3D.h new file mode 100644 index 0000000000000..322612b0ccdcf --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Polar3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Polar3D +#define ROOT_MathX_Polar3D + + +#include "MathX/GenVectorX/Polar3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/PositionVector2D.h b/math/experimental/genvectorx/inc/MathX/PositionVector2D.h new file mode 100644 index 0000000000000..008c770de34da --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PositionVector2D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_PositionVector2D +#define ROOT_MathX_PositionVector2D + + +#include "MathX/GenVectorX/PositionVector2D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/PositionVector3D.h b/math/experimental/genvectorx/inc/MathX/PositionVector3D.h new file mode 100644 index 0000000000000..5a8652b3f103d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PositionVector3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_PositionVector3D +#define ROOT_MathX_PositionVector3D + + +#include "MathX/GenVectorX/PositionVector3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/PtEtaPhiE4D.h b/math/experimental/genvectorx/inc/MathX/PtEtaPhiE4D.h new file mode 100644 index 0000000000000..612dfe73ba403 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PtEtaPhiE4D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_PtEtaPhiE4D +#define ROOT_MathX_PtEtaPhiE4D + + +#include "MathX/GenVectorX/PtEtaPhiE4D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/PtEtaPhiM4D.h b/math/experimental/genvectorx/inc/MathX/PtEtaPhiM4D.h new file mode 100644 index 0000000000000..2e26e42853d0e --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PtEtaPhiM4D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_PtEtaPhiM4D +#define ROOT_MathX_PtEtaPhiM4D + + +#include "MathX/GenVectorX/PtEtaPhiM4D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/PxPyPzE4D.h b/math/experimental/genvectorx/inc/MathX/PxPyPzE4D.h new file mode 100644 index 0000000000000..45381c31bae6c --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PxPyPzE4D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_PxPyPzE4D +#define ROOT_MathX_PxPyPzE4D + + +#include "MathX/GenVectorX/PxPyPzE4D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/PxPyPzM4D.h b/math/experimental/genvectorx/inc/MathX/PxPyPzM4D.h new file mode 100644 index 0000000000000..f72ccd25e112a --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PxPyPzM4D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_PxPyPzM4D +#define ROOT_MathX_PxPyPzM4D + + +#include "MathX/GenVectorX/PxPyPzM4D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Quaternion.h b/math/experimental/genvectorx/inc/MathX/Quaternion.h new file mode 100644 index 0000000000000..0fa20b8f6f3c3 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Quaternion.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Quaternion +#define ROOT_MathX_Quaternion + + +#include "MathX/GenVectorX/Quaternion.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Rotation3D.h b/math/experimental/genvectorx/inc/MathX/Rotation3D.h new file mode 100644 index 0000000000000..9b6e48303e502 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Rotation3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Rotation3D +#define ROOT_MathX_Rotation3D + + +#include "MathX/GenVectorX/Rotation3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/RotationX.h b/math/experimental/genvectorx/inc/MathX/RotationX.h new file mode 100644 index 0000000000000..030ef0554094c --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/RotationX.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_RotationX +#define ROOT_MathX_RotationX + + +#include "MathX/GenVectorX/RotationX.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/RotationY.h b/math/experimental/genvectorx/inc/MathX/RotationY.h new file mode 100644 index 0000000000000..e0b300457b734 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/RotationY.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_RotationY +#define ROOT_MathX_RotationY + + +#include "MathX/GenVectorX/RotationY.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/RotationZ.h b/math/experimental/genvectorx/inc/MathX/RotationZ.h new file mode 100644 index 0000000000000..df6a57f781344 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/RotationZ.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_RotationZ +#define ROOT_MathX_RotationZ + + +#include "MathX/GenVectorX/RotationZ.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/RotationZYX.h b/math/experimental/genvectorx/inc/MathX/RotationZYX.h new file mode 100644 index 0000000000000..15bc6abefca0d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/RotationZYX.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_RotationZYX +#define ROOT_MathX_RotationZYX + + +#include "MathX/GenVectorX/RotationZYX.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Transform3D.h b/math/experimental/genvectorx/inc/MathX/Transform3D.h new file mode 100644 index 0000000000000..adcc90825ae72 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Transform3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Transform3D +#define ROOT_MathX_Transform3D + + +#include "MathX/GenVectorX/Transform3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Translation3D.h b/math/experimental/genvectorx/inc/MathX/Translation3D.h new file mode 100644 index 0000000000000..add4b9d2b8050 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Translation3D.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Translation3D +#define ROOT_MathX_Translation3D + + +#include "MathX/GenVectorX/Translation3D.h" + + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Vector2D.h b/math/experimental/genvectorx/inc/MathX/Vector2D.h new file mode 100644 index 0000000000000..52298b58089c5 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector2D.h @@ -0,0 +1,17 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_ROOT_MathX_Vector2D +#define ROOT_ROOT_MathX_Vector2D + +// defines typedefs to specific vectors and forward declarations +#include "MathX/Vector2Dfwd.h" + +// coordinate system types +#include "MathX/GenVectorX/Cartesian2D.h" +#include "MathX/GenVectorX/Polar2D.h" + +// generic Vector2D class definition +#include "MathX/GenVectorX/DisplacementVector2D.h" + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Vector2Dfwd.h b/math/experimental/genvectorx/inc/MathX/Vector2Dfwd.h new file mode 100644 index 0000000000000..4978b2ddb48ca --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector2Dfwd.h @@ -0,0 +1,83 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file Vector2Dfwd +// +// Created by: Lorenzo Moneta at Mon Apr 16 2007 +// +// +#ifndef ROOT_MathX_Vector2Dfwd +#define ROOT_MathX_Vector2Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +// forward declarations of displacement vectors (Vectors) and type defs definitions + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + + template class DisplacementVector2D; + + template class Cartesian2D; + template class Polar2D; + + class DefaultCoordinateSystemTag; + + + /** + 2D Vector based on the cartesian coordinates x,y in double precision + + To use it add the line `#include ` + + See the documentation on the DisplacementVector2D page. + */ + typedef DisplacementVector2D< Cartesian2D, DefaultCoordinateSystemTag > XYVector; + typedef XYVector XYVectorD; + + /** + 2D Vector based on the cartesian coordinates x,y,z in single precision + + To use it add the line `#include ` + + See the documentation on the DisplacementVector2D page. + */ + typedef DisplacementVector2D< Cartesian2D, DefaultCoordinateSystemTag > XYVectorF; + + + /** + 2D Vector based on the polar coordinates rho, phi in double precision. + + To use it add the line `#include ` + + See the documentation on the DisplacementVector2D page. + */ + typedef DisplacementVector2D< Polar2D, DefaultCoordinateSystemTag > Polar2DVector; + typedef Polar2DVector Polar2DVectorD; + + /** + 2D Vector based on the polar coordinates rho, phi in single precision. + + To use it add the line `#include ` + + See the documentation on the DisplacementVector2D page. + */ + typedef DisplacementVector2D< Polar2D, DefaultCoordinateSystemTag > Polar2DVectorF; + + + + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_Vector2Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/Vector3D.h b/math/experimental/genvectorx/inc/MathX/Vector3D.h new file mode 100644 index 0000000000000..36d633b5aa7b0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector3D.h @@ -0,0 +1,19 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_ROOT_MathX_Vector3D +#define ROOT_ROOT_MathX_Vector3D + +// defines typedefs to specific vectors and forward declarations +#include "MathX/Vector3Dfwd.h" + +// coordinate system types +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#include "MathX/GenVectorX/Polar3D.h" +#include "MathX/GenVectorX/Cylindrical3D.h" + +// generic Vector3D class definition +#include "MathX/GenVectorX/DisplacementVector3D.h" + +#endif diff --git a/math/experimental/genvectorx/inc/MathX/Vector3Dfwd.h b/math/experimental/genvectorx/inc/MathX/Vector3Dfwd.h new file mode 100644 index 0000000000000..1f804fdcdf194 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector3Dfwd.h @@ -0,0 +1,117 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file Vector3Dfwd +// +// Created by: Lorenzo Moneta at Mon May 30 18:08:35 2005 +// +// Last update: Mon May 30 18:08:35 2005 +// +#ifndef ROOT_MathX_Vector3Dfwd +#define ROOT_MathX_Vector3Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + +// forward declarations of displacement vectors (Vectors) and type defs definitions + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + + template class DisplacementVector3D; + + template class Cartesian3D; + template class CylindricalEta3D; + template class Polar3D; + template class Cylindrical3D; + + class DefaultCoordinateSystemTag; + + + /** + 3D Vector based on the cartesian coordinates x,y,z in double precision + + To use it add the line `#include ` + + See the documentation on the DisplacementVector3D page. + */ + typedef DisplacementVector3D< Cartesian3D, DefaultCoordinateSystemTag > XYZVector; + /** + 3D Vector based on the cartesian coordinates x,y,z in single precision + + To use it add the line `#include ` + + See the documentation on the DisplacementVector3D page. + */ + typedef DisplacementVector3D< Cartesian3D, DefaultCoordinateSystemTag > XYZVectorF; + typedef XYZVector XYZVectorD; + + /** + 3D Vector based on the eta based cylindrical coordinates rho, eta, phi in double precision. + + To use it add the line `#include ` + + See the documentation on the DisplacementVector3D page. + */ + typedef DisplacementVector3D< CylindricalEta3D, DefaultCoordinateSystemTag > RhoEtaPhiVector; + /** + 3D Vector based on the eta based cylindrical coordinates rho, eta, phi in single precision. + + To use it add the line `#include ` + + See the documentation on the DisplacementVector3D page. + */ + typedef DisplacementVector3D< CylindricalEta3D, DefaultCoordinateSystemTag > RhoEtaPhiVectorF; + typedef RhoEtaPhiVector RhoEtaPhiVectorD; + + /** + 3D Vector based on the polar coordinates rho, theta, phi in double precision. + + To use it add the line `#include ` + + See the documentation on the DisplacementVector3D page. + */ + typedef DisplacementVector3D< Polar3D, DefaultCoordinateSystemTag > Polar3DVector; + /** + 3D Vector based on the polar coordinates rho, theta, phi in single precision. + + To use it add the line `#include ` + + See the documentation on the DisplacementVector3D page. + */ + typedef DisplacementVector3D< Polar3D, DefaultCoordinateSystemTag > Polar3DVectorF; + typedef Polar3DVector Polar3DVectorD; + + /** + 3D Vector based on the cylindrical coordinates rho, z, phi in double precision. + + To use it add the line `#include ` + + See the documentation on the DisplacementVector3D page. + */ + typedef DisplacementVector3D< Cylindrical3D, DefaultCoordinateSystemTag > RhoZPhiVector; + /** + 3D Vector based on the cylindrical coordinates rho, z, phi in single precision. + + To use it add the line `#include ` + + See the documentation on the DisplacementVector3D page. + */ + typedef DisplacementVector3D< Cylindrical3D, DefaultCoordinateSystemTag > RhoZPhiVectorF; + typedef RhoZPhiVector RhoZPhiVectorD; + + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_MathX_Vector3Dfwd */ diff --git a/math/experimental/genvectorx/inc/MathX/Vector4D.h b/math/experimental/genvectorx/inc/MathX/Vector4D.h new file mode 100644 index 0000000000000..0c35f0dd987db --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector4D.h @@ -0,0 +1,33 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_Vector4D +#define ROOT_MathX_Vector4D + +// defines typedefs to specific vectors and forward declarations +// define additional (to Cartesian) coordinate system types +#include "MathX/Vector4Dfwd.h" +// generic LorentzVector class definition + +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/PtEtaPhiE4D.h" +#include "MathX/GenVectorX/PxPyPzM4D.h" +#include "MathX/GenVectorX/PtEtaPhiM4D.h" + + +#include "MathX/GenVectorX/LorentzVector.h" + +//#include "MathX/GenVectorX/PtEtaPhiMSystem.h" +//#include "MathX/GenVectorX/EEtaPhiMSystem.h" + + + +#endif + + + + + + + + diff --git a/math/experimental/genvectorx/inc/MathX/Vector4Dfwd.h b/math/experimental/genvectorx/inc/MathX/Vector4Dfwd.h new file mode 100644 index 0000000000000..97e52948b6c19 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector4Dfwd.h @@ -0,0 +1,102 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class LorentzVectorfwd +// +// Created by: moneta at Tue May 31 21:06:43 2005 +// +// Last update: Tue May 31 21:06:43 2005 +// +#ifndef ROOT_MathX_Vector4Dfwd +#define ROOT_MathX_Vector4Dfwd 1 + +#include "MathX/GenVectorX/AccHeaders.h" + + +namespace ROOT { + + namespace ROOT_MATH_ARCH { + + + // forward declarations of Lorentz Vectors and type defs definitions + + template class LorentzVector; + + template class PxPyPzE4D; + template class PtEtaPhiE4D; + template class PxPyPzM4D; + template class PtEtaPhiM4D; +// template class EEtaPhiMSystem; + + + // for LorentzVector have only double classes (define the vector in the global ref frame) + + /** + LorentzVector based on x,y,x,t (or px,py,pz,E) coordinates in double precision with metric (-,-,-,+) + + To use it add the line `#include ` + + See the documentation on the LorentzVector page. + */ + typedef LorentzVector > XYZTVector; + // for consistency + typedef LorentzVector > PxPyPzEVector; + + + /** + LorentzVector based on x,y,x,t (or px,py,pz,E) coordinates in float precision with metric (-,-,-,+) + + To use it add the line `#include ` + + See the documentation on the LorentzVector page. + */ + typedef LorentzVector< PxPyPzE4D > XYZTVectorF; + + + /** + LorentzVector based on the x, y, z, and Mass in double precision + + To use it add the line `#include ` + + See the documentation on the LorentzVector page. + */ + typedef LorentzVector > PxPyPzMVector; + + /** + LorentzVector based on the cylindrical coordinates Pt, eta, phi and E (rho, eta, phi, t) in double precision + + To use it add the line `#include ` + + See the documentation on the LorentzVector page. + */ + typedef LorentzVector > PtEtaPhiEVector; + + /** + LorentzVector based on the cylindrical coordinates pt, eta, phi and Mass in double precision + + To use it add the line `#include ` + + See the documentation on the LorentzVector page. + */ + typedef LorentzVector > PtEtaPhiMVector; + +// /** +// LorentzVector based on the coordinates E, Eta, Phi and Mass in double precision. These coordinates are normally used to represents a cluster objects in a calorimeter at a collider experiment. +// */ +// typedef BasicLorentzVector > LorentzVectorEEtaPhiM; + + + + } // end namespace Math + +} // end namespace ROOT + +#endif + diff --git a/math/experimental/genvectorx/inc/MathX/VectorUtil.h b/math/experimental/genvectorx/inc/MathX/VectorUtil.h new file mode 100644 index 0000000000000..87dc2566d213e --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/VectorUtil.h @@ -0,0 +1,11 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#ifndef ROOT_MathX_VectorUtil +#define ROOT_MathX_VectorUtil + + +#include "MathX/GenVectorX/VectorUtil.h" + + +#endif diff --git a/math/experimental/genvectorx/src/3DConversions.cxx b/math/experimental/genvectorx/src/3DConversions.cxx new file mode 100644 index 0000000000000..b680158dfce41 --- /dev/null +++ b/math/experimental/genvectorx/src/3DConversions.cxx @@ -0,0 +1,741 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005, LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Source file for something else +// +// Created by: Mark Fischler and Walter Brown Thurs July 7, 2005 +// +// Last update: $Id$ +// + +// TODO - For now, all conversions are grouped in this one compilation unit. +// The intention is to seraparte them into a few .cpp files instead, +// so that users needing one form need not incorporate code for them all. + +#include "MathX/GenVectorX/3DConversions.h" + +#include "Math/Math.h" + +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/AxisAngle.h" +#include "MathX/GenVectorX/EulerAngles.h" +#include "MathX/GenVectorX/Quaternion.h" +#include "MathX/GenVectorX/RotationZYX.h" +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" + +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { +namespace ROOT_MATH_ARCH { +namespace gv_detail { + +enum ERotation3DMatrixIndex +{ kXX = Rotation3D::kXX, kXY = Rotation3D::kXY, kXZ = Rotation3D::kXZ +, kYX = Rotation3D::kYX, kYY = Rotation3D::kYY, kYZ = Rotation3D::kYZ +, kZX = Rotation3D::kZX, kZY = Rotation3D::kZY, kZZ = Rotation3D::kZZ +}; + + +// ---------------------------------------------------------------------- +void convert( Rotation3D const & from, AxisAngle & to) +{ + // conversions from Rotation3D + double m[9]; + from.GetComponents(m, m+9); + + const double uZ = m[kYX] - m[kXY]; + const double uY = m[kXZ] - m[kZX]; + const double uX = m[kZY] - m[kYZ]; + + + // in case of rotation of an angle PI, the rotation matrix is symmetric and + // uX = uY = uZ = 0. Use then conversion through the quaternion + if ( math_fabs( uX ) < 8.*std::numeric_limits::epsilon() && + math_fabs( uY ) < 8.*std::numeric_limits::epsilon() && + math_fabs( uZ ) < 8.*std::numeric_limits::epsilon() ) { + Quaternion tmp; + convert (from,tmp); + convert (tmp,to); + return; + } + + AxisAngle::AxisVector u; + + u.SetCoordinates( uX, uY, uZ ); + + static const double pi = M_PI; + + double angle; + const double cosdelta = (m[kXX] + m[kYY] + m[kZZ] - 1.0) / 2.0; + if (cosdelta > 1.0) { + angle = 0; + } else if (cosdelta < -1.0) { + angle = pi; + } else { + angle = math_acos( cosdelta ); + } + + + //to.SetAngle(angle); + to.SetComponents(u, angle); + to.Rectify(); + +} // convert to AxisAngle + +static void correctByPi ( double& psi, double& phi ) { + static const double pi = M_PI; + if (psi > 0) { + psi -= pi; + } else { + psi += pi; + } + if (phi > 0) { + phi -= pi; + } else { + phi += pi; + } +} + +void convert( Rotation3D const & from, EulerAngles & to) +{ + // conversion from Rotation3D to Euler Angles + // Mathematical justification appears in + // http://www.cern.ch/mathlibs/documents/eulerAngleComputation.pdf + + double r[9]; + from.GetComponents(r,r+9); + + double phi, theta, psi; + double psiPlusPhi, psiMinusPhi; + static const double pi = M_PI; + static const double pi_2 = M_PI_2; + + theta = (math_fabs(r[kZZ]) <= 1.0) ? math_acos(r[kZZ]) : + (r[kZZ] > 0.0) ? 0 : pi; + + double cosTheta = r[kZZ]; + if (cosTheta > 1) cosTheta = 1; + if (cosTheta < -1) cosTheta = -1; + + // Compute psi +/- phi: + // Depending on whether cosTheta is positive or negative and whether it + // is less than 1 in absolute value, different mathematically equivalent + // expressions are numerically stable. + if (cosTheta == 1) { + psiPlusPhi = math_atan2 ( r[kXY] - r[kYX], r[kXX] + r[kYY] ); + psiMinusPhi = 0; + } else if (cosTheta >= 0) { + psiPlusPhi = math_atan2 ( r[kXY] - r[kYX], r[kXX] + r[kYY] ); + double s = -r[kXY] - r[kYX]; // sin (psi-phi) * (1 - cos theta) + double c = r[kXX] - r[kYY]; // cos (psi-phi) * (1 - cos theta) + psiMinusPhi = math_atan2 ( s, c ); + } else if (cosTheta > -1) { + psiMinusPhi = math_atan2 ( -r[kXY] - r[kYX], r[kXX] - r[kYY] ); + double s = r[kXY] - r[kYX]; // sin (psi+phi) * (1 + cos theta) + double c = r[kXX] + r[kYY]; // cos (psi+phi) * (1 + cos theta) + psiPlusPhi = math_atan2 ( s, c ); + } else { // cosTheta == -1 + psiMinusPhi = math_atan2 ( -r[kXY] - r[kYX], r[kXX] - r[kYY] ); + psiPlusPhi = 0; + } + + psi = .5 * (psiPlusPhi + psiMinusPhi); + phi = .5 * (psiPlusPhi - psiMinusPhi); + + // Now correct by pi if we have managed to get a value of psiPlusPhi + // or psiMinusPhi that was off by 2 pi: + + // set up w[i], all of which would be positive if sin and cosine of + // psi and phi were positive: + double w[4]; + w[0] = r[kXZ]; w[1] = r[kZX]; w[2] = r[kYZ]; w[3] = -r[kZY]; + + // find biggest relevant term, which is the best one to use in correcting. + double maxw = math_fabs(w[0]); + int imax = 0; + for (int i = 1; i < 4; ++i) { + if (math_fabs(w[i]) > maxw) { + maxw = math_fabs(w[i]); + imax = i; + } + } + // Determine if the correction needs to be applied: The criteria are + // different depending on whether a sine or cosine was the determinor: + switch (imax) { + case 0: + if (w[0] > 0 && psi < 0) correctByPi ( psi, phi ); + if (w[0] < 0 && psi > 0) correctByPi ( psi, phi ); + break; + case 1: + if (w[1] > 0 && phi < 0) correctByPi ( psi, phi ); + if (w[1] < 0 && phi > 0) correctByPi ( psi, phi ); + break; + case 2: + if (w[2] > 0 && math_fabs(psi) > pi_2) correctByPi ( psi, phi ); + if (w[2] < 0 && math_fabs(psi) < pi_2) correctByPi ( psi, phi ); + break; + case 3: + if (w[3] > 0 && math_fabs(phi) > pi_2) correctByPi ( psi, phi ); + if (w[3] < 0 && math_fabs(phi) < pi_2) correctByPi ( psi, phi ); + break; + } + + to.SetComponents( phi, theta, psi ); + +} // convert to EulerAngles + +//////////////////////////////////////////////////////////////////////////////// +/// conversion from Rotation3D to Quaternion + +void convert( Rotation3D const & from, Quaternion & to) +{ + double m[9]; + from.GetComponents(m, m+9); + + const double d0 = m[kXX] + m[kYY] + m[kZZ]; + const double d1 = + m[kXX] - m[kYY] - m[kZZ]; + const double d2 = - m[kXX] + m[kYY] - m[kZZ]; + const double d3 = - m[kXX] - m[kYY] + m[kZZ]; + + // these are related to the various q^2 values; + // choose the largest to avoid dividing two small numbers and losing accuracy. + + if ( d0 >= d1 && d0 >= d2 && d0 >= d3 ) { + const double q0 = .5*math_sqrt(1+d0); + const double f = .25/q0; + const double q1 = f*(m[kZY]-m[kYZ]); + const double q2 = f*(m[kXZ]-m[kZX]); + const double q3 = f*(m[kYX]-m[kXY]); + to.SetComponents(q0,q1,q2,q3); + to.Rectify(); + return; + } else if ( d1 >= d2 && d1 >= d3 ) { + const double q1 = .5*math_sqrt(1+d1); + const double f = .25/q1; + const double q0 = f*(m[kZY]-m[kYZ]); + const double q2 = f*(m[kXY]+m[kYX]); + const double q3 = f*(m[kXZ]+m[kZX]); + to.SetComponents(q0,q1,q2,q3); + to.Rectify(); + return; + } else if ( d2 >= d3 ) { + const double q2 = .5*math_sqrt(1+d2); + const double f = .25/q2; + const double q0 = f*(m[kXZ]-m[kZX]); + const double q1 = f*(m[kXY]+m[kYX]); + const double q3 = f*(m[kYZ]+m[kZY]); + to.SetComponents(q0,q1,q2,q3); + to.Rectify(); + return; + } else { + const double q3 = .5*math_sqrt(1+d3); + const double f = .25/q3; + const double q0 = f*(m[kYX]-m[kXY]); + const double q1 = f*(m[kXZ]+m[kZX]); + const double q2 = f*(m[kYZ]+m[kZY]); + to.SetComponents(q0,q1,q2,q3); + to.Rectify(); + return; + } +} // convert to Quaternion + +//////////////////////////////////////////////////////////////////////////////// +/// conversion from Rotation3D to RotationZYX +/// same Math used as for EulerAngles apart from some different meaning of angles and +/// matrix elements. But the basic algorithms principles are the same described in +/// http://www.cern.ch/mathlibs/documents/eulerAngleComputation.pdf + +void convert( Rotation3D const & from, RotationZYX & to) +{ + // theta is assumed to be in range [-PI/2,PI/2]. + // this is guaranteed by the Rectify function + + static const double pi_2 = M_PI_2; + + double r[9]; + from.GetComponents(r,r+9); + + double phi,theta,psi = 0; + + // careful for numeical error make sin(theta) ourtside [-1,1] + double sinTheta = r[kXZ]; + if ( sinTheta < -1.0) sinTheta = -1.0; + if ( sinTheta > 1.0) sinTheta = 1.0; + theta = math_asin( sinTheta ); + + // compute psi +/- phi + // Depending on whether cosTheta is positive or negative and whether it + // is less than 1 in absolute value, different mathematically equivalent + // expressions are numerically stable. + // algorithm from + // adapted for the case 3-2-1 + + double psiPlusPhi = 0; + double psiMinusPhi = 0; + + // valid if sinTheta not eq to -1 otherwise is zero + if (sinTheta > - 1.0) + psiPlusPhi = atan2 ( r[kYX] + r[kZY], r[kYY] - r[kZX] ); + + // valid if sinTheta not eq. to 1 + if (sinTheta < 1.0) + psiMinusPhi = atan2 ( r[kZY] - r[kYX] , r[kYY] + r[kZX] ); + + psi = .5 * (psiPlusPhi + psiMinusPhi); + phi = .5 * (psiPlusPhi - psiMinusPhi); + + // correction is not necessary if sinTheta = +/- 1 + //if (sinTheta == 1.0 || sinTheta == -1.0) return; + + // apply the corrections according to max of the other terms + // I think is assumed convention that theta is between -PI/2,PI/2. + // OTHERWISE RESULT MIGHT BE DIFFERENT ??? + + //since we determine phi+psi or phi-psi phi and psi can be both have a shift of +/- PI. + // The shift must be applied on both (the sum (or difference) is knows to +/- 2PI ) + //This can be fixed looking at the other 4 matrix terms, which have terms in sin and cos of psi + // and phi. sin(psi+/-PI) = -sin(psi) and cos(psi+/-PI) = -cos(psi). + //Use then the biggest term for making the correction to minimize possible numerical errors + + // set up w[i], all of which would be positive if sin and cosine of + // psi and phi were positive: + double w[4]; + w[0] = -r[kYZ]; w[1] = -r[kXY]; w[2] = r[kZZ]; w[3] = r[kXX]; + + // find biggest relevant term, which is the best one to use in correcting. + double maxw = math_fabs(w[0]); + int imax = 0; + for (int i = 1; i < 4; ++i) { + if (math_fabs(w[i]) > maxw) { + maxw = math_fabs(w[i]); + imax = i; + } + } + + // Determine if the correction needs to be applied: The criteria are + // different depending on whether a sine or cosine was the determinor: + switch (imax) { + case 0: + if (w[0] > 0 && psi < 0) correctByPi ( psi, phi ); + if (w[0] < 0 && psi > 0) correctByPi ( psi, phi ); + break; + case 1: + if (w[1] > 0 && phi < 0) correctByPi ( psi, phi ); + if (w[1] < 0 && phi > 0) correctByPi ( psi, phi ); + break; + case 2: + if (w[2] > 0 && math_fabs(psi) > pi_2) correctByPi ( psi, phi ); + if (w[2] < 0 && math_fabs(psi) < pi_2) correctByPi ( psi, phi ); + break; + case 3: + if (w[3] > 0 && math_fabs(phi) > pi_2) correctByPi ( psi, phi ); + if (w[3] < 0 && math_fabs(phi) < pi_2) correctByPi ( psi, phi ); + break; + } + + to.SetComponents(phi, theta, psi); + +} // convert to RotationZYX + +// ---------------------------------------------------------------------- +// conversions from AxisAngle + +void convert( AxisAngle const & from, Rotation3D & to) +{ + // conversion from AxisAngle to Rotation3D + + const double sinDelta = math_sin( from.Angle() ); + const double cosDelta = math_cos( from.Angle() ); + const double oneMinusCosDelta = 1.0 - cosDelta; + + const AxisAngle::AxisVector & u = from.Axis(); + const double uX = u.X(); + const double uY = u.Y(); + const double uZ = u.Z(); + + double m[9]; + + m[kXX] = oneMinusCosDelta * uX * uX + cosDelta; + m[kXY] = oneMinusCosDelta * uX * uY - sinDelta * uZ; + m[kXZ] = oneMinusCosDelta * uX * uZ + sinDelta * uY; + + m[kYX] = oneMinusCosDelta * uY * uX + sinDelta * uZ; + m[kYY] = oneMinusCosDelta * uY * uY + cosDelta; + m[kYZ] = oneMinusCosDelta * uY * uZ - sinDelta * uX; + + m[kZX] = oneMinusCosDelta * uZ * uX - sinDelta * uY; + m[kZY] = oneMinusCosDelta * uZ * uY + sinDelta * uX; + m[kZZ] = oneMinusCosDelta * uZ * uZ + cosDelta; + + to.SetComponents(m,m+9); +} // convert to Rotation3D + +void convert( AxisAngle const & from , EulerAngles & to ) +{ + // conversion from AxisAngle to EulerAngles + // TODO better : temporary make conversion using Rotation3D + + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} + +void convert( AxisAngle const & from, Quaternion & to) +{ + // conversion from AxisAngle to Quaternion + + double s = math_sin (from.Angle()/2); + DisplacementVector3D< Cartesian3D > axis = from.Axis(); + + to.SetComponents( math_cos(from.Angle()/2), + s*axis.X(), + s*axis.Y(), + s*axis.Z() + ); +} // convert to Quaternion + +void convert( AxisAngle const & from , RotationZYX & to ) +{ + // conversion from AxisAngle to RotationZYX + // TODO better : temporary make conversion using Rotation3D + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} + + +// ---------------------------------------------------------------------- +// conversions from EulerAngles + +void convert( EulerAngles const & from, Rotation3D & to) +{ + // conversion from EulerAngles to Rotation3D + + typedef double Scalar; + const Scalar sPhi = math_sin( from.Phi() ); + const Scalar cPhi = math_cos( from.Phi() ); + const Scalar sTheta = math_sin( from.Theta() ); + const Scalar cTheta = math_cos( from.Theta() ); + const Scalar sPsi = math_sin( from.Psi() ); + const Scalar cPsi = math_cos( from.Psi() ); + to.SetComponents + ( cPsi*cPhi-sPsi*cTheta*sPhi, cPsi*sPhi+sPsi*cTheta*cPhi, sPsi*sTheta + , -sPsi*cPhi-cPsi*cTheta*sPhi, -sPsi*sPhi+cPsi*cTheta*cPhi, cPsi*sTheta + , sTheta*sPhi, -sTheta*cPhi, cTheta + ); +} + +void convert( EulerAngles const & from, AxisAngle & to) +{ + // conversion from EulerAngles to AxisAngle + // make converting first to quaternion + Quaternion q; + convert (from, q); + convert (q, to); +} + +void convert( EulerAngles const & from, Quaternion & to) +{ + // conversion from EulerAngles to Quaternion + + typedef double Scalar; + const Scalar plus = (from.Phi()+from.Psi())/2; + const Scalar minus = (from.Phi()-from.Psi())/2; + const Scalar sPlus = math_sin( plus ); + const Scalar cPlus = math_cos( plus ); + const Scalar sMinus = math_sin( minus ); + const Scalar cMinus = math_cos( minus ); + const Scalar sTheta = math_sin( from.Theta()/2 ); + const Scalar cTheta = math_cos( from.Theta()/2 ); + + to.SetComponents ( cTheta*cPlus, -sTheta*cMinus, -sTheta*sMinus, -cTheta*sPlus ); + // TODO -- carefully check that this is correct +} + +void convert( EulerAngles const & from , RotationZYX & to ) +{ + // conversion from EulerAngles to RotationZYX + // TODO better : temporary make conversion using Rotation3D + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} + + +// ---------------------------------------------------------------------- +// conversions from Quaternion + +void convert( Quaternion const & from, Rotation3D & to) +{ + // conversion from Quaternion to Rotation3D + + const double q0 = from.U(); + const double q1 = from.I(); + const double q2 = from.J(); + const double q3 = from.K(); + const double q00 = q0*q0; + const double q01 = q0*q1; + const double q02 = q0*q2; + const double q03 = q0*q3; + const double q11 = q1*q1; + const double q12 = q1*q2; + const double q13 = q1*q3; + const double q22 = q2*q2; + const double q23 = q2*q3; + const double q33 = q3*q3; + + to.SetComponents ( + q00+q11-q22-q33 , 2*(q12-q03) , 2*(q02+q13), + 2*(q12+q03) , q00-q11+q22-q33 , 2*(q23-q01), + 2*(q13-q02) , 2*(q23+q01) , q00-q11-q22+q33 ); + +} // conversion to Rotation3D + +void convert( Quaternion const & from, AxisAngle & to) +{ + // conversion from Quaternion to AxisAngle + + double u = from.U(); + if ( u >= 0 ) { + if ( u > 1 ) u = 1; + const double angle = 2.0 * math_acos ( from.U() ); + DisplacementVector3D< Cartesian3D > + axis (from.I(), from.J(), from.K()); + to.SetComponents ( axis, angle ); + } else { + if ( u < -1 ) u = -1; + const double angle = 2.0 * math_acos ( -from.U() ); + DisplacementVector3D< Cartesian3D > + axis (-from.I(), -from.J(), -from.K()); + to.SetComponents ( axis, angle ); + } +} // conversion to AxisAngle + +void convert( Quaternion const & from, EulerAngles & to ) +{ + // conversion from Quaternion to EulerAngles + // TODO better + // temporary make conversion using Rotation3D + + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} + +void convert( Quaternion const & from , RotationZYX & to ) +{ + // conversion from Quaternion to RotationZYX + // TODO better : temporary make conversion using Rotation3D + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} + +// ---------------------------------------------------------------------- +// conversions from RotationZYX +void convert( RotationZYX const & from, Rotation3D & to) { + // conversion to Rotation3D (matrix) + + double phi,theta,psi = 0; + from.GetComponents(phi,theta,psi); + to.SetComponents( math_cos(theta)*math_cos(phi), + - math_cos(theta)*math_sin(phi), + math_sin(theta), + + math_cos(psi)*math_sin(phi) + math_sin(psi)*math_sin(theta)*math_cos(phi), + math_cos(psi)*math_cos(phi) - math_sin(psi)*math_sin(theta)*math_sin(phi), + -math_sin(psi)*math_cos(theta), + + math_sin(psi)*math_sin(phi) - math_cos(psi)*math_sin(theta)*math_cos(phi), + math_sin(psi)*math_cos(phi) + math_cos(psi)*math_sin(theta)*math_sin(phi), + math_cos(psi)*math_cos(theta) + ); + +} +void convert( RotationZYX const & from, AxisAngle & to) { + // conversion to axis angle + // TODO better : temporary make conversion using Rotation3D + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} +void convert( RotationZYX const & from, EulerAngles & to) { + // conversion to Euler angle + // TODO better : temporary make conversion using Rotation3D + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} +void convert( RotationZYX const & from, Quaternion & to) { + double phi,theta,psi = 0; + from.GetComponents(phi,theta,psi); + + double sphi2 = math_sin(phi/2); + double cphi2 = math_cos(phi/2); + double stheta2 = math_sin(theta/2); + double ctheta2 = math_cos(theta/2); + double spsi2 = math_sin(psi/2); + double cpsi2 = math_cos(psi/2); + to.SetComponents( cphi2 * cpsi2 * ctheta2 - sphi2 * spsi2 * stheta2, + sphi2 * cpsi2 * stheta2 + cphi2 * spsi2 * ctheta2, + cphi2 * cpsi2 * stheta2 - sphi2 * spsi2 * ctheta2, + sphi2 * cpsi2 * ctheta2 + cphi2 * spsi2 * stheta2 + ); +} + + +// ---------------------------------------------------------------------- +// conversions from RotationX + +void convert( RotationX const & from, Rotation3D & to) +{ + // conversion from RotationX to Rotation3D + + const double c = from.CosAngle(); + const double s = from.SinAngle(); + to.SetComponents ( 1, 0, 0, + 0, c, -s, + 0, s, c ); +} + +void convert( RotationX const & from, AxisAngle & to) +{ + // conversion from RotationX to AxisAngle + + DisplacementVector3D< Cartesian3D > axis (1, 0, 0); + to.SetComponents ( axis, from.Angle() ); +} + +void convert( RotationX const & from , EulerAngles & to ) +{ + // conversion from RotationX to EulerAngles + //TODO better: temporary make conversion using Rotation3D + + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} + +void convert( RotationX const & from, Quaternion & to) +{ + // conversion from RotationX to Quaternion + + to.SetComponents (math_cos(from.Angle()/2), math_sin(from.Angle()/2), 0, 0); +} + +void convert( RotationX const & from , RotationZYX & to ) +{ + // conversion from RotationX to RotationZYX + to.SetComponents(0,0,from.Angle()); +} + + +// ---------------------------------------------------------------------- +// conversions from RotationY + +void convert( RotationY const & from, Rotation3D & to) +{ + // conversion from RotationY to Rotation3D + + const double c = from.CosAngle(); + const double s = from.SinAngle(); + to.SetComponents ( c, 0, s, + 0, 1, 0, + -s, 0, c ); +} + +void convert( RotationY const & from, AxisAngle & to) +{ + // conversion from RotationY to AxisAngle + + DisplacementVector3D< Cartesian3D > axis (0, 1, 0); + to.SetComponents ( axis, from.Angle() ); +} + +void convert( RotationY const & from, EulerAngles & to ) +{ + // conversion from RotationY to EulerAngles + // TODO better: temporary make conversion using Rotation3D + + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} + +void convert( RotationY const & from , RotationZYX & to ) +{ + // conversion from RotationY to RotationZYX + to.SetComponents(0,from.Angle(),0); +} + + +void convert( RotationY const & from, Quaternion & to) +{ + // conversion from RotationY to Quaternion + + to.SetComponents (math_cos(from.Angle()/2), 0, math_sin(from.Angle()/2), 0); +} + + + +// ---------------------------------------------------------------------- +// conversions from RotationZ + +void convert( RotationZ const & from, Rotation3D & to) +{ + // conversion from RotationZ to Rotation3D + + const double c = from.CosAngle(); + const double s = from.SinAngle(); + to.SetComponents ( c, -s, 0, + s, c, 0, + 0, 0, 1 ); +} + +void convert( RotationZ const & from, AxisAngle & to) +{ + // conversion from RotationZ to AxisAngle + + DisplacementVector3D< Cartesian3D > axis (0, 0, 1); + to.SetComponents ( axis, from.Angle() ); +} + +void convert( RotationZ const & from , EulerAngles & to ) +{ + // conversion from RotationZ to EulerAngles + // TODO better: temporary make conversion using Rotation3D + + Rotation3D tmp; + convert(from,tmp); + convert(tmp,to); +} + +void convert( RotationZ const & from , RotationZYX & to ) +{ + // conversion from RotationY to RotationZYX + to.SetComponents(from.Angle(),0,0); +} + +void convert( RotationZ const & from, Quaternion & to) +{ + // conversion from RotationZ to Quaternion + + to.SetComponents (math_cos(from.Angle()/2), 0, 0, math_sin(from.Angle()/2)); +} + +} //namespace gv_detail +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/3DDistances.cxx b/math/experimental/genvectorx/src/3DDistances.cxx new file mode 100644 index 0000000000000..e31c4b1df3f7f --- /dev/null +++ b/math/experimental/genvectorx/src/3DDistances.cxx @@ -0,0 +1,346 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005, LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Source file for something else +// +// Created by: Mark Fischler Thurs July 7, 2005 +// +// Last update: Wed Thurs July 7, 2005 +// + + +#include "MathX/GenVectorX/3DDistances.h" + +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/AxisAngle.h" +#include "MathX/GenVectorX/EulerAngles.h" +#include "MathX/GenVectorX/Quaternion.h" +#include "MathX/GenVectorX/RotationZYX.h" +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" + +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { +namespace ROOT_MATH_ARCH { +namespace gv_detail { + + +enum ERotation3DMatrixIndex +{ kXX = 0, kXY = 1, kXZ = 2 +, kYX = 3, kYY = 4, kYZ = 5 +, kZX = 6, kZY = 7, kZZ = 8 +}; + + +// ---------------------------------------------------------------------- +// distance from Rotation3D + +double dist( Rotation3D const & from, Rotation3D const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( Rotation3D const & from, AxisAngle const & to) +{ return Quaternion(from).Distance(Quaternion(to));} + +double dist( Rotation3D const & from, EulerAngles const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( Rotation3D const & from, Quaternion const & to) +{ return Quaternion(from).Distance(to); } + +double dist( Rotation3D const & from, RotationZYX const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} +double dist( Rotation3D const & from, RotationX const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( Rotation3D const & from, RotationY const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( Rotation3D const & from, RotationZ const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + + + +// ---------------------------------------------------------------------- +// distance from AxisAngle + +double dist( AxisAngle const & from, Rotation3D const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( AxisAngle const & from, AxisAngle const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( AxisAngle const & from, EulerAngles const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( AxisAngle const & from, Quaternion const & to) +{ return Quaternion(from).Distance(to); } + +double dist( AxisAngle const & from, RotationZYX const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( AxisAngle const & from, RotationX const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( AxisAngle const & from, RotationY const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( AxisAngle const & from, RotationZ const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + + + +// ---------------------------------------------------------------------- +// distance from EulerAngles + +double dist( EulerAngles const & from, Rotation3D const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( EulerAngles const & from, AxisAngle const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( EulerAngles const & from, EulerAngles const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( EulerAngles const & from, Quaternion const & to) +{ return Quaternion(from).Distance(to); } + +double dist( EulerAngles const & from, RotationZYX const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( EulerAngles const & from, RotationX const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( EulerAngles const & from, RotationY const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( EulerAngles const & from, RotationZ const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + + + +// ---------------------------------------------------------------------- +// distance from Quaternion + +double dist( Quaternion const & from, Rotation3D const & to) +{ return from.Distance(Quaternion(to)); } + +double dist( Quaternion const & from, AxisAngle const & to) +{ return from.Distance(Quaternion(to)); } + +double dist( Quaternion const & from, EulerAngles const & to) +{ return from.Distance(Quaternion(to)); } + +double dist( Quaternion const & from, Quaternion const & to) +{ return from.Distance(to); } + +double dist( Quaternion const & from, RotationZYX const & to) +{ return from.Distance(Quaternion(to)); } + +double dist( Quaternion const & from, RotationX const & to) +{ /*TODO*/ + return from.Distance(Quaternion(to)); +} + +double dist( Quaternion const & from, RotationY const & to) +{ /*TODO*/ + return from.Distance(Quaternion(to)); +} + +double dist( Quaternion const & from, RotationZ const & to) +{ /*TODO*/ + return from.Distance(Quaternion(to)); +} + +// ---------------------------------------------------------------------- +// distance from RotationZYX + +double dist( RotationZYX const & from, Rotation3D const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationZYX const & from, AxisAngle const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationZYX const & from, EulerAngles const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationZYX const & from, Quaternion const & to) +{ return Quaternion(from).Distance(to); } + +double dist( RotationZYX const & from, RotationZYX const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationZYX const & from, RotationX const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationZYX const & from, RotationY const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationZYX const & from, RotationZ const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + + + +// ---------------------------------------------------------------------- +// distance from RotationX + +double dist( RotationX const & from, Rotation3D const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationX const & from, AxisAngle const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationX const & from, EulerAngles const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationX const & from, Quaternion const & to) +{ return Quaternion(from).Distance(to); } + +double dist( RotationX const & from, RotationZYX const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationX const & from, RotationX const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationX const & from, RotationY const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationX const & from, RotationZ const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + + + +// ---------------------------------------------------------------------- +// distance from RotationY + +double dist( RotationY const & from, Rotation3D const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationY const & from, AxisAngle const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationY const & from, EulerAngles const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationY const & from, Quaternion const & to) +{ return Quaternion(from).Distance(to); } + +double dist( RotationY const & from, RotationZYX const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationY const & from, RotationX const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationY const & from, RotationY const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationY const & from, RotationZ const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + + + +// ---------------------------------------------------------------------- +// distance from RotationZ + +double dist( RotationZ const & from, Rotation3D const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationZ const & from, AxisAngle const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationZ const & from, EulerAngles const & to) +{ return Quaternion(from).Distance(Quaternion(to)); } + +double dist( RotationZ const & from, Quaternion const & to) +{ return Quaternion(from).Distance(to); } + +double dist( RotationZ const & from, RotationZYX const & to) +{ /*TODO better */ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationZ const & from, RotationX const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationZ const & from, RotationY const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + +double dist( RotationZ const & from, RotationZ const & to) +{ /*TODO*/ + return Quaternion(from).Distance(Quaternion(to)); +} + + +} //namespace gv_detail +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/AxisAngle.cxx b/math/experimental/genvectorx/src/AxisAngle.cxx new file mode 100644 index 0000000000000..86a171d47c0b0 --- /dev/null +++ b/math/experimental/genvectorx/src/AxisAngle.cxx @@ -0,0 +1,107 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class AxisAngle, a rotation in 3 dimensions +// represented by its axis and angle of rotation +// +// Created by: Mark Fischler Tues July 5 2005 +// +#include "MathX/GenVectorX/AxisAngle.h" + +#include +#include + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Rotation3D.h" + + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +// ========== Constructors and Assignment ===================== + +void AxisAngle::RectifyAngle() { + // Note: We could require the angle to be in [0,pi) since we + // can represent negative angles by flipping the axis. + // We choose not to do this. + + if ( fAngle <= Pi() && fAngle > -Pi() ) return; + + if ( fAngle > 0 ) { + int n = static_cast( (fAngle+Pi())/(2*Pi()) ); + fAngle -= 2*Pi()*n; + } else { + int n = static_cast( -(fAngle-Pi())/(2*Pi()) ); + fAngle += 2*Pi()*n; + } +} // RectifyAngle() + +void AxisAngle::Rectify() +{ + // The two conditions are that the angle is in (-pi, pi] and + // the axis is a unit vector. + + Scalar r2 = fAxis.Mag2(); + if ( r2 == 0 ) { + fAxis.SetCoordinates(0,0,1); + fAngle = 0; + return; + } + fAxis *= (1.0/r2); + RectifyAngle(); +} // Rectify() + +// ======== Transformation to other Rotation Forms ================== + +enum ERotation3DMatrixIndex { + kXX = 0, kXY = 1, kXZ = 2 + , kYX = 3, kYY = 4, kYZ = 5 + , kZX = 6, kZY = 7, kZZ = 8 +}; + + + +// ========== Operations ===================== + +DisplacementVector3D< Cartesian3D > +AxisAngle:: +operator() (const XYZVector & v) const +{ + Scalar c = math_cos(fAngle); + Scalar s = math_sin(fAngle); + Scalar p = fAxis.Dot(v) * ( 1 - c ); + return DisplacementVector3D< Cartesian3D > + ( + c*v.X() + p*fAxis.X() + s * (fAxis.Y()*v.Z() - fAxis.Z()*v.Y()) + , c*v.Y() + p*fAxis.Y() + s * (fAxis.Z()*v.X() - fAxis.X()*v.Z()) + , c*v.Z() + p*fAxis.Z() + s * (fAxis.X()*v.Y() - fAxis.Y()*v.X()) + ); +} + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// ========== I/O ===================== + +std::ostream & operator<< (std::ostream & os, const AxisAngle & a) { + // TODO - this will need changing for machine-readable issues + // and even the human readable form may need formatting improvements + os << "\n" << a.Axis() << " " << a.Angle() << "\n"; + return os; +} +#endif + + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/AxisAngleXother.cxx b/math/experimental/genvectorx/src/AxisAngleXother.cxx new file mode 100644 index 0000000000000..9dd42485b41b3 --- /dev/null +++ b/math/experimental/genvectorx/src/AxisAngleXother.cxx @@ -0,0 +1,199 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for multiplications of AxisAngle by a rotation +// +// Created by: Mark Fischler Tues July 5 2005 +// + +#include "MathX/GenVectorX/AxisAngle.h" + +#include + +#include "MathX/GenVectorX/Quaternion.h" +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" + +#include "MathX/GenVectorX/Rotation3Dfwd.h" +#include "MathX/GenVectorX/EulerAnglesfwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + +AxisAngle AxisAngle::operator * (const Rotation3D & r) const { + // combination with a Rotation3D + return operator* ( Quaternion(r) ); + +} + +AxisAngle AxisAngle::operator * (const AxisAngle & a) const { + // combination with another AxisAngle + return operator* ( Quaternion(a) ); +} + +AxisAngle AxisAngle::operator * (const EulerAngles & e) const { + // combination with EulerAngles + return operator* ( Quaternion(e) ); +} + +AxisAngle AxisAngle::operator * (const RotationZYX & r) const { + // combination with RotationZYX + return operator* ( Quaternion(r) ); +} + +AxisAngle AxisAngle::operator * (const Quaternion & q) const { + // combination with Quaternion + return AxisAngle ( Quaternion(*this) * q ); +} + +#ifdef MOVE + +AxisAngle AxisAngle::operator * (const Quaternion & q) const { + // combination with quaternion (not used) + const Scalar s1 = math_sin(fAngle/2); + const Scalar au = math_cos(fAngle/2); + const Scalar ai = s1 * fAxis.X(); + const Scalar aj = s1 * fAxis.Y(); + const Scalar ak = s1 * fAxis.Z(); + Scalar aqu = au*q.U() - ai*q.I() - aj*q.J() - ak*q.K(); + Scalar aqi = au*q.I() + ai*q.U() + aj*q.K() - ak*q.J(); + Scalar aqj = au*q.J() - ai*q.K() + aj*q.U() + ak*q.I(); + Scalar aqk = au*q.K() + ai*q.J() - aj*q.I() + ak*q.U(); + Scalar r = math_sqrt(aqi*aqi + aqj*aqj + aqk*aqk); + if (r > 1) r = 1; + if (aqu < 0) { aqu = - aqu; aqi = - aqi; aqj = - aqj, aqk = - aqk; } + const Scalar angle = 2*math_asin ( r ); + DisplacementVector3D< Cartesian3D > axis ( aqi, aqj, aqk ); + if ( r == 0 ) { + axis.SetCoordinates(0,0,1); + } else { + axis /= r; + } + return AxisAngle ( axis, angle ); +} + +#endif + +AxisAngle AxisAngle::operator * (const RotationX & rx) const { + // combination with RotationX + + const Scalar s1 = math_sin(fAngle/2); + const Scalar au = math_cos(fAngle/2); + const Scalar ai = s1 * fAxis.X(); + const Scalar aj = s1 * fAxis.Y(); + const Scalar ak = s1 * fAxis.Z(); + Scalar c = rx.CosAngle(); + if ( c > 1 ) c = 1; + if ( c < -1 ) c = -1; + Scalar qu = math_sqrt( .5*(1+c) ); + Scalar qi = math_sqrt( .5*(1-c) ); + if ( rx.SinAngle() < 0 ) qi = -qi; + Scalar aqu = au*qu - ai*qi; + Scalar aqi = ai*qu + au*qi; + Scalar aqj = aj*qu + ak*qi; + Scalar aqk = ak*qu - aj*qi; + Scalar r = math_sqrt(aqi*aqi + aqj*aqj + aqk*aqk); + if (r > 1) r = 1; + if (aqu < 0) { aqu = - aqu; aqi = - aqi; aqj = - aqj, aqk = - aqk; } + const Scalar angle = 2*math_asin ( r ); + DisplacementVector3D< Cartesian3D > axis ( aqi, aqj, aqk ); + if ( r == 0 ) { + axis.SetCoordinates(0,0,1); + } else { + axis /= r; + } + return AxisAngle ( axis, angle ); +} + +AxisAngle AxisAngle::operator * (const RotationY & ry) const { + // combination with RotationY + + const Scalar s1 = math_sin(fAngle/2); + const Scalar au = math_cos(fAngle/2); + const Scalar ai = s1 * fAxis.X(); + const Scalar aj = s1 * fAxis.Y(); + const Scalar ak = s1 * fAxis.Z(); + Scalar c = ry.CosAngle(); + if ( c > 1 ) c = 1; + if ( c < -1 ) c = -1; + Scalar qu = math_sqrt( .5*(1+c) ); + Scalar qj = math_sqrt( .5*(1-c) ); + if ( ry.SinAngle() < 0 ) qj = -qj; + Scalar aqu = au*qu - aj*qj; + Scalar aqi = ai*qu - ak*qj; + Scalar aqj = aj*qu + au*qj; + Scalar aqk = ak*qu + ai*qj; + Scalar r = math_sqrt(aqi*aqi + aqj*aqj + aqk*aqk); + if (r > 1) r = 1; + if (aqu < 0) { aqu = - aqu; aqi = - aqi; aqj = - aqj, aqk = - aqk; } + const Scalar angle = 2*math_asin ( r ); + DisplacementVector3D< Cartesian3D > axis ( aqi, aqj, aqk ); + if ( r == 0 ) { + axis.SetCoordinates(0,0,1); + } else { + axis /= r; + } + return AxisAngle ( axis, angle ); +} + +AxisAngle AxisAngle::operator * (const RotationZ & rz) const { + // combination with RotationZ + + const Scalar s1 = math_sin(fAngle/2); + const Scalar au = math_cos(fAngle/2); + const Scalar ai = s1 * fAxis.X(); + const Scalar aj = s1 * fAxis.Y(); + const Scalar ak = s1 * fAxis.Z(); + Scalar c = rz.CosAngle(); + if ( c > 1 ) c = 1; + if ( c < -1 ) c = -1; + Scalar qu = math_sqrt( .5*(1+c) ); + Scalar qk = math_sqrt( .5*(1-c) ); + if ( rz.SinAngle() < 0 ) qk = -qk; + Scalar aqu = au*qu - ak*qk; + Scalar aqi = ai*qu + aj*qk; + Scalar aqj = aj*qu - ai*qk; + Scalar aqk = ak*qu + au*qk; + Scalar r = math_sqrt(aqi*aqi + aqj*aqj + aqk*aqk); + if (r > 1) r = 1; + if (aqu < 0) { aqu = - aqu; aqi = - aqi; aqj = - aqj, aqk = - aqk; } + const Scalar angle = 2*math_asin ( r ); + DisplacementVector3D< Cartesian3D > axis ( aqi, aqj, aqk ); + if ( r == 0 ) { + axis.SetCoordinates(0,0,1); + } else { + axis /= r; + } + return AxisAngle ( axis, angle ); +} + +AxisAngle operator*( RotationX const & r, AxisAngle const & a ) { + return AxisAngle(r) * a; // TODO: improve performance +} + +AxisAngle operator*( RotationY const & r, AxisAngle const & a ) { + return AxisAngle(r) * a; // TODO: improve performance +} + +AxisAngle operator*( RotationZ const & r, AxisAngle const & a ) { + return AxisAngle(r) * a; // TODO: improve performance +} + + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/BitReproducible.cxx b/math/experimental/genvectorx/src/BitReproducible.cxx new file mode 100644 index 0000000000000..f594dd4ff5368 --- /dev/null +++ b/math/experimental/genvectorx/src/BitReproducible.cxx @@ -0,0 +1,140 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#include "MathX/GenVectorX/BitReproducible.h" + +#include +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +namespace ROOT { +namespace ROOT_MATH_ARCH { +namespace GenVector_detail { + +bool BitReproducible::fgByte_order_known = false; +int BitReproducible::fgByte_order[8]; + +void BitReproducible::Fill_byte_order () { + // Fill_byte_order + double x = 1.0; + int t30 = 1 << 30; + int t22 = 1 << 22; + x *= t30; + x *= t22; + double y = 1; + double z = 1; + x *= z; + for (int k=0; k<6; k++) { + x += y*z; + y += 1; + z *= 256; + } + // x, in IEEE format, would now be 0x4330060504030201 + DB8 xb; + xb.fD = x; + int n; + static const int kUNSET = -1; + for (n=0; n<8; n++) { + fgByte_order[n] = kUNSET; + } + int order; + for (n=0; n<8; n++) { + switch ( xb.fB[n] ) { + case 0x43: + order = 0; + break; + case 0x30: + order = 1; + break; + case 0x06: + order = 2; + break; + case 0x05: + order = 3; + break; + case 0x04: + order = 4; + break; + case 0x03: + order = 5; + break; + case 0x02: + order = 6; + break; + case 0x01: + order = 7; + break; + default: + throw BitReproducibleException( + "Cannot determine byte-ordering of doubles on this system"); + } + if (fgByte_order[n] != kUNSET) { + throw BitReproducibleException( + "Confusion in byte-ordering of doubles on this system"); + } + fgByte_order[n] = order; + fgByte_order_known = true; + } + return; +} + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +std::string BitReproducible::D2x(double d) { + // hex conversion + if ( !fgByte_order_known ) Fill_byte_order (); + DB8 db; + db.fD = d; + std::ostringstream ss; + for (int i=0; i<8; ++i) { + int k = fgByte_order[i]; + ss << std::hex << std::setw(2) << std::setfill('0') << (int)db.fB[k]; + } + return ss.str(); +} +#endif + +void BitReproducible::Dto2longs(double d, unsigned int& i, unsigned int& j) { + // conversion to 2 longs + if ( !fgByte_order_known ) Fill_byte_order (); + DB8 db; + db.fD = d; + i = ((static_cast(db.fB[fgByte_order[0]])) << 24) + | ((static_cast(db.fB[fgByte_order[1]])) << 16) + | ((static_cast(db.fB[fgByte_order[2]])) << 8) + | ((static_cast(db.fB[fgByte_order[3]])) ); + j = ((static_cast(db.fB[fgByte_order[4]])) << 24) + | ((static_cast(db.fB[fgByte_order[5]])) << 16) + | ((static_cast(db.fB[fgByte_order[6]])) << 8) + | ((static_cast(db.fB[fgByte_order[7]])) ); +} + +double BitReproducible::Longs2double (unsigned int i, unsigned int j) { + // conversion longs to double + DB8 db; + unsigned char bytes[8]; + if ( !fgByte_order_known ) Fill_byte_order (); + bytes[0] = static_cast((i >> 24) & 0xFF); + bytes[1] = static_cast((i >> 16) & 0xFF); + bytes[2] = static_cast((i >> 8) & 0xFF); + bytes[3] = static_cast((i ) & 0xFF); + bytes[4] = static_cast((j >> 24) & 0xFF); + bytes[5] = static_cast((j >> 16) & 0xFF); + bytes[6] = static_cast((j >> 8) & 0xFF); + bytes[7] = static_cast((j ) & 0xFF); + for (int k=0; k<8; ++k) { + db.fB[fgByte_order[k]] = bytes[k]; + } + return db.fD; +} + +} // namespace _GenVector_detail +} // namespace Math +} // namespace ROOT + +#endif \ No newline at end of file diff --git a/math/experimental/genvectorx/src/Boost.cxx b/math/experimental/genvectorx/src/Boost.cxx new file mode 100644 index 0000000000000..98754fe982d99 --- /dev/null +++ b/math/experimental/genvectorx/src/Boost.cxx @@ -0,0 +1,195 @@ +// @(#)root/mathcore:$Id$ +// Authors: M. Fischler 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Boost, a 4x4 symmetric matrix representation of +// an axial Lorentz transformation +// +// Created by: Mark Fischler Mon Nov 1 2005 +// +#include "MathX/GenVectorX/Boost.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/GenVector_exception.h" + +#include +#include + +//#ifdef TEX +/** + + A variable names bgamma appears in several places in this file. A few + words of elaboration are needed to make its meaning clear. On page 69 + of Misner, Thorne and Wheeler, (Exercise 2.7) the elements of the matrix + for a general Lorentz boost are given as + + \f[ \Lambda^{j'}_k = \Lambda^{k'}_j + = (\gamma - 1) n^j n^k + \delta^{jk} \f] + + where the n^i are unit vectors in the direction of the three spatial + axes. Using the definitions, \f$ n^i = \beta_i/\beta \f$ , then, for example, + + \f[ \Lambda_{xy} = (\gamma - 1) n_x n_y + = (\gamma - 1) \beta_x \beta_y/\beta^2 \f] + + By definition, \f[ \gamma^2 = 1/(1 - \beta^2) \f] + + so that \f[ \gamma^2 \beta^2 = \gamma^2 - 1 \f] + + or \f[ \beta^2 = (\gamma^2 - 1)/\gamma^2 \f] + + If we insert this into the expression for \f$ \Lambda_{xy} \f$, we get + + \f[ \Lambda_{xy} = (\gamma - 1) \gamma^2/(\gamma^2 - 1) \beta_x \beta_y \f] + + or, finally + + \f[ \Lambda_{xy} = \gamma^2/(\gamma+1) \beta_x \beta_y \f] + + The expression \f$ \gamma^2/(\gamma+1) \f$ is what we call bgamma in the code below. + + \class ROOT::Math::Boost +*/ +//#endif + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +void Boost::SetIdentity() { + // set identity boost + fM[kXX] = 1.0; fM[kXY] = 0.0; fM[kXZ] = 0.0; fM[kXT] = 0.0; + fM[kYY] = 1.0; fM[kYZ] = 0.0; fM[kYT] = 0.0; + fM[kZZ] = 1.0; fM[kZT] = 0.0; + fM[kTT] = 1.0; +} + + +void Boost::SetComponents (Scalar bx, Scalar by, Scalar bz) { + // set the boost beta as 3 components + Scalar bp2 = bx*bx + by*by + bz*bz; + if (bp2 >= 1) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "Beta Vector supplied to set Boost represents speed >= c"); +#endif +// SetIdentity(); + return; + } + Scalar gamma = 1.0 / math_sqrt(1.0 - bp2); + Scalar bgamma = gamma * gamma / (1.0 + gamma); + fM[kXX] = 1.0 + bgamma * bx * bx; + fM[kYY] = 1.0 + bgamma * by * by; + fM[kZZ] = 1.0 + bgamma * bz * bz; + fM[kXY] = bgamma * bx * by; + fM[kXZ] = bgamma * bx * bz; + fM[kYZ] = bgamma * by * bz; + fM[kXT] = gamma * bx; + fM[kYT] = gamma * by; + fM[kZT] = gamma * bz; + fM[kTT] = gamma; +} + +void Boost::GetComponents (Scalar& bx, Scalar& by, Scalar& bz) const { + // get beta of the boots as 3 components + Scalar gaminv = 1.0/fM[kTT]; + bx = fM[kXT]*gaminv; + by = fM[kYT]*gaminv; + bz = fM[kZT]*gaminv; +} + +DisplacementVector3D< Cartesian3D > +Boost::BetaVector() const { + // get boost beta vector + Scalar gaminv = 1.0/fM[kTT]; + return DisplacementVector3D< Cartesian3D > + ( fM[kXT]*gaminv, fM[kYT]*gaminv, fM[kZT]*gaminv ); +} + +void Boost::GetLorentzRotation (Scalar r[]) const { + // get Lorentz rotation corresponding to this boost as an array of 16 values + r[kLXX] = fM[kXX]; r[kLXY] = fM[kXY]; r[kLXZ] = fM[kXZ]; r[kLXT] = fM[kXT]; + r[kLYX] = fM[kXY]; r[kLYY] = fM[kYY]; r[kLYZ] = fM[kYZ]; r[kLYT] = fM[kYT]; + r[kLZX] = fM[kXZ]; r[kLZY] = fM[kYZ]; r[kLZZ] = fM[kZZ]; r[kLZT] = fM[kZT]; + r[kLTX] = fM[kXT]; r[kLTY] = fM[kYT]; r[kLTZ] = fM[kZT]; r[kLTT] = fM[kTT]; +} + +void Boost::Rectify() { + // Assuming the representation of this is close to a true Lorentz Rotation, + // but may have drifted due to round-off error from many operations, + // this forms an "exact" orthosymplectic matrix for the Lorentz Rotation + // again. + + if (fM[kTT] <= 0) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "Attempt to rectify a boost with non-positive gamma"); +#endif + return; + } + DisplacementVector3D< Cartesian3D > beta ( fM[kXT], fM[kYT], fM[kZT] ); + beta /= fM[kTT]; + if ( beta.mag2() >= 1 ) { + beta /= ( beta.R() * ( 1.0 + 1.0e-16 ) ); + } + SetComponents ( beta ); +} + +LorentzVector< PxPyPzE4D > +Boost::operator() (const LorentzVector< PxPyPzE4D > & v) const { + // apply bosost to a PxPyPzE LorentzVector + Scalar x = v.Px(); + Scalar y = v.Py(); + Scalar z = v.Pz(); + Scalar t = v.E(); + return LorentzVector< PxPyPzE4D > + ( fM[kXX]*x + fM[kXY]*y + fM[kXZ]*z + fM[kXT]*t + , fM[kXY]*x + fM[kYY]*y + fM[kYZ]*z + fM[kYT]*t + , fM[kXZ]*x + fM[kYZ]*y + fM[kZZ]*z + fM[kZT]*t + , fM[kXT]*x + fM[kYT]*y + fM[kZT]*z + fM[kTT]*t ); +} + +void Boost::Invert() { + // invert in place boost (modifying the object) + fM[kXT] = -fM[kXT]; + fM[kYT] = -fM[kYT]; + fM[kZT] = -fM[kZT]; +} + +Boost Boost::Inverse() const { + // return inverse of boost + Boost tmp(*this); + tmp.Invert(); + return tmp; +} + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// ========== I/O ===================== + +std::ostream & operator<< (std::ostream & os, const Boost & b) { + // TODO - this will need changing for machine-readable issues + // and even the human readable form needs formatting improvements + double m[16]; + b.GetLorentzRotation(m); + os << "\n" << m[0] << " " << m[1] << " " << m[2] << " " << m[3]; + os << "\n" << "\t" << " " << m[5] << " " << m[6] << " " << m[7]; + os << "\n" << "\t" << " " << "\t" << " " << m[10] << " " << m[11]; + os << "\n" << "\t" << " " << "\t" << " " << "\t" << " " << m[15] << "\n"; + return os; +} +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/BoostX.cxx b/math/experimental/genvectorx/src/BoostX.cxx new file mode 100644 index 0000000000000..8c57aa7534cf1 --- /dev/null +++ b/math/experimental/genvectorx/src/BoostX.cxx @@ -0,0 +1,124 @@ + // @(#)root/mathcore:$Id$ +// Authors: M. Fischler 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class BoostX, a 4x4 symmetric matrix representation of +// an axial Lorentz transformation +// +// Created by: Mark Fischler Mon Nov 1 2005 +// +#include "MathX/GenVectorX/BoostX.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/GenVector_exception.h" + +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + +BoostX::BoostX() : fBeta(0.0), fGamma(1.0) {} + +void BoostX::SetComponents (Scalar bx ) { + // set component + Scalar bp2 = bx*bx; + if (bp2 >= 1) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "Beta Vector supplied to set BoostX represents speed >= c"); +#endif + return; + } + fBeta = bx; + fGamma = 1.0 / math_sqrt(1.0 - bp2); +} + +void BoostX::GetComponents (Scalar& bx) const { + // get component + bx = fBeta; +} + +DisplacementVector3D< Cartesian3D > +BoostX::BetaVector() const { + // return beta vector + return DisplacementVector3D< Cartesian3D > ( fBeta, 0.0, 0.0 ); +} + +void BoostX::GetLorentzRotation (Scalar r[]) const { + // get corresponding LorentzRotation + r[kLXX] = fGamma; r[kLXY] = 0.0; r[kLXZ] = 0.0; r[kLXT] = fGamma*fBeta; + r[kLYX] = 0.0; r[kLYY] = 1.0; r[kLYZ] = 0.0; r[kLYT] = 0.0; + r[kLZX] = 0.0; r[kLZY] = 0.0; r[kLZZ] = 1.0; r[kLZT] = 0.0; + r[kLTX] = fGamma*fBeta; r[kLTY] = 0.0; r[kLTZ] = 0.0; r[kLTT] = fGamma; +} + +void BoostX::Rectify() { + // Assuming the representation of this is close to a true Lorentz Rotation, + // but may have drifted due to round-off error from many operations, + // this forms an "exact" orthosymplectic matrix for the Lorentz Rotation + // again. + + if (fGamma <= 0) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "Attempt to rectify a boost with non-positive gamma"); +#endif + return; + } + Scalar beta = fBeta; + if ( beta >= 1 ) { + beta /= ( beta * ( 1.0 + 1.0e-16 ) ); + } + SetComponents ( beta ); +} + +LorentzVector< PxPyPzE4D > +BoostX::operator() (const LorentzVector< PxPyPzE4D > & v) const { + // apply boost to a LV + Scalar x = v.Px(); + Scalar t = v.E(); + return LorentzVector< PxPyPzE4D > + ( fGamma*x + fGamma*fBeta*t + , v.Py() + , v.Pz() + , fGamma*fBeta*x + fGamma*t ); +} + +void BoostX::Invert() { + // invert + fBeta = -fBeta; +} + +BoostX BoostX::Inverse() const { + // return an inverse boostX + BoostX tmp(*this); + tmp.Invert(); + return tmp; +} + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// ========== I/O ===================== + +std::ostream & operator<< (std::ostream & os, const BoostX & b) { + os << " BoostX( beta: " << b.Beta() << ", gamma: " << b.Gamma() << " ) "; + return os; +} +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/BoostY.cxx b/math/experimental/genvectorx/src/BoostY.cxx new file mode 100644 index 0000000000000..2d6d8004dfdc5 --- /dev/null +++ b/math/experimental/genvectorx/src/BoostY.cxx @@ -0,0 +1,124 @@ +// @(#)root/mathcore:$Id$ +// Authors: M. Fischler 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class BoostY, a 4x4 symmetric matrix representation of +// an axial Lorentz transformation +// +// Created by: Mark Fischler Mon Nov 1 2005 +// +#include "MathX/GenVectorX/BoostY.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/GenVector_exception.h" + +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +BoostY::BoostY() : fBeta(0.0), fGamma(1.0) {} + +void BoostY::SetComponents (Scalar by) { + // set component + Scalar bp2 = by*by; + if (bp2 >= 1) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw( + "Beta Vector supplied to set BoostY represents speed >= c"); +#endif + return; + } + fBeta = by; + fGamma = 1.0 / math_sqrt(1.0-bp2); +} + +void BoostY::GetComponents (Scalar& by) const { + // get component + by = fBeta; +} + +DisplacementVector3D< Cartesian3D > +BoostY::BetaVector() const { + // return beta vector + return DisplacementVector3D< Cartesian3D > ( 0.0, fBeta, 0.0 ); +} + +void BoostY::GetLorentzRotation (Scalar r[]) const { + // get corresponding LorentzRotation + r[kLXX] = 1.0; r[kLXY] = 0.0; r[kLXZ] = 0.0; r[kLXT] = 0.0; + r[kLYX] = 0.0; r[kLYY] = fGamma; r[kLYZ] = 0.0; r[kLYT] = fGamma*fBeta; + r[kLZX] = 0.0; r[kLZY] = 0.0; r[kLZZ] = 1.0; r[kLZT] = 0.0; + r[kLTX] = 0.0; r[kLTY] = fGamma*fBeta; r[kLTZ] = 0.0; r[kLTT] = fGamma; +} + +void BoostY::Rectify() { + // Assuming the representation of this is close to a true Lorentz Rotation, + // but may have drifted due to round-off error from many operations, + // this forms an "exact" orthosymplectic matrix for the Lorentz Rotation + // again. + + if (fGamma <= 0) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "Attempt to rectify a boost with non-positive gamma"); +#endif + return; + } + Scalar beta = fBeta; + if ( beta >= 1 ) { + beta /= ( beta * ( 1.0 + 1.0e-16 ) ); + } + SetComponents ( beta ); +} + +LorentzVector< PxPyPzE4D > +BoostY::operator() (const LorentzVector< PxPyPzE4D > & v) const { + // apply boost to a LV + Scalar y = v.Py(); + Scalar t = v.E(); + return LorentzVector< PxPyPzE4D > + ( v.Px() + , fGamma*y + fGamma*fBeta*t + , v.Pz() + , fGamma*fBeta*y + fGamma*t ); +} + +void BoostY::Invert() { + // invert Boost + fBeta = -fBeta; +} + +BoostY BoostY::Inverse() const { + // return inverse + BoostY tmp(*this); + tmp.Invert(); + return tmp; +} + + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// ========== I/O ===================== + +std::ostream & operator<< (std::ostream & os, const BoostY & b) { + os << " BoostY( beta: " << b.Beta() << ", gamma: " << b.Gamma() << " ) "; + return os; +} +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/BoostZ.cxx b/math/experimental/genvectorx/src/BoostZ.cxx new file mode 100644 index 0000000000000..f5058ddc0fc85 --- /dev/null +++ b/math/experimental/genvectorx/src/BoostZ.cxx @@ -0,0 +1,125 @@ +// @(#)root/mathcore:$Id$ +// Authors: M. Fischler 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class BoostZ, a 4x4 symmetric matrix representation of +// an axial Lorentz transformation +// +// Created by: Mark Fischler Mon Nov 1 2005 +// +#include "MathX/GenVectorX/BoostZ.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/GenVector_exception.h" + +#include +#include + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +BoostZ::BoostZ() : fBeta(0.0), fGamma(1.0) {} + +void BoostZ::SetComponents (Scalar bz) { + // set component + Scalar bp2 = bz*bz; + if (bp2 >= 1) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "Beta Vector supplied to set BoostZ represents speed >= c"); +#endif + return; + } + fBeta = bz; + fGamma = 1.0 / math_sqrt(1.0 - bp2); +} + +void BoostZ::GetComponents (Scalar& bz) const { + // get component + bz = fBeta; +} + +DisplacementVector3D< Cartesian3D > +BoostZ::BetaVector() const { + // return beta vector + return DisplacementVector3D< Cartesian3D > + ( 0.0, 0.0, fBeta ); +} + +void BoostZ::GetLorentzRotation (Scalar r[]) const { + // get corresponding LorentzRotation + r[kLXX] = 1.0; r[kLXY] = 0.0; r[kLXZ] = 0.0; r[kLXT] = 0.0 ; + r[kLYX] = 0.0; r[kLYY] = 1.0; r[kLYZ] = 0.0; r[kLYT] = 0.0 ; + r[kLZX] = 0.0; r[kLZY] = 0.0; r[kLZZ] = fGamma; r[kLZT] = fGamma*fBeta; + r[kLTX] = 0.0; r[kLTY] = 0.0; r[kLTZ] = fGamma*fBeta; r[kLTT] = fGamma; +} + +void BoostZ::Rectify() { + // Assuming the representation of this is close to a true Lorentz Rotation, + // but may have drifted due to round-off error from many operations, + // this forms an "exact" orthosymplectic matrix for the Lorentz Rotation + // again. + + if (fGamma <= 0) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "Attempt to rectify a boost with non-positive gamma"); +#endif + return; + } + Scalar beta = fBeta; + if ( beta >= 1 ) { + beta /= ( beta * ( 1.0 + 1.0e-16 ) ); + } + SetComponents ( beta ); +} + +LorentzVector< PxPyPzE4D > +BoostZ::operator() (const LorentzVector< PxPyPzE4D > & v) const { + // apply boost to a LV + Scalar z = v.Pz(); + Scalar t = v.E(); + return LorentzVector< PxPyPzE4D > + ( v.Px() + , v.Py() + , fGamma*z + fGamma*fBeta*t + , fGamma*fBeta*z + fGamma*t ); +} + +void BoostZ::Invert() { + // invert + fBeta = -fBeta; +} + +BoostZ BoostZ::Inverse() const { + // return an inverse boostZ + BoostZ tmp(*this); + tmp.Invert(); + return tmp; +} + + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// ========== I/O ===================== + +std::ostream & operator<< (std::ostream & os, const BoostZ & b) { + os << " BoostZ( beta: " << b.Beta() << ", gamma: " << b.Gamma() << " ) "; + return os; +} +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/EulerAngles.cxx b/math/experimental/genvectorx/src/EulerAngles.cxx new file mode 100644 index 0000000000000..a71a8547379fd --- /dev/null +++ b/math/experimental/genvectorx/src/EulerAngles.cxx @@ -0,0 +1,143 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Implementation file for rotation in 3 dimensions, represented by EulerAngles +// +// Created by: Mark Fischler Thurs June 9 2005 +// +// Last update: $Id$ +// +#include "MathX/GenVectorX/EulerAngles.h" + +#include + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/Quaternion.h" +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" + +#include "MathX/GenVectorX/AxisAnglefwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +// ========== Constructors and Assignment ===================== + +void EulerAngles::Rectify() +{ + // rectify + if ( fTheta < 0 || fTheta > Pi() ) { + Scalar t = fTheta - math_floor( fTheta/(2*Pi()) ) * 2*Pi(); + if ( t <= Pi() ) { + fTheta = t; + } else { + fTheta = 2*Pi() - t; + fPhi = fPhi + Pi(); + fPsi = fPsi + Pi(); + } + } + + if ( fPhi <= -Pi()|| fPhi > Pi() ) { + fPhi = fPhi - math_floor( fPhi/(2*Pi()) +.5 ) * 2*Pi(); + } + + if ( fPsi <= -Pi()|| fPsi > Pi() ) { + fPsi = fPsi - math_floor( fPsi/(2*Pi()) +.5 ) * 2*Pi(); + } + +} // Rectify() + + +// ========== Operations ===================== + +// DisplacementVector3D< Cartesian3D > +// EulerAngles:: +// operator() (const DisplacementVector3D< Cartesian3D > & v) const +// { +// return Rotation3D(*this)(v); +// } + + +EulerAngles EulerAngles::operator * (const Rotation3D & r) const { + // combine with a Rotation3D + return EulerAngles ( Rotation3D(*this) * r ); +} + +EulerAngles EulerAngles::operator * (const AxisAngle & a) const { + // combine with a AxisAngle + return EulerAngles ( Quaternion(*this) * Quaternion(a) ); +} + +EulerAngles EulerAngles::operator * (const EulerAngles & e) const { + // combine with a EulerAngles + return EulerAngles ( Quaternion(*this) * Quaternion(e) ); +} +EulerAngles EulerAngles::operator * (const Quaternion & q) const { + // combination with a Quaternion + return EulerAngles ( Quaternion(*this) * q ); +} + +EulerAngles EulerAngles::operator * (const RotationX & r) const { + // combine with a RotationX + return EulerAngles ( Quaternion(*this) * r ); +} + +EulerAngles EulerAngles::operator * (const RotationY & r) const { + // combine with a RotationY + return EulerAngles ( Quaternion(*this) * r ); +} + +EulerAngles EulerAngles::operator * (const RotationZ & r) const { + // combine with a RotationZ + // TODO -- this can be made much faster because it merely adds + // the r.Angle() to phi. + Scalar newPhi = fPhi + r.Angle(); + if ( newPhi <= -Pi()|| newPhi > Pi() ) { + newPhi = newPhi - math_floor( newPhi/(2*Pi()) +.5 ) * 2*Pi(); + } + return EulerAngles ( newPhi, fTheta, fPsi ); +} + +EulerAngles operator * ( RotationX const & r, EulerAngles const & e ) { + return EulerAngles(r) * e; // TODO: improve performance +} + +EulerAngles operator * ( RotationY const & r, EulerAngles const & e ) { + return EulerAngles(r) * e; // TODO: improve performance +} + +EulerAngles +operator * ( RotationZ const & r, EulerAngles const & e ) { + return EulerAngles(r) * e; // TODO: improve performance +} + + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// ========== I/O ===================== + +std::ostream & operator<< (std::ostream & os, const EulerAngles & e) { + // TODO - this will need changing for machine-readable issues + // and even the human readable form may need formatting improvements + os << "\n{phi: " << e.Phi() << " theta: " << e.Theta() + << " psi: " << e.Psi() << "}\n"; + return os; +} +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/LorentzRotation.cxx b/math/experimental/genvectorx/src/LorentzRotation.cxx new file mode 100644 index 0000000000000..cf99631f1ccd5 --- /dev/null +++ b/math/experimental/genvectorx/src/LorentzRotation.cxx @@ -0,0 +1,249 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class LorentzRotation, a 4x4 matrix representation of +// a general Lorentz transformation +// +// Created by: Mark Fischler Mon Aug 8 2005 +// + +#include "MathX/GenVectorX/GenVectorIO.h" + +#include "MathX/GenVectorX/LorentzRotation.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/GenVector_exception.h" + +#include +#include + +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +LorentzRotation::LorentzRotation() { + // constructor of an identity LR + fM[kXX] = 1.0; fM[kXY] = 0.0; fM[kXZ] = 0.0; fM[kXT] = 0.0; + fM[kYX] = 0.0; fM[kYY] = 1.0; fM[kYZ] = 0.0; fM[kYT] = 0.0; + fM[kZX] = 0.0; fM[kZY] = 0.0; fM[kZZ] = 1.0; fM[kZT] = 0.0; + fM[kTX] = 0.0; fM[kTY] = 0.0; fM[kTZ] = 0.0; fM[kTT] = 1.0; +} + +LorentzRotation::LorentzRotation(Rotation3D const & r) { + // construct from Rotation3D + r.GetComponents ( fM[kXX], fM[kXY], fM[kXZ], + fM[kYX], fM[kYY], fM[kYZ], + fM[kZX], fM[kZY], fM[kZZ] ); + fM[kXT] = 0.0; + fM[kYT] = 0.0; + fM[kZT] = 0.0; + fM[kTX] = 0.0; fM[kTY] = 0.0; fM[kTZ] = 0.0; fM[kTT] = 1.0; +} + +LorentzRotation::LorentzRotation(AxisAngle const & a) { + // construct from AxisAngle + const Rotation3D r(a); + r.GetComponents ( fM[kXX], fM[kXY], fM[kXZ], + fM[kYX], fM[kYY], fM[kYZ], + fM[kZX], fM[kZY], fM[kZZ] ); + fM[kXT] = 0.0; + fM[kYT] = 0.0; + fM[kZT] = 0.0; + fM[kTX] = 0.0; fM[kTY] = 0.0; fM[kTZ] = 0.0; fM[kTT] = 1.0; +} + +LorentzRotation::LorentzRotation(EulerAngles const & e) { + // construct from EulerAngles + const Rotation3D r(e); + r.GetComponents ( fM[kXX], fM[kXY], fM[kXZ], + fM[kYX], fM[kYY], fM[kYZ], + fM[kZX], fM[kZY], fM[kZZ] ); + fM[kXT] = 0.0; + fM[kYT] = 0.0; + fM[kZT] = 0.0; + fM[kTX] = 0.0; fM[kTY] = 0.0; fM[kTZ] = 0.0; fM[kTT] = 1.0; +} + +LorentzRotation::LorentzRotation(Quaternion const & q) { + // construct from Quaternion + const Rotation3D r(q); + r.GetComponents ( fM[kXX], fM[kXY], fM[kXZ], + fM[kYX], fM[kYY], fM[kYZ], + fM[kZX], fM[kZY], fM[kZZ] ); + fM[kXT] = 0.0; + fM[kYT] = 0.0; + fM[kZT] = 0.0; + fM[kTX] = 0.0; fM[kTY] = 0.0; fM[kTZ] = 0.0; fM[kTT] = 1.0; +} + +LorentzRotation::LorentzRotation(RotationX const & r) { + // construct from RotationX + Scalar s = r.SinAngle(); + Scalar c = r.CosAngle(); + fM[kXX] = 1.0; fM[kXY] = 0.0; fM[kXZ] = 0.0; fM[kXT] = 0.0; + fM[kYX] = 0.0; fM[kYY] = c ; fM[kYZ] = -s ; fM[kYT] = 0.0; + fM[kZX] = 0.0; fM[kZY] = s ; fM[kZZ] = c ; fM[kZT] = 0.0; + fM[kTX] = 0.0; fM[kTY] = 0.0; fM[kTZ] = 0.0; fM[kTT] = 1.0; +} + +LorentzRotation::LorentzRotation(RotationY const & r) { + // construct from RotationY + Scalar s = r.SinAngle(); + Scalar c = r.CosAngle(); + fM[kXX] = c ; fM[kXY] = 0.0; fM[kXZ] = s ; fM[kXT] = 0.0; + fM[kYX] = 0.0; fM[kYY] = 1.0; fM[kYZ] = 0.0; fM[kYT] = 0.0; + fM[kZX] = -s ; fM[kZY] = 0.0; fM[kZZ] = c ; fM[kZT] = 0.0; + fM[kTX] = 0.0; fM[kTY] = 0.0; fM[kTZ] = 0.0; fM[kTT] = 1.0; +} + +LorentzRotation::LorentzRotation(RotationZ const & r) { + // construct from RotationX + Scalar s = r.SinAngle(); + Scalar c = r.CosAngle(); + fM[kXX] = c ; fM[kXY] = -s ; fM[kXZ] = 0.0; fM[kXT] = 0.0; + fM[kYX] = s ; fM[kYY] = c ; fM[kYZ] = 0.0; fM[kYT] = 0.0; + fM[kZX] = 0.0; fM[kZY] = 0.0; fM[kZZ] = 1.0; fM[kZT] = 0.0; + fM[kTX] = 0.0; fM[kTY] = 0.0; fM[kTZ] = 0.0; fM[kTT] = 1.0; +} + +void +LorentzRotation::Rectify() { + // Assuming the representation of this is close to a true Lorentz Rotation, + // but may have drifted due to round-off error from many operations, + // this forms an "exact" orthosymplectic matrix for the Lorentz Rotation + // again. + + typedef LorentzVector< PxPyPzE4D > FourVector; + if (fM[kTT] <= 0) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "LorentzRotation:Rectify(): Non-positive TT component - cannot rectify"); +#endif + return; + } + FourVector t ( fM[kTX], fM[kTY], fM[kTZ], fM[kTT] ); + Scalar m2 = t.M2(); + if ( m2 <= 0 ) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "LorentzRotation:Rectify(): Non-timelike time row - cannot rectify"); +#endif + return; + } + t /= math_sqrt(m2); + FourVector z ( fM[kZX], fM[kZY], fM[kZZ], fM[kZT] ); + z = z - z.Dot(t)*t; + m2 = z.M2(); + if ( m2 >= 0 ) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "LorentzRotation:Rectify(): Non-spacelike Z row projection - " + "cannot rectify"); +#endif + return; + } + z /= math_sqrt(-m2); + FourVector y ( fM[kYX], fM[kYY], fM[kYZ], fM[kYT] ); + y = y - y.Dot(t)*t - y.Dot(z)*z; + m2 = y.M2(); + if ( m2 >= 0 ) { + #if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "LorentzRotation:Rectify(): Non-spacelike Y row projection - " + "cannot rectify"); +#endif + return; + } + y /= math_sqrt(-m2); + FourVector x ( fM[kXX], fM[kXY], fM[kXZ], fM[kXT] ); + x = x - x.Dot(t)*t - x.Dot(z)*z - x.Dot(y)*y; + m2 = x.M2(); + if ( m2 >= 0 ) { +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + GenVector::Throw ( + "LorentzRotation:Rectify(): Non-spacelike X row projection - " + "cannot rectify"); +#endif + return; + } + x /= math_sqrt(-m2); +} + + +void LorentzRotation::Invert() { + // invert modifying current content + Scalar temp; + temp = fM[kXY]; fM[kXY] = fM[kYX]; fM[kYX] = temp; + temp = fM[kXZ]; fM[kXZ] = fM[kZX]; fM[kZX] = temp; + temp = fM[kYZ]; fM[kYZ] = fM[kZY]; fM[kZY] = temp; + temp = fM[kXT]; fM[kXT] = -fM[kTX]; fM[kTX] = -temp; + temp = fM[kYT]; fM[kYT] = -fM[kTY]; fM[kTY] = -temp; + temp = fM[kZT]; fM[kZT] = -fM[kTZ]; fM[kTZ] = -temp; +} + +LorentzRotation LorentzRotation::Inverse() const { + // return an inverse LR + return LorentzRotation + ( fM[kXX], fM[kYX], fM[kZX], -fM[kTX] + , fM[kXY], fM[kYY], fM[kZY], -fM[kTY] + , fM[kXZ], fM[kYZ], fM[kZZ], -fM[kTZ] + , -fM[kXT], -fM[kYT], -fM[kZT], fM[kTT] + ); +} + +LorentzRotation LorentzRotation::operator * (const LorentzRotation & r) const { + // combination with another LR + return LorentzRotation + ( fM[kXX]*r.fM[kXX] + fM[kXY]*r.fM[kYX] + fM[kXZ]*r.fM[kZX] + fM[kXT]*r.fM[kTX] + , fM[kXX]*r.fM[kXY] + fM[kXY]*r.fM[kYY] + fM[kXZ]*r.fM[kZY] + fM[kXT]*r.fM[kTY] + , fM[kXX]*r.fM[kXZ] + fM[kXY]*r.fM[kYZ] + fM[kXZ]*r.fM[kZZ] + fM[kXT]*r.fM[kTZ] + , fM[kXX]*r.fM[kXT] + fM[kXY]*r.fM[kYT] + fM[kXZ]*r.fM[kZT] + fM[kXT]*r.fM[kTT] + , fM[kYX]*r.fM[kXX] + fM[kYY]*r.fM[kYX] + fM[kYZ]*r.fM[kZX] + fM[kYT]*r.fM[kTX] + , fM[kYX]*r.fM[kXY] + fM[kYY]*r.fM[kYY] + fM[kYZ]*r.fM[kZY] + fM[kYT]*r.fM[kTY] + , fM[kYX]*r.fM[kXZ] + fM[kYY]*r.fM[kYZ] + fM[kYZ]*r.fM[kZZ] + fM[kYT]*r.fM[kTZ] + , fM[kYX]*r.fM[kXT] + fM[kYY]*r.fM[kYT] + fM[kYZ]*r.fM[kZT] + fM[kYT]*r.fM[kTT] + , fM[kZX]*r.fM[kXX] + fM[kZY]*r.fM[kYX] + fM[kZZ]*r.fM[kZX] + fM[kZT]*r.fM[kTX] + , fM[kZX]*r.fM[kXY] + fM[kZY]*r.fM[kYY] + fM[kZZ]*r.fM[kZY] + fM[kZT]*r.fM[kTY] + , fM[kZX]*r.fM[kXZ] + fM[kZY]*r.fM[kYZ] + fM[kZZ]*r.fM[kZZ] + fM[kZT]*r.fM[kTZ] + , fM[kZX]*r.fM[kXT] + fM[kZY]*r.fM[kYT] + fM[kZZ]*r.fM[kZT] + fM[kZT]*r.fM[kTT] + , fM[kTX]*r.fM[kXX] + fM[kTY]*r.fM[kYX] + fM[kTZ]*r.fM[kZX] + fM[kTT]*r.fM[kTX] + , fM[kTX]*r.fM[kXY] + fM[kTY]*r.fM[kYY] + fM[kTZ]*r.fM[kZY] + fM[kTT]*r.fM[kTY] + , fM[kTX]*r.fM[kXZ] + fM[kTY]*r.fM[kYZ] + fM[kTZ]*r.fM[kZZ] + fM[kTT]*r.fM[kTZ] + , fM[kTX]*r.fM[kXT] + fM[kTY]*r.fM[kYT] + fM[kTZ]*r.fM[kZT] + fM[kTT]*r.fM[kTT] + ); +} + + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +std::ostream & operator<< (std::ostream & os, const LorentzRotation & r) { + // TODO - this will need changing for machine-readable issues + // and even the human readable form needs formatting improvements + double m[16]; + r.GetComponents(m, m+16); + os << "\n" << m[0] << " " << m[1] << " " << m[2] << " " << m[3]; + os << "\n" << m[4] << " " << m[5] << " " << m[6] << " " << m[7]; + os << "\n" << m[8] << " " << m[9] << " " << m[10] << " " << m[11]; + os << "\n" << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << "\n"; + return os; +} +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/Quaternion.cxx b/math/experimental/genvectorx/src/Quaternion.cxx new file mode 100644 index 0000000000000..46f02b3391ce1 --- /dev/null +++ b/math/experimental/genvectorx/src/Quaternion.cxx @@ -0,0 +1,115 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Implementation file for rotation in 3 dimensions, represented by quaternion +// +// Created by: Mark Fischler Thurs June 9 2005 +// +// Last update: $Id$ +// +#include "MathX/GenVectorX/Quaternion.h" + +#include + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" + +#include "MathX/GenVectorX/Rotation3Dfwd.h" +#include "MathX/GenVectorX/AxisAnglefwd.h" +#include "MathX/GenVectorX/EulerAnglesfwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +// ========== Constructors and Assignment ===================== + +void Quaternion::Rectify() +{ + + // The vector should be a unit vector, and the first element should be + // non-negative (though negative fU quaternions would work just fine, + // being isomorphic to a quaternion with positive fU). + + if ( fU < 0 ) { + fU = - fU; fI = - fI; fJ = - fJ; fK = - fK; + } + + Scalar a = 1.0 / math_sqrt(fU*fU + fI*fI + fJ*fJ + fK*fK); + fU *= a; + fI *= a; + fJ *= a; + fK *= a; + +} // Rectify() + + +// ========== Operations ===================== + +// DisplacementVector3D< Cartesian3D > +// Quaternion::operator() (const DisplacementVector3D< Cartesian3D > & v) const +// { +// // apply to a 3D Vector +// } + +// Quaternion Quaternion::operator * (const Quaternion & q) const { +// // combination of rotations +// return Quaternion ( +// fU*q.fU - fI*q.fI - fJ*q.fJ - fK*q.fK +// , fU*q.fI + fI*q.fU + fJ*q.fK - fK*q.fJ +// , fU*q.fJ - fI*q.fK + fJ*q.fU + fK*q.fI +// , fU*q.fK + fI*q.fJ - fJ*q.fI + fK*q.fU ); +//} + +Quaternion Quaternion::operator * (const Rotation3D & r) const { + // combination of rotations + return operator* ( Quaternion(r) ); +} + +Quaternion Quaternion::operator * (const AxisAngle & a) const { + // combination of rotations + return operator* ( Quaternion(a) ); +} + +Quaternion Quaternion::operator * (const EulerAngles & e) const { + // combination of rotations + return operator* ( Quaternion(e) ); +} + +Quaternion Quaternion::operator * (const RotationZYX & r) const { + // combination of rotations + return operator* ( Quaternion(r) ); +} + +Quaternion::Scalar Quaternion::Distance(const Quaternion & q) const { + // distance + Scalar chordLength = math_fabs(fU*q.fU + fI*q.fI + fJ*q.fJ + fK*q.fK); + if (chordLength > 1) chordLength = 1; // in case roundoff fouls us up + return acos(chordLength); +} + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) +// ========== I/O ===================== + +std::ostream & operator<< (std::ostream & os, const Quaternion & q) { + // TODO - this will need changing for machine-readable issues + // and even the human readable form may need formatting improvements + os << "\n{" << q.U() << " " << q.I() + << " " << q.J() << " " << q.K() << "}\n"; + return os; +} +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/QuaternionXaxial.cxx b/math/experimental/genvectorx/src/QuaternionXaxial.cxx new file mode 100644 index 0000000000000..19e32f1593979 --- /dev/null +++ b/math/experimental/genvectorx/src/QuaternionXaxial.cxx @@ -0,0 +1,83 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Implementation file for quaternion times other non-axial rotations. +// Decoupled from main Quaternion implementations. +// +// Created by: Mark Fischler Tues July 19, 2005 +// +// Last update: $Id$ +// +#include "MathX/GenVectorX/Quaternion.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + +// Although the same technique would work with axial rotations, +// we know that two of the four quaternion components will be zero, +// and we exploit that knowledge: + +Quaternion Quaternion::operator * (const RotationX & rx) const { + // combination with a RotationX + Quaternion q(rx); + return Quaternion ( + U()*q.U() - I()*q.I() + , I()*q.U() + U()*q.I() + , J()*q.U() + K()*q.I() + , K()*q.U() - J()*q.I() + ); +} + +Quaternion Quaternion::operator * (const RotationY & ry) const { + // combination with a RotationY + Quaternion q(ry); + return Quaternion ( + U()*q.U() - J()*q.J() + , I()*q.U() - K()*q.J() + , J()*q.U() + U()*q.J() + , K()*q.U() + I()*q.J() + ); +} + +Quaternion Quaternion::operator * (const RotationZ & rz) const { + // combination with a RotationZ + Quaternion q(rz); + return Quaternion ( + U()*q.U() - K()*q.K() + , I()*q.U() + J()*q.K() + , J()*q.U() - I()*q.K() + , K()*q.U() + U()*q.K() + ); +} + +Quaternion +operator * ( RotationX const & r, Quaternion const & q ) { + return Quaternion(r) * q; // TODO: improve performance +} + +Quaternion +operator * ( RotationY const & r, Quaternion const & q ) { + return Quaternion(r) * q; // TODO: improve performance +} + +Quaternion +operator * ( RotationZ const & r, Quaternion const & q ) { + return Quaternion(r) * q; // TODO: improve performance +} + + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/Rotation3D.cxx b/math/experimental/genvectorx/src/Rotation3D.cxx new file mode 100644 index 0000000000000..bb525471910d1 --- /dev/null +++ b/math/experimental/genvectorx/src/Rotation3D.cxx @@ -0,0 +1,157 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for class Rotation in 3 dimensions, represented by 3x3 matrix +// +// Created by: Mark Fischler Tues July 5 2005 +// +#include "MathX/GenVectorX/Rotation3D.h" + +#include +#include + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +// ========== Constructors and Assignment ===================== + +Rotation3D::Rotation3D() +{ + // constructor of a identity rotation + fM[kXX] = 1.0; fM[kXY] = 0.0; fM[kXZ] = 0.0; + fM[kYX] = 0.0; fM[kYY] = 1.0; fM[kYZ] = 0.0; + fM[kZX] = 0.0; fM[kZY] = 0.0; fM[kZZ] = 1.0; +} + + +void Rotation3D::Rectify() +{ + // rectify rotation matrix (make orthogonal) + // The "nearest" orthogonal matrix X to a nearly-orthogonal matrix A + // (in the sense that X is exactly orthogonal and the sum of the squares + // of the element differences X-A is as small as possible) is given by + // X = A * inverse(sqrt(A.transpose()*A.inverse())). + + // Step 1 -- form symmetric M = A.transpose * A + + double m11 = fM[kXX]*fM[kXX] + fM[kYX]*fM[kYX] + fM[kZX]*fM[kZX]; + double m12 = fM[kXX]*fM[kXY] + fM[kYX]*fM[kYY] + fM[kZX]*fM[kZY]; + double m13 = fM[kXX]*fM[kXZ] + fM[kYX]*fM[kYZ] + fM[kZX]*fM[kZZ]; + double m22 = fM[kXY]*fM[kXY] + fM[kYY]*fM[kYY] + fM[kZY]*fM[kZY]; + double m23 = fM[kXY]*fM[kXZ] + fM[kYY]*fM[kYZ] + fM[kZY]*fM[kZZ]; + double m33 = fM[kXZ]*fM[kXZ] + fM[kYZ]*fM[kYZ] + fM[kZZ]*fM[kZZ]; + + // Step 2 -- find lower-triangular U such that U * U.transpose = M + + double u11 = math_sqrt(m11); + double u21 = m12/u11; + double u31 = m13/u11; + double u22 = math_sqrt(m22-u21*u21); + double u32 = (m23-m12*m13/m11)/u22; + double u33 = math_sqrt(m33 - u31*u31 - u32*u32); + + + // Step 3 -- find V such that V*V = U. U is also lower-triangular + + double v33 = 1/u33; + double v32 = -v33*u32/u22; + double v31 = -(v32*u21+v33*u31)/u11; + double v22 = 1/u22; + double v21 = -v22*u21/u11; + double v11 = 1/u11; + + + // Step 4 -- N = V.transpose * V is inverse(sqrt(A.transpose()*A.inverse())) + + double n11 = v11*v11 + v21*v21 + v31*v31; + double n12 = v11*v21 + v21*v22 + v31*v32; + double n13 = v11*v31 + v21*v32 + v31*v33; + double n22 = v21*v21 + v22*v22 + v32*v32; + double n23 = v21*v31 + v22*v32 + v32*v33; + double n33 = v31*v31 + v32*v32 + v33*v33; + + + // Step 5 -- The new matrix is A * N + + double mA[9]; + std::copy(fM, &fM[9], mA); + + fM[kXX] = mA[kXX]*n11 + mA[kXY]*n12 + mA[kXZ]*n13; + fM[kXY] = mA[kXX]*n12 + mA[kXY]*n22 + mA[kXZ]*n23; + fM[kXZ] = mA[kXX]*n13 + mA[kXY]*n23 + mA[kXZ]*n33; + fM[kYX] = mA[kYX]*n11 + mA[kYY]*n12 + mA[kYZ]*n13; + fM[kYY] = mA[kYX]*n12 + mA[kYY]*n22 + mA[kYZ]*n23; + fM[kYZ] = mA[kYX]*n13 + mA[kYY]*n23 + mA[kYZ]*n33; + fM[kZX] = mA[kZX]*n11 + mA[kZY]*n12 + mA[kZZ]*n13; + fM[kZY] = mA[kZX]*n12 + mA[kZY]*n22 + mA[kZZ]*n23; + fM[kZZ] = mA[kZX]*n13 + mA[kZY]*n23 + mA[kZZ]*n33; + + +} // Rectify() + + +static inline void swap(double & a, double & b) { + // swap two values + double t=b; b=a; a=t; +} + +void Rotation3D::Invert() { + // invert a rotation + swap (fM[kXY], fM[kYX]); + swap (fM[kXZ], fM[kZX]); + swap (fM[kYZ], fM[kZY]); +} + + +Rotation3D Rotation3D::operator * (const AxisAngle & a) const { + // combine with an AxisAngle rotation + return operator* ( Rotation3D(a) ); +} + +Rotation3D Rotation3D::operator * (const EulerAngles & e) const { + // combine with an EulerAngles rotation + return operator* ( Rotation3D(e) ); +} + +Rotation3D Rotation3D::operator * (const Quaternion & q) const { + // combine with a Quaternion rotation + return operator* ( Rotation3D(q) ); +} + +Rotation3D Rotation3D::operator * (const RotationZYX & r) const { + // combine with a RotastionZYX rotation + return operator* ( Rotation3D(r) ); +} + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +std::ostream & operator<< (std::ostream & os, const Rotation3D & r) { + // TODO - this will need changing for machine-readable issues + // and even the human readable form needs formatting improvements + double m[9]; + r.GetComponents(m, m+9); + os << "\n" << m[0] << " " << m[1] << " " << m[2]; + os << "\n" << m[3] << " " << m[4] << " " << m[5]; + os << "\n" << m[6] << " " << m[7] << " " << m[8] << "\n"; + return os; +} + +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/Rotation3DxAxial.cxx b/math/experimental/genvectorx/src/Rotation3DxAxial.cxx new file mode 100644 index 0000000000000..f839e3ff68519 --- /dev/null +++ b/math/experimental/genvectorx/src/Rotation3DxAxial.cxx @@ -0,0 +1,151 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + +#include "MathX/GenVectorX/Rotation3D.h" + +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +Rotation3D Rotation3D::operator * (const RotationX & rx) const { + // combination of a Rotation3D with a RotationX + Scalar s = rx.SinAngle(); + Scalar c = rx.CosAngle(); + return Rotation3D + ( + fM[kXX], fM[kXY]*c + fM[kXZ]*s, fM[kXZ]*c - fM[kXY]*s + , fM[kYX], fM[kYY]*c + fM[kYZ]*s, fM[kYZ]*c - fM[kYY]*s + , fM[kZX], fM[kZY]*c + fM[kZZ]*s, fM[kZZ]*c - fM[kZY]*s + ); +} + +Rotation3D Rotation3D::operator * (const RotationY & ry) const { + // combination of a Rotation3D with a RotationY + Scalar s = ry.SinAngle(); + Scalar c = ry.CosAngle(); + return Rotation3D + ( + fM[kXX]*c - fM[kXZ]*s, fM[kXY], fM[kXX]*s + fM[kXZ]*c + , fM[kYX]*c - fM[kYZ]*s, fM[kYY], fM[kYX]*s + fM[kYZ]*c + , fM[kZX]*c - fM[kZZ]*s, fM[kZY], fM[kZX]*s + fM[kZZ]*c + ); +} + + +Rotation3D Rotation3D::operator * (const RotationZ & rz) const { + // combination of a Rotation3D with a RotationZ + Scalar s = rz.SinAngle(); + Scalar c = rz.CosAngle(); + return Rotation3D + ( + fM[kXX]*c + fM[kXY]*s, fM[kXY]*c - fM[kXX]*s, fM[kXZ] + , fM[kYX]*c + fM[kYY]*s, fM[kYY]*c - fM[kYX]*s, fM[kYZ] + , fM[kZX]*c + fM[kZY]*s, fM[kZY]*c - fM[kZX]*s, fM[kZZ] + ); +} + +Rotation3D operator* (RotationX const & r1, Rotation3D const & r2) { + // combination of a RotationX with a Rotation3D + // TODO -- recode for much better efficiency! + return Rotation3D(r1)*r2; +} + +Rotation3D operator* (RotationY const & r1, Rotation3D const & r2) { + // combination of a RotationY with a Rotation3D + // TODO -- recode for much better efficiency! + return Rotation3D(r1)*r2; +} + +Rotation3D operator* (RotationZ const & r1, Rotation3D const & r2) { + // combination of a RotationZ with a Rotation3D + // TODO -- recode for much better efficiency! + return Rotation3D(r1)*r2; +} + +typedef Rotation3D::Scalar Scalar; + +// Rx * Ry +Rotation3D operator* (RotationX const & rx, RotationY const & ry) { + Scalar sx = rx.SinAngle(); + Scalar cx = rx.CosAngle(); + Scalar sy = ry.SinAngle(); + Scalar cy = ry.CosAngle(); + return Rotation3D + ( cy , 0 , sy , + sx*sy , cx , -sx*cy , + -sy*cx , sx , cx*cy ); +} + +// Rx * Rz +Rotation3D operator* (RotationX const & rx, RotationZ const & rz) { + Scalar sx = rx.SinAngle(); + Scalar cx = rx.CosAngle(); + Scalar sz = rz.SinAngle(); + Scalar cz = rz.CosAngle(); + return Rotation3D + ( cz , -sz , 0 , + cx*sz , cx*cz , -sx , + sx*sz , cz*sx , cx ); +} + +// Ry * Rx +Rotation3D operator* (RotationY const & ry, RotationX const & rx) { + Scalar sx = rx.SinAngle(); + Scalar cx = rx.CosAngle(); + Scalar sy = ry.SinAngle(); + Scalar cy = ry.CosAngle(); + return Rotation3D + ( cy , sx*sy , sy*cx , + 0 , cx , -sx , + -sy , cy*sx , cx*cy ); +} + +// Ry * Rz +Rotation3D operator* (RotationY const & ry, RotationZ const & rz) { + Scalar sy = ry.SinAngle(); + Scalar cy = ry.CosAngle(); + Scalar sz = rz.SinAngle(); + Scalar cz = rz.CosAngle(); + return Rotation3D + ( cy*cz ,-cy*sz , sy , + sz , cz , 0 , + -cz*sy , sy*sz , cy ); +} + +// Rz * Rx +Rotation3D operator* (RotationZ const & rz, RotationX const & rx) { + Scalar sx = rx.SinAngle(); + Scalar cx = rx.CosAngle(); + Scalar sz = rz.SinAngle(); + Scalar cz = rz.CosAngle(); + return Rotation3D + ( cz ,-cx*sz , sx*sz , + sz , cx*cz ,-cz*sx , + 0 , sx , cx ); +} + +// Rz * Ry +Rotation3D operator* (RotationZ const & rz, RotationY const & ry) { + Scalar sy = ry.SinAngle(); + Scalar cy = ry.CosAngle(); + Scalar sz = rz.SinAngle(); + Scalar cz = rz.CosAngle(); + return Rotation3D + ( cy*cz , -sz , cz*sy , + cy*sz , cz , sy*sz , + -sy , 0 , cy ); +} + + + + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/RotationZYX.cxx b/math/experimental/genvectorx/src/RotationZYX.cxx new file mode 100644 index 0000000000000..0544cd1dd0f8a --- /dev/null +++ b/math/experimental/genvectorx/src/RotationZYX.cxx @@ -0,0 +1,166 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2005 + + /********************************************************************** + * * + * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team * + * * + * * + **********************************************************************/ + +// Implementation file for rotation in 3 dimensions, represented by RotationZYX +// +// Created by: Lorenzo Moneta, May 23 2007 +// +// Last update: $Id$ +// +#include "MathX/GenVectorX/RotationZYX.h" + +#include + +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/Quaternion.h" +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" + +#include "MathX/GenVectorX/AxisAnglefwd.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + +// ========== Constructors and Assignment ===================== + + + +// ========== Operations ===================== + +// DisplacementVector3D< Cartesian3D > +// RotationZYX:: +// operator() (const DisplacementVector3D< Cartesian3D > & v) const +// { +// return Rotation3D(*this)(v); +// } + + +RotationZYX RotationZYX::operator * (const Rotation3D & r) const { + // combine with a Rotation3D + return RotationZYX ( Rotation3D(*this) * r ); +} + +RotationZYX RotationZYX::operator * (const AxisAngle & a) const { + // combine with a AxisAngle + return RotationZYX ( Quaternion(*this) * Quaternion(a) ); +} + +RotationZYX RotationZYX::operator * (const EulerAngles & e) const { + // combine with EulerAngles + return RotationZYX ( Quaternion(*this) * Quaternion(e) ); +} + +RotationZYX RotationZYX::operator * (const RotationZYX & e) const { + // combine with a RotationZYX + //return RotationZYX ( Quaternion(*this) * Quaternion(e) ); + return RotationZYX ( Rotation3D(*this) * Rotation3D(e) ); +} +RotationZYX RotationZYX::operator * (const Quaternion & q) const { + // combination with a Quaternion + return RotationZYX ( Quaternion(*this) * q ); +} + +RotationZYX RotationZYX::operator * (const RotationX & r) const { + // combine with a RotationX + return RotationZYX ( Quaternion(*this) * r ); +} + +RotationZYX RotationZYX::operator * (const RotationY & r) const { + // combine with a RotationY + return RotationZYX ( Quaternion(*this) * r ); +} + +RotationZYX RotationZYX::operator * (const RotationZ & r) const { + // combine with a RotationZ + // TODO -- this can be made much faster because it merely adds + // the r.Angle() to phi. + Scalar newPhi = fPhi + r.Angle(); + if ( newPhi <= -Pi()|| newPhi > Pi() ) { + newPhi = newPhi - math_floor( newPhi/(2*Pi()) +.5 ) * 2*Pi(); + } + return RotationZYX ( newPhi, fTheta, fPsi ); +} + +RotationZYX operator * ( RotationX const & r, RotationZYX const & e ) { + return RotationZYX(r) * e; // TODO: improve performance +} + +RotationZYX operator * ( RotationY const & r, RotationZYX const & e ) { + return RotationZYX(r) * e; // TODO: improve performance +} + +RotationZYX +operator * ( RotationZ const & r, RotationZYX const & e ) { + return RotationZYX(r) * e; // TODO: improve performance +} + +void RotationZYX::Rectify() +{ + // rectify . The angle theta must be defined between [-PI/2,PI.2] + // same as Euler- Angles, just here Theta is shifted by PI/2 with respect to + // the theta of the EulerAngles class + + Scalar theta2 = fTheta + M_PI_2; + if ( theta2 < 0 || theta2 > Pi() ) { + Scalar t = theta2 - math_floor( theta2/(2*Pi() ) ) * 2*Pi(); + if ( t <= Pi() ) { + theta2 = t; + } else { + theta2 = 2*Pi() - t; + fPhi = fPhi + Pi(); + fPsi = fPsi + Pi(); + } + // ftheta is shifted of PI/2 w.r.t theta2 + fTheta = theta2 - M_PI_2; + } + + if ( fPhi <= -Pi()|| fPhi > Pi() ) { + fPhi = fPhi - math_floor( fPhi/(2*Pi()) +.5 ) * 2*Pi(); + } + + if ( fPsi <= -Pi()|| fPsi > Pi() ) { + fPsi = fPsi - math_floor( fPsi/(2*Pi()) +.5 ) * 2*Pi(); + } + +} // Rectify() + +void RotationZYX::Invert() +{ + // invert this rotation. + // use Rotation3D. TO Do :have algorithm to invert it directly + Rotation3D r(*this); + //Quaternion r(*this); + r.Invert(); + *this = r; +} + +#if !defined(ROOT_MATH_SYCL) && !defined(ROOT_MATH_CUDA) + +// ========== I/O ===================== + +std::ostream & operator<< (std::ostream & os, const RotationZYX & e) { + // TODO - this will need changing for machine-readable issues + // and even the human readable form may need formatting improvements + os << "\n{phi(Z angle): " << e.Phi() << " theta(Y angle): " << e.Theta() + << " psi(X angle): " << e.Psi() << "}\n"; + return os; +} +#endif + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/src/VectorUtil.cxx b/math/experimental/genvectorx/src/VectorUtil.cxx new file mode 100644 index 0000000000000..b4f4f714c5f79 --- /dev/null +++ b/math/experimental/genvectorx/src/VectorUtil.cxx @@ -0,0 +1,59 @@ +// @(#)root/mathcore:$Id$ +// Authors: W. Brown, M. Fischler, L. Moneta 2006 + + /********************************************************************** + * * + * Copyright (c) 2006 , LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Implementation of VectorUtil functions +// +// Created by: Lorenzo Moneta 22 Aug 2006 +// +#include "MathX/GenVectorX/VectorUtil.h" + + +#include "MathX/GenVectorX/AccHeaders.h" + +#include "MathX/GenVectorX/MathHeaders.h" + +namespace ROOT { + +namespace ROOT_MATH_ARCH { + + +double VectorUtil::Phi_0_2pi(double angle) { + // returns phi angle in the interval (0,2*PI] + if ( angle <= 2.*M_PI && angle > 0 ) return angle; + + if ( angle > 0 ) { + int n = static_cast( angle/(2.*M_PI) ); + angle -= 2.*M_PI*n; + } else { + int n = static_cast( -(angle)/(2.*M_PI) ); + angle += 2.*M_PI*(n+1); + } + return angle; +} + +double VectorUtil::Phi_mpi_pi(double angle) { + // returns phi angle in the interval (-PI,PI] + + if ( angle <= M_PI && angle > -M_PI ) return angle; + + if ( angle > 0 ) { + int n = static_cast( (angle+M_PI)/(2.*M_PI) ); + angle -= 2*M_PI*n; + } else { + int n = static_cast( -(angle-M_PI)/(2.*M_PI) ); + angle += 2*M_PI*n; + } + return angle; +} + + + +} //namespace Math +} //namespace ROOT diff --git a/math/experimental/genvectorx/test/CMakeLists.txt b/math/experimental/genvectorx/test/CMakeLists.txt new file mode 100644 index 0000000000000..00fbd2364f824 --- /dev/null +++ b/math/experimental/genvectorx/test/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (C) 1995-2023, Rene Brun and Fons Rademakers. +# All rights reserved. +# +# For the licensing terms see $ROOTSYS/LICENSE. +# For the list of contributors see $ROOTSYS/README/CREDITS. + +# @author Danilo Piparo CERN + + + ROOT_EXECUTABLE(testGenvectorSYCL testGenVectorSYCL.cxx) # LIBRARIES GenVectorSYCL) + if (oneapi) + target_link_options(testGenvectorSYCL PUBLIC -E) + endif() + target_link_libraries(testGenvectorSYCL PUBLIC GenVectorSYCL ) + #target_include_directories(testGenvectorSYCL PUBLIC $) + #add_custom_target(genexdebug COMMAND ${CMAKE_COMMAND} -E echo "GenVectorSYCL inc dirs $") + add_sycl_to_root_target(TARGET testGenvectorSYCL + SOURCES testGenVectorSYCL.cxx + COMPILE_DEFINITIONS ROOT_MATH_SYCL + DEPENDENCIES GenVectorSYCL + ) + ROOT_ADD_TEST(test-genvector-genvectorsycl COMMAND testGenvectorSYCL) + diff --git a/math/experimental/genvectorx/test/CoordinateTraits.h b/math/experimental/genvectorx/test/CoordinateTraits.h new file mode 100644 index 0000000000000..36da6da258659 --- /dev/null +++ b/math/experimental/genvectorx/test/CoordinateTraits.h @@ -0,0 +1,124 @@ +#ifndef COORDINATETRAITS_H +#define COORDINATETRAITS_H + +// $Id: CoordinateTraits.h,v 1.1 2005/09/19 14:22:38 brun Exp $ +// +// Coordinate System traits useful for testing purposes. +// +// For example, when reporting a problem, it is nice to be able +// to present a human-readable name for the system. +// +// Created by: Mark Fischler at Mon May 30 12:21:43 2005 +// +// Last update: Wed Jun 1 2005 + +#include +#include +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/Cylindrical3D.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#include "MathX/GenVectorX/Polar3D.h" +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/PxPyPzM4D.h" +#include "MathX/GenVectorX/PtEtaPhiE4D.h" +#include "MathX/GenVectorX/PtEtaPhiM4D.h" + +namespace ROOT { +namespace Math { + +template +struct CoordinateTraits { + static const std::string name() { + std::string s = "NOT-A-COORDINATE-SYSTEM: "; + s += typeid(C).name(); + return s; + } +}; + +template +struct CoordinateTraits < Cartesian3D >{ + static const std::string name() { + std::string s = "Cartesian Coordinates <"; + s += typeid(Scalar).name(); + s += "> (x, y, z)"; + return s; + } +}; + +template +struct CoordinateTraits < CylindricalEta3D >{ + static const std::string name() { + std::string s = "Cylindrical/Eta Coordinates <"; + s += typeid(Scalar).name(); + s += "> (rho, eta, phi)"; + return s; + } +}; + +template +struct CoordinateTraits < Cylindrical3D >{ + static const std::string name() { + std::string s = "Cylindrical Coordinates <"; + s += typeid(Scalar).name(); + s += "> (rho, z, phi)"; + return s; + } +}; + +template +struct CoordinateTraits < Polar3D >{ + static const std::string name() { + std::string s = "Polar Coordinates <"; + s += typeid(Scalar).name(); + s += "> (r, theta, phi)"; + return s; + } +}; + + // 4D COORDINATES + +template +struct CoordinateTraits < PxPyPzE4D >{ + static const std::string name() { + std::string s = "PxPyPzE4D Coordinates <"; + s += typeid(Scalar).name(); + s += "> (Px, Py, Pz, E)"; + return s; + } +}; + +template +struct CoordinateTraits < PxPyPzM4D >{ + static const std::string name() { + std::string s = "PxPyPzM4D Coordinates <"; + s += typeid(Scalar).name(); + s += "> (Px, Py, Pz, M)"; + return s; + } +}; + +template +struct CoordinateTraits < PtEtaPhiE4D >{ + static const std::string name() { + std::string s = "PtEtaPhiE4D4D Coordinates <"; + s += typeid(Scalar).name(); + s += "> (Pt, eta, phi, E)"; + return s; + } +}; + +template +struct CoordinateTraits < PtEtaPhiM4D >{ + static const std::string name() { + std::string s = "PtEtaPhiM4D4D Coordinates <"; + s += typeid(Scalar).name(); + s += "> (Pt, eta, phi, mass)"; + return s; + } +}; + + +} // namespace Math +} // namespace ROOT + +#endif // COORDINATETRAITS_H diff --git a/math/experimental/genvectorx/test/Makefile b/math/experimental/genvectorx/test/Makefile new file mode 100644 index 0000000000000..89f2dfabfa6ad --- /dev/null +++ b/math/experimental/genvectorx/test/Makefile @@ -0,0 +1,207 @@ +# Makefile for the ROOT test programs. +# This Makefile shows nicely how to compile and link applications +# using the ROOT libraries on all supported platforms. +# +# Copyright (c) 2000 Rene Brun and Fons Rademakers +# +# Author: Fons Rademakers, 29/2/2000 + +ROOTSYS = ../../.. +include $(ROOTSYS)/etc/Makefile.arch + +#------------------------------------------------------------------------------ + +ifeq ($(PLATFORM),win32) +EXTRALIBS = -include:_G__cpp_setupG__GenVector -include:_G__cpp_setupG__GenVector32 "$(ROOTSYS)/lib/libGenVector.lib" +else +EXTRALIBS = -lGenVector +CXXFLAGS += -g +endif + +ifeq ($(DIM),2) +CXXFLAGS += -DDIM_2 +endif +ifeq ($(DIM),3) +CXXFLAGS += -DDIM_3 +endif +ifneq ($(USE_CLHEP),) +CXXFLAGS += -DUSE_CLHEP +endif +ifneq ($(USE_ROOT),) +CXXFLAGS += -DUSE_ROOT +endif + + +# use reflex +#useReflex=yes +ifneq ($(USE_REFLEX),) +GCCXML=yes +CXXFLAGS += -DUSE_REFLEX +endif + + +# if have clhep +ifneq ($(CLHEPBASE),) +CXXFLAGS+= -I$(CLHEPBASE)/include -DHAVE_CLHEP +ifeq ($(PLATFORM),win32) +EXTRALIBS += "$(CLHEPBASE)/lib/CLHEP.lib" +else +#EXTRALIBS+= $(CLHEPBASE)/lib/libCLHEP.a +EXTRALIBS+= -L$(CLHEPBASE)/lib -lCLHEP +endif +endif + + +COORDINATES3DOBJ = coordinates3D.$(ObjSuf) +COORDINATES3DSRC = coordinates3D.$(SrcSuf) +COORDINATES3D = coordinates3D$(ExeSuf) + +COORDINATES4DOBJ = coordinates4D.$(ObjSuf) +COORDINATES4DSRC = coordinates4D.$(SrcSuf) +COORDINATES4D = coordinates4D$(ExeSuf) + +ROTATIONOBJ = rotationApplication.$(ObjSuf) +ROTATIONSRC = rotationApplication.$(SrcSuf) +ROTATION = rotationApplication$(ExeSuf) + +BOOSTOBJ = testBoost.$(ObjSuf) +BOOSTSRC = testBoost.$(SrcSuf) +BOOST = testBoost$(ExeSuf) + +ITERATOROBJ = testIterator.$(ObjSuf) +ITERATORSRC = testIterator.$(SrcSuf) +ITERATOR = testIterator$(ExeSuf) + +GENVECTOROBJ = testGenVector.$(ObjSuf) +GENVECTORSRC = testGenVector.$(SrcSuf) +GENVECTOR = testGenVector$(ExeSuf) + +VECTORIOOBJ = testVectorIO.$(ObjSuf) +VECTORIOSRC = testVectorIO.$(SrcSuf) +VECTORIO = testVectorIO$(ExeSuf) + +STRESS3DOBJ = stress3D.$(ObjSuf) +STRESS3DSRC = stress3D.$(SrcSuf) +STRESS3D = stress3D$(ExeSuf) + +STRESS2DOBJ = stress2D.$(ObjSuf) +STRESS2DSRC = stress2D.$(SrcSuf) +STRESS2D = stress2D$(ExeSuf) + +VECTOROPOBJ = vectorOperation.$(ObjSuf) +VECTOROPSRC = vectorOperation.$(SrcSuf) +VECTOROP = vectorOperation$(ExeSuf) + +#VECTORSCALEOBJ = testVectorScale.$(ObjSuf) +#VECTORSCALESRC = testVectorScale.$(SrcSuf) +#VECTORSCALE = testVectorScale$(ExeSuf) + + +OBJS = $(COORDINATES3DOBJ) $(COORDINATES4DOBJ) $(ROTATIONOBJ) $(BOOSTOBJ) $(GENVECTOROBJ) $(VECTORIOOBJ) $(STRESS3DOBJ) $(STRESS2DOBJ) $(ITERATOROBJ) $(VECTOROPOBJ) + + +PROGRAMS = $(COORDINATES3D) $(COORDINATES4D) $(ROTATION) $(BOOST) $(GENVECTOR) $(VECTORIO) $(STRESS3D) $(STRESS2D) $(ITERATOR) $(VECTOROP) + + + +.SUFFIXES: .$(SrcSuf) .$(ObjSuf) $(ExeSuf) + + +all: $(PROGRAMS) libTrackDict.$(DllSuf) + + +$(COORDINATES3D): $(COORDINATES3DOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(COORDINATES4D): $(COORDINATES4DOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(ROTATION): $(ROTATIONOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(BOOST): $(BOOSTOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(GENVECTOR): $(GENVECTOROBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(VECTORIO): $(VECTORIOOBJ) libTrackDict.$(DllSuf) + $(LD) $(LDFLAGS) $(VECTORIOOBJ) $(LIBS) $(EXTRALIBS) $(EXTRAIOLIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(STRESS3D): $(STRESS3DOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(STRESS2D): $(STRESS2DOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(ITERATOR): $(ITERATOROBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + + +$(VECTOROP): $(VECTOROPOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(EXTRAIOLIBS) $(OutPutOpt)$@ + @echo "$@ done" + +# $(VECTORSCALE): $(VECTORSCALEOBJ) +# $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(EXTRAIOLIBS) $(OutPutOpt)$@ +# @echo "$@ done" + + +ifneq ($(USE_REFLEX),) +TrackDict.$(SrcSuf): Track.h TrackDict.xml + @echo "Generating dictionary $@ using gccxml ..." + genreflex Track.h --selection_file=TrackDict.xml -o TrackDict.cxx -I$(ROOTSYS)/include +else +TrackDict.$(SrcSuf): Track.h TrackLinkDef.h + @echo "Generating dictionary $@ using rootcling ..." + $(ROOTCLING) -f $@ -c $^ +endif + + +libTrackDict.$(DllSuf): TrackDict.$(ObjSuf) +ifeq ($(ARCH),aix) + /usr/ibmcxx/bin/makeC++SharedLib $(OutPutOpt) $@ $(GLIBS) -p 0 $^ +else +ifeq ($(ARCH),aix5) + /usr/vacpp/bin/makeC++SharedLib $(OutPutOpt) $@ $(GLIBS) -p 0 $^ +else +ifeq ($(PLATFORM),macosx) + $(LD) $(SOFLAGS) $^ $(OutPutOpt) $@ +else +ifeq ($(PLATFORM),win32) + bindexplib libTrackDict $^ > libTrackDict.def + lib -nologo -MACHINE:IX86 $^ -def:$*.def \ + $(OutPutOpt)libTrackDict.lib + $(LD) $(SOFLAGS) $(LDFLAGS) $^ libTrackDict.exp $(LIBS) \ + $(OutPutOpt)$@ +else + $(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt)$@ +endif +endif +endif +endif + + + + +clean: + @rm -f $(OBJS) core TrackDict.$(SrcSuf) TrackDict.h + +distclean: clean + @rm -f $(PROGRAMS) libTrackDict.* + + +.SUFFIXES: .$(SrcSuf) + + +.$(SrcSuf).$(ObjSuf): + $(CXX) $(CXXFLAGS) -c $< diff --git a/math/experimental/genvectorx/test/RotationTraits.h b/math/experimental/genvectorx/test/RotationTraits.h new file mode 100644 index 0000000000000..54c29c3243f4f --- /dev/null +++ b/math/experimental/genvectorx/test/RotationTraits.h @@ -0,0 +1,136 @@ +#ifndef ROTATIONTRAITS_H +#define ROTATIONTRAITS_H + +// $Id: RotationTraits.h,v 1.1 2005/08/11 14:18:00 fischler Exp $ +// +// Rotation traits useful for testing purposes. +// +// For example, when reporting a problem, it is nice to be able +// to present a human-readable name for the rotation. +// +// Created by: Mark Fischler at Thu Aug 12 2005 +// + +#include +#include +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/AxisAngle.h" +#include "MathX/GenVectorX/EulerAngles.h" +#include "MathX/GenVectorX/Quaternion.h" +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" +#include "MathX/GenVectorX/LorentzRotation.h" + +namespace ROOT { +namespace Math { + +template +struct RotationTraits { + static const std::string name() {return "NOT-A-ROTATION!";} +}; + +template <> +struct RotationTraits < Rotation3D >{ + static const std::string name() { + std::string s = "Rotation3D"; + return s; + } +}; + +template <> +struct RotationTraits < AxisAngle >{ + static const std::string name() { + std::string s = "AxisAngle"; + return s; + } +}; + +template <> +struct RotationTraits < EulerAngles >{ + static const std::string name() { + std::string s = "EulerAngles"; + return s; + } +}; + +template <> +struct RotationTraits < Quaternion >{ + static const std::string name() { + std::string s = "Quaternion"; + return s; + } +}; + +template <> +struct RotationTraits < RotationX >{ + static const std::string name() { + std::string s = "RotationX"; + return s; + } +}; + +template <> +struct RotationTraits < RotationY >{ + static const std::string name() { + std::string s = "RotationY"; + return s; + } +}; + +template <> +struct RotationTraits < RotationZ >{ + static const std::string name() { + std::string s = "RotationZ"; + return s; + } +}; + +template <> +struct RotationTraits < LorentzRotation >{ + static const std::string name() { + std::string s = "LorentzRotation"; + return s; + } +}; + +#ifdef TODO +template <> +struct RotationTraits < Boost >{ + static const std::string name() { + std::string s = "Boost"; + return s; + } +}; + +template <> +struct RotationTraits < BoostX >{ + static const std::string name() { + std::string s = "BoostX"; + return s; + } +}; + +template <> +struct RotationTraits < BoostY >{ + static const std::string name() { + std::string s = "BoostY"; + return s; + } +}; + +template <> +struct RotationTraits < BoostZ >{ + static const std::string name() { + std::string s = "BoostZ"; + return s; + } +}; +#endif // TODO + + + +} // namespace Math +} // namespace ROOT + +#endif // COORDINATETRAITS_H diff --git a/math/experimental/genvectorx/test/Track.h b/math/experimental/genvectorx/test/Track.h new file mode 100644 index 0000000000000..593c91fbb1aea --- /dev/null +++ b/math/experimental/genvectorx/test/Track.h @@ -0,0 +1,167 @@ +// dummy track class for testing I/o of matric + +#include "MathX/Point3D.h" +#include "MathX/Vector4D.h" + +#include + +#include "TRandom.h" + +typedef double Double32_t; + + + +typedef ROOT::Math::LorentzVector > Vector4D; +typedef ROOT::Math::LorentzVector > Vector4D32; +//typedef ROOT::Math::LorentzVector > Vector4D32; + +typedef ROOT::Math::PositionVector3D > Point3D; +typedef ROOT::Math::PositionVector3D > Point3D32; + + + +// track class +class TrackD { + +public: + + typedef Vector4D VectorType; + typedef Point3D PointType; + + TrackD() {} + + TrackD(const Vector4D & q, const Point3D & p) : fVec(q), fPos(p) {} + + const Vector4D & Vec() const { return fVec; } + const Point3D & Pos() const { return fPos; } + + double mag2() const { + return fVec.mag2() + fPos.mag2(); + } + + void Set( const Vector4D & q, const Point3D & p) { + fVec = q; fPos = p; + } + +private: + + Vector4D fVec; + Point3D fPos; + +}; + +// track class based on of Double32 + + +class TrackD32 { + +public: + + typedef Vector4D32 VectorType; + typedef Point3D32 PointType; + + + TrackD32() {} + + TrackD32(const Vector4D32 & q, const Point3D32 & p) : fVec(q), fPos(p) {} + + const Vector4D32 & Vec() const { return fVec; } + const Point3D32 & Pos() const { return fPos; } + + double mag2() const { + return fVec.mag2() + fPos.mag2(); + } + + void Set( const Vector4D32 & q, const Point3D32 & p) { + fVec = q; + fPos = p; + } +private: + + Vector4D32 fVec; + Point3D32 fPos; + +}; + + +// class containning a vector of tracks +class VecTrackD { + +public: + + typedef std::vector::const_iterator It; + typedef Vector4D VectorType; + typedef Point3D PointType; + + + VecTrackD() {} + + It begin() const { return fTrks.begin(); } + It end() const { return fTrks.end(); } + + + double mag2() const { + double s = 0; + for (unsigned int i = 0; i < fTrks.size() ; ++i) + s += fTrks[i].mag2(); + + return s; + } + + void Set( const Vector4D & q, const Point3D & p) { + int n = (gRandom->Poisson(4) + 1); + fTrks.clear(); + fTrks.reserve(n); + for (int i = 0; i < n; ++i) { + double x,y,z; + gRandom->Sphere(x,y,z, p.R() ); + fTrks.push_back( TrackD(q,Point3D( x,y,z )) ); + } + } + +private: + + std::vector fTrks; + +}; + +// cluster class (containing a vector of points) + +class ClusterD { + +public: + + ClusterD() {} + + typedef Vector4D VectorType; + typedef Point3D PointType; + + + Vector4D & Vec() { return fVec; } + Point3D & Pos() { return fPos[0]; } + + double mag2() const { + double s = fVec.mag2(); + for (unsigned int i = 0; i < fPos.size() ; ++i) + s += fPos[i].mag2(); + return s; + } + + void Set( const Vector4D & q, const Point3D & p) { + fVec = q; + int n = (gRandom->Poisson(4) + 1); + fPos.clear(); + fPos.reserve(n); + for (int i = 0; i < n; ++i) { + double x,y,z; + gRandom->Sphere(x,y,z,p.R() ); + fPos.push_back( Point3D( x,y,z ) ); + } + } + +private: + + Vector4D fVec; + std::vector fPos; + +}; diff --git a/math/experimental/genvectorx/test/TrackDict.xml b/math/experimental/genvectorx/test/TrackDict.xml new file mode 100644 index 0000000000000..0db9a489ec666 --- /dev/null +++ b/math/experimental/genvectorx/test/TrackDict.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/math/experimental/genvectorx/test/TrackLinkDef.h b/math/experimental/genvectorx/test/TrackLinkDef.h new file mode 100644 index 0000000000000..cc953a68d58aa --- /dev/null +++ b/math/experimental/genvectorx/test/TrackLinkDef.h @@ -0,0 +1,22 @@ +#ifdef __CINT__ + + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + + + +#pragma link C++ class TrackD+; +#pragma link C++ class TrackD32+; + +#pragma extra_include "vector"; +#include + +#pragma link C++ class std::vector+; +#pragma link C++ class std::vector+; + +#pragma link C++ class VecTrackD+; +#pragma link C++ class ClusterD+; + +#endif diff --git a/math/experimental/genvectorx/test/coordinates3D.cxx b/math/experimental/genvectorx/test/coordinates3D.cxx new file mode 100644 index 0000000000000..fb06c026d99ae --- /dev/null +++ b/math/experimental/genvectorx/test/coordinates3D.cxx @@ -0,0 +1,324 @@ +// $Id $ +// +// Tests that each form of vector has all the properties that stem from +// owning and forwarding to a coordinates instance, and that they give proper +// results. +// +// 3D vectors have: +// +// accessors x(), y(), z(), r(), theta(), phi(), rho(), eta() +// +// ================================================================= + +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/Polar3D.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#include "MathX/GenVectorX/Cylindrical3D.h" +#include "MathX/GenVectorX/etaMax.h" + +#include "MathX/Vector3Dfwd.h" + +#include "CoordinateTraits.h" + +#include +#include +#include +#include + +//#define TRACE1 +#define DEBUG + +using namespace ROOT::Math; + + + + +template +struct Precision { + enum { result = std::numeric_limits::digits <= std::numeric_limits::digits }; +}; + +template +struct LessPreciseType { + typedef T1 type; +}; +template +struct LessPreciseType { + typedef T2 type; +}; + + +template +int +closeEnough ( Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks ) { + int ret = 0; + int pr = std::cout.precision(18); + Scalar1 eps1 = std::numeric_limits::epsilon(); + Scalar2 eps2 = std::numeric_limits::epsilon(); + typedef typename LessPreciseType::result>::type Scalar; + Scalar epsilon = (eps1 >= eps2) ? eps1 : eps2; + Scalar ss1 (s1); + Scalar ss2 (s2); + Scalar diff = ss1 - ss2; + if (diff < 0) diff = -diff; + if (ss1 == 0 || ss2 == 0) { // TODO - the ss2==0 makes a big change?? + if ( diff > ticks*epsilon ) { + ret=3; + std::cout << "\nAbsolute discrepancy in " << coord << "(): " + << ss1 << " != " << ss2 << "\n" + << " (Allowed discrepancy is " << ticks*epsilon + << ")\nDifference is " << diff/epsilon << " ticks\n"; + } + std::cout.precision (pr); + return ret; + } + // infinity dicrepancy musy be checked with max precision + long double sd1(ss1); + long double sd2(ss2); + if ( (sd1 + sd2 == sd1) != (sd1 + sd2 == sd2) ) { + ret=5; + std::cout << "\nInfinity discrepancy in " << coord << "(): " + << sd1 << " != " << sd2 << "\n"; + std::cout.precision (pr); + return ret; + } + Scalar denom = ss1 > 0 ? ss1 : -ss1; + if ((diff/denom > ticks*epsilon) && (diff > ticks*epsilon)) { + ret=9; + std::cout << "\nDiscrepancy in " << coord << "(): " + << ss1 << " != " << ss2 << "\n" + << " (Allowed discrepancy is " << ticks*epsilon*ss1 + << ")\nDifference is " << (diff/denom)/epsilon << " ticks\n"; + } + std::cout.precision (pr); + return ret; +} + +template +int compare3D (const V1 & v1, const V2 & v2, double ticks) { + int ret =0; + typedef typename V1::CoordinateType CoordType1; + typedef typename V2::CoordinateType CoordType2; + ret |= closeEnough ( v1.x(), v2.x(), "x" ,ticks); + ret |= closeEnough ( v1.y(), v2.y(), "y" ,ticks); + ret |= closeEnough ( v1.z(), v2.z(), "z" ,ticks); + ret |= closeEnough ( v1.rho(), v2.rho(), "rho" ,ticks); + // case in phi that difference is close to 2pi + typedef typename V2::Scalar Scalar; + Scalar phi2 = v2.phi(); + if (std::abs(v1.phi()- phi2 ) > ROOT::Math::Pi() ) { + if (phi2<0) + phi2 += 2.*ROOT::Math::Pi(); + else + phi2 -= 2*ROOT::Math::Pi(); + } + ret |= closeEnough ( v1.phi(), phi2, "phi" ,ticks); + ret |= closeEnough ( v1.r(), v2.r(), "r" ,ticks); + ret |= closeEnough ( v1.theta(), v2.theta(), "theta" ,ticks); + ret |= closeEnough ( v1.mag2(), v2.mag2(), "mag2" ,ticks); + ret |= closeEnough ( v1.perp2(), v2.perp2(), "perp2" ,ticks); + if ( v1.rho() > 0 && v2.rho() > 0 ) { // eta can legitimately vary if rho == 0 + ret |= closeEnough ( v1.eta(), v2.eta(), "eta" ,ticks); + } + + if (ret != 0) { + std::cout << "\nDiscrepancy detected (see above) is between:\n " + << CoordinateTraits::name() << " and\n " + << CoordinateTraits::name() << "\n" + << "with v = (" << v1.x() << ", " << v1.y() << ", " << v1.z() + << ")\n\n\n"; + } + else { +#ifdef DEBUG + std::cout << "."; +#endif + } + + + return ret; +} + +template +int test3D ( const DisplacementVector3D & v, double ticks ) { + +#ifdef DEBUG + std::cout <<"\n>>>>> Testing 3D from " << v << " ticks = " << ticks << std::endl; +#endif + + int ret = 0; + DisplacementVector3D< Cartesian3D > vxyz_d (v.x(), v.y(), v.z()); + + double r = std::sqrt (v.x()*v.x() + v.y()*v.y() + v.z()*v.z()); + double rho = std::sqrt (v.x()*v.x() + v.y()*v.y()); + double z = v.z(); +// double theta = r>0 ? std::acos ( z/r ) : 0; +// if (std::abs( std::abs(z) - r) < 10*r* std::numeric_limits::epsilon() ) + double theta = std::atan2( rho, z ); // better when theta is small or close to pi + + double phi = rho>0 ? std::atan2 (v.y(), v.x()) : 0; + DisplacementVector3D< Polar3D > vrtp_d ( r, theta, phi ); + + double eta; + if (rho != 0) { + eta = -std::log(std::tan(theta/2)); + #ifdef TRACE1 + std::cout << ":::: rho != 0\n" + << ":::: theta = << " << theta + <<"/n:::: tan(theta/2) = " << std::tan(theta/2) + <<"\n:::: eta = " << eta << "\n"; + #endif + } else if (v.z() == 0) { + eta = 0; + #ifdef TRACE1 + std::cout << ":::: v.z() == 0\n" + <<"\n:::: eta = " << eta << "\n"; + #endif + } else if (v.z() > 0) { + eta = v.z() + etaMax(); + #ifdef TRACE1 + std::cout << ":::: v.z() > 0\n" + << ":::: etaMax = " << etaMax() + <<"\n:::: eta = " << eta << "\n"; + #endif + } else { + eta = v.z() - etaMax(); + #ifdef TRACE1 + std::cout << ":::: v.z() < 0\n" + << ":::: etaMax = " << etaMax() + <<"\n:::: eta = " << eta << "\n"; + #endif + } + +#ifdef DEBUG + std::cout << " Testing DisplacementVector3D : "; +#endif + + DisplacementVector3D< CylindricalEta3D > vrep_d ( rho, eta, phi ); + + ret |= compare3D( vxyz_d, vrtp_d, ticks); + ret |= compare3D( vrtp_d, vxyz_d, ticks); + ret |= compare3D( vxyz_d, vrep_d, ticks); + ret |= compare3D( vrtp_d, vrep_d, ticks); + + DisplacementVector3D< Cylindrical3D > vrzp_d ( rho, z, phi ); + + ret |= compare3D( vxyz_d, vrzp_d, ticks); + ret |= compare3D( vrtp_d, vrzp_d, ticks); + ret |= compare3D( vrep_d, vrzp_d, ticks); + + DisplacementVector3D< Cartesian3D > vxyz_f (v.x(), v.y(), v.z()); + DisplacementVector3D< Polar3D > vrtp_f ( r, theta, phi ); + DisplacementVector3D< CylindricalEta3D > vrep_f ( rho, eta, phi ); + + ret |= compare3D( vxyz_d, vxyz_f, ticks); + ret |= compare3D( vxyz_d, vrep_f, ticks); + ret |= compare3D( vrtp_d, vrep_f, ticks); + + ret |= compare3D( vxyz_f, vxyz_f, ticks); + ret |= compare3D( vxyz_f, vrep_f, ticks); + ret |= compare3D( vrtp_f, vrep_f, ticks); + +#ifdef DEBUG + if (ret == 0) std::cout << "\t OK\n"; + else { + std::cout << "\t FAIL\n"; + std::cerr << "\n>>>>> Testing DisplacementVector3D from " << v << " ticks = " << ticks + << "\t:\t FAILED\n"; + } + std::cout << " Testing PositionVector3D : "; +#endif + + + PositionVector3D< Cartesian3D > pxyz_d; pxyz_d = vxyz_d; + PositionVector3D< Polar3D > prtp_d; prtp_d = vrtp_d; + PositionVector3D< CylindricalEta3D > prep_d; prep_d = vrep_d; + PositionVector3D< Cylindrical3D > przp_d; przp_d = vrzp_d; + + ret |= compare3D( pxyz_d, prtp_d, ticks); + ret |= compare3D( vxyz_d, prep_d, ticks); + ret |= compare3D( vrtp_d, prep_d, ticks); + ret |= compare3D( vxyz_d, przp_d, ticks); + + PositionVector3D< Cartesian3D > pxyz_f (v.x(), v.y(), v.z()); + PositionVector3D< Polar3D > prtp_f ( r, theta, phi ); + PositionVector3D< CylindricalEta3D > prep_f ( rho, eta, phi ); + + ret |= compare3D( vxyz_d, pxyz_f, ticks); + ret |= compare3D( vxyz_d, prep_f, ticks); + ret |= compare3D( vrtp_d, prep_f, ticks); + + ret |= compare3D( vxyz_f, pxyz_f, ticks); + ret |= compare3D( vxyz_f, prep_f, ticks); + ret |= compare3D( vrtp_f, prep_f, ticks); + +#ifdef DEBUG + if (ret == 0) std::cout << "\t\t OK\n"; + else { + std::cout << "\t FAIL\n"; + std::cerr << "\n>>>>> Testing PositionVector3D from " << v << " ticks = " << ticks + << "\t:\t FAILED\n"; + } +#endif + return ret; +} + + + +int coordinates3D () { + int ret = 0; + + ret |= test3D (XYZVector ( 0.0, 0.0, 0.0 ) ,2 ); + ret |= test3D (XYZVector ( 1.0, 2.0, 3.0 ) ,6 ); + ret |= test3D (XYZVector ( -1.0, 2.0, 3.0 ) ,6 ); + ret |= test3D (XYZVector ( 1.0, -2.0, 3.0 ) ,6 ); + ret |= test3D (XYZVector ( 1.0, 2.0, -3.0 ) ,6 ); + ret |= test3D (XYZVector ( -1.0, -2.0, 3.0 ) ,6 ); + ret |= test3D (XYZVector ( -1.0, 2.0, -3.0 ) ,6 ); + ret |= test3D (XYZVector ( 1.0, -2.0, -3.0 ) ,6 ); + ret |= test3D (XYZVector ( -1.0, -2.0, -3.0 ) ,6 ); + ret |= test3D (XYZVector ( 8.0, 0.0, 0.0 ) ,6 ); + ret |= test3D (XYZVector ( -8.0, 0.0, 0.0 ) ,12 ); + ret |= test3D (XYZVector ( 0.0, 9.0, 0.0 ) ,6 ); + ret |= test3D (XYZVector ( 0.0, -9.0, 0.0 ) ,6 ); +// rho == 0 tests the beyon-eta-max cases of cylindricalEta + ret |= test3D (XYZVector ( 0.0, 0.0, 7.0 ) ,8 ); + ret |= test3D (XYZVector ( 0.0, 0.0, -7.0 ) ,8 ); +// Larger ratios among coordinates presents a precision challenge + ret |= test3D (XYZVector ( 16.0, 0.02, .01 ) ,10 ); + ret |= test3D (XYZVector ( -16.0, 0.02, .01 ) ,10 ); + ret |= test3D (XYZVector ( -.01, 16.0, .01 ) ,2000 ); + ret |= test3D (XYZVector ( -.01, -16.0, .01 ) ,2000 ); + ret |= test3D (XYZVector ( 1.0, 2.0, 30.0 ) ,10 ); + // NOTE -- these larger errors are likely the results of treating + // the vector in a ctor or assignment as foreign... + // NO -- I'm fouling up the value of x() !!!!! +// As we push to higher z with zero rho, some accuracy loss is expected + ret |= test3D (XYZVector ( 0.0, 0.0, 15.0 ) ,30 ); + ret |= test3D (XYZVector ( 0.0, 0.0, -15.0 ) ,30 ); + ret |= test3D (XYZVector ( 0.0, 0.0, 35.0 ) ,30 ); + ret |= test3D (XYZVector ( 0.0, 0.0, -35.0 ) ,30 ); +// When z is big compared to rho, it is very hard to get precision in polar/eta: + ret |= test3D (XYZVector ( 0.01, 0.02, 16.0 ) ,10 ); + ret |= test3D (XYZVector ( 0.01, 0.02, -16.0 ) ,40000 ); +// test case when eta is large + ret |= test3D (XYZVector ( 1.E-8, 1.E-8, 10.0 ) , 20 ); +// when z is neg error is larger in eta when calculated from polar +// since we have a larger error in theta which is closer to pi + ret |= test3D (XYZVector ( 1.E-8, 1.E-8, -10.0 ) ,2.E9 ); + + // small value of z + ret |= test3D (XYZVector ( 10., 10., 1.E-8 ) ,1.0E6 ); + ret |= test3D (XYZVector ( 10., 10., -1.E-8 ) ,1.0E6 ); + + + return ret; +} + +int main() { + int ret = coordinates3D(); + if (ret) std::cerr << "test FAILED !!! " << std::endl; + else std::cout << "test OK " << std::endl; + return ret; +} diff --git a/math/experimental/genvectorx/test/coordinates4D.cxx b/math/experimental/genvectorx/test/coordinates4D.cxx new file mode 100644 index 0000000000000..19d5d916e4fc2 --- /dev/null +++ b/math/experimental/genvectorx/test/coordinates4D.cxx @@ -0,0 +1,258 @@ +// $Id $ +// +// Tests that each form of 4-vector has all the properties that stem from +// owning and forwarding to a 4D coordinates instance +// +// 6/28/05 m fischler +// from contents of test_coordinates.h by L. Moneta. +// +// ================================================================= + + +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/Polar3D.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#include "MathX/GenVectorX/etaMax.h" + +#include "MathX/GenVectorX/PxPyPzE4D.h" +#include "MathX/GenVectorX/PxPyPzM4D.h" +#include "MathX/GenVectorX/PtEtaPhiE4D.h" +#include "MathX/GenVectorX/PtEtaPhiM4D.h" +#include "MathX/GenVectorX/LorentzVector.h" + +#include "MathX/Vector4Dfwd.h" // for typedefs definitions + +#include "CoordinateTraits.h" + +#include +#include +#include +#include + +//#define TRACE1 +#define DEBUG + +using namespace ROOT::Math; + + + +template +struct Precision { + enum { result = std::numeric_limits::digits <= std::numeric_limits::digits }; +}; + +template +struct LessPreciseType { + typedef T1 type; +}; +template +struct LessPreciseType { + typedef T2 type; +}; + + +template +int +closeEnough ( Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks ) { + int ret = 0; + Scalar1 eps1 = std::numeric_limits::epsilon(); + Scalar2 eps2 = std::numeric_limits::epsilon(); + typedef typename LessPreciseType::result>::type Scalar; + Scalar epsilon = (eps1 >= eps2) ? eps1 : eps2; + int pr = std::cout.precision(18); + Scalar ss1 (s1); + Scalar ss2 (s2); + Scalar diff = ss1 - ss2; + if (diff < 0) diff = -diff; + if (ss1 == 0 || ss2 == 0) { // TODO - the ss2==0 makes a big change?? + if ( diff > ticks*epsilon ) { + ret=3; + std::cout << "\nAbsolute discrepancy in " << coord << "(): " + << ss1 << " != " << ss2 << "\n" + << " (Allowed discrepancy is " << ticks*epsilon + << ")\nDifference is " << diff/epsilon << " ticks\n"; + } + std::cout.precision (pr); + return ret; + } + // infinity dicrepancy musy be checked with max precision + long double sd1(ss1); + long double sd2(ss2); + if ( (sd1 + sd2 == sd1) != (sd1 + sd2 == sd2) ) { + ret=5; + std::cout << "\nInfinity discrepancy in " << coord << "(): " + << sd1 << " != " << sd2 << "\n"; + std::cout.precision (pr); + return ret; + } + Scalar denom = ss1 > 0 ? ss1 : -ss1; + if ((diff/denom > ticks*epsilon) && (diff > ticks*epsilon)) { + ret=9; + std::cout << "\nDiscrepancy in " << coord << "(): " + << ss1 << " != " << ss2 << "\n" + << " (Allowed discrepancy is " << ticks*epsilon*ss1 + << ")\nDifference is " << (diff/denom)/epsilon << " ticks\n"; + } + std::cout.precision (pr); + return ret; +} + + +template +int compare4D (const V1 & v1, const V2 & v2, double ticks) { + int ret =0; + typedef typename V1::CoordinateType CoordType1; + typedef typename V2::CoordinateType CoordType2; + + ret |= closeEnough ( v1.x(), v2.x(), "x" ,ticks); + ret |= closeEnough ( v1.y(), v2.y(), "y" ,ticks); + ret |= closeEnough ( v1.z(), v2.z(), "z" ,ticks); + ret |= closeEnough ( v1.t(), v2.t(), "t" ,ticks); + ret |= closeEnough ( v1.rho(), v2.rho(), "rho" ,ticks); + ret |= closeEnough ( v1.phi(), v2.phi(), "phi" ,ticks); + ret |= closeEnough ( v1.P(), v2.P(), "p" ,ticks); + ret |= closeEnough ( v1.theta(), v2.theta(), "theta" ,ticks); + ret |= closeEnough ( v1.perp2(), v2.perp2(), "perp2" ,ticks); + ret |= closeEnough ( v1.M2(), v2.M2(), "m2" ,ticks); + ret |= closeEnough ( v1.M(), v2.M(), "m" ,ticks); + ret |= closeEnough ( v1.Mt(), v2.Mt(), "mt" ,ticks); + ret |= closeEnough ( v1.Et(), v2.Et(), "et" ,ticks); + if ( v1.rho() > 0 && v2.rho() > 0 ) { // eta can legitimately vary if rho == 0 + ret |= closeEnough ( v1.eta(), v2.eta(), "eta" ,ticks); + } + + if (ret != 0) { + std::cout << "Discrepancy detected (see above) is between:\n " + << CoordinateTraits::name() << " and\n " + << CoordinateTraits::name() << "\n" + << "with v = (" << v1.x() << ", " << v1.y() << ", " + << v1.z() << ", " << v1.t() << ")\n"; + } + else { + std::cout << "."; + } + + return ret; +} + + + + +template +int test4D ( const LorentzVector & v, double ticks ) { + +#ifdef DEBUG + std::cout <<"\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks << "\t: "; +#endif + + int ret = 0; + LorentzVector< PxPyPzE4D > vxyzt_d (v.x(), v.y(), v.z(), v.t()); + + //double m = std::sqrt ( v.t()*v.t() - v.x()*v.x() - v.y()*v.y() - v.z()*v.z()); + //double r = std::sqrt (v.x()*v.x() + v.y()*v.y() + v.z()*v.z()); + double rho = std::sqrt (v.x()*v.x() + v.y()*v.y()); + double theta = std::atan2( rho, v.z() ); // better than using acos + //double theta = r>0 ? std::acos ( v.z()/r ) : 0; + double phi = rho>0 ? std::atan2 (v.y(), v.x()) : 0; + + double eta; + if (rho != 0) { + eta = -std::log(std::tan(theta/2)); + #ifdef TRACE1 + std::cout << ":::: rho != 0\n" + << ":::: theta = " << theta + <<"/n:::: tan(theta/2) = " << std::tan(theta/2) + <<"\n:::: eta = " << eta << "\n"; + #endif + } else if (v.z() == 0) { + eta = 0; + #ifdef TRACE1 + std::cout << ":::: v.z() == 0\n" + <<"\n:::: eta = " << eta << "\n"; + #endif + } else if (v.z() > 0) { + eta = v.z() + etaMax(); + #ifdef TRACE1 + std::cout << ":::: v.z() > 0\n" + << ":::: etaMax = " << etaMax() + <<"\n:::: eta = " << eta << "\n"; + #endif + } else { + eta = v.z() - etaMax(); + #ifdef TRACE1 + std::cout << ":::: v.z() < 0\n" + << ":::: etaMax = " << etaMax() + <<"\n:::: eta = " << eta << "\n"; + #endif + } + + + LorentzVector< PtEtaPhiE4D > vrep_d ( rho, eta, phi, v.t() ); + ret |= compare4D( vxyzt_d, vrep_d, ticks); + + LorentzVector< PtEtaPhiM4D > vrepm_d ( rho, eta, phi, v.M() ); + ret |= compare4D( vxyzt_d, vrepm_d, ticks); + + LorentzVector< PxPyPzM4D > vxyzm_d ( v.x(), v.y(), v.z(), v.M() ); + ret |= compare4D( vrep_d, vxyzm_d, ticks); + + LorentzVector< PxPyPzE4D > vxyzt_f (v.x(), v.y(), v.z(), v.t()); + ret |= compare4D( vxyzt_d, vxyzt_f, ticks); + + LorentzVector< PtEtaPhiE4D > vrep_f ( rho, eta, phi, v.t() ); + ret |= compare4D( vxyzt_f, vrep_f, ticks); + + LorentzVector< PtEtaPhiM4D > vrepm_f ( rho, eta, phi, v.M() ); + ret |= compare4D( vxyzt_f, vrepm_f, ticks); + + LorentzVector< PxPyPzM4D > vxyzm_f (v.x(), v.y(), v.z(), v.M()); + ret |= compare4D( vrep_f, vxyzm_f, ticks); + + if (ret == 0) std::cout << "\t OK\n"; + else { + std::cout << "\t FAIL\n"; + std::cerr << "\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks + << "\t:\t FAILED\n"; + } + return ret; +} + + +int coordinates4D (bool testAll = false) { + int ret = 0; + + ret |= test4D (XYZTVector ( 0.0, 0.0, 0.0, 0.0 ) , 1 ); + ret |= test4D (XYZTVector ( 1.0, 2.0, 3.0, 4.0 ) ,10 ); + ret |= test4D (XYZTVector ( -1.0, -2.0, 3.0, 4.0 ) ,10 ); + // test for large eta values (which was giving inf before Jun 07) + ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, 10.0, 100.0 ) ,10 ); + // for z < 0 precision in eta is worse since theta is close to Pi + ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, -10.0, 100.0 ) ,1000000000 ); + + // test cases with zero mass + + // tick should be p /sqrt(eps) ~ 4 /sqrt(eps) + // take a factor 1.5 in ticks to be conservative + ret |= test4D (PxPyPzMVector ( 1., 2., 3., 0.) , 1.5 * 4./std::sqrt(std::numeric_limits::epsilon()) ); + + // this test fails in some machines (skip by default) + if (!testAll) return ret; + + // take a factor 1.5 in ticks to be conservative + ret |= test4D (PxPyPzMVector ( 1., 1., 100., 0.) , 150./std::sqrt(std::numeric_limits::epsilon()) ); + // need a larger a factor here + ret |= test4D (PxPyPzMVector ( 1.E8, 1.E8, 1.E8, 0.) , 1.E9/std::sqrt(std::numeric_limits::epsilon()) ); + // if use 1 here fails + ret |= test4D (PxPyPzMVector ( 1.E-8, 1.E-8, 1.E-8, 0.) , 2.E-8/std::sqrt(std::numeric_limits::epsilon()) ); + + return ret; +} + +int main() { + int ret = coordinates4D(); + if (ret) std::cerr << "test FAILED !!! " << std::endl; + else std::cout << "test OK " << std::endl; + return ret; +} diff --git a/math/experimental/genvectorx/test/rotationApplication.cxx b/math/experimental/genvectorx/test/rotationApplication.cxx new file mode 100644 index 0000000000000..f51fe6a644f0d --- /dev/null +++ b/math/experimental/genvectorx/test/rotationApplication.cxx @@ -0,0 +1,721 @@ +/********************************************************************** + * * + * Copyright (c) 2005 , FNAL LCG ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// RotationApplication.cpp +// +// Created by: M. Fischler, Aug 10, 2005 +// +// Tests that each Rotation produces correct results when applied to +// each form of vector in each coordinate system, and incidentally that products +// of rotations work properly. +// +// The strategy is to build up sequences of rotations about the X, Y, and Z +// axes, such that we can easily determine the correct vector answer. +// +// ================================================================= + +#include "MathX/GenVectorX/DisplacementVector3D.h" +#include "MathX/GenVectorX/PositionVector3D.h" +#include "MathX/GenVectorX/Cartesian3D.h" +#include "MathX/GenVectorX/Polar3D.h" +#include "MathX/GenVectorX/CylindricalEta3D.h" +#include "MathX/GenVectorX/LorentzVector.h" +#include "MathX/GenVectorX/Rotation3D.h" +#include "MathX/GenVectorX/AxisAngle.h" +#include "MathX/GenVectorX/EulerAngles.h" +#include "MathX/GenVectorX/Quaternion.h" +#include "MathX/GenVectorX/RotationZYX.h" +#include "MathX/GenVectorX/RotationX.h" +#include "MathX/GenVectorX/RotationY.h" +#include "MathX/GenVectorX/RotationZ.h" + +#include "MathX/GenVectorX/VectorUtil.h" + +#include "MathX/Vector3Dfwd.h" + +#include "CoordinateTraits.h" +#include "RotationTraits.h" + +#include +#include +#include +#include + +using std::sin; +using std::cos; + +//#define TRACE2 +//#define TRACE1 +//#define DEBUG + +using namespace ROOT::Math; + +template +struct Precision { + enum { result = std::numeric_limits::digits <= std::numeric_limits::digits }; +}; + +template +struct LessPreciseType { + typedef T1 type; +}; +template +struct LessPreciseType { + typedef T2 type; +}; + +template +int +closeEnough (Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks) { + int ret = 0; + int pr = std::cout.precision(18); + Scalar1 eps1 = std::numeric_limits::epsilon(); + Scalar2 eps2 = std::numeric_limits::epsilon(); + typedef typename LessPreciseType::result>::type Scalar; + Scalar epsilon = (eps1 >= eps2) ? eps1 : eps2; + Scalar ss1 (s1); + Scalar ss2 (s2); + Scalar diff = ss1 - ss2; + if (diff < 0) diff = -diff; + if ( diff > ticks*epsilon ) { + ret=3; + std::cout << "\n\n????????\n\nAbsolute discrepancy in " << coord << "(): " + << ss1 << " != " << ss2 << "\n" + << " (Allowed discrepancy is " << ticks + << " ticks = " << ticks*epsilon + << ")\nDifference is " << diff/epsilon << " ticks\n"; + } + std::cout.precision (pr); + return ret; +} + +template +int compare3D (const V1 & v1, const V2 & v2, double ticks) { + int ret =0; + typedef typename V1::CoordinateType CoordType1; + typedef typename V2::CoordinateType CoordType2; + + ret |= closeEnough ( v1.x(), v2.x(), "x" ,ticks); + ret |= closeEnough ( v1.y(), v2.y(), "y" ,ticks); + ret |= closeEnough ( v1.z(), v2.z(), "z" ,ticks); + + if (ret != 0) { + std::cout << "Discrepancy detected (see above) is between:\n " + << CoordinateTraits::name() << " and\n " + << CoordinateTraits::name() << "\n" + << "with v = (" << v1.x() << ", " << v1.y() << ", " << v1.z() + << ")\nv1 is " << v1 + << "\nv2 is " << v2 << "\n\n"; + } + + return ret; +} + +template struct correctedTicks { + double operator()(double ticks, const V& /*v */ , const XYZVector & /* ans */) + { + return ticks; + } +}; + +double correctTicks (double ticks,double z,double r) { + double e = ticks*std::fabs( z*z / (r*r-z*z) ); + if (e < ticks) return ticks; + return e; +} + +template<> struct +correctedTicks< DisplacementVector3D < CylindricalEta3D > > { + double operator()(double ticks, + const DisplacementVector3D< CylindricalEta3D >& v, + const XYZVector & ans) { + double t1 = correctTicks (ticks, v.z(), v.r()); + double t2 = correctTicks (ticks, ans.z(), ans.r()); + return t1 > t2 ? t1 : t2; + } +}; + +template<> struct +correctedTicks< PositionVector3D < CylindricalEta3D > > { + double operator()(double ticks, + const PositionVector3D< CylindricalEta3D >& v, + const XYZVector & ans) { + double t1 = correctTicks (ticks, v.z(), v.r()); + double t2 = correctTicks (ticks, ans.z(), ans.r()); + return t1 > t2 ? t1 : t2; + } +}; + +template +int testApplication(const R& r,const V& v,const XYZVector &answer,double t) { + + typedef typename V::CoordinateType CoordType; + + int ret = 0; + correctedTicks ct; + double ticks = ct(t, v, answer); +#ifdef DEBUG + std::cout <<">>>>> Testing application of " + << RotationTraits::name() << " " << r << "\non " + << CoordinateTraits::name() << + v << " ticks = " << ticks; +#endif +#ifdef TRACE2 + std::cout << " about to do V rv = r(v) - \n"; +#endif + V rv = r(v); +#ifdef TRACE2 + std::cout << "ok "; +#endif + // comparison here should be == but need to use 10 ticks to be sure for 32 bits machines + // when results are flushed in memory and approximated + if ( compare3D(rv, r*v, 10 ) != 0) { + std::cout << "Inconsistency between R(v) and R*v for R = " + << RotationTraits::name() << " " << r + << "\nacting on " << CoordinateTraits::name() << v << "\n"; + ret |= 9; + } +#ifdef TRACE2 + std::cout << "+ also did rv != r*v "; +#endif + if ( closeEnough(v.r(), rv.r(), "r", ticks) != 0 ) { + std::cout << "Radius change between R(v) and R*v for R = " + << RotationTraits::name() << " " << r + << "\nacting on " + << CoordinateTraits::name() + << v << "\n"; + ret |= 17; + } +#ifdef TRACE2 + std::cout << "\n---- about to do compare3D ----"; +#endif + ret |= compare3D (rv, answer, ticks); +#ifdef TRACE2 + std::cout << " done \n"; +#endif +#ifdef DEBUG + if (ret == 0) std::cout << " OK\n"; +#endif + return ret; +} + + +XYZVector rxv ( double phi, XYZVector v ) { + double c = cos(phi); + double s = sin(phi); + return XYZVector ( v.x(), c*v.y()-s*v.z(), s*v.y()+c*v.z() ); +} + +XYZVector ryv ( double phi, XYZVector v ) { + double c = cos(phi); + double s = sin(phi); + return XYZVector ( c*v.x()+s*v.z(), v.y(), -s*v.x()+c*v.z() ); +} + +XYZVector rzv ( double phi, XYZVector v ) { + double c = cos(phi); + double s = sin(phi); + return XYZVector ( c*v.x()-s*v.y(), s*v.x()+c*v.y(), v.z() ); +} + +enum XYZ { X, Y, Z } ; + +struct TestRotation { + std::vector xyz; + std::vector phi; + TestRotation (std::vector const & xyz_, std::vector const & phi_) + : xyz(xyz_), phi(phi_) {} +}; + + +Rotation3D rrr (TestRotation const & t) { +#ifdef TRACE1 + std::cout << "---- rrr ----"; +#endif + Rotation3D r; + for (unsigned int i=0; i= 0; --i) { + switch ( t.xyz[i] ) { + case X: + v = rxv ( t.phi[i],v ); + break; + case Y: + v = ryv ( t.phi[i],v ); + break; + case Z: + v = rzv ( t.phi[i],v ); + break; + } + } + return v; +} + +const double pi = 3.1415926535897932385; + +std::vector +makeTestRotations () { +#ifdef TRACE1 + std::cout << "---- makeTestRotations ----"; +#endif + std::vector t; + std::vector xyz; + std::vector phi; + + + + xyz.clear(); phi.clear(); + xyz.push_back(X); phi.push_back( pi/2 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(Y); phi.push_back( pi/2 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(Z); phi.push_back( pi/2 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(X); phi.push_back( -pi/6 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(Y); phi.push_back( pi/6 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(Z); phi.push_back( pi/3 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(X); phi.push_back( -pi/6 ); + xyz.push_back(Y); phi.push_back( pi/3 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(X); phi.push_back( -pi/6 ); + xyz.push_back(Y); phi.push_back( pi/4 ); + xyz.push_back(Z); phi.push_back( -pi/5 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(Y); phi.push_back( pi ); + xyz.push_back(X); phi.push_back( -pi/2 ); + xyz.push_back(Z); phi.push_back( -pi/1.5 ); + xyz.push_back(Y); phi.push_back( -pi/3 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(Z); phi.push_back( 1.3 ); + xyz.push_back(Y); phi.push_back( -1.1 ); + xyz.push_back(X); phi.push_back( 0.4 ); + xyz.push_back(Y); phi.push_back( 0.7 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(X); phi.push_back( 1.3 ); + xyz.push_back(Z); phi.push_back( -1.1 ); + xyz.push_back(Y); phi.push_back( 0.4 ); + xyz.push_back(Z); phi.push_back( 0.7 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(Y); phi.push_back( 1.3 ); + xyz.push_back(X); phi.push_back( -1.1 ); + xyz.push_back(Z); phi.push_back( 0.4 ); + xyz.push_back(X); phi.push_back( 0.7 ); + t.push_back(TestRotation(xyz,phi)); + + xyz.clear(); phi.clear(); + xyz.push_back(Z); phi.push_back( .03 ); + xyz.push_back(Y); phi.push_back( -.05 ); + xyz.push_back(X); phi.push_back( 0.04 ); + xyz.push_back(Y); phi.push_back( 0.07 ); + xyz.push_back(Z); phi.push_back( -0.02 ); + t.push_back(TestRotation(xyz,phi)); + +#ifdef TRACE1 + std::cout << " done\n"; +#endif + return t; +} + +std::vector makeTestVectors () { +#ifdef TRACE1 + std::cout << "---- makeTestVectors ----"; +#endif + std::vector vs; + vs.push_back(XYZVector ( 1, 0, 0 )); + vs.push_back(XYZVector ( 0, 1, 0 )); + vs.push_back(XYZVector ( 0, 0, 1 )); + vs.push_back(XYZVector ( -1, 0, 0 )); + vs.push_back(XYZVector ( 0, -1, 0 )); + vs.push_back(XYZVector ( 0, 0, -1 )); + vs.push_back(XYZVector ( 1, 2, 3 )); + vs.push_back(XYZVector ( 2, -1, 3 )); + vs.push_back(XYZVector ( -3, 1, -2 )); + vs.push_back(XYZVector ( 0, .00001, -2 )); + +#ifdef TRACE1 + std::cout << " done\n"; +#endif + return vs; +} + +template +int doTest (TestRotation const & testRotation, XYZVector const & testVector, + double ticks) { +#ifdef TRACE1 + std::cout << "---- doTest ----"; +#endif + int ret = 0; + R r ( rrr(testRotation) ); + V v(testVector); + XYZVector rv = ans (testRotation, testVector); + ret |= testApplication (r, v, rv, ticks); +#ifdef TRACE1 + std::cout << " done\n"; +#endif + + if (ret == 0) std::cout << "."; + + return ret; +} + +template +int doTestL (TestRotation const & testRotation, XYZVector const & testVector, + double ticks) { +#ifdef TRACE1 + std::cout << "---- doTestL ----"; +#endif + int ret = 0; + R r ( rrr(testRotation) ); + LorentzVector v; + double x = testVector.X(); + double y = testVector.Y(); + double z = testVector.Z(); + double t = std::sqrt (x*x + y*y + z*z + 1); + v.SetXYZT ( x, y, z, t ); + XYZVector rv = ans (testRotation, testVector); + ret |= testApplication (r, v, rv, ticks); + LorentzVector rv2 = r(v); + ret |= closeEnough (t, rv2.E(), "t", ticks); +#ifdef TRACE1 + std::cout << " done\n"; +#endif + return ret; +} + +struct ForeignVector { + typedef Cartesian3D<> CoordinateType; + XYZVector v; + template + explicit ForeignVector (V const & v_) : v(v_) {} + ForeignVector (double xx, double yy, double zz) : v(xx,yy,zz) {} + double x() const { return v.x(); } + double y() const { return v.y(); } + double z() const { return v.z(); } + double r() const { return v.r(); } + bool operator==(ForeignVector const & rhs) {return v == rhs.v;} + bool operator!=(ForeignVector const & rhs) {return v != rhs.v;} +}; +std::ostream & operator<< (std::ostream& os, const ForeignVector& v) { + return os << v.v; +} + + +template +int doTestOfR (TestRotation const & testRotation, XYZVector const & testVector){ +#ifdef TRACE1 + std::cout << "---- doTestofR ----\n"; +#endif + int ret = 0; + const double ticks = 100; // move from 32 to 100 +#ifdef DEBUG + std::cout << ">>>>> DisplacementVector3D< Cartesian3D \n"; +#endif + ret |= doTest > > + (testRotation,testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> DisplacementVector3D< Polar3D \n"; +#endif + ret |= doTest > > + (testRotation,testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> DisplacementVector3D< CylindricalEta3D \n"; +#endif + ret |= doTest > > + (testRotation,testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> PositionVector3D< Cartesian3D \n"; +#endif + ret |= doTest > > + (testRotation,testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> PositionVector3D< Polar3D \n"; +#endif + ret |= doTest > > + (testRotation,testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> PositionVector3D< CylindricalEta3D \n"; +#endif + ret |= doTest > > + (testRotation,testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> ForeignVector\n"; +#endif + ret |= doTest + (testRotation,testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> LorentzVector >\n"; +#endif + ret |= doTestL > + (testRotation,testVector,ticks); +#ifdef TRACE1 + std::cout << " ---- doTestofR ---- done\n"; +#endif + + if (ret == 0) std::cout << "."; + + // TODO - other 4D coordinates + + return ret; +} + + +int exerciseTestCase (TestRotation const & testRotation, + XYZVector const & testVector) +{ + + std::cout << ">>>>> Rotation Tests of " << testVector << "\t\t: " ; + +#ifdef TRACE1 + std::cout << "---- exerciseTestCase ----"; +#endif + int ret = 0; + ret |= doTestOfR (testRotation,testVector); + ret |= doTestOfR (testRotation,testVector); + ret |= doTestOfR (testRotation,testVector); + ret |= doTestOfR (testRotation,testVector); + ret |= doTestOfR (testRotation,testVector); +#ifdef TRACE1 + std::cout << " done\n"; +#endif + + if (ret == 0) + std::cout << "\t OK\n"; + else { + std::cout << "\t Failed!\n "; + std::cerr << "\n>>>>> Rotation Tests of " << testVector << "\t\t:\t FAILED \n"; + } + + return ret; +} + +// ===== Axial test section ============= + +template +int doTestA (XYZVector const & testVector, double ticks) { +#ifdef TRACE1 + std::cout << "---- doTestA ----"; +#endif + int ret = 0; + V v(testVector); + XYZVector rv; + for (double angle = -4.0; angle < 4.0; angle += .15) { + RotationX rx (angle); + rv = rxv (angle, testVector); + ret |= testApplication (rx, v, rv, ticks); + RotationY ry (angle); + rv = ryv (angle, testVector); + ret |= testApplication (ry, v, rv, ticks); + RotationZ rz (angle); + rv = rzv (angle, testVector); + ret |= testApplication (rz, v, rv, ticks); + } +#ifdef TRACE1 + std::cout << " done\n"; +#endif + if (ret == 0) std::cout << "."; + return ret; +} + +template +int doTestLA (XYZVector const & testVector, double ticks) { +#ifdef TRACE1 + std::cout << "---- doTestLA ----"; +#endif + int ret = 0; + LorentzVector v; + double x = testVector.X(); + double y = testVector.Y(); + double z = testVector.Z(); + double t = std::sqrt (x*x + y*y + z*z + 1); + v.SetXYZT ( x, y, z, t ); + XYZVector rv; + for (double angle = -4.0; angle < 4.0; angle += .15) { + //std::cout << "\n============ angle is " << angle << "\n"; + RotationX rx (angle); + rv = rxv (angle, testVector); + ret |= testApplication (rx, v, rv, ticks); + RotationY ry (angle); + rv = ryv (angle, testVector); + ret |= testApplication (ry, v, rv, ticks); + RotationZ rz (angle); + rv = rzv (angle, testVector); + ret |= testApplication (rz, v, rv, ticks); + } +#ifdef TRACE1 + std::cout << " done\n"; +#endif + + if (ret == 0) std::cout << "."; + return ret; +} + +template +int doTestOfAxial (XYZVector const & testVector){ +#ifdef TRACE1 + std::cout << "---- doTestOfAxial ----\n"; +#endif + int ret = 0; + const double ticks = 32; +#ifdef DEBUG + std::cout << ">>>>> DisplacementVector3D< Cartesian3D \n"; +#endif + ret |= doTestA > > + (testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> DisplacementVector3D< Polar3D \n"; +#endif + ret |= doTestA > > + (testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> DisplacementVector3D< CylindricalEta3D \n"; +#endif + ret |= doTestA > > + (testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> PositionVector3D< Cartesian3D \n"; +#endif + ret |= doTestA > > + (testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> PositionVector3D< Polar3D \n"; +#endif + ret |= doTestA > > (testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> PositionVector3D< CylindricalEta3D \n"; +#endif + ret |= doTestA > > + (testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> ForeignVector\n"; +#endif + ret |= doTestA (testVector,ticks); +#ifdef DEBUG + std::cout << ">>>>> LorentzVector >\n"; +#endif + ret |= doTestLA > (testVector,ticks); +#ifdef TRACE1 + std::cout << " ---- doTestofR ---- done\n"; +#endif + // TODO - other 4D coordinates + + if (ret == 0) std::cout << "."; + + return ret; +} + +int exerciseAxialTest (XYZVector const & testVector) +{ + +#ifdef TRACE1 + std::cout << "---- exerciseAxialTest ----"; +#endif + + std::cout << ">>>>> Axial Rotation Tests of " << testVector << "\t\t: "; + + int ret = 0; + ret |= doTestOfAxial (testVector); + ret |= doTestOfAxial (testVector); + ret |= doTestOfAxial (testVector); +#ifdef TRACE1 + std::cout << " done\n"; +#endif + + if (ret == 0) + std::cout << "\t OK\n"; + else { + std::cout << "\t Failed!\n "; + std::cerr << "\n>>>>> Axial Rotation Tests of " << testVector << "\t\t:\t FAILED \n"; + } + + return ret; +} + +// ====================================== + + +int rotationApplication (bool forceRun = false) { + int ret = 0; + + bool skipTests = false; +#if defined(__i386__) + // do not run by default tests on 32 bit architecture + // since extended precision will make it difficult + skipTests = true; +#endif + + if (skipTests && !forceRun) { + std::cout << "Skip the tests - it is probably a 32 bit arch - return 0" << std::endl; + return 0; + } + + std::vector testRotations = makeTestRotations(); + std::vector testVectors = makeTestVectors(); + for ( std::vector::const_iterator n = testRotations.begin(); + n != testRotations.end(); ++n ) { + for ( std::vector::const_iterator m = testVectors.begin(); + m != testVectors.end(); ++m ) { + ret |= exerciseTestCase (*n, *m); + } + } + for ( std::vector::const_iterator vp = testVectors.begin(); + vp != testVectors.end(); ++vp ) { + ret |= exerciseAxialTest (*vp); + } + + return ret; +} + +int main() { + int ret = rotationApplication(true); + if (ret) std::cerr << "test FAILED !!! " << std::endl; + else std::cout << "test OK " << std::endl; + return ret; +} diff --git a/math/experimental/genvectorx/test/stress2D.cxx b/math/experimental/genvectorx/test/stress2D.cxx new file mode 100644 index 0000000000000..884d5b3e86827 --- /dev/null +++ b/math/experimental/genvectorx/test/stress2D.cxx @@ -0,0 +1,771 @@ +// @(#)root/test:$Id$ +// Author: Lorenzo Moneta 06/2005 +/////////////////////////////////////////////////////////////////////////////////// +// +// MathCore Benchmark test suite +// ============================== +// +// This program performs tests of ROOT::Math 4D LorentzVectors comparing with TLorentzVector +// The time performing various vector operations on a collection of vectors is measured. +// The benchmarked operations are: +// - vector construction from 4 values +// - construction using a setter method +// - simple addition of all the vector pairs in the collection +// - calculation of deltaR = phi**2 + eta**2 of all vector pairs in the collection +// - two simple analysis: +// - the first requires some cut (on pt and eta) and on the invariant mass +// of the selected pairs +// - the second requires just some cut in pt, eta and delta R on all the +// vector pair +// - conversion between XYZTVectors to PtRhoEtaPhi based vectors +// +// The two analysis demonstrates, especially in the second case, the advantage of using +// vector based on cylindrical coordinate, given the fact that the time spent in the conversion is +// much less than the time spent in the analysis routine. +// +// To run the program do: +// stressVector : run standard test with collection of 1000 vectors +// stressVector 10000 : run with a collection of 10000 vectors +// +/////////////////////////////////////////////////////////////////////////////////// + + + +#include +#include +#include + +#include +#include + +#include "TStopwatch.h" + +#include "TRandom3.h" +#include "TVector2.h" + +#include "MathX/Vector2D.h" +#include "MathX/Point2D.h" +#include "MathX/SVector.h" + +#include + +#include "limits" + +#ifdef HAVE_CLHEP +#include "CLHEP/Vector/TwoVector.h" +#endif + + +//#define DEBUG + +using namespace ROOT::Math; + + + + +class VectorTest { + +private: + +// global data variables + std::vector dataX; + std::vector dataY; + + size_t nGen; + size_t n2Loop ; + + +public: + + VectorTest(int n1, int n2) : + nGen(n1), + n2Loop(n2) + {} + + + + + void print(TStopwatch & time, std::string s) { + int pr = std::cout.precision(8); + std::cout << s << "\t" << " time = " << time.RealTime() << "\t(sec)\t" + // << time.CpuTime() + << std::endl; + std::cout.precision(pr); + } + + + int check(std::string name, double s1, double s2, double s3, double scale=1) { + double eps = 10*scale*std::numeric_limits::epsilon(); + if ( std::fabs(s1-s2) < eps*std::fabs(s1) && std::fabs(s1-s3) < eps*std::fabs(s1) ) return 0; + int pr = std::cout.precision(16); + std::cout << s1 << "\t" << s2 <<"\t" << s3 << "\n"; + std::cout << "Rel Diff 1-2:\t" << (s1-s2)/std::fabs(s1) << " Diff 1-3:\t" << (s1-s3)/std::fabs(s1) << std::endl; + std::cout << "Test " << name << " failed !!\n\n"; + std::cout.precision(pr); + return -1; + } + + + void genData() { + int n = nGen; + + // generate 2 d data + TRandom3 rdm; + for (int i = 0; i < n ; ++ i) { + + double phi = rdm.Rndm()*3.1415926535897931; + double r = rdm.Exp(10.); + // fill vectors + + Polar2DVector q( r, phi); + dataX.push_back( q.x() ); + dataY.push_back( q.y() ); + + } + } + + + + template + void testCreate( std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + + int n = dataX.size(); + dataV.resize(n); + tim.Start(); + for (int i = 0; i < n; ++i) { + dataV[i] = new V( dataX[i], dataY[i] ); + } + tim.Stop(); + t += tim.RealTime(); + print(tim,s); + } + + + template + void testCreate2( std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + + int n = dataX.size(); + dataV.resize(n); + tim.Start(); + for (int i = 0; i < n; ++i) { + dataV[i] = new V(); + dataV[i]->SetXY(dataX[i], dataY[i] ); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + } + void testCreate2( std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + + int n = dataX.size(); + dataV.resize(n); + tim.Start(); + for (int i = 0; i < n; ++i) { + dataV[i] = new TVector2(); + dataV[i]->Set(dataX[i], dataY[i] ); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + } +#ifdef HAVE_CLHEP + void testCreate2( std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + + int n = dataX.size(); + dataV.resize(n); + tim.Start(); + for (int i = 0; i < n; ++i) { + dataV[i] = new Hep2Vector(); + dataV[i]->set(dataX[i], dataY[i] ); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + } +#endif + + + template + void clear( std::vector & dataV ) { + for (unsigned int i = 0; i < dataV.size(); ++i) { + V * p = dataV[i]; + delete p; + } + dataV.clear(); + +} + +template +inline double addXY(const V & v) { + return v.X() + v.Y(); +} +inline double addXY(const SVector & v) { + return v(0) + v(1); +} +template +inline double getSum(const V & v1, const V & v2) { + return v1.X()+v1.Y() + v2.X() + v2.Y(); +} + +inline double getSum(const SVector & v1, const SVector & v2 ) { + return v1(0)+v1(1) + v2(0)+v2(1); +} + +template +inline double dotProd(const V & v1, const V & v2) { + return v1 * v2; +} + +inline double dotProd(const XYVector & v1, const XYVector & v2) { + return v1.Dot(v2); +} + +inline double dotProd(const SVector & v1, const SVector & v2 ) { + return Dot(v1,v2); +} + + +#ifdef HAVE_CLHEP +inline double addXY(const Hep2Vector & v) { + return v.x() + v.y(); +} +inline double getSum(const Hep2Vector & v1, const Hep2Vector & v2 ) { + return v1.x() + v1.y() + v2.x() + v2.y(); +} +#endif + +template +double testAddition( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + unsigned int n = dataV.size(); + double tot = 0; + V v0 = *(dataV[0]); + tim.Start(); + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + V v3 = v1 + v0; + tot += addXY(v3); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return tot; +} + +template +double testAddition2( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + unsigned int n = dataV.size(); + double tot = 0; + V v0 = *(dataV[0]); + tim.Start(); + for (unsigned int i = 0; i < n; ++i) { + const V & v1 = *(dataV[i]); + v0 += v1; + tot += addXY(v0); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return tot; +} + +template +double testAddition3( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + //unsigned int n = std::min(n2Loop, dataV.size() ); + unsigned int n = dataV.size(); + double tot = 0; + V v0 = *(dataV[0]); + tim.Start(); + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); +// for (unsigned int j = i +1; j < n; ++j) { +// V & v2 = *(dataV[j]); +// tot += getSum(v1,v2); +// } + tot += getSum(v1,v0); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return tot; +} + + +template +double testDotProduct( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + //unsigned int n = std::min(n2Loop, dataV.size() ); + double tot = 0; + unsigned int n = dataV.size(); + V v0 = *(dataV[0]); + tim.Start(); + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); +// for (unsigned int j = i +1; j < n; ++j) { +// V & v2 = *(dataV[j]); +// tot += dotProd(v1,v2); +// } + tot += dotProd(v1,v0); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return tot; +} + + +template +double testScale( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + unsigned int n = dataV.size(); + double tot = 0; + tim.Start(); + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + // scale + V v2 = 2.0*v1; + tot += addXY(v2); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return tot; +} + +template +double testScale2( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + //unsigned int n = std::min(n2Loop, dataV.size() ); + unsigned int n = dataV.size(); + double tot = 0; + tim.Start(); + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + // scale + v1 *= 2.0; + tot += addXY(v1); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return tot; +} + +template +double testOperations( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + //unsigned int n = std::min(n2Loop, dataV.size() ); + // test operations like in CMS + unsigned int n = dataV.size(); + double tot = 0; + V v0a = *(dataV[0]); + V v0b = *(dataV[n-1]); + tim.Start(); + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + //V v2(v1 - dotProd(v1,v0a)*v0b ); + double a = dotProd(v1,v0a); + V v2(v1 - a*v0b ); + tot += addXY(v2); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return tot; +} + + +template +inline double dPhi(V & v1, V& v2) { + return std::abs(v1.Phi() - v2.Phi() ); +} + +#ifdef HAVE_CLHEP +inline double dPhi(Hep2Vector & v1, Hep2Vector & v2) { + return std::abs(v1.phi() - v2.phi() ); +} +#endif + + +template +double testDeltaPhi( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + unsigned int n = std::min(n2Loop, dataV.size() ); + tim.Start(); + double tot = 0; + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + for (unsigned int j = i +1; j < n; ++j) { + V & v2 = *(dataV[j]); + double delta = dPhi(v1,v2); + tot += delta; + } + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return tot; +} + + +// template +// int testAnalysis( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { +// int nsel = 0; +// int nsel2 = 0; +// double deltaMax = 1.; +// double ptMin = 1.; +// double etaMax = 3.; + +// unsigned int n = std::min(n2Loop, dataV.size() ); +// tim.Start(); +// for (unsigned int i = 0; i < n; ++i) { +// V & v1 = *(dataV[i]); +// if (cutPtEta(v1,ptMin, etaMax) ) { +// double delta; +// for (unsigned int j = i +1; j < n; ++j) { +// V & v2 = *(dataV[j]); +// delta = VectorUtil::DeltaR(v1,v2); +// if (delta < deltaMax) { +// V v3 = v1 + v2; +// nsel++; +// if ( cutPtEtaAndMass(v3)) +// nsel2++; +// } +// } +// } +// } +// tim.Stop(); +// print(tim,s); +// //std::cout << nsel << "\n"; +// t += tim.RealTime(); +// return nsel2; +// } + + + +// template +// int testAnalysis2( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { +// int nsel = 0; +// double ptMin = 1.; +// double etaMax = 3.; +// unsigned int n = std::min(n2Loop, dataV.size() ); +// tim.Start(); +// //seal::SealTimer t(tim.name(), true, std::cout); +// for (unsigned int i = 0; i < n; ++i) { +// V & v1 = *(dataV[i]); +// if ( cutPtEta(v1, ptMin, etaMax) ) { +// for (unsigned int j = i +1; j < n; ++j) { +// V & v2 = *(dataV[j]); +// if ( VectorUtil::DeltaR(v1,v2) < 0.5) nsel++; +// } +// } +// } +// tim.Stop(); +// print(tim,s); +// t += tim.RealTime(); +// return nsel; +// } + + + + template + void testConversion( std::vector & dataV1, std::vector & dataV2, TStopwatch & tim, double& t, std::string s) { + + int n = dataX.size(); + dataV2.resize(n); + tim.Start(); + for (int i = 0; i < n; ++i) { + dataV2[i] = new V2( *dataV1[i] ); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + } + + + + // rotation + template + double testRotation( std::vector & dataV, double rotAngle, TStopwatch & tim, double& t, std::string s) { + + unsigned int n = std::min(n2Loop, dataV.size() ); + tim.Start(); + double sum = 0; + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + V v2 = v1; + v2.Rotate(rotAngle); + sum += addXY(v2); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return sum; + } + + + +}; + + + +int main(int argc,const char *argv[]) { + + int ngen = 1000000; + if (argc > 1) ngen = atoi(argv[1]); + int nloop2 = int(std::sqrt(2.0*ngen)+0.5); + if (argc > 2) nloop2 = atoi(argv[2]); + + std::cout << "Test with Ngen = " << ngen << " n2loop = " << nloop2 << std::endl; + + + TStopwatch t; + + VectorTest a(ngen,nloop2); + + a.genData(); + + int niter = 1; + for (int i = 0; i < niter; ++i) { + +#ifdef DEBUG + std::cout << "iteration " << i << std::endl; +#endif + + double t1 = 0; + double t2 = 0; + double t3 = 0; + double t4 = 0; + double t5 = 0; + double t6 = 0; + + std::vector v1; + std::vector v2; + std::vector v3; + std::vector v4; + std::vector v5; + std::vector *> v6; + + a.testCreate (v1, t, t1, "creation TVector2 " ); + a.testCreate (v2, t, t2, "creation XYVector " ); + a.testCreate (v3, t, t3, "creation Polar2DVector " ); + a.testCreate (v4, t, t4, "creation XYPoint " ); + a.testCreate (v5, t, t5, "creation Polar2DPoint " ); + a.testCreate (v6, t, t6, "creation SVector<2> " ); +#ifdef HAVE_CLHEP + double t7 = 0; + std::vector v7; + a.testCreate (v7, t, t7, "creation Hep2Vector " ); +#endif + + + a.clear(v3); + a.clear(v4); + a.clear(v5); + +#ifdef HAVE_CLHEP + a.clear(v7); +#endif + + std::cout << "\n"; + a.testConversion (v2, v3, t, t3, "Conversion XY->Polar " ); + a.testConversion (v2, v4, t, t4, "Conversion XYVec->XYPoint " ); + a.testConversion (v2, v5, t, t5, "Conversion XYVec->PolarP " ); + + a.clear(v1); + a.clear(v2); + a.clear(v3); + a.clear(v4); + a.clear(v5); + std::cout << "\n"; + + a.testCreate2 (v1, t, t1, "creationSet TVector2 " ); + a.testCreate2 (v2, t, t2, "creationSet XYVector " ); + a.testCreate2 (v3, t, t3, "creationSet Polar2DVector " ); + a.testCreate2 (v4, t, t4, "creationSet XYPoint " ); + a.testCreate2 (v5, t, t5, "creationSet Polar2DPoint " ); +// a.testCreate2 (v6, t, t6, "creationSet Polar2DPoint " ); +#ifdef HAVE_CLHEP + a.testCreate2 (v7, t, t7, "creationSet Hep2Vector " ); +#endif + + std::cout << "\n"; + + double s1,s2,s3,s4,s5,s6; + s1=a.testAddition (v1, t, t1, "Addition TVector2 " ); + s2=a.testAddition (v2, t, t2, "Addition XYVector " ); + s3=a.testAddition (v3, t, t3, "Addition Polar2DVector " ); + s6=a.testAddition (v6, t, t6, "Addition SVector<2> " ); + a.check("Addition test1",s1,s2,s3); + a.check("Addition test2",s1,s2,s6); +#ifdef HAVE_CLHEP + double s7; + s7=a.testAddition (v7, t, t7, "Addition Hep2Vector " ); + a.check("Addition",s7,s1,s2); +#endif + + double s0 = s2; + std::cout << "\n"; + + s1=a.testAddition2 (v1, t, t1, "Addition2 TVector2 " ); + s2=a.testAddition2 (v2, t, t2, "Addition2 XYVector " ); + s3=a.testAddition2 (v3, t, t3, "Addition2 Polar2DVector " ); + s6=a.testAddition2 (v6, t, t6, "Addition2 SVector<2> " ); + a.check("Addition2 test1",s1,s2,s3,100); + a.check("Addition2 test2",s1,s2,s6); +#ifdef HAVE_CLHEP + s7=a.testAddition2 (v7, t, t7, "Addition2 Hep2Vector " ); + a.check("Addition2 CLHEP",s7,s1,s2); +#endif + + std::cout << "\n"; + + s1=a.testAddition3 (v1, t, t1, "Addition3 TVector2 " ); + s2=a.testAddition3 (v2, t, t2, "Addition3 XYVector " ); + s3=a.testAddition3 (v3, t, t3, "Addition3 Polar2DVector " ); + s6=a.testAddition3 (v6, t, t6, "Addition3 SVector<2> " ); + a.check("Addition3 test1",s1,s2,s3); + a.check("Addition3 test2",s6,s0,s2); +#ifdef HAVE_CLHEP + s7=a.testAddition3 (v7, t, t7, "Addition3 Hep2Vector " ); + a.check("Addition3 CLHEP",s7,s1,s2); +#endif + + std::cout << "\n"; + + s1=a.testDotProduct (v1, t, t1, "DotProduct TVector2 " ); + s2=a.testDotProduct (v2, t, t2, "DotProduct XYVector " ); +// s3=a.testDotProduct (v3, t, t3, "DotProduct Polar2DVector " ); + s6=a.testDotProduct (v6, t, t6, "DotProduct SVector<2> " ); + a.check("DotProduct test1",s1,s2,s6); +// a.check("DotProduct test2",s6,s1,s2); +#ifdef HAVE_CLHEP + s7=a.testDotProduct (v7, t, t7, "DotProduct Hep2Vector " ); + a.check("DotProduct CLHEP",s7,s1,s2); +#endif + + + std::cout << "\n"; + + s1=a.testDeltaPhi (v1, t, t1, "DeltaPhi TVector2 " ); + s2=a.testDeltaPhi (v2, t, t2, "DeltaPhi XYVector " ); + s3=a.testDeltaPhi (v3, t, t3, "DeltaPhi Polar2DVector " ); + s4=a.testDeltaPhi (v4, t, t4, "DeltaPhi XYPoint " ); + s5=a.testDeltaPhi (v5, t, t5, "DeltaPhi Polar2DPoint " ); +#ifdef WIN32 + //windows is bad here + a.check("DeltaPhi",s1,s2,s3,10); + a.check("DeltaPhi",s2,s4,s5,10); +#else + a.check("DeltaPhi",s1,s2,s3); + a.check("DeltaPhi",s2,s4,s5); +#endif +#ifdef HAVE_CLHEP + s7=a.testDeltaPhi (v7, t, t7, "DeltaPhi HEP2Vector " ); + a.check("DeltaPhi",s7,s1,s2); +#endif + + std::cout << "\n"; + s1=a.testScale (v1, t, t1, "Scale of TVector2 " ); + s2=a.testScale (v2, t, t2, "Scale of XYVector " ); + s3=a.testScale (v3, t, t3, "Scale of Polar2DVector " ); + s4=a.testScale (v4, t, t4, "Scale of XYPoint " ); + s5=a.testScale (v5, t, t5, "Scale of Polar2DPoint " ); + a.check("Scaling",s1,s2,s3); + a.check("Scaling",s2,s4,s5, 10); + s6=a.testScale (v6, t, t6, "Scale of SVector<2> " ); + a.check("Scaling SV",s6,s1,s2); + +#ifdef HAVE_CLHEP + s7=a.testScale (v7, t, t7, "Scale of HEP2Vector " ); + a.check("Scaling CLHEP",s7,s2,s3); +#endif + + std::cout << "\n"; + s1=a.testScale2 (v1, t, t1, "Scale2 of TVector2 " ); + s2=a.testScale2 (v2, t, t2, "Scale2 of XYVector " ); + s3=a.testScale2 (v3, t, t3, "Scale2 of Polar2DVector " ); + s4=a.testScale2 (v4, t, t4, "Scale2 of XYPoint " ); + s5=a.testScale2 (v5, t, t5, "Scale2 of Polar2DPoint " ); + a.check("Scaling2",s1,s2,s3); + a.check("Scaling2",s2,s4,s5, 10); + s6=a.testScale2 (v6, t, t6, "Scale2 of SVector<2> " ); + a.check("Scaling2 SV",s6,s1,s2); + +#ifdef HAVE_CLHEP + s7=a.testScale2 (v7, t, t7, "Scale2 of HEP2Vector " ); + a.check("Scaling CLHEP",s7,s2,s3); +#endif + + std::cout << "\n"; + + s1=a.testOperations (v1, t, t1, "Operations of TVector2 " ); + s2=a.testOperations (v2, t, t2, "Operations of XYVector " ); + s6=a.testOperations (v6, t, t6, "Operations of SVector<2> " ); + a.check("Operations testSV",s6,s1,s2); +#ifdef HAVE_CLHEP + s7=a.testOperations (v7, t, t7, "Operations of HEP2Vector " ); + a.check("Operations CLHEP",s7,s1,s2); +#endif + + + +#ifdef LATER + + int n1, n2, n3,n4,n5; + n1 = a.testAnalysis (v1, t, t1, "Analysis1 TVector2 " ); + n2 = a.testAnalysis (v2, t, t2, "Analysis1 XYVector " ); + n3 = a.testAnalysis (v3, t, t3, "Analysis1 Polar2DVector " ); + n4 = a.testAnalysis (v4, t, t4, "Analysis1 XYPoint " ); + n5 = a.testAnalysis (v5, t, t5, "Analysis1 Polar2DPoint " ); + a.check("Analysis1",n1,n2,n3); + a.check("Analysis1",n2,n4,n5); +#ifdef HAVE_CLHEP + int n6; + n6 = a.testAnalysis (v7, t, t7, "Analysis1 HEP2Vector " ); + a.check("Analysis2 CLHEP",n6,n1,n2); +#endif + + + n1 = a.testAnalysis2 (v1, t, t1, "Analysis2 TVector2 " ); + n2 = a.testAnalysis2 (v2, t, t2, "Analysis2 XYVector " ); + n3 = a.testAnalysis2 (v3, t, t3, "Analysis2 Polar2DVector " ); + n4 = a.testAnalysis2 (v4, t, t4, "Analysis2 XYPoint " ); + n5 = a.testAnalysis2 (v5, t, t5, "Analysis2 Polar2DPoint " ); + a.check("Analysis2",n1,n2,n3); + a.check("Analysis2",n2,n4,n5); +#ifdef HAVE_CLHEP + n6 = a.testAnalysis2 (v7, t, t7, "Analysis2 HEP2Vector " ); + a.check("Analysis2 CLHEP",n6,n1,n2); +#endif + + + n1 = a.testAnalysis3 (v1, t, t1, "Analysis3 TVector2 " ); + n2 = a.testAnalysis3 (v2, t, t2, "Analysis3 XYVector " ); + n3 = a.testAnalysis3 (v3, t, t3, "Analysis3 Polar2DVector " ); + n4 = a.testAnalysis3 (v4, t, t4, "Analysis3 XYPoint " ); + n5 = a.testAnalysis3 (v5, t, t5, "Analysis3 Polar2DPoint " ); + a.check("Analysis3",n1,n2,n3); + a.check("Analysis3",n2,n4,n5); +#ifdef HAVE_CLHEP + n6 = a.testAnalysis3 (v7, t, t7,"Analysis3 HEP2Vector " ); + a.check("Analysis3 CLHEP",n6,n1,n2); +#endif + +#endif + + + // clean all at the end + a.clear(v1); + a.clear(v2); + a.clear(v3); + + std::cout << std::endl; + std::cout << "Total Time for TVector2 = " << t1 << "\t(sec)" << std::endl; + std::cout << "Total Time for XYVector = " << t2 << "\t(sec)" << std::endl; + std::cout << "Total Time for Polar2DVector = " << t3 << "\t(sec)" << std::endl; +#ifdef HAVE_CLHEP + std::cout << "Total Time for Hep2Vector = " << t7 << "\t(sec)" << std::endl; +#endif + } + + //tr.dump(); + +} + + + diff --git a/math/experimental/genvectorx/test/stress3D.cxx b/math/experimental/genvectorx/test/stress3D.cxx new file mode 100644 index 0000000000000..1de86466c42b2 --- /dev/null +++ b/math/experimental/genvectorx/test/stress3D.cxx @@ -0,0 +1,436 @@ +#include "MathX/Vector3D.h" +#include "MathX/Point3D.h" +#include "TVector3.h" + +#include "MathX/Transform3D.h" +#include "MathX/Rotation3D.h" +#include "MathX/Translation3D.h" +#include "MathX/RotationZYX.h" +#include "TRotation.h" + +#include "TStopwatch.h" +#include "TRandom3.h" + +#include + +using namespace ROOT::Math; + +class VectorTest { + +private: + + size_t n2Loop ; + size_t nGen; + +// global data variables + std::vector dataX; + std::vector dataY; + std::vector dataZ; + + + +public: + + VectorTest(int n1, int n2) : + n2Loop(n1), + nGen(n2), + dataX(std::vector(n2)), + dataY(std::vector(n2)), + dataZ(std::vector(n2)) + {} + + + + + void print(TStopwatch & time, std::string s) { + int pr = std::cout.precision(8); + std::cout << s << "\t" << " time = " << time.RealTime() << "\t(sec)\t" + // << time.CpuTime() + << std::endl; + std::cout.precision(pr); + } + + + int check(std::string name, double s1, double s2, double s3, double scale=1) { + double eps = 10*scale*std::numeric_limits::epsilon(); + if ( std::fabs(s1-s2) < eps*std::fabs(s1) && std::fabs(s1-s3) < eps*std::fabs(s1) ) return 0; + std::cout.precision(16); + std::cout << s1 << "\t" << s2 <<"\t" << s3 << "\n"; + std::cout << "Test " << name << " failed !!\n\n"; + return -1; + } + + + void genData() { + int n = nGen; + + // generate n -4 momentum quantities + TRandom3 r; + for (int i = 0; i < n ; ++ i) { + + double phi = r.Rndm()*3.1415926535897931; + double eta = r.Uniform(-5.,5.); + double pt = r.Exp(10.); + + // fill vectors + + ROOT::Math::RhoEtaPhiVector q( pt, eta, phi); + dataX[i] = q.x(); + dataY[i] = q.y(); + dataZ[i] = q.z(); + + } + } + + + + template + void testCreate( std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + + int n = dataX.size(); + dataV.resize(n); + tim.Start(); + for (int i = 0; i < n; ++i) { + dataV[i] = new V( dataX[i], dataY[i], dataZ[i] ); + } + tim.Stop(); + t += tim.RealTime(); + print(tim,s); + } + + +template +double testVectorAddition( const std::vector & dataV, TStopwatch & tim, double& t, std::string s) { + unsigned int n = std::min(n2Loop, dataV.size() ); + tim.Start(); + V vSum = *(dataV[0]); + for (unsigned int i = 1; i < n; ++i) { + vSum += *(dataV[i]); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return vSum.Mag2(); +} + +template +double testPointAddition( const std::vector

& dataP, TStopwatch & tim, double& t, std::string s) { + unsigned int n = std::min(n2Loop, dataP.size() ); + tim.Start(); + P pSum = *(dataP[0]); + for (unsigned int i = 1; i < n; ++i) { + P & p2 = *(dataP[i]); +#ifndef HEAP_CREATION + pSum += ROOT::Math::XYZVector(p2); +#else + ROOT::Math::XYZVector * v2 = new ROOT::Math::XYZVector(p2); + pSum += *v2; +#endif + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return pSum.Mag2(); +} + +template +double getSum(const V & v) { + return v.x() + v.y() + v.z(); +} + + +// direct translation +template + double testTranslation( std::vector & dataV, const Translation3D & tr, TStopwatch & tim, double& t, std::string s) { + + unsigned int n = dataV.size(); + tim.Start(); + double sum = 0; + double dx,dy,dz; + tr.GetComponents(dx,dy,dz); + V vtrans(dx,dy,dz); + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + V v2 = v1 + vtrans; + sum += getSum(v2); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return sum; + } + +// transformation +template + double testTransform( std::vector & dataV, const T & trans, TStopwatch & tim, double& t, std::string s) { + + unsigned int n = dataV.size(); + tim.Start(); + double sum = 0; + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + V v2 = trans * v1; + sum += getSum(v2); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return sum; + } + +// transformation product +template + double testTransformProd( std::vector & dataV, const T1 & trans, const T2 &, TStopwatch & tim, double& t, std::string s) { + + unsigned int n = dataV.size(); + tim.Start(); + double sum = 0; + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + V v2 = T2(XYZVector(v1)) * trans * v1; + sum += getSum(v2); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return sum; + } + +// transformation product +template +double testTransformProd2( std::vector & dataV, const T1 & trans, const T2 &, TStopwatch & tim, double& t, std::string s) { + + unsigned int n = dataV.size(); + tim.Start(); + double sum = 0; + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + V v2 = trans * T2(XYZVector(v1)) * v1; + sum += getSum(v2); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return sum; + } + +// transformation product +template +double testTransformProd3( std::vector & dataV, const T1 & trans1, const T2 & trans2, TStopwatch & tim, double& t, std::string s) { + + unsigned int n = dataV.size(); + tim.Start(); + double sum = 0; + for (unsigned int i = 0; i < n; ++i) { + V & v1 = *(dataV[i]); + V v2 = trans2 * trans1 * v1; + sum += getSum(v2); + } + tim.Stop(); + print(tim,s); + t += tim.RealTime(); + return sum; + } + +}; // end class VectorTest + + +int main(int argc,const char *argv[]) { + + int ngen = 1000000; + if (argc > 1) ngen = atoi(argv[1]); + int nloop2 = ngen; + if (argc > 2) nloop2 = atoi(argv[1]); + + std::cout << "Test with Ngen = " << ngen << " n2loop = " << nloop2 << std::endl; + + TStopwatch t; + + VectorTest a(ngen,nloop2); + + a.genData(); + + + double t1 = 0; + double t2 = 0; + double t3 = 0; + + std::vector v1; + std::vector v2; + std::vector v3; + + double s1,s2,s3; + + a.genData(); + a.testCreate (v2, t, t2, "creation XYZVector " ); + + a.genData(); + a.testCreate (v3, t, t3, "creation XYZPoint " ); + + a.genData(); + a.testCreate (v1, t, t1, "creation TVector3 " ); + + std::cout << "\n"; + + + s1=a.testVectorAddition (v1, t, t1, "Addition TVector3 " ); + s2=a.testVectorAddition (v2, t, t2, "Addition XYZVector " ); + s3=a.testPointAddition (v3, t, t3, "Addition XYZPoint " ); + + a.check("Addition",s1,s2,s3); + +#ifdef MORETEST + + s2=a.testVectorAddition (v2, t, t2, "Addition XYZVector " ); + s1=a.testVectorAddition (v1, t, t1, "Addition TVector3 " ); + s3=a.testPointAddition (v3, t, t3, "Addition XYZPoint " ); + + s2=a.testVectorAddition (v2, t, t2, "Addition XYZVector " ); + s3=a.testPointAddition (v3, t, t3, "Addition XYZPoint " ); + s1=a.testVectorAddition (v1, t, t1, "Addition TVector3 " ); + + s1=a.testVectorAddition (v1, t, t1, "Addition TVector3 " ); + s3=a.testPointAddition (v3, t, t3, "Addition XYZPoint " ); + s2=a.testVectorAddition (v2, t, t2, "Addition XYZVector " ); + + s3=a.testPointAddition (v3, t, t3, "Addition XYZPoint " ); + s2=a.testVectorAddition (v2, t, t2, "Addition XYZVector " ); + s1=a.testVectorAddition (v1, t, t1, "Addition TVector3 " ); + + s3=a.testPointAddition (v3, t, t3, "Addition XYZPoint " ); + s1=a.testVectorAddition (v1, t, t1, "Addition TVector3 " ); + s2=a.testVectorAddition (v2, t, t2, "Addition XYZVector " ); + +#endif + std::cout << "\n"; + + // test the rotation and transformations + TRotation r1; r1.RotateZ(3.); r1.RotateY(2.); r1.RotateX(1); + Rotation3D r2 (RotationZYX(3., 2., 1.) ); + + s1=a.testTransform (v1, r1, t, t1, "TRotation TVector3 " ); + s2=a.testTransform (v2, r2, t, t2, "Rotation3D XYZVector " ); + s3=a.testTransform (v3, r2, t, t3, "Rotation3D XYZPoint " ); + + a.check("Rotation3D",s1,s2,s3); + double s2a = s2; + std::cout << "\n"; + + double s4; + double t0; + Translation3D tr(1.,2.,3.); + s1=a.testTranslation (v1, tr, t, t1, "Shift TVector3 " ); + s2=a.testTranslation (v2, tr, t, t2, "Shift XYZVector " ); + s3=a.testTransform (v3, tr, t, t3, "Translation3D XYZPoint " ); + s4=a.testTransform (v2, tr, t, t0, "Translation3D XYZVector " ); + + a.check("Translation3D",s1,s2,s3); + + std::cout << "\n"; + + Transform3D tf(r2,tr); + //s1=a.testTransform (v1, tf, t, t1, "Transform3D TVector3 " ); + s2=a.testTransform (v2, tf, t, t0, "Transform3D XYZVector " ); + s3=a.testTransform (v3, tf, t, t0, "Transform3D XYZPoint " ); + double s2b = s2; + + + std::cout << "\n"; + + // test product of one vs the other + + double s5; + // rotation x translation + //s1=a.testTransformProd (v1, r2, tf, t, t1, "Delta * Rot TVector3 " ); + s2=a.testTransformProd (v2, r2, tr, t, t0, "Delta * Rot XYZVector " ); + s3=a.testTransformProd (v3, r2, tr, t, t0, "Delta * Rot XYZPoint " ); + + Transform3D tfr(r2); + s4=a.testTransformProd (v2, tfr, tf, t, t0, "Delta * Rot(T) XYZVector " ); + s5=a.testTransformProd (v3, tfr, tf, t, t0, "Delta * Rot(T) XYZPoint " ); + a.check("Delta * Rot",s3,s5,s5); + // only rot on vectors + a.check("Trans Vec",s2a,s2b,s2); + a.check("Trans Vec",s2a,s2,s4); + + + std::cout << "\n"; + + // translation x rotation + //s1=a.testTransformProd2 (v1, r2, tf, t, t1, "Rot * Delta TVector3 " ); + s2=a.testTransformProd2 (v2, r2, tr, t, t0, "Rot * Delta XYZVector " ); + s3=a.testTransformProd2 (v3, r2, tr, t, t0, "Rot * Delta XYZPoint " ); + + s4=a.testTransformProd2 (v2, tfr, tf, t, t0, "Rot * Delta(T) XYZVector " ); + s5=a.testTransformProd2 (v3, tfr, tf, t, t0, "Rot * Delta(T) XYZPoint " ); + + a.check("Rot * Delta",s3,s5,s5); + // only rot per vec + a.check("Trans Vec",s2a,s2,s4); + + + std::cout << "\n"; + s2=a.testTransformProd (v2, tf, Translation3D(), t, t0, "Delta * Trans XYZVector " ); + s3=a.testTransformProd (v3, tf, Translation3D(), t, t0, "Delta * Trans XYZPoint " ); + s4=a.testTransformProd (v2, tf, Transform3D(), t, t0, "TDelta * Trans XYZVector " ); + s5=a.testTransformProd (v3, tf, Transform3D(), t, t0, "TDelta * Trans XYZPoint " ); + a.check("Delta * Trans",s3,s5,s5); + a.check("Delta * Trans Vec",s2a,s2,s4); + + std::cout << "\n"; + s2=a.testTransformProd2 (v2, tf, Translation3D(), t, t0, "Trans * Delta XYZVector " ); + s3=a.testTransformProd2 (v3, tf, Translation3D(), t, t0, "Trans * Delta XYZPoint " ); + s4=a.testTransformProd2 (v2, tf, Transform3D(), t, t0, "Trans * TDelta XYZVector " ); + s5=a.testTransformProd2 (v3, tf, Transform3D(), t, t0, "Trans * TDelta XYZPoint " ); + a.check("Delta * Trans",s3,s5,s5); + a.check("Delta * Trans Vec",s2a,s2,s4); + + std::cout << "\n"; + s2=a.testTransformProd (v2, tf, Translation3D(), t, t0, "Delta * Trans XYZVector " ); + s3=a.testTransformProd (v3, tf, Translation3D(), t, t0, "Delta * Trans XYZPoint " ); + s4=a.testTransformProd (v2, tf, Transform3D(), t, t0, "TDelta * Trans XYZVector " ); + s5=a.testTransformProd (v3, tf, Transform3D(), t, t0, "TDelta * Trans XYZPoint " ); + a.check("Delta * Trans",s3,s5,s5); + a.check("Delta * Trans Vec",s2a,s2,s4); + + std::cout << "\n"; + s2=a.testTransformProd2 (v2, tf, Translation3D(), t, t0, "Trans * Delta XYZVector " ); + s3=a.testTransformProd2 (v3, tf, Translation3D(), t, t0, "Trans * Delta XYZPoint " ); + s4=a.testTransformProd2 (v2, tf, Transform3D(), t, t0, "Trans * TDelta XYZVector " ); + s5=a.testTransformProd2 (v3, tf, Transform3D(), t, t0, "Trans * TDelta XYZPoint " ); + a.check("Delta * Trans",s3,s5,s5); + a.check("Delta * Trans Vec",s2a,s2,s4); + + std::cout << "\n"; + s1=a.testTransformProd3 (v1, r2, r2, t, t0, "Rot * Rot TVector3 " ); + s2=a.testTransformProd3 (v2, r2, r2, t, t0, "Rot * Rot XYZVector " ); + s3=a.testTransformProd3 (v3, r2, r2, t, t0, "Rot * Rot XYZPoint " ); + a.check("Rot * Rot",s1,s2,s3); + s2a = s2; + + std::cout << "\n"; + + s2=a.testTransformProd3 (v2, tf, r2, t, t0, "Rot * Trans XYZVector " ); + s3=a.testTransformProd3 (v3, tf, r2, t, t0, "Rot * Trans XYZPoint " ); + s4=a.testTransformProd3 (v2, tf, Transform3D(r2), t, t0, "TRot * Trans XYZVector " ); + s5=a.testTransformProd3 (v3, tf, Transform3D(r2), t, t0, "TRot * Trans XYZPoint " ); + a.check("Rot * Trans Pnt",s3,s5,s5); + a.check("Rot * Trans Vec",s2a,s2,s4); + + std::cout << "\n"; + + s2=a.testTransformProd3 (v2, r2, tf, t, t0, "Trans * Rot XYZVector " ); + s3=a.testTransformProd3 (v3, r2, tf, t, t0, "Trans * Rot XYZPoint " ); + s4=a.testTransformProd3 (v2, Transform3D(r2), tf, t, t0, "Trans * TRot XYZVector " ); + s5=a.testTransformProd3 (v3, Transform3D(r2), tf, t, t0, "Trans * TRot XYZPoint " ); + + a.check("Rot * Trans Pnt",s3,s5,s5); + a.check("Rot * Trans Vec",s2a,s2,s4); + + std::cout << "\n"; + + std::cout << "Total Time for TVector3 = " << t1 << "\t(sec)" << std::endl; + std::cout << "Total Time for XYZVector = " << t2 << "\t(sec)" << std::endl; + std::cout << "Total Time for XYZPoint = " << t3 << "\t(sec)" << std::endl; + +} diff --git a/math/experimental/genvectorx/test/testBoost.cxx b/math/experimental/genvectorx/test/testBoost.cxx new file mode 100644 index 0000000000000..8ed9e1a0b50d4 --- /dev/null +++ b/math/experimental/genvectorx/test/testBoost.cxx @@ -0,0 +1,61 @@ +#include "MathX/BoostX.h" +#include "MathX/Boost.h" +#include "MathX/VectorUtil.h" +#include "MathX/Vector3D.h" +#include "MathX/Vector4D.h" + +#include + +using namespace ROOT::Math; + +bool AlmostEq(const XYZTVector &v1, const XYZTVector &v2) +{ + const double eps = 0.00000001; + return std::abs(v2.X() - v1.X()) < eps && std::abs(v2.Y() - v1.Y()) < eps && std::abs(v2.Z() - v1.Z()) < eps && + std::abs(v2.T() - v1.T()) < eps; +} + +int main() +{ + + BoostX bx(0.8); + std::cout << "BoostX - beta : " << bx.Beta() << " gamma : " << bx.Gamma() << std::endl; + + XYZTVector v(1., 2., 3., 4.); + + XYZTVector vb1 = bx(v); + XYZTVector vb2 = VectorUtil::boostX(v, 0.8); + + int nFailedTests = 0; + + if (!AlmostEq(vb1, vb2)) { + std::cout << "BoostX test failed" << std::endl; + int pr = std::cout.precision(18); + std::cout << vb1 << std::endl; + std::cout << vb2 << std::endl; + std::cout.precision(pr); + nFailedTests++; + } + + // Polar3DVector bv(1.,2.,0.8); + Polar3DVector bv(0.99999, 1., 2); + std::cout << "BoostVector " << XYZVector(bv) << " beta boost = " << XYZVector(bv).R() << std::endl; + Boost b(bv); + std::cout << "Boost Components : "; + std::ostream_iterator oi(std::cout, "\t"); + b.GetComponents(oi); + std::cout << std::endl; + + vb1 = b(v); + vb2 = VectorUtil::boost(v, bv); + if (!AlmostEq(vb1, vb2)) { + std::cout << "Boost test failed" << std::endl; + int pr = std::cout.precision(18); + std::cout << vb1 << std::endl; + std::cout << vb2 << std::endl; + std::cout.precision(pr); + nFailedTests++; + } + + return nFailedTests; +} diff --git a/math/experimental/genvectorx/test/testGenVector.cxx b/math/experimental/genvectorx/test/testGenVector.cxx new file mode 100644 index 0000000000000..396628538187e --- /dev/null +++ b/math/experimental/genvectorx/test/testGenVector.cxx @@ -0,0 +1,808 @@ + +#include "MathX/Vector3D.h" +#include "MathX/Point3D.h" + +#include "MathX/Vector2D.h" +#include "MathX/Point2D.h" + +#include "MathX/EulerAngles.h" + +#include "MathX/Transform3D.h" +#include "MathX/Translation3D.h" + +#include "MathX/Rotation3D.h" +#include "MathX/RotationX.h" +#include "MathX/RotationY.h" +#include "MathX/RotationZ.h" +#include "MathX/Quaternion.h" +#include "MathX/AxisAngle.h" +#include "MathX/RotationZYX.h" + +#include "MathX/LorentzRotation.h" + +#include "MathX/VectorUtil.h" +#ifndef NO_SMATRIX +#include "MathX/SMatrix.h" +#endif + +#include + +using namespace ROOT::Math; +using namespace ROOT::Math::VectorUtil; + + + +typedef DisplacementVector3D, GlobalCoordinateSystemTag> GlobalXYZVector; +typedef DisplacementVector3D, LocalCoordinateSystemTag> LocalXYZVector; +typedef DisplacementVector3D, GlobalCoordinateSystemTag> GlobalPolar3DVector; + + + +typedef PositionVector3D, GlobalCoordinateSystemTag> GlobalXYZPoint; +typedef PositionVector3D, LocalCoordinateSystemTag> LocalXYZPoint; +typedef PositionVector3D, GlobalCoordinateSystemTag> GlobalPolar3DPoint; +typedef PositionVector3D, LocalCoordinateSystemTag> LocalPolar3DPoint; + + +//#define TEST_COMPILE_ERROR + + +int compare( double v1, double v2, const std::string & name = "", double scale = 1.0) { + // ntest = ntest + 1; + + // numerical double limit for epsilon + double eps = scale* std::numeric_limits::epsilon(); + int iret = 0; + double delta = v2 - v1; + double d = 0; + if (delta < 0 ) delta = - delta; + if (v1 == 0 || v2 == 0) { + if (delta > eps ) { + iret = 1; + } + } + // skip case v1 or v2 is infinity + else { + d = v1; + + if ( v1 < 0) d = -d; + // add also case when delta is small by default + if ( delta/d > eps && delta > eps ) + iret = 1; + } + + if (iret == 0) + std::cout << "."; + else { + int pr = std::cout.precision (18); + std::cout << "\nDiscrepancy in " << name << "() : " << v1 << " != " << v2 << " discr = " << int(delta/d/eps) + << " (Allowed discrepancy is " << eps << ")\n"; + std::cout.precision (pr); + //nfail = nfail + 1; + } + return iret; +} + +template +bool IsEqual(const Transform & t1, const Transform & t2, unsigned int size) { +// size should be an enum of the Transform class + std::vector x1(size); + std::vector x2(size); + t1.GetComponents(x1.begin(), x1.end() ); + t2.GetComponents(x2.begin(), x2.end() ); + bool ret = true; + unsigned int i = 0; + while (ret && i < size) { + // from TMath::AreEqualRel(x1,x2,2*eps) + bool areEqual = std::abs(x1[i]-x2[i]) < std::numeric_limits::epsilon() * + ( std::abs(x1[i]) + std::abs(x2[i] ) ); + ret &= areEqual; + i++; + } + return ret; +} + +int testVector3D() { + + int iret = 0; + + std::cout << "testing Vector3D \t:\t"; + + // test the vector tags + + GlobalXYZVector vg(1.,2.,3.); + GlobalXYZVector vg2(vg); + + GlobalPolar3DVector vpg(vg); + + iret |= compare(vpg.R(), vg2.R() ); + +// std::cout << vg2 << std::endl; + + double r = vg.Dot(vpg); + iret |= compare(r, vg.Mag2() ); + + GlobalXYZVector vcross = vg.Cross(vpg); + iret |= compare(vcross.R(), 0.0,"cross",10 ); + +// std::cout << vg.Dot(vpg) << std::endl; +// std::cout << vg.Cross(vpg) << std::endl; + + + + + + GlobalXYZVector vg3 = vg + vpg; + iret |= compare(vg3.R(), 2*vg.R() ); + + GlobalXYZVector vg4 = vg - vpg; + iret |= compare(vg4.R(), 0.0,"diff",10 ); + + + + +#ifdef TEST_COMPILE_ERROR + LocalXYZVector vl; vl = vg; + LocalXYZVector vl2(vg2); + LocalXYZVector vl3(vpg); + vg.Dot(vl); + vg.Cross(vl); + vg3 = vg + vl; + vg4 = vg - vl; +#endif + + + if (iret == 0) std::cout << "\t\t\t\t\tOK\n"; + else std::cout << "\t\t\t\tFAILED\n"; + + + return iret; +} + + + +int testPoint3D() { + + int iret = 0; + + std::cout << "testing Point3D \t:\t"; + + // test the vector tags + + GlobalXYZPoint pg(1.,2.,3.); + GlobalXYZPoint pg2(pg); + + GlobalPolar3DPoint ppg(pg); + + iret |= compare(ppg.R(), pg2.R() ); + //std::cout << pg2 << std::endl; + + + + + GlobalXYZVector vg(pg); + + double r = pg.Dot(vg); + iret |= compare(r, pg.Mag2() ); + + GlobalPolar3DVector vpg(pg); + GlobalXYZPoint pcross = pg.Cross(vpg); + iret |= compare(pcross.R(), 0.0,"cross",10 ); + + GlobalPolar3DPoint pg3 = ppg + vg; + iret |= compare(pg3.R(), 2*pg.R() ); + + GlobalXYZVector vg4 = pg - ppg; + iret |= compare(vg4.R(), 0.0,"diff",10 ); + + +#ifdef TEST_COMPILE_ERROR + LocalXYZPoint pl; pl = pg; + LocalXYZVector pl2(pg2); + LocalXYZVector pl3(ppg); + pl.Dot(vg); + pl.Cross(vg); + pg3 = ppg + pg; + pg3 = ppg + pl; + vg4 = pg - pl; +#endif + + // operator - + XYZPoint q1(1.,2.,3.); + XYZPoint q2 = -1.* q1; + XYZVector v2 = -XYZVector(q1); + iret |= compare(XYZVector(q2) == v2,true,"reflection"); + + + if (iret == 0) std::cout << "\t\t\t\t\tOK\n"; + else std::cout << "\t\t\t\tFAILED\n"; + + return iret; +} + + + +typedef DisplacementVector2D, GlobalCoordinateSystemTag> GlobalXYVector; +typedef DisplacementVector2D, LocalCoordinateSystemTag> LocalXYVector; +typedef DisplacementVector2D, GlobalCoordinateSystemTag> GlobalPolar2DVector; + + + + +int testVector2D() { + + int iret = 0; + + std::cout << "testing Vector2D \t:\t"; + + // test the vector tags + + GlobalXYVector vg(1.,2.); + GlobalXYVector vg2(vg); + + GlobalPolar2DVector vpg(vg); + + iret |= compare(vpg.R(), vg2.R() ); + +// std::cout << vg2 << std::endl; + + double r = vg.Dot(vpg); + iret |= compare(r, vg.Mag2() ); + +// std::cout << vg.Dot(vpg) << std::endl; + + + GlobalXYVector vg3 = vg + vpg; + iret |= compare(vg3.R(), 2*vg.R() ); + + GlobalXYVector vg4 = vg - vpg; + iret |= compare(vg4.R(), 0.0,"diff",10 ); + + + double angle = 1.; + vg.Rotate(angle); + iret |= compare(vg.Phi(), vpg.Phi() + angle ); + iret |= compare(vg.R(), vpg.R() ); + + GlobalXYZVector v3d(1,2,0); + GlobalXYZVector vr3d = RotationZ(angle) * v3d; + iret |= compare(vg.X(), vr3d.X() ); + iret |= compare(vg.Y(), vr3d.Y() ); + + GlobalXYVector vu = vg3.Unit(); + iret |= compare(vu.R(), 1. ); + + +#ifdef TEST_COMPILE_ERROR + LocalXYVector vl; vl = vg; + LocalXYVector vl2(vg2); + LocalXYVector vl3(vpg); + vg.Dot(vl); + vg3 = vg + vl; + vg4 = vg - vl; +#endif + + + if (iret == 0) std::cout << "\t\t\t\tOK\n"; + else std::cout << "\t\t\tFAILED\n"; + + + return iret; +} + + +typedef PositionVector2D, GlobalCoordinateSystemTag> GlobalXYPoint; +typedef PositionVector2D, LocalCoordinateSystemTag> LocalXYPoint; +typedef PositionVector2D, GlobalCoordinateSystemTag> GlobalPolar2DPoint; +typedef PositionVector2D, LocalCoordinateSystemTag> LocalPolar2DPoint; + + + +int testPoint2D() { + + int iret = 0; + + std::cout << "testing Point2D \t:\t"; + + // test the vector tags + + GlobalXYPoint pg(1.,2.); + GlobalXYPoint pg2(pg); + + GlobalPolar2DPoint ppg(pg); + + iret |= compare(ppg.R(), pg2.R() ); + //std::cout << pg2 << std::endl; + + + + + GlobalXYVector vg(pg); + + double r = pg.Dot(vg); + iret |= compare(r, pg.Mag2() ); + + GlobalPolar2DVector vpg(pg); + + GlobalPolar2DPoint pg3 = ppg + vg; + iret |= compare(pg3.R(), 2*pg.R() ); + + GlobalXYVector vg4 = pg - ppg; + iret |= compare(vg4.R(), 0.0,"diff",10 ); + + +#ifdef TEST_COMPILE_ERROR + LocalXYPoint pl; pl = pg; + LocalXYVector pl2(pg2); + LocalXYVector pl3(ppg); + pl.Dot(vg); + pl.Cross(vg); + pg3 = ppg + pg; + pg3 = ppg + pl; + vg4 = pg - pl; +#endif + + // operator - + XYPoint q1(1.,2.); + XYPoint q2 = -1.* q1; + XYVector v2 = -XYVector(q1); + iret |= compare(XYVector(q2) == v2,true,"reflection"); + + + + double angle = 1.; + pg.Rotate(angle); + iret |= compare(pg.Phi(), ppg.Phi() + angle ); + iret |= compare(pg.R(), ppg.R() ); + + GlobalXYZVector v3d(1,2,0); + GlobalXYZVector vr3d = RotationZ(angle) * v3d; + iret |= compare(pg.X(), vr3d.X() ); + iret |= compare(pg.Y(), vr3d.Y() ); + + + + if (iret == 0) std::cout << "\t\t\t\tOK\n"; + else std::cout << "\t\t\tFAILED\n"; + + return iret; +} + + +// missing LV test + +int testRotations3D() { + + int iret=0; + std::cout << "testing 3D Rotations\t:\t"; + + + Rotation3D rot = RotationZ(1.) * RotationY(2) * RotationX(3); + GlobalXYZVector vg(1.,2.,3); + GlobalXYZPoint pg(1.,2.,3); + GlobalPolar3DVector vpg(vg); + + // GlobalXYZVector vg2 = rot.operator() (vg); + GlobalXYZVector vg2 = rot(vg); + iret |= compare(vg2.R(), vg.R(),"rot3D" ); + + GlobalXYZPoint pg2 = rot(pg); + iret |= compare(pg2.X(), vg2.X(),"x diff"); + iret |= compare(pg2.Y(), vg2.Y(),"y diff"); + iret |= compare(pg2.Z(), vg2.Z(),"z diff"); + + + Quaternion qrot(rot); + + pg2 = qrot(pg); + iret |= compare(pg2.X(), vg2.X(),"x diff",10); + iret |= compare(pg2.Y(), vg2.Y(),"y diff",10); + iret |= compare(pg2.Z(), vg2.Z(),"z diff",10); + + GlobalPolar3DVector vpg2 = qrot * vpg; + + iret |= compare(vpg2.X(), vg2.X(),"x diff",10 ); + iret |= compare(vpg2.Y(), vg2.Y(),"y diff",10 ); + iret |= compare(vpg2.Z(), vg2.Z(),"z diff",10 ); + + AxisAngle arot(rot); + pg2 = arot(pg); + iret |= compare(pg2.X(), vg2.X(),"x diff",10 ); + iret |= compare(pg2.Y(), vg2.Y(),"y diff",10 ); + iret |= compare(pg2.Z(), vg2.Z(),"z diff",10 ); + + vpg2 = arot (vpg); + iret |= compare(vpg2.X(), vg2.X(),"x diff",10 ); + iret |= compare(vpg2.Y(), vg2.Y(),"y diff",10 ); + iret |= compare(vpg2.Z(), vg2.Z(),"z diff",10 ); + + EulerAngles erot(rot); + + vpg2 = erot (vpg); + iret |= compare(vpg2.X(), vg2.X(),"x diff",10 ); + iret |= compare(vpg2.Y(), vg2.Y(),"y diff",10 ); + iret |= compare(vpg2.Z(), vg2.Z(),"z diff",10 ); + + GlobalXYZVector vrx = RotationX(3) * vg; + GlobalXYZVector vry = RotationY(2) * vrx; + vpg2 = RotationZ(1) * GlobalPolar3DVector (vry); + iret |= compare(vpg2.X(), vg2.X(),"x diff",10 ); + iret |= compare(vpg2.Y(), vg2.Y(),"y diff",10 ); + iret |= compare(vpg2.Z(), vg2.Z(),"z diff",10 ); + + // test Get/SetComponents + XYZVector v1,v2,v3; + rot.GetComponents(v1,v2,v3); + const Rotation3D rot2(v1,v2,v3); + //rot2.SetComponents(v1,v2,v3); + double r1[9],r2[9]; + rot.GetComponents(r1,r1+9); + rot2.GetComponents(r2,r2+9); + for (int i = 0; i < 9; ++i) { + iret |= compare(r1[i],r2[i],"Get/SetComponents"); + } + // operator == fails for numerical precision + //iret |= compare( (rot2==rot),true,"Get/SetComponens"); + + // test get/set with a matrix +#ifndef NO_SMATRIX + SMatrix mat; + rot2.GetRotationMatrix(mat); + rot.SetRotationMatrix(mat); + iret |= compare( (rot2==rot),true,"Get/SetRotMatrix"); +#endif + + //test inversion + Rotation3D rotInv = rot.Inverse(); + rot.Invert(); // invert in place + bool comp = (rotInv == rot ); + iret |= compare(comp,true,"inversion"); + + // rotation and scaling of points + XYZPoint q1(1.,2,3); double a = 3; + XYZPoint qr1 = rot( a * q1); + XYZPoint qr2 = a * rot( q1); + iret |= compare(qr1.X(), qr2.X(),"x diff",10 ); + iret |= compare(qr1.Y(), qr2.Y(),"y diff",10 ); + iret |= compare(qr1.Z(), qr2.Z(),"z diff",10 ); + + + if (iret == 0) std::cout << "\tOK\n"; + else std::cout << "\t FAILED\n"; + + return iret; +} + + +int testTransform3D() { + + + std::cout << "testing 3D Transform\t:\t"; + int iret = 0; + + EulerAngles r(1.,2.,3.); + + GlobalPolar3DVector v(1.,2.,3.); + GlobalXYZVector w(v); + + Transform3D t1( v ); + GlobalXYZPoint pg; + t1.Transform( LocalXYZPoint(), pg ); + iret |= compare(pg.X(), v.X(),"x diff",10 ); + iret |= compare(pg.Y(), v.Y(),"y diff",10 ); + iret |= compare(pg.Z(), v.Z(),"z diff",10 ); + + + Transform3D t2( r, v ); + + GlobalPolar3DVector vr = r.Inverse()*v; + +// std::cout << GlobalXYZVector(v) << std::endl; +// std::cout << GlobalXYZVector(vr) << std::endl; +// std::cout << GlobalXYZVector (r(v)) << std::endl; +// std::cout << GlobalXYZVector (r(vr)) << std::endl; +// std::cout << vr << std::endl; +// std::cout << r(vr) << std::endl; + + + +// std::cout << r << std::endl; +// std::cout << r.Inverse() << std::endl; +// std::cout << r * r.Inverse() << std::endl; +// std::cout << Rotation3D(r) * Rotation3D(r.Inverse()) << std::endl; +// std::cout << Rotation3D(r) * Rotation3D(r).Inverse() << std::endl; + + + // test Translation3D + + Translation3D tr1(v); + Translation3D tr2(v.X(),v.Y(),v.Z()); +// skip this test on 32 bits architecture. It might fail due to extended precision +#if !defined(__i386__) + iret |= compare(tr1 ==tr2, 1,"eq transl",1 ); +#else + // add a dummy test to have the same outputfile for roottest + // otherwise it will complain that the output is different ! + iret |= compare(0, 0,"dummy test",1 ); +#endif + + Translation3D tr3 = tr1 * tr1.Inverse(); + GlobalPolar3DVector vp2 = tr3 * v; + iret |= compare(vp2.X(), v.X(),"x diff",10 ); + iret |= compare(vp2.Y(), v.Y(),"y diff",10 ); + iret |= compare(vp2.Z(), v.Z(),"z diff",10 ); + + + Transform3D t2b = tr1 * Rotation3D(r); + // this above fails on Windows - use a comparison with tolerance + // 12 is size of Transform3D internal vector + iret |= compare( IsEqual(t2,t2b,12), true,"eq1 transf",1 ); + //iret |= compare(t2 ==t2b, 1,"eq1 transf",1 ); + Transform3D t2c( r, tr1); + iret |= compare( IsEqual(t2,t2c,12), true,"eq2 transf",1 ); + //iret |= compare(t2 ==t2c, 1,"eq2 transf",1 ); + + + Transform3D t3 = Rotation3D(r) * Translation3D(vr); + + Rotation3D rrr; + XYZVector vvv; + t2b.GetDecomposition(rrr,vvv); + iret |= compare(Rotation3D(r) ==rrr, 1,"eq transf rot",1 ); + iret |= compare( tr1.Vect() == vvv, 1,"eq transf vec",1 ); +// if (iret) std::cout << vvv << std::endl; +// if (iret) std::cout << Translation3D(vr) << std::endl; + + Translation3D ttt; + t2b.GetDecomposition(rrr,ttt); + iret |= compare( tr1 == ttt, 1,"eq transf trans",1 ); +// if (iret) std::cout << ttt << std::endl; + + EulerAngles err2; + GlobalPolar3DVector vvv2; + t2b.GetDecomposition(err2,vvv2); + iret |= compare( r.Phi(), err2.Phi(),"transf rot phi",4 ); + iret |= compare( r.Theta(), err2.Theta(),"transf rot theta",1 ); + iret |= compare( r.Psi(), err2.Psi(),"transf rot psi",1 ); + +//iret |= compare( v == vvv2, 1,"eq transf g vec",1 ); + iret |= compare( v.X(), vvv2.X(),"eq transf g vec",4 ); + iret |= compare( v.Y(), vvv2.Y(),"eq transf g vec",1 ); + iret |= compare( v.Z(), vvv2.Z(),"eq transf g vec",1 ); + + // create from other rotations + RotationZYX rzyx(r); + Transform3D t4( rzyx); + iret |= compare( t4.Rotation() == Rotation3D(rzyx), 1,"eq trans rzyx",1 ); + + Transform3D trf2 = tr1 * r; + iret |= compare( trf2 == t2b, 1,"trasl * e rot",1 ); + Transform3D trf3 = r * Translation3D(vr); + //iret |= compare( trf3 == t3, 1,"e rot * transl",1 ); + // this above fails on i686-slc5-gcc43-opt - use a comparison with tolerance + iret |= compare( IsEqual(trf3,t3,12), true,"e rot * transl",1 ); + + Transform3D t5(rzyx, v); + Transform3D trf5 = Translation3D(v) * rzyx; + //iret |= compare( trf5 == t5, 1,"trasl * rzyx",1 ); + iret |= compare( IsEqual(trf5,t5,12), true,"trasl * rzyx",1 ); + + Transform3D t6(rzyx, rzyx * Translation3D(v).Vect() ); + Transform3D trf6 = rzyx * Translation3D(v); + iret |= compare( trf6 == t6, 1,"rzyx * transl",1 ); + if (iret) std::cout << t6 << "\n---\n" << trf6 << std::endl; + + + + Transform3D trf7 = t4 * Translation3D(v); + //iret |= compare( trf7 == trf6, 1,"tranf * transl",1 ); + iret |= compare( IsEqual(trf7,trf6,12), true,"tranf * transl",1 ); + Transform3D trf8 = Translation3D(v) * t4; + iret |= compare( trf8 == trf5, 1,"trans * transf",1 ); + + Transform3D trf9 = Transform3D(v) * rzyx; + iret |= compare( trf9 == trf5, 1,"tranf * rzyx",1 ); + Transform3D trf10 = rzyx * Transform3D(v); + iret |= compare( trf10 == trf6, 1,"rzyx * transf",1 ); + Transform3D trf11 = Rotation3D(rzyx) * Transform3D(v); + iret |= compare( trf11 == trf10, 1,"r3d * transf",1 ); + + RotationZYX rrr2 = trf10.Rotation(); + //iret |= compare( rzyx == rrr2, 1,"gen Rotation()",1 ); + iret |= compare( rzyx.Phi() , rrr2.Phi(),"gen Rotation() Phi",1 ); + iret |= compare( rzyx.Theta(), rrr2.Theta(),"gen Rotation() Theta",10 ); + iret |= compare( rzyx.Psi(), rrr2.Psi(),"gen Rotation() Psi",1 ); + if (iret) std::cout << rzyx << "\n---\n" << rrr2 << std::endl; + + + //std::cout << t2 << std::endl; + //std::cout << t3 << std::endl; + + XYZPoint p1(-1.,2.,-3); + + XYZPoint p2 = t2 (p1); + Polar3DPoint p3 = t3 ( Polar3DPoint(p1) ); + iret |= compare(p3.X(), p2.X(),"x diff",10 ); + iret |= compare(p3.Y(), p2.Y(),"y diff",10 ); + iret |= compare(p3.Z(), p2.Z(),"z diff",10 ); + + GlobalXYZVector v1(1.,2.,3.); + LocalXYZVector v2; t2.Transform (v1, v2); + GlobalPolar3DVector v3; t3.Transform ( GlobalPolar3DVector(v1), v3 ); + + iret |= compare(v3.X(), v2.X(),"x diff",10 ); + iret |= compare(v3.Y(), v2.Y(),"y diff",10 ); + iret |= compare(v3.Z(), v2.Z(),"z diff",10 ); + + XYZPoint q1(1,2,3); + XYZPoint q2(-1,-2,-3); + XYZPoint q3 = q1 + XYZVector(q2); + //std::cout << q3 << std::endl; + XYZPoint qt3 = t3(q3); + //std::cout << qt3 << std::endl; + XYZPoint qt1 = t3(q1); + XYZVector vt2 = t3( XYZVector(q2) ); + XYZPoint qt4 = qt1 + vt2; + iret |= compare(qt3.X(), qt4.X(),"x diff",10 ); + iret |= compare(qt3.Y(), qt4.Y(),"y diff",10 ); + iret |= compare(qt3.Z(), qt4.Z(),"z diff",10 ); + //std::cout << qt4 << std::endl; + + // this fails +// double a = 3; + //XYZPoint q4 = a*q1; +// std::cout << t3( a * q1) << std::endl; +// std::cout << a * t3(q1) << std::endl; + + // test get/set with a matrix +#ifndef NO_SMATRIX + SMatrix mat; + t3.GetTransformMatrix(mat); + Transform3D t3b; t3b.SetTransformMatrix(mat); + iret |= compare( (t3==t3b),true,"Get/SetTransformMatrix"); + + // test LR + Boost b(0.2,0.4,0.8); + LorentzRotation lr(b); + SMatrix mat4; + lr.GetRotationMatrix(mat4); + LorentzRotation lr2; lr2.SetRotationMatrix(mat4); + iret |= compare( (lr==lr2),true,"Get/SetLRotMatrix"); +#endif + + { + // testing ApplyInverse on Point + XYZPoint point(1., -2., 3.); + Transform3D tr(EulerAngles(10, -10, 10), XYZVector(10, -10, 0)); + + // test that applying transformation + Inverse is identity + auto r0 = tr.ApplyInverse(tr(point)); + auto r0_2 = tr.Inverse()(tr(point)); + + iret |= compare(r0.X(), point.X(), "ApplyInverse/PointX", 100); + iret |= compare(r0_2.X(), point.X(), "ApplyInverse/PointX", 100); + iret |= compare(r0.Y(), point.Y(), "ApplyInverse/PointY", 10); + iret |= compare(r0_2.Y(), point.Y(), "ApplyInverse/PointY", 10); + iret |= compare(r0.Z(), point.Z(), "ApplyInverse/PointZ", 10); + iret |= compare(r0_2.Z(), point.Z(), "ApplyInverse/PointZ", 10); + + // compare ApplyInverse with Inverse() + auto r1 = tr.ApplyInverse(point); + auto r2 = tr.Inverse()(point); + iret |= compare(r1.X(), r2.X(), "ApplyInverse/Point", 10); + iret |= compare(r1.Y(), r2.Y(), "ApplyInverse/Point", 10); + iret |= compare(r1.Z(), r2.Z(), "ApplyInverse/Point", 10); + } + + { + // testing ApplyInverse on Vector + XYZVector vector(1, -2., 3); + Transform3D tr(EulerAngles(10, -10, 10), XYZVector(10, -10, 0)); + auto r1 = tr.ApplyInverse(vector); + auto r2 = tr.Inverse()(vector); + iret |= compare(r1.X(), r2.X(), "ApplyInverse/Vector", 10); + iret |= compare(r1.Y(), r2.Y(), "ApplyInverse/Vector", 10); + iret |= compare(r1.Z(), r2.Z(), "ApplyInverse/Vector", 10); + } + + if (iret == 0) std::cout << "OK\n"; + else std::cout << "\t\t\tFAILED\n"; + + return iret; +} + + +int testVectorUtil() { + + std::cout << "testing VectorUtil \t:\t"; + int iret = 0; + + // test new perp functions + XYZVector v(1.,2.,3.); + + XYZVector vx = ProjVector(v,XYZVector(3,0,0) ); + iret |= compare(vx.X(), v.X(),"x",1 ); + iret |= compare(vx.Y(), 0,"y",1 ); + iret |= compare(vx.Z(), 0,"z",1 ); + + XYZVector vpx = PerpVector(v,XYZVector(2,0,0) ); + iret |= compare(vpx.X(), 0,"x",1 ); + iret |= compare(vpx.Y(), v.Y(),"y",1 ); + iret |= compare(vpx.Z(), v.Z(), "z",1 ); + + double perpy = Perp(v, XYZVector(0,2,0) ); + iret |= compare(perpy, std::sqrt( v.Mag2() - v.y()*v.y()),"perpy" ); + + XYZPoint u(1,1,1); + XYZPoint un = u/u.R(); + + + XYZVector vl = ProjVector(v,u); + XYZVector vl2 = XYZVector(un) * ( v.Dot(un ) ); + + iret |= compare(vl.X(), vl2.X(),"x",1 ); + iret |= compare(vl.Y(), vl2.Y(),"y",1 ); + iret |= compare(vl.Z(), vl2.Z(),"z",1 ); + + XYZVector vp = PerpVector(v,u); + XYZVector vp2 = v - XYZVector ( un * ( v.Dot(un ) ) ); + iret |= compare(vp.X(), vp2.X(),"x",10 ); + iret |= compare(vp.Y(), vp2.Y(),"y",10 ); + iret |= compare(vp.Z(), vp2.Z(),"z",10 ); + + double perp = Perp(v,u); + iret |= compare(perp, vp.R(),"perp",1 ); + double perp2 = Perp2(v,u); + iret |= compare(perp2, vp.Mag2(),"perp2",1 ); + + // test rotations + double angle = 1; + XYZVector vr1 = RotateX(v,angle); + XYZVector vr2 = RotationX(angle) * v; + iret |= compare(vr1.Y(), vr2.Y(),"y",1 ); + iret |= compare(vr1.Z(), vr2.Z(),"z",1 ); + + vr1 = RotateY(v,angle); + vr2 = RotationY(angle) * v; + iret |= compare(vr1.X(), vr2.X(),"x",1 ); + iret |= compare(vr1.Z(), vr2.Z(),"z",1 ); + + vr1 = RotateZ(v,angle); + vr2 = RotationZ(angle) * v; + iret |= compare(vr1.X(), vr2.X(),"x",1 ); + iret |= compare(vr1.Y(), vr2.Y(),"y",1 ); + + + if (iret == 0) std::cout << "\t\t\tOK\n"; + else std::cout << "\t\t\t\t\t\tFAILED\n"; + return iret; + +} + +int testGenVector() { + + int iret = 0; + iret |= testVector3D(); + iret |= testPoint3D(); + + iret |= testVector2D(); + iret |= testPoint2D(); + + iret |= testRotations3D(); + + iret |= testTransform3D(); + + iret |= testVectorUtil(); + + + if (iret !=0) std::cout << "\nTest GenVector FAILED!!!!!!!!!\n"; + return iret; + +} + +int main() { + int ret = testGenVector(); + if (ret) std::cerr << "test FAILED !!! " << std::endl; + else std::cout << "test OK " << std::endl; + return ret; +} diff --git a/math/experimental/genvectorx/test/testGenVectorSYCL.cxx b/math/experimental/genvectorx/test/testGenVectorSYCL.cxx new file mode 100644 index 0000000000000..6778a8d833124 --- /dev/null +++ b/math/experimental/genvectorx/test/testGenVectorSYCL.cxx @@ -0,0 +1,848 @@ +#include "MathX/Vector3D.h" +#include "MathX/Point3D.h" + +#include "MathX/Vector2D.h" +#include "MathX/Point2D.h" + +#include "MathX/EulerAngles.h" + +// #include "MathX/Transform3D.h" +// #include "MathX/Translation3D.h" + +#include "MathX/Rotation3D.h" +#include "MathX/RotationX.h" +#include "MathX/RotationY.h" +#include "MathX/RotationZ.h" +#include "MathX/Quaternion.h" +#include "MathX/AxisAngle.h" +#include "MathX/RotationZYX.h" + +#include "MathX/LorentzRotation.h" + +#include "MathX/VectorUtil.h" + +#include "MathX/GenVectorX/AccHeaders.h" + +#include + +#include + +using namespace ROOT::ROOT_MATH_ARCH; +// using namespace ROOT::Math::VectorUtil; + +typedef DisplacementVector3D, GlobalCoordinateSystemTag> GlobalXYZVector; +typedef DisplacementVector3D, LocalCoordinateSystemTag> LocalXYZVector; +typedef DisplacementVector3D, GlobalCoordinateSystemTag> GlobalPolar3DVector; + +typedef PositionVector3D, GlobalCoordinateSystemTag> GlobalXYZPoint; +typedef PositionVector3D, LocalCoordinateSystemTag> LocalXYZPoint; +typedef PositionVector3D, GlobalCoordinateSystemTag> GlobalPolar3DPoint; +typedef PositionVector3D, LocalCoordinateSystemTag> LocalPolar3DPoint; + + +int compare(double v1, double v2, double scale = 1.0) +{ + // ntest = ntest + 1; + + // numerical double limit for epsilon + double eps = scale * std::numeric_limits::epsilon(); + int iret = 0; + double delta = v2 - v1; + double d = 0; + if (delta < 0) + delta = -delta; + if (v1 == 0 || v2 == 0) { + if (delta > eps) { + iret = 1; + } + } + // skip case v1 or v2 is infinity + else { + d = v1; + + if (v1 < 0) + d = -d; + // add also case when delta is small by default + if (delta / d > eps && delta > eps) + iret = 1; + } + + // if (iret == 0) + // std::cout << "."; + // else { + // int pr = std::cout.precision(18); + // std::cout << "\nDiscrepancy in " << name << "() : " << v1 << " != " << v2 << " discr = " << int(delta / d / + // eps) + // << " (Allowed discrepancy is " << eps << ")\n"; + // std::cout.precision(pr); + // // nfail = nfail + 1; + // } + return iret; +} + +template +bool IsEqual(const Transform &t1, const Transform &t2, unsigned int size) +{ + // size should be an enum of the Transform class + std::vector x1(size); + std::vector x2(size); + t1.GetComponents(x1.begin(), x1.end()); + t2.GetComponents(x2.begin(), x2.end()); + bool ret = true; + unsigned int i = 0; + while (ret && i < size) { + // from TMath::AreEqualRel(x1,x2,2*eps) + bool areEqual = + std::abs(x1[i] - x2[i]) < std::numeric_limits::epsilon() * (std::abs(x1[i]) + std::abs(x2[i])); + ret &= areEqual; + i++; + } + return ret; +} + +int testVector3D() +{ + int iret_host = 0; + + std::cout << "testing Vector3D \t:\t"; + + sycl::buffer iret_buf(& iret_host, sycl::range<1>(1)); + sycl::default_selector device_selector; + sycl::queue queue(device_selector); + +{ + queue.submit([&](sycl::handler &cgh) { + auto iret = iret_buf.get_access(cgh); + cgh.single_task([=]() { + // test the vector tags + + GlobalXYZVector vg(1., 2., 3.); + GlobalXYZVector vg2(vg); + GlobalPolar3DVector vpg(vg); + + iret[0] |= compare(vpg.R(), vg2.R()); + + // std::cout << vg2 << std::endl; + + double r = vg.Dot(vpg); + iret[0] |= compare(r, vg.Mag2()); + + GlobalXYZVector vcross = vg.Cross(vpg); + iret[0] |= compare(vcross.R(), 0.0, 10); + + // std::cout << vg.Dot(vpg) << std::endl; + // std::cout << vg.Cross(vpg) << std::endl; + + GlobalXYZVector vg3 = vg + vpg; + iret[0] |= compare(vg3.R(), 2 * vg.R()); + + GlobalXYZVector vg4 = vg - vpg; + iret[0] |= compare(vg4.R(), 0.0, 10); + +#ifdef TEST_COMPILE_ERROR + LocalXYZVector vl; + vl = vg; + LocalXYZVector vl2(vg2); + LocalXYZVector vl3(vpg); + vg.Dot(vl); + vg.Cross(vl); + vg3 = vg + vl; + vg4 = vg - vl; +#endif + }); + }); +} + + if ( iret_host == 0) + std::cout << "\t\t\t\t\tOK\n"; + else + std::cout << "\t\t\t\tFAILED\n"; + + return iret_host; +} + +int testPoint3D() +{ + + int iret_host = 0; + + std::cout << "testing Point3D \t:\t"; + + sycl::buffer iret_buf(& iret_host, sycl::range<1>(1)); + sycl::default_selector device_selector; + sycl::queue queue(device_selector); + +{ + queue.submit([&](sycl::handler &cgh) { + auto iret = iret_buf.get_access(cgh); + cgh.single_task([=]() { + // test the vector tags + + GlobalXYZPoint pg(1., 2., 3.); + GlobalXYZPoint pg2(pg); + + GlobalPolar3DPoint ppg(pg); + + iret[0] |= compare(ppg.R(), pg2.R()); + // std::cout << pg2 << std::endl; + + GlobalXYZVector vg(pg); + + double r = pg.Dot(vg); + iret[0] |= compare(r, pg.Mag2()); + + GlobalPolar3DVector vpg(pg); + GlobalXYZPoint pcross = pg.Cross(vpg); + iret[0] |= compare(pcross.R(), 0.0, 10); + + GlobalPolar3DPoint pg3 = ppg + vg; + iret[0] |= compare(pg3.R(), 2 * pg.R()); + + GlobalXYZVector vg4 = pg - ppg; + iret[0] |= compare(vg4.R(), 0.0, 10); + +#ifdef TEST_COMPILE_ERROR + LocalXYZPoint pl; + pl = pg; + LocalXYZVector pl2(pg2); + LocalXYZVector pl3(ppg); + pl.Dot(vg); + pl.Cross(vg); + pg3 = ppg + pg; + pg3 = ppg + pl; + vg4 = pg - pl; +#endif + + // operator - + XYZPoint q1(1., 2., 3.); + XYZPoint q2 = -1. * q1; + XYZVector v2 = -XYZVector(q1); + iret[0] |= compare(XYZVector(q2) == v2, true); + }); + }); +} + + if (iret_host == 0) + std::cout << "\t\t\t\t\tOK\n"; + else + std::cout << "\t\t\t\tFAILED\n"; + + return iret_host; +} + +typedef DisplacementVector2D, GlobalCoordinateSystemTag> GlobalXYVector; +typedef DisplacementVector2D, LocalCoordinateSystemTag> LocalXYVector; +typedef DisplacementVector2D, GlobalCoordinateSystemTag> GlobalPolar2DVector; + +int testVector2D() +{ + + int iret_host = 0; + + std::cout << "testing Vector2D \t:\t"; + + sycl::buffer iret_buf(& iret_host, sycl::range<1>(1)); + sycl::default_selector device_selector; + sycl::queue queue(device_selector); + +{ + queue.submit([&](sycl::handler &cgh) { + auto iret = iret_buf.get_access(cgh); + cgh.single_task([=]() { + // test the vector tags + + GlobalXYVector vg(1., 2.); + GlobalXYVector vg2(vg); + + GlobalPolar2DVector vpg(vg); + + iret[0] |= compare(vpg.R(), vg2.R()); + + // std::cout << vg2 << std::endl; + + double r = vg.Dot(vpg); + iret[0] |= compare(r, vg.Mag2()); + + // std::cout << vg.Dot(vpg) << std::endl; + + GlobalXYVector vg3 = vg + vpg; + iret[0] |= compare(vg3.R(), 2 * vg.R()); + + GlobalXYVector vg4 = vg - vpg; + iret[0] |= compare(vg4.R(), 0.0, 10); + + double angle = 1.; + vg.Rotate(angle); + iret[0] |= compare(vg.Phi(), vpg.Phi() + angle); + iret[0] |= compare(vg.R(), vpg.R()); + + GlobalXYZVector v3d(1, 2, 0); + GlobalXYZVector vr3d = RotationZ(angle) * v3d; + iret[0] |= compare(vg.X(), vr3d.X()); + iret[0] |= compare(vg.Y(), vr3d.Y()); + + GlobalXYVector vu = vg3.Unit(); + iret[0] |= compare(vu.R(), 1.); + +#ifdef TEST_COMPILE_ERROR + LocalXYVector vl; + vl = vg; + LocalXYVector vl2(vg2); + LocalXYVector vl3(vpg); + vg.Dot(vl); + vg3 = vg + vl; + vg4 = vg - vl; +#endif + }); + }); +} + + + if (iret_host == 0) + std::cout << "\t\t\t\tOK\n"; + else + std::cout << "\t\t\tFAILED\n"; + + return iret_host; +} + +typedef PositionVector2D, GlobalCoordinateSystemTag> GlobalXYPoint; +typedef PositionVector2D, LocalCoordinateSystemTag> LocalXYPoint; +typedef PositionVector2D, GlobalCoordinateSystemTag> GlobalPolar2DPoint; +typedef PositionVector2D, LocalCoordinateSystemTag> LocalPolar2DPoint; + +int testPoint2D() +{ + + int iret_host = 0; + + std::cout << "testing Point2D \t:\t"; + + sycl::buffer iret_buf(& iret_host, sycl::range<1>(1)); + sycl::queue queue{sycl::default_selector_v}; + +{ + queue.submit([&](sycl::handler &cgh) { + auto iret = iret_buf.get_access(cgh); + cgh.single_task([=]() { + + // test the vector tags + + GlobalXYPoint pg(1., 2.); + GlobalXYPoint pg2(pg); + + GlobalPolar2DPoint ppg(pg); + + iret[0] |= compare(ppg.R(), pg2.R()); + // std::cout << pg2 << std::endl; + + GlobalXYVector vg(pg); + + double r = pg.Dot(vg); + iret[0] |= compare(r, pg.Mag2()); + + GlobalPolar2DVector vpg(pg); + + GlobalPolar2DPoint pg3 = ppg + vg; + iret[0] |= compare(pg3.R(), 2 * pg.R()); + + GlobalXYVector vg4 = pg - ppg; + iret[0] |= compare(vg4.R(), 0.0, 10); + +#ifdef TEST_COMPILE_ERROR + LocalXYPoint pl; + pl = pg; + LocalXYVector pl2(pg2); + LocalXYVector pl3(ppg); + pl.Dot(vg); + pl.Cross(vg); + pg3 = ppg + pg; + pg3 = ppg + pl; + vg4 = pg - pl; +#endif + + // operator - + XYPoint q1(1., 2.); + XYPoint q2 = -1. * q1; + XYVector v2 = -XYVector(q1); + iret[0] |= compare(XYVector(q2) == v2, true); + + double angle = 1.; + pg.Rotate(angle); + iret[0] |= compare(pg.Phi(), ppg.Phi() + angle); + iret[0] |= compare(pg.R(), ppg.R()); + + GlobalXYZVector v3d(1, 2, 0); + GlobalXYZVector vr3d = RotationZ(angle) * v3d; + iret[0] |= compare(pg.X(), vr3d.X()); + iret[0] |= compare(pg.Y(), vr3d.Y()); + }); + }); +} + + if (iret_host == 0) + std::cout << "\t\t\t\tOK\n"; + else + std::cout << "\t\t\tFAILED\n"; + + return iret_host; +} + + +// int testRotations3D() +// { + +// int iret_host = 0; +// std::cout << "testing 3D Rotations\t:\t"; + +// sycl::buffer iret_buf(& iret_host, sycl::range<1>(1)); +// sycl::default_selector device_selector; +// sycl::queue queue(device_selector); + +// { +// queue.submit([&](sycl::handler &cgh) { +// auto iret = iret_buf.get_access(cgh); +// cgh.single_task([=]() { + +// // RotationZYX rotZ = RotationZYX(RotationZ(1)); +// // RotationZYX rotY = RotationZYX(RotationY(2)); +// // RotationZYX rotX = RotationZYX(RotationX(3)); + +// RotationZ rotZ = RotationZ(1); +// RotationY rotY = RotationY(2); +// RotationX rotX = RotationX(3); + +// Rotation3D rot = rotY * rotX; //RotationZ(1.) * RotationY(2) * RotationX(3); +// GlobalXYZVector vg(1., 2., 3); +// GlobalXYZPoint pg(1., 2., 3); +// GlobalPolar3DVector vpg(vg); + +// // GlobalXYZVector vg2 = rot.operator() (vg); +// GlobalXYZVector vg2 = rot(vg); +// iret[0] |= compare(vg2.R(), vg.R()); + +// GlobalXYZPoint pg2 = rot(pg); +// iret[0] |= compare(pg2.X(), vg2.X()); +// iret[0] |= compare(pg2.Y(), vg2.Y()); +// iret[0] |= compare(pg2.Z(), vg2.Z()); + +// Quaternion qrot(rot); + +// pg2 = qrot(pg); +// iret[0] |= compare(pg2.X(), vg2.X(), 10); +// iret[0] |= compare(pg2.Y(), vg2.Y(), 10); +// iret[0] |= compare(pg2.Z(), vg2.Z(), 10); + +// GlobalPolar3DVector vpg2 = qrot * vpg; +// iret[0] |= compare(vpg2.X(), vg2.X(), 10); +// iret[0] |= compare(vpg2.Y(), vg2.Y(), 10); +// iret[0] |= compare(vpg2.Z(), vg2.Z(), 10); + +// AxisAngle arot(rot); +// pg2 = arot(pg); +// iret[0] |= compare(pg2.X(), vg2.X(), 10); +// iret[0] |= compare(pg2.Y(), vg2.Y(), 10); +// iret[0] |= compare(pg2.Z(), vg2.Z(), 10); + +// vpg2 = arot(vpg); +// iret[0] |= compare(vpg2.X(), vg2.X(), 10); +// iret[0] |= compare(vpg2.Y(), vg2.Y(), 10); +// iret[0] |= compare(vpg2.Z(), vg2.Z(), 10); + +// EulerAngles erot(rot); + +// vpg2 = erot(vpg); +// iret[0] |= compare(vpg2.X(), vg2.X(), 10); +// iret[0] |= compare(vpg2.Y(), vg2.Y(), 10); +// iret[0] |= compare(vpg2.Z(), vg2.Z(), 10); + +// GlobalXYZVector vrx = RotationX(3) * vg; +// GlobalXYZVector vry = RotationY(2) * vrx; +// vpg2 = RotationZ(1) * GlobalPolar3DVector(vry); +// iret[0] |= compare(vpg2.X(), vg2.X(), 10); +// iret[0] |= compare(vpg2.Y(), vg2.Y(), 10); +// iret[0] |= compare(vpg2.Z(), vg2.Z(), 10); + +// // test Get/SetComponents +// XYZVector v1, v2, v3; +// rot.GetComponents(v1, v2, v3); +// const Rotation3D rot2(v1, v2, v3); +// // rot2.SetComponents(v1,v2,v3); +// double r1[9], r2[9]; +// rot.GetComponents(r1, r1 + 9); +// rot2.GetComponents(r2, r2 + 9); +// for (int i = 0; i < 9; ++i) { +// iret[0] |= compare(r1[i], r2[i]); +// } +// // operator == fails for numerical precision +// // iret |= compare( (rot2==rot),true,"Get/SetComponens"); + +// // test get/set with a matrix +// // #ifndef NO_SMATRIX +// // SMatrix mat; +// // rot2.GetRotationMatrix(mat); +// // rot.SetRotationMatrix(mat); +// // iret[0] |= compare((rot2 == rot), true); +// // #endif + +// // test inversion +// Rotation3D rotInv = rot.Inverse(); +// rot.Invert(); // invert in place +// bool comp = (rotInv == rot); +// iret[0] |= compare(comp, true); + +// // rotation and scaling of points +// XYZPoint q1(1., 2, 3); +// double a = 3; +// XYZPoint qr1 = rot(a * q1); +// XYZPoint qr2 = a * rot(q1); +// iret[0] |= compare(qr1.X(), qr2.X(), 10); +// iret[0] |= compare(qr1.Y(), qr2.Y(), 10); +// iret[0] |= compare(qr1.Z(), qr2.Z(), 10); +// }); +// }); +// } + +// if (iret_host == 0) +// std::cout << "\tOK\n"; +// else +// std::cout << "\t FAILED\n"; + +// return iret_host; +// } + +// int testTransform3D() +// { + +// std::cout << "testing 3D Transform\t:\t"; +// int iret = 0; + +// EulerAngles r(1., 2., 3.); + +// GlobalPolar3DVector v(1., 2., 3.); +// GlobalXYZVector w(v); + +// Transform3D t1(v); +// GlobalXYZPoint pg; +// t1.Transform(LocalXYZPoint(), pg); +// iret |= compare(pg.X(), v.X(), "x diff", 10); +// iret |= compare(pg.Y(), v.Y(), "y diff", 10); +// iret |= compare(pg.Z(), v.Z(), "z diff", 10); + +// Transform3D t2(r, v); + +// GlobalPolar3DVector vr = r.Inverse() * v; + +// // std::cout << GlobalXYZVector(v) << std::endl; +// // std::cout << GlobalXYZVector(vr) << std::endl; +// // std::cout << GlobalXYZVector (r(v)) << std::endl; +// // std::cout << GlobalXYZVector (r(vr)) << std::endl; +// // std::cout << vr << std::endl; +// // std::cout << r(vr) << std::endl; + +// // std::cout << r << std::endl; +// // std::cout << r.Inverse() << std::endl; +// // std::cout << r * r.Inverse() << std::endl; +// // std::cout << Rotation3D(r) * Rotation3D(r.Inverse()) << std::endl; +// // std::cout << Rotation3D(r) * Rotation3D(r).Inverse() << std::endl; + +// // test Translation3D + +// Translation3D tr1(v); +// Translation3D tr2(v.X(), v.Y(), v.Z()); +// // skip this test on 32 bits architecture. It might fail due to extended precision +// #if !defined(__i386__) +// iret |= compare(tr1 == tr2, 1, "eq transl", 1); +// #else +// // add a dummy test to have the same outputfile for roottest +// // otherwise it will complain that the output is different ! +// iret |= compare(0, 0, "dummy test", 1); +// #endif + +// Translation3D tr3 = tr1 * tr1.Inverse(); +// GlobalPolar3DVector vp2 = tr3 * v; +// iret |= compare(vp2.X(), v.X(), "x diff", 10); +// iret |= compare(vp2.Y(), v.Y(), "y diff", 10); +// iret |= compare(vp2.Z(), v.Z(), "z diff", 10); + +// Transform3D t2b = tr1 * Rotation3D(r); +// // this above fails on Windows - use a comparison with tolerance +// // 12 is size of Transform3D internal vector +// iret |= compare(IsEqual(t2, t2b, 12), true, "eq1 transf", 1); +// // iret |= compare(t2 ==t2b, 1,"eq1 transf",1 ); +// Transform3D t2c(r, tr1); +// iret |= compare(IsEqual(t2, t2c, 12), true, "eq2 transf", 1); +// // iret |= compare(t2 ==t2c, 1,"eq2 transf",1 ); + +// Transform3D t3 = Rotation3D(r) * Translation3D(vr); + +// Rotation3D rrr; +// XYZVector vvv; +// t2b.GetDecomposition(rrr, vvv); +// iret |= compare(Rotation3D(r) == rrr, 1, "eq transf rot", 1); +// iret |= compare(tr1.Vect() == vvv, 1, "eq transf vec", 1); +// // if (iret) std::cout << vvv << std::endl; +// // if (iret) std::cout << Translation3D(vr) << std::endl; + +// Translation3D ttt; +// t2b.GetDecomposition(rrr, ttt); +// iret |= compare(tr1 == ttt, 1, "eq transf trans", 1); +// // if (iret) std::cout << ttt << std::endl; + +// EulerAngles err2; +// GlobalPolar3DVector vvv2; +// t2b.GetDecomposition(err2, vvv2); +// iret |= compare(r.Phi(), err2.Phi(), "transf rot phi", 4); +// iret |= compare(r.Theta(), err2.Theta(), "transf rot theta", 1); +// iret |= compare(r.Psi(), err2.Psi(), "transf rot psi", 1); + +// // iret |= compare( v == vvv2, 1,"eq transf g vec",1 ); +// iret |= compare(v.X(), vvv2.X(), "eq transf g vec", 4); +// iret |= compare(v.Y(), vvv2.Y(), "eq transf g vec", 1); +// iret |= compare(v.Z(), vvv2.Z(), "eq transf g vec", 1); + +// // create from other rotations +// RotationZYX rzyx(r); +// Transform3D t4(rzyx); +// iret |= compare(t4.Rotation() == Rotation3D(rzyx), 1, "eq trans rzyx", 1); + +// Transform3D trf2 = tr1 * r; +// iret |= compare(trf2 == t2b, 1, "trasl * e rot", 1); +// Transform3D trf3 = r * Translation3D(vr); +// // iret |= compare( trf3 == t3, 1,"e rot * transl",1 ); +// // this above fails on i686-slc5-gcc43-opt - use a comparison with tolerance +// iret |= compare(IsEqual(trf3, t3, 12), true, "e rot * transl", 1); + +// Transform3D t5(rzyx, v); +// Transform3D trf5 = Translation3D(v) * rzyx; +// // iret |= compare( trf5 == t5, 1,"trasl * rzyx",1 ); +// iret |= compare(IsEqual(trf5, t5, 12), true, "trasl * rzyx", 1); + +// Transform3D t6(rzyx, rzyx * Translation3D(v).Vect()); +// Transform3D trf6 = rzyx * Translation3D(v); +// iret |= compare(trf6 == t6, 1, "rzyx * transl", 1); +// if (iret) +// std::cout << t6 << "\n---\n" << trf6 << std::endl; + +// Transform3D trf7 = t4 * Translation3D(v); +// // iret |= compare( trf7 == trf6, 1,"tranf * transl",1 ); +// iret |= compare(IsEqual(trf7, trf6, 12), true, "tranf * transl", 1); +// Transform3D trf8 = Translation3D(v) * t4; +// iret |= compare(trf8 == trf5, 1, "trans * transf", 1); + +// Transform3D trf9 = Transform3D(v) * rzyx; +// iret |= compare(trf9 == trf5, 1, "tranf * rzyx", 1); +// Transform3D trf10 = rzyx * Transform3D(v); +// iret |= compare(trf10 == trf6, 1, "rzyx * transf", 1); +// Transform3D trf11 = Rotation3D(rzyx) * Transform3D(v); +// iret |= compare(trf11 == trf10, 1, "r3d * transf", 1); + +// RotationZYX rrr2 = trf10.Rotation(); +// // iret |= compare( rzyx == rrr2, 1,"gen Rotation()",1 ); +// iret |= compare(rzyx.Phi(), rrr2.Phi(), "gen Rotation() Phi", 1); +// iret |= compare(rzyx.Theta(), rrr2.Theta(), "gen Rotation() Theta", 10); +// iret |= compare(rzyx.Psi(), rrr2.Psi(), "gen Rotation() Psi", 1); +// if (iret) +// std::cout << rzyx << "\n---\n" << rrr2 << std::endl; + +// // std::cout << t2 << std::endl; +// // std::cout << t3 << std::endl; + +// XYZPoint p1(-1., 2., -3); + +// XYZPoint p2 = t2(p1); +// Polar3DPoint p3 = t3(Polar3DPoint(p1)); +// iret |= compare(p3.X(), p2.X(), "x diff", 10); +// iret |= compare(p3.Y(), p2.Y(), "y diff", 10); +// iret |= compare(p3.Z(), p2.Z(), "z diff", 10); + +// GlobalXYZVector v1(1., 2., 3.); +// LocalXYZVector v2; +// t2.Transform(v1, v2); +// GlobalPolar3DVector v3; +// t3.Transform(GlobalPolar3DVector(v1), v3); + +// iret |= compare(v3.X(), v2.X(), "x diff", 10); +// iret |= compare(v3.Y(), v2.Y(), "y diff", 10); +// iret |= compare(v3.Z(), v2.Z(), "z diff", 10); + +// XYZPoint q1(1, 2, 3); +// XYZPoint q2(-1, -2, -3); +// XYZPoint q3 = q1 + XYZVector(q2); +// // std::cout << q3 << std::endl; +// XYZPoint qt3 = t3(q3); +// // std::cout << qt3 << std::endl; +// XYZPoint qt1 = t3(q1); +// XYZVector vt2 = t3(XYZVector(q2)); +// XYZPoint qt4 = qt1 + vt2; +// iret |= compare(qt3.X(), qt4.X(), "x diff", 10); +// iret |= compare(qt3.Y(), qt4.Y(), "y diff", 10); +// iret |= compare(qt3.Z(), qt4.Z(), "z diff", 10); +// // std::cout << qt4 << std::endl; + +// // this fails +// // double a = 3; +// // XYZPoint q4 = a*q1; +// // std::cout << t3( a * q1) << std::endl; +// // std::cout << a * t3(q1) << std::endl; + +// // test get/set with a matrix +// #ifndef NO_SMATRIX +// SMatrix mat; +// t3.GetTransformMatrix(mat); +// Transform3D t3b; +// t3b.SetTransformMatrix(mat); +// iret |= compare((t3 == t3b), true, "Get/SetTransformMatrix"); + +// // test LR +// Boost b(0.2, 0.4, 0.8); +// LorentzRotation lr(b); +// SMatrix mat4; +// lr.GetRotationMatrix(mat4); +// LorentzRotation lr2; +// lr2.SetRotationMatrix(mat4); +// iret |= compare((lr == lr2), true, "Get/SetLRotMatrix"); +// #endif + +// { +// // testing ApplyInverse on Point +// XYZPoint point(1., -2., 3.); +// Transform3D tr(EulerAngles(10, -10, 10), XYZVector(10, -10, 0)); + +// // test that applying transformation + Inverse is identity +// auto r0 = tr.ApplyInverse(tr(point)); +// auto r0_2 = tr.Inverse()(tr(point)); + +// iret |= compare(r0.X(), point.X(), "ApplyInverse/PointX", 100); +// iret |= compare(r0_2.X(), point.X(), "ApplyInverse/PointX", 100); +// iret |= compare(r0.Y(), point.Y(), "ApplyInverse/PointY", 10); +// iret |= compare(r0_2.Y(), point.Y(), "ApplyInverse/PointY", 10); +// iret |= compare(r0.Z(), point.Z(), "ApplyInverse/PointZ", 10); +// iret |= compare(r0_2.Z(), point.Z(), "ApplyInverse/PointZ", 10); + +// // compare ApplyInverse with Inverse() +// auto r1 = tr.ApplyInverse(point); +// auto r2 = tr.Inverse()(point); +// iret |= compare(r1.X(), r2.X(), "ApplyInverse/Point", 10); +// iret |= compare(r1.Y(), r2.Y(), "ApplyInverse/Point", 10); +// iret |= compare(r1.Z(), r2.Z(), "ApplyInverse/Point", 10); +// } + +// { +// // testing ApplyInverse on Vector +// XYZVector vector(1, -2., 3); +// Transform3D tr(EulerAngles(10, -10, 10), XYZVector(10, -10, 0)); +// auto r1 = tr.ApplyInverse(vector); +// auto r2 = tr.Inverse()(vector); +// iret |= compare(r1.X(), r2.X(), "ApplyInverse/Vector", 10); +// iret |= compare(r1.Y(), r2.Y(), "ApplyInverse/Vector", 10); +// iret |= compare(r1.Z(), r2.Z(), "ApplyInverse/Vector", 10); +// } + +// if (iret == 0) +// std::cout << "OK\n"; +// else +// std::cout << "\t\t\tFAILED\n"; + +// return iret; +// } + +// int testVectorUtil() +// { + +// std::cout << "testing VectorUtil \t:\t"; +// int iret = 0; + +// // test new perp functions +// XYZVector v(1., 2., 3.); + +// XYZVector vx = ProjVector(v, XYZVector(3, 0, 0)); +// iret |= compare(vx.X(), v.X(), "x", 1); +// iret |= compare(vx.Y(), 0, "y", 1); +// iret |= compare(vx.Z(), 0, "z", 1); + +// XYZVector vpx = PerpVector(v, XYZVector(2, 0, 0)); +// iret |= compare(vpx.X(), 0, "x", 1); +// iret |= compare(vpx.Y(), v.Y(), "y", 1); +// iret |= compare(vpx.Z(), v.Z(), "z", 1); + +// double perpy = Perp(v, XYZVector(0, 2, 0)); +// iret |= compare(perpy, std::sqrt(v.Mag2() - v.y() * v.y()), "perpy"); + +// XYZPoint u(1, 1, 1); +// XYZPoint un = u / u.R(); + +// XYZVector vl = ProjVector(v, u); +// XYZVector vl2 = XYZVector(un) * (v.Dot(un)); + +// iret |= compare(vl.X(), vl2.X(), "x", 1); +// iret |= compare(vl.Y(), vl2.Y(), "y", 1); +// iret |= compare(vl.Z(), vl2.Z(), "z", 1); + +// XYZVector vp = PerpVector(v, u); +// XYZVector vp2 = v - XYZVector(un * (v.Dot(un))); +// iret |= compare(vp.X(), vp2.X(), "x", 10); +// iret |= compare(vp.Y(), vp2.Y(), "y", 10); +// iret |= compare(vp.Z(), vp2.Z(), "z", 10); + +// double perp = Perp(v, u); +// iret |= compare(perp, vp.R(), "perp", 1); +// double perp2 = Perp2(v, u); +// iret |= compare(perp2, vp.Mag2(), "perp2", 1); + +// // test rotations +// double angle = 1; +// XYZVector vr1 = RotateX(v, angle); +// XYZVector vr2 = RotationX(angle) * v; +// iret |= compare(vr1.Y(), vr2.Y(), "y", 1); +// iret |= compare(vr1.Z(), vr2.Z(), "z", 1); + +// vr1 = RotateY(v, angle); +// vr2 = RotationY(angle) * v; +// iret |= compare(vr1.X(), vr2.X(), "x", 1); +// iret |= compare(vr1.Z(), vr2.Z(), "z", 1); + +// vr1 = RotateZ(v, angle); +// vr2 = RotationZ(angle) * v; +// iret |= compare(vr1.X(), vr2.X(), "x", 1); +// iret |= compare(vr1.Y(), vr2.Y(), "y", 1); + +// if (iret == 0) +// std::cout << "\t\t\tOK\n"; +// else +// std::cout << "\t\t\t\t\t\tFAILED\n"; +// return iret; +// } + +int testGenVector() +{ + // SYCL syclcontext(); + + int iret = 0; + iret |= testVector3D(); + iret |= testPoint3D(); + + iret |= testVector2D(); + iret |= testPoint2D(); + + // iret |= testRotations3D(); + + // iret |= testTransform3D(); + + // iret |= testVectorUtil(); + + if (iret != 0) + std::cout << "\nTest GenVector FAILED!!!!!!!!!\n"; + return iret; +} + +int main() +{ + + int ret = testGenVector(); + if (ret) + std::cerr << "test FAILED !!! " << std::endl; + else + std::cout << "test OK " << std::endl; + return ret; +} diff --git a/math/experimental/genvectorx/test/testIterator.cxx b/math/experimental/genvectorx/test/testIterator.cxx new file mode 100644 index 0000000000000..be1c0428d3b11 --- /dev/null +++ b/math/experimental/genvectorx/test/testIterator.cxx @@ -0,0 +1,159 @@ + +#include "MathX/Vector3D.h" +#include "MathX/Point3D.h" +#include "MathX/Vector4D.h" +#include "MathX/EulerAngles.h" + +#include "MathX/Transform3D.h" +#include "MathX/LorentzRotation.h" +#include "MathX/Boost.h" + +#include "MathX/Rotation3D.h" +#include "MathX/RotationX.h" +#include "MathX/RotationY.h" +#include "MathX/RotationZ.h" +#include "MathX/Quaternion.h" +#include "MathX/AxisAngle.h" + +#include "MathX/VectorUtil.h" + +#include +#include +#include +#include +#include +#include + +using namespace ROOT::Math; +using namespace ROOT::Math::VectorUtil; + +template +void printRot(const Rot & rot) { + std::cout << "rot: ( " ; + std::ostream_iterator oi(std::cout," "); + rot.GetComponents(oi); + std::cout << ") " << std::endl; +} +template +void printVec(const V & v ) { + std::cout << "vec : ( " ; + std::ostream_iterator oi(std::cout," "); + v.GetCoordinates(oi); + std::cout << ") " << std::endl; +} +template +void printList(const L & l ) { + std::cout << "list : ( " ; + std::ostream_iterator oi(std::cout," "); + std::copy(l.begin(),l.end(),oi); + std::cout << ") " << std::endl; +} + +void testOstreamIter() { + + XYZVector v(1.,2.,3); + printVec(v); + XYZPoint p(v); printVec(p); + XYZTVector q(1.,2,3,4); printVec(q); + + AxisAngle ar(v,4.); printRot(ar); + EulerAngles er(ar); printRot(er); + Quaternion qr(er); printRot(qr); + Rotation3D rr(qr) ; printRot(rr); + + Transform3D t(rr,v); printRot(t); + + + Boost b(0.3,0.4,0.8); printRot(b); + LorentzRotation lr(rr); printRot(lr); + LorentzRotation lr2(b); printRot(lr2); + +} + +void testListIter() { + + // test with lists + double d[10] = {1,2,3,4,5,6,7,8,9,10}; + std::list inputData(d,d+3); + + XYZVector v; v.SetCoordinates(inputData.begin(), inputData.end() ); + std::list data(3); + v.GetCoordinates(data.begin(),data.end()); + printList(data); + + inputData = std::list(d+3,d+6); + XYZPoint p; p.SetCoordinates(inputData.begin(),inputData.end() ); + data.clear(); + data = std::list(3); + p.GetCoordinates(data.begin(), data.end() ); + printList(data); + + inputData = std::list(d+6,d+10); + XYZTVector q; q.SetCoordinates(inputData.begin(),inputData.end() ); + data.clear(); + data = std::list(4); + q.GetCoordinates(data.begin(), data.end() ); + printList(data); + + // test on rotations + inputData = std::list(d,d+3); + EulerAngles re(inputData.begin(), inputData.end() ); + data = std::list(3); + re.GetComponents(data.begin(), data.end() ); + printList(data); + + inputData = std::list(d,d+4); + AxisAngle ra(inputData.begin(), inputData.end() ); + data = std::list(4); + ra.GetComponents(data.begin(), data.end() ); + printList(data); + + inputData = std::list(d,d+4); + Quaternion rq(inputData.begin(), inputData.end() ); + data = std::list(4); + rq.GetComponents(data.begin(), data.end() ); + printList(data); + + double b[3] = {0.3,0.4,0.8}; + inputData = std::list(b,b+3); + Boost bst(inputData.begin(), inputData.end() ); + data = std::list(3); + bst.GetComponents(data.begin(), data.end() ); + printList(data); + + Rotation3D tmp(ra); + inputData = std::list(9); + tmp.GetComponents(inputData.begin()); printList(inputData); + Rotation3D r(inputData.begin(),inputData.end()); + data = std::list(9); + r.GetComponents(data.begin(), data.end() ); + printList(data); + + + Transform3D ttmp(r,XYZVector(1,2,3)); + inputData = std::list(12); + ttmp.GetComponents(inputData.begin()); printList(inputData); + Transform3D t(inputData.begin(),inputData.end()); + data = std::list(12); + t.GetComponents(data.begin(), data.end() ); + printList(data); + + + LorentzRotation ltmp(bst); + inputData = std::list(16); + ltmp.GetComponents(inputData.begin()); printList(inputData); + LorentzRotation lr(inputData.begin(),inputData.end()); + data = std::list(16); + lr.GetComponents(data.begin(), data.end() ); + printList(data); + + +} + +int main() { + + testOstreamIter(); + testListIter(); + + +} diff --git a/math/experimental/genvectorx/test/testVectorIO.cxx b/math/experimental/genvectorx/test/testVectorIO.cxx new file mode 100644 index 0000000000000..2618cd9599b7b --- /dev/null +++ b/math/experimental/genvectorx/test/testVectorIO.cxx @@ -0,0 +1,463 @@ + +// +// Cint macro to test I/O of mathcore Lorentz Vectors in a Tree and compare with a +// TLorentzVector. A ROOT tree is written and read in both using either a XYZTVector or /// a TLorentzVector. +// +// To execute the macro type in: +// +// root[0]: .x mathcoreVectorIO.C +// +#include "TRandom3.h" +#include "TStopwatch.h" +#include "TSystem.h" +#include "TFile.h" +#include "TTree.h" +#include "TH1D.h" +#include "TCanvas.h" + +#include + +#include "TLorentzVector.h" + +#include "MathX/Vector4D.h" +#include "MathX/Vector3D.h" +#include "MathX/Point3D.h" + +#include "Track.h" + + +#define DEBUG + + +//#define READONLY + +#define DEFVECTOR4D(TYPE) \ +typedef TYPE AVector4D; \ +const std::string vector4d_type = #TYPE ; + +#define DEFVECTOR3D(TYPE) \ +typedef TYPE AVector3D; \ +const std::string vector3d_type = #TYPE ; + +#define DEFPOINT3D(TYPE) \ +typedef TYPE APoint3D; \ +const std::string point3d_type = #TYPE ; + + + +//const double tol = 1.0E-16; +const double tol = 1.0E-6; // or doublr 32 or float + +DEFVECTOR4D(ROOT::Math::LorentzVector >); +//DEFVECTOR4D(ROOT::Math::LorentzVector >); + +DEFVECTOR3D(ROOT::Math::DisplacementVector3D >); + +DEFPOINT3D(ROOT::Math::PositionVector3D >); + + +// DEFVECTOR4D(ROOT::Math::LorentzVector >) + +//using namespace ROOT::Math; + +template +inline double getMag2(const Vector & v) { + return v.mag2(); +} + +// inline double getMag2(const VecTrackD & v) { +// // print the read points +// std::cout << "VecTRackD " << std::endl; +// for (VecTrackD::It itr = v.begin() ; itr != v.end(); ++itr) +// std::cout << (*itr).Pos() << std::endl; + +// return v.mag2(); +// } + + +inline double getMag2(const TVector3 & v) { + return v.Mag2(); +} + +inline double getMag2(const TLorentzVector & v) { + return v.Mag2(); +} + +template +inline void setValues(ROOT::Math::DisplacementVector3D & v, const double x[] ) { + v.SetXYZ(x[0],x[1],x[2]); +} + +template +inline void setValues(ROOT::Math::PositionVector3D & v, const double x[]) { + v.SetXYZ(x[0],x[1],x[2]); +} + +template +inline void setValues(ROOT::Math::LorentzVector & v, const double x[]) { + v.SetXYZT(x[0],x[1],x[2],x[3]); +} +// specialization for T -classes +inline void setValues(TVector3 & v, const double x[]) { + v.SetXYZ(x[0],x[1],x[2]); +} +inline void setValues(TLorentzVector & v, const double x[]) { + v.SetXYZT(x[0],x[1],x[2],x[3]); +} + + +template +double testDummy(int n) { + + TRandom3 R(111); + + TStopwatch timer; + + Vector v1; + double s = 0; + double p[4]; + + timer.Start(); + for (int i = 0; i < n; ++i) { + p[0] = R.Gaus(0,10); + p[1] = R.Gaus(0,10); + p[2] = R.Gaus(0,10); + p[3] = R.Gaus(100,10); + setValues(v1,p); + s += getMag2(v1); + } + + timer.Stop(); + + double average = std::sqrt(s/double(n)); + + std::cout << " Time for Random gen " << timer.RealTime() << " " << timer.CpuTime() << std::endl; + int pr = std::cout.precision(18); std::cout << "Average : " << average << std::endl; std::cout.precision(pr); + + return average; +} + +//---------------------------------------------------------------- +/// writing +//---------------------------------------------------------------- + +template +double write(int n, const std::string & file_name, const std::string & vector_type, int compress = 0) { + + TStopwatch timer; + + TRandom3 R(111); + + std::cout << "writing a tree with " << vector_type << std::endl; + + std::string fname = file_name + ".root"; + TFile f1(fname.c_str(),"RECREATE","",compress); + + // create tree + std::string tree_name="Tree with" + vector_type; + TTree t1("t1",tree_name.c_str()); + + Vector *v1 = new Vector(); + std::cout << "typeID written : " << typeid(*v1).name() << std::endl; + + t1.Branch("Vector branch",vector_type.c_str(),&v1); + + timer.Start(); + double p[4]; + double s = 0; + for (int i = 0; i < n; ++i) { + p[0] = R.Gaus(0,10); + p[1] = R.Gaus(0,10); + p[2] = R.Gaus(0,10); + p[3] = R.Gaus(100,10); + //CylindricalEta4D & c = v1->Coordinates(); + //c.SetValues(Px,pY,pZ,E); + setValues(*v1,p); + t1.Fill(); + s += getMag2(*v1); + } + + f1.Write(); + timer.Stop(); + + double average = std::sqrt(s/double(n)); + + +#ifdef DEBUG + t1.Print(); + std::cout << " Time for Writing " << file_name << "\t: " << timer.RealTime() << " " << timer.CpuTime() << std::endl; + int pr = std::cout.precision(18); std::cout << "Average : " << average << std::endl; std::cout.precision(pr); +#endif + + return average; +} + + +//---------------------------------------------------------------- +/// reading +//---------------------------------------------------------------- + +template +double read(const std::string & file_name) { + + TStopwatch timer; + + std::string fname = file_name + ".root"; + + TFile f1(fname.c_str()); + if (f1.IsZombie() ) { + std::cout << " Error opening file " << file_name << std::endl; + return -1; + } + + //TFile f1("mathcoreVectorIO_D32.root"); + + // create tree + TTree *t1 = (TTree*)f1.Get("t1"); + + Vector *v1 = nullptr; + + std::cout << "reading typeID : " << typeid(*v1).name() << std::endl; + + t1->SetBranchAddress("Vector branch",&v1); + + timer.Start(); + int n = (int) t1->GetEntries(); + std::cout << " Tree Entries " << n << std::endl; + double s=0; + for (int i = 0; i < n; ++i) { + t1->GetEntry(i); + s += getMag2(*v1); + } + + + timer.Stop(); + + double average = std::sqrt(s/double(n)); + +#ifdef DEBUG + std::cout << " Time for Reading " << file_name << "\t: " << timer.RealTime() << " " << timer.CpuTime() << std::endl; + int pr = std::cout.precision(18); std::cout << "Average : " << average << std::endl; std::cout.precision(pr); +#endif + + return average; +} + +template +double writeTrack(int n, const std::string & file_name, int compress = 0) { + + std::cout << "\n"; + std::cout << " Test writing .." << file_name << " .....\n"; + std::cout << "**************************************************\n"; + + TRandom3 R(111); + + TStopwatch timer; + + //std::cout << "writing a tree with " << vector_type << std::endl; + + std::string fname = file_name + ".root"; + TFile f1(fname.c_str(),"RECREATE","",compress); + + // create tree + std::string tree_name="Tree with TrackD"; + TTree t1("t1",tree_name.c_str()); + + TrackType *track = new TrackType(); + std::cout << "typeID written : " << typeid(*track).name() << std::endl; + + + //t1.Branch("Vector branch",&track,16000,0); + // default split model + t1.Branch("Vector branch",&track); + + timer.Start(); + double s = 0; + ROOT::Math::XYZTVector q; + ROOT::Math::XYZPoint p; + typedef typename TrackType::VectorType V; + typedef typename TrackType::PointType P; + + for (int i = 0; i < n; ++i) { + q.SetXYZT( R.Gaus(0,10), + R.Gaus(0,10), + R.Gaus(0,10), + R.Gaus(100,10) ); + p.SetXYZ( q.X(), q.Y(), q.Z() ); + + track->Set( V(q), P(p) ); + + t1.Fill(); + s += getMag2( *track ); + } + + f1.Write(); + timer.Stop(); + + double average = std::sqrt(s/double(n)); + + +#ifdef DEBUG + t1.Print(); + std::cout << " Time for Writing " << file_name << "\t: " << timer.RealTime() << " " << timer.CpuTime() << std::endl; + int pr = std::cout.precision(18); std::cout << "Average : " << average << std::endl; std::cout.precision(pr); +#endif + + return average; + +} + + + +int testResult(double w1, double r1, const std::string & type) { + + int iret = 0; + std::cout << w1 << " r " << r1 << std::endl; + // do like this to avoid nan's + if (!( fabs(w1-r1) < tol)) { + std::cout << "\nERROR: Differeces found when reading " << std::endl; + int pr = std::cout.precision(18); std::cout << w1 << " != " << r1 << std::endl; std::cout.precision(pr); + iret = -1; + } + + std::cout << "\n*********************************************************************************************\n"; + std::cout << "Test :\t " << type << "\t\t"; + if (iret ==0) + std::cout << "OK" << std::endl; + else + std::cout << "FAILED" << std::endl; + std::cout << "********************************************************************************************\n\n"; + + return iret; +} + + + +int testVectorIO(bool readOnly = false) { + + int iret = 0; + +// #ifdef __CINT__ +// gSystem->Load("libMathCore"); +// gSystem->Load("libPhysics"); +// using namespace ROOT::Math; +// #endif + + int nEvents = 100000; + //int nEvents = 100; + + double w1, r1 = 0; + std::string fname; + + testDummy(nEvents); + + fname = "lorentzvector"; + if (readOnly) { + w1 = 98.995527276968474; + fname += "_prev"; + } + else + w1 = write(nEvents,fname,vector4d_type); + + r1 = read(fname); + iret |= testResult(w1,r1,vector4d_type); + + fname = "displacementvector"; + if (readOnly) { + w1 = 17.3281570633214095; + fname += "_prev"; + } + else + w1 = write(nEvents,fname,vector3d_type); + + r1 = read(fname); + iret |= testResult(w1,r1,vector3d_type); + + fname = "positionvector"; + if (readOnly) + fname += "_prev"; + else + w1 = write(nEvents,fname,point3d_type); + + r1 = read(fname); + iret |= testResult(w1,r1,point3d_type); + + + // test TrackD + fname = "track"; + // load track dictionary + gInterpreter->ProcessLine(".L Track.h+"); + + //nEvents = 10000; + + if (readOnly) { + fname += "_prev"; + } + else + w1 = writeTrack( nEvents,fname); + + r1 = read(fname); + iret |= testResult(w1,r1,"TrackD"); + + // test TrackD32 + + fname = "trackD32"; + // load track dictionary + // gSystem->Load("libTrackDict"); + + if (readOnly) { + fname += "_prev"; + } + else + w1 = writeTrack( nEvents,fname); + + r1 = read(fname); + iret |= testResult(w1,r1,"TrackD32"); + + + // test vector of tracks + fname = "vectrack"; + + nEvents = 10000; + + if (readOnly) { + fname += "_prev"; + } + else + w1 = writeTrack( nEvents,fname); + + r1 = read(fname); + iret |= testResult(w1,r1,"VecTrackD"); + + // test ClusterD (cotaining a vector of points) + fname = "cluster"; + + nEvents = 10000; + + if (readOnly) { + fname += "_prev"; + } + else + w1 = writeTrack( nEvents,fname); + + r1 = read(fname); + iret |= testResult(w1,r1,"ClusterD"); + + return iret; +} + +int main(int argc, char ** ) { + + bool readOnly = false; + if (argc > 1) readOnly = true; + + int iret = testVectorIO(readOnly); + if (iret != 0) + std::cerr << "testVectorIO:\t FAILED ! " << std::endl; + else + std::cout << "testVectorIO:\t OK ! " << std::endl; + + return iret; + +} + diff --git a/math/experimental/genvectorx/test/vectorOperation.cxx b/math/experimental/genvectorx/test/vectorOperation.cxx new file mode 100644 index 0000000000000..caa3b6ab39804 --- /dev/null +++ b/math/experimental/genvectorx/test/vectorOperation.cxx @@ -0,0 +1,347 @@ +// test performance of all vectors operations +,- and * + +// results on mactelm g++ 4.01 showing ROOT::Math performs best overall + +//v3 = v1+v2 v2 += v1 v3 = v1-v2 v2 -= v1 v2 = a*v1 v1 *= a v2 = v1/a v1 /= a +// 0.59 0.57 0.58 0.56 0.69 0.7 1.65 1.64 2D +// 0.79 0.79 0.78 0.8 0.97 0.95 1.85 1.84 3D +// 1.07 1.07 1.07 1.07 1.32 1.31 1.72 1.71 4D + +// ROOT Physics Vector (TVector's): +//v3 = v1+v2 v2 += v1 v3 = v1-v2 v2 -= v1 v2 = a*v1 v1 *= a +// 4.4 0.97 4.41 0.96 4.43 1.13 2D +// 5.44 1.25 5.48 1.24 6.12 1.46 3D +// 17.65 7.32 17.65 7.35 10.25 7.79 4D + +// CLHEP Vector (HepVector's): +//v3 = v1+v2 v2 += v1 v3 = v1-v2 v2 -= v1 v2 = a*v1 v1 *= a +// 0.57 0.55 0.56 0.55 0.7 0.7 2D +// 0.8 0.79 0.78 0.77 0.96 0.94 2.7 3.7 3D +// 1.06 1.02 1.06 1.02 1.26 1.26 2.99 3.98 4D + + + + +#include "TRandom2.h" +#include "TStopwatch.h" + +#include +#include +#include + +#ifdef DIM_2 +#ifdef USE_POINT +#include "MathX/Point2D.h" +typedef ROOT::Math::XYPoint VecType; +#elif USE_CLHEP +#include "CLHEP/Vector/TwoVector.h" +typedef Hep2Vector VecType; +#elif USE_ROOT +#include "TVector2.h" +typedef TVector2 VecType; +#else +#include "MathX/Vector2D.h" +typedef ROOT::Math::XYVector VecType; +#endif + +#ifndef USE_ROOT +#define VSUM(v) v.x() + v.y() +#else +#define VSUM(v) v.X() + v.Y() +#endif + + +#elif DIM_3 // 3 Dimensions + +#ifdef USE_POINT +#include "MathX/Point3D.h" +typedef ROOT::Math::XYZPoint VecType; +#elif USE_CLHEP +#include "CLHEP/Vector/ThreeVector.h" +typedef Hep3Vector VecType; +#elif USE_ROOT +#include "TVector3.h" +typedef TVector3 VecType; +#else +#include "MathX/Vector3D.h" +typedef ROOT::Math::XYZVector VecType; +#endif + +#ifndef USE_ROOT +#define VSUM(v) v.x() + v.y() + v.z() +#else +#define VSUM(v) v.X() + v.Y() + v.Z() +#endif + +#else // default is 4D + +#undef USE_POINT +#ifdef USE_CLHEP +#include "CLHEP/Vector/LorentzVector.h" +typedef HepLorentzVector VecType; +#elif USE_ROOT +#include "TLorentzVector.h" +typedef TLorentzVector VecType; +#else +#include "MathX/Vector4D.h" +typedef ROOT::Math::XYZTVector VecType; +#endif + +#ifndef USE_ROOT +#define VSUM(v) v.x() + v.y() + v.z() + v.t() +#else +#define VSUM(v) v.X() + v.Y() + v.Z() + v.T() +#endif + +#endif + + +const int N = 1000000; + +template +class TestVector { +public: + + TestVector(); + void Add(); + void Add2(); + void Sub(); + void Sub2(); + void Scale(); + void Scale2(); + void Divide(); + void Divide2(); + + void PrintSummary(); + +private: + + std::vector vlist; + std::vector scale; + double fTime[10]; // timing results + int fTest; +}; + + + +template +TestVector::TestVector() : + vlist(std::vector(N) ), + scale(std::vector(N) ), + fTest(0) +{ + + // create list of vectors and fill them + + TRandom2 r(111); + for (int i = 0; i< N; ++i) { +#ifdef DIM_2 + vlist[i] = Vector( r.Uniform(-1,1), r.Uniform(-1,1) ); +#elif DIM_3 + vlist[i] = Vector( r.Uniform(-1,1),r.Uniform(-1,1),r.Uniform(-1,1) ); +#else // 4D + vlist[i] = Vector( r.Uniform(-1,1),r.Uniform(-1,1),r.Uniform(-1,1), r.Uniform(2,10) ); +#endif + scale[i] = r.Uniform(0,1); + } + + std::cout << "test using " << typeid(vlist[0]).name() << std::endl; +} + +template +void TestVector::Add() + // normal addition +{ + TStopwatch w; + w.Start(); + double s = 0; + for (int l = 0; l<100; ++l) { + for (int i = 1; i< N; ++i) { + Vector v3 = vlist[i-1] + vlist[i]; + s += VSUM(v3); + } + } + + std::cout << "Time for v3 = v1 + v2 :\t" << w.RealTime() << "\t" << w.CpuTime() << std::endl; + std::cout << "value " << s << std::endl << std::endl; + fTime[fTest++] = w.CpuTime(); +} + +template +void TestVector::Add2() +{ + // self addition + TStopwatch w; + Vector v3; + w.Start(); + double s = 0; + for (int l = 0; l<100; ++l) { + for (int i = 0; i< N; ++i) { + v3 += vlist[i]; + s += VSUM(v3); + } + } + + std::cout << "Time for v2 += v1 :\t" << w.RealTime() << "\t" << w.CpuTime() << std::endl; + std::cout << "value " << s << std::endl << std::endl; + fTime[fTest++] = w.CpuTime(); +} + +template +void TestVector::Sub() +{ + // normal sub + TStopwatch w; + w.Start(); + double s = 0; + for (int l = 0; l<100; ++l) { + for (int i = 1; i< N; ++i) { + Vector v3 = vlist[i-1] - vlist[i]; + s += VSUM(v3); + } + } + + std::cout << "Time for v3 = v1 - v2 :\t" << w.RealTime() << "\t" << w.CpuTime() << std::endl; + std::cout << "value " << s << std::endl << std::endl; + fTime[fTest++] = w.CpuTime(); +} + +template +void TestVector::Sub2() +{ + // self subtruction + TStopwatch w; + Vector v3; + w.Start(); + double s = 0; + for (int l = 0; l<100; ++l) { + for (int i = 0; i< N; ++i) { + v3 -= vlist[i]; + s += VSUM(v3); + } + } + + std::cout << "Time for v2 -= v1 :\t" << w.RealTime() << "\t" << w.CpuTime() << std::endl; + std::cout << "value " << s << std::endl << std::endl; + fTime[fTest++] = w.CpuTime(); +} + + +template +void TestVector::Scale() +{ +// normal multiply + TStopwatch w; + w.Start(); + double s = 0; + for (int l = 0; l<100; ++l) { + for (int i = 1; i< N; ++i) { + Vector v3 = scale[i]*vlist[i]; + s += VSUM(v3); + } + } + + std::cout << "Time for v2 = A * v1 :\t" << w.RealTime() << "\t" << w.CpuTime() << std::endl; + std::cout << "value " << s << std::endl << std::endl; + fTime[fTest++] = w.CpuTime(); +} + +template +void TestVector::Scale2() +{ + // self scale + TStopwatch w; + Vector v3; + w.Start(); + double s = 0; + for (int l = 0; l<100; ++l) { + for (int i = 0; i< N; ++i) { + v3 = vlist[i]; + v3 *= scale[i]; + s += VSUM(v3); + } + } + + std::cout << "Time for v *= a :\t" << w.RealTime() << "\t" << w.CpuTime() << std::endl; + std::cout << "value " << s << std::endl << std::endl; + fTime[fTest++] = w.CpuTime(); +} + +template +void TestVector::Divide() +{ +// normal divide + TStopwatch w; + w.Start(); + double s = 0; + for (int l = 0; l<100; ++l) { + for (int i = 1; i< N; ++i) { + Vector v3 = vlist[i]/scale[i]; + s += VSUM(v3); + } + } + + std::cout << "Time for v2 = v1 / a :\t" << w.RealTime() << "\t" << w.CpuTime() << std::endl; + std::cout << "value " << s << std::endl << std::endl; + fTime[fTest++] = w.CpuTime(); +} + +template +void TestVector::Divide2() +{ + // self divide + TStopwatch w; + Vector v3; + w.Start(); + double s = 0; + for (int l = 0; l<100; ++l) { + for (int i = 0; i< N; ++i) { + v3 = vlist[i]; + v3 /= scale[i]; + s += VSUM(v3); + } + } + + std::cout << "Time for v /= a :\t" << w.RealTime() << "\t" << w.CpuTime() << std::endl; + std::cout << "value " << s << std::endl << std::endl; + fTime[fTest++] = w.CpuTime(); +} + + +template +void TestVector::PrintSummary() +{ + std::cout << "\nResults for " << typeid(vlist[0]).name() << std::endl; + std::cout << " v3 = v1+v2" + << " v2 += v1 " + << " v3 = v1-v2" + << " v2 -= v1 " + << " v2 = a*v1 " + << " v1 *= a " + << " v2 = v1/a " + << " v1 /= a " << std::endl; + + for (int i = 0; i < fTest; ++i) { + std::cout << std::setw(8) << fTime[i] << " "; + } + std::cout << std::endl << std::endl; +} + +int main() { + TestVector t; +#ifndef USE_POINT + t.Add(); + t.Add2(); + t.Sub(); + t.Sub2(); +#endif + t.Scale(); + t.Scale2(); +#ifndef USE_ROOT + t.Divide(); + t.Divide2(); +#endif + + // summarize test + t.PrintSummary(); +}