diff --git a/.github/workflows/root-ci-config/buildconfig/fedora41.txt b/.github/workflows/root-ci-config/buildconfig/fedora41.txt index 3870c8f23c051..e31818cfd7dc9 100644 --- a/.github/workflows/root-ci-config/buildconfig/fedora41.txt +++ b/.github/workflows/root-ci-config/buildconfig/fedora41.txt @@ -2,3 +2,5 @@ builtin_zstd=ON builtin_zlib=ON builtin_vdt=On ccache=On +experimental_adaptivecpp=ON +experimental_genvectorx=ON diff --git a/.github/workflows/root-ci-config/buildconfig/fedora42.txt b/.github/workflows/root-ci-config/buildconfig/fedora42.txt index cb6ac259c9857..f277ca170c020 100644 --- a/.github/workflows/root-ci-config/buildconfig/fedora42.txt +++ b/.github/workflows/root-ci-config/buildconfig/fedora42.txt @@ -1,4 +1,6 @@ builtin_zlib=ON builtin_zstd=ON ccache=ON +experimental_adaptivecpp=ON +experimental_genvectorx=ON vdt=OFF diff --git a/.github/workflows/root-ci-config/buildconfig/ubuntu2404-cuda.txt b/.github/workflows/root-ci-config/buildconfig/ubuntu2404-cuda.txt index b7b693c1dbcfd..cd2afc32ff38b 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 diff --git a/.github/workflows/root-ci-config/buildconfig/ubuntu2404.txt b/.github/workflows/root-ci-config/buildconfig/ubuntu2404.txt index e4cf831b6111d..e8c5a9e5192b3 100644 --- a/.github/workflows/root-ci-config/buildconfig/ubuntu2404.txt +++ b/.github/workflows/root-ci-config/buildconfig/ubuntu2404.txt @@ -1,3 +1,5 @@ ccache=ON +experimental_adaptivecpp=ON +experimental_genvectorx=ON pythia8=OFF tmva-sofie=ON diff --git a/.github/workflows/root-ci-config/buildconfig/ubuntu2504.txt b/.github/workflows/root-ci-config/buildconfig/ubuntu2504.txt index 9439d1f4057e1..8f9b303cc99b2 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 diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index c06e585264333..78682f8faa122 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -126,6 +126,8 @@ ROOT_BUILD_OPTION(davix ON "Enable support for Davix (HTTP/WebDAV access)") ROOT_BUILD_OPTION(dcache OFF "Enable support for dCache (requires libdcap from DESY)") ROOT_BUILD_OPTION(dev OFF "Enable recommended developer compilation flags, reduce exposed includes") ROOT_BUILD_OPTION(distcc OFF "Enable distcc usage for speeding up builds (ccache is called first if enabled)") +ROOT_BUILD_OPTION(experimental_adaptivecpp OFF "Build AdaptiveCPP for SYCL support") +ROOT_BUILD_OPTION(experimental_genvectorx OFF "Build GenvectorX (requires SYCL support)") ROOT_BUILD_OPTION(fcgi OFF "Enable FastCGI support in HTTP server") ROOT_BUILD_OPTION(fftw3 OFF "Enable support for FFTW3 [GPL]") ROOT_BUILD_OPTION(fitsio ON "Enable support for reading FITS images") diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 634a5f12fc25f..d7a75856f74ec 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -1592,6 +1592,41 @@ if (vecgeom) endif() endif() +if(experimental_adaptivecpp) + # Building adaptivecpp requires an internet connection, if we're not side-loading the source directory + if(NOT DEFINED ADAPTIVECPP_SOURCE_DIR) + ROOT_CHECK_CONNECTION_AND_DISABLE_OPTION("experimental_adaptivecpp") + endif() + include(SetupAdaptiveCpp) + set(HIPSYCL_NO_FIBERS ON) + set(WITH_OPENCL_BACKEND OFF) + set(WITH_LEVEL_ZERO_BACKEND OFF) + + find_package(AdaptiveCpp) + 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_to_root_target) + CMAKE_PARSE_ARGUMENTS(ARG "" "TARGET" "SOURCES" "COMPILE_DEFINITIONS" ${ARGN}) + add_dependencies(${ARG_TARGET} acpp-rt) + 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}) + target_compile_definitions(${ARG_TARGET} PUBLIC ${ARG_COMPILE_DEFINITIONS}) + 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() + #---Check for protobuf------------------------------------------------------------------- if(tmva-sofie) diff --git a/cmake/modules/SetupAdaptiveCpp.cmake b/cmake/modules/SetupAdaptiveCpp.cmake new file mode 100644 index 0000000000000..6e9c87502a2bb --- /dev/null +++ b/cmake/modules/SetupAdaptiveCpp.cmake @@ -0,0 +1,116 @@ +message(STATUS "Building AdaptiveCpp for SYCL support.") + +include(FetchContent) + +if(NOT DEFINED ADAPTIVE_CPP_SOURCE_DIR) + FetchContent_Declare( + AdaptiveCpp + GIT_REPOSITORY https://github.com/root-project/AdaptiveCpp.git + GIT_TAG ROOT-acpp-v25.02.0-20250615-01) + FetchContent_GetProperties(AdaptiveCpp) + if(NOT AdaptiveCpp_POPULATED) + FetchContent_Populate(AdaptiveCpp) + endif() + set(ADAPTIVE_CPP_SOURCE_DIR ${adaptivecpp_SOURCE_DIR}) + message(STATUS "Fetched AdaptiveCpp source to: ${ADAPTIVE_CPP_SOURCE_DIR}") +else() + message( + STATUS "ADAPTIVE_CPP_SOURCE_DIR already defined: ${ADAPTIVE_CPP_SOURCE_DIR}" + ) +endif() + +set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR}/interpreter/llvm-project/llvm) +set(CLANG_EXECUTABLE_PATH ${LLVM_BINARY_DIR}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}) + +set(ACPP_CLANG + ${CLANG_EXECUTABLE_PATH} + CACHE STRING "Clang compiler executable used for compilation." FORCE) + +set(ADAPTIVE_CPP_BINARY_DIR ${CMAKE_BINARY_DIR}) +message(STATUS "AdaptiveCpp will be built in: ${ADAPTIVE_CPP_BINARY_DIR}") + +set(ADAPTIVECPP_INSTALL_CMAKE_DIR + lib/cmake/AdaptiveCpp + CACHE PATH "Install path for CMake config files") + +# Set relative paths for install root in the following variables so that +# configure_package_config_file will generate paths relative whatever is the +# future install root +set(ADAPTIVECPP_INSTALL_COMPILER_DIR bin) +set(ACPP_CONFIG_FILE_INSTALL_DIR etc/AdaptiveCpp) +set(ADAPTIVECPP_INSTALL_LAUNCHER_DIR ${ADAPTIVECPP_INSTALL_CMAKE_DIR}) +set(ADAPTIVECPP_INSTALL_LAUNCHER_RULE_DIR ${ADAPTIVECPP_INSTALL_CMAKE_DIR}) + +install(FILES ${ADAPTIVE_CPP_BINARY_DIR}/lib/libacpp-rt.so DESTINATION lib) +install(DIRECTORY ${ADAPTIVE_CPP_BINARY_DIR}/lib/hipSYCL/bitcode/ + DESTINATION lib/hipSYCL/bitcode) +install(DIRECTORY ${ADAPTIVE_CPP_BINARY_DIR}/include/AdaptiveCpp/ + DESTINATION include/AdaptiveCpp) + +file( + COPY ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/syclcc-launcher + DESTINATION ${ADAPTIVE_CPP_BINARY_DIR}/${ADAPTIVECPP_INSTALL_LAUNCHER_DIR}) +file( + COPY ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/syclcc-launch.rule.in + DESTINATION ${ADAPTIVE_CPP_BINARY_DIR}/${ADAPTIVECPP_INSTALL_LAUNCHER_RULE_DIR}) + +list(APPEND CMAKE_PREFIX_PATH ${ADAPTIVE_CPP_BINARY_DIR}/${ADAPTIVECPP_INSTALL_CMAKE_DIR}) +message(STATUS "Added ${ADAPTIVE_CPP_BINARY_DIR}/${ADAPTIVECPP_INSTALL_CMAKE_DIR} to CMAKE_PREFIX_PATH.") + +install(PROGRAMS ${ADAPTIVE_CPP_BINARY_DIR}/bin/acpp + DESTINATION ${ADAPTIVECPP_INSTALL_COMPILER_DIR}) +install(FILES ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/syclcc-launcher + DESTINATION ${ADAPTIVECPP_INSTALL_LAUNCHER_DIR}) +install(FILES ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/syclcc-launch.rule.in + DESTINATION ${ADAPTIVECPP_INSTALL_LAUNCHER_RULE_DIR}) + +file(GLOB CLANG_EXECUTABLES "${LLVM_BINARY_DIR}/bin/clang*") +install(PROGRAMS ${CLANG_EXECUTABLES} + DESTINATION ${ADAPTIVECPP_INSTALL_COMPILER_DIR}) + +file(GLOB CONFIG_FILES "${ADAPTIVE_CPP_BINARY_DIR}/etc/AdaptiveCpp/*") +install(FILES ${CONFIG_FILES} DESTINATION ${ACPP_CONFIG_FILE_INSTALL_DIR}) + +# Create imported target AdaptiveCpp::acpp-common +add_library(AdaptiveCpp::acpp-common STATIC IMPORTED) + +set_target_properties(AdaptiveCpp::acpp-common PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${ADAPTIVE_CPP_BINARY_DIR}/include;${ADAPTIVE_CPP_BINARY_DIR}/include/AdaptiveCpp" + INTERFACE_LINK_LIBRARIES "-Wl,-Bsymbolic-functions;\$" +) + +# Create imported target AdaptiveCpp::acpp-rt +add_library(AdaptiveCpp::acpp-rt SHARED IMPORTED) + +set_target_properties(AdaptiveCpp::acpp-rt PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${ADAPTIVE_CPP_BINARY_DIR}/include;${ADAPTIVE_CPP_BINARY_DIR}/include/AdaptiveCpp" + INTERFACE_LINK_LIBRARIES "AdaptiveCpp::acpp-common" +) + +# Import target "AdaptiveCpp::acpp-common" for configuration "Release" +set_property(TARGET AdaptiveCpp::acpp-common APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(AdaptiveCpp::acpp-common PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" + IMPORTED_LOCATION_RELEASE "${ADAPTIVE_CPP_BINARY_DIR}/lib/libacpp-common.a" + ) + +# Import target "AdaptiveCpp::acpp-rt" for configuration "Release" +set_property(TARGET AdaptiveCpp::acpp-rt APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(AdaptiveCpp::acpp-rt PROPERTIES + IMPORTED_LOCATION_RELEASE "${ADAPTIVE_CPP_BINARY_DIR}/lib/libacpp-rt.so" + IMPORTED_SONAME_RELEASE "libacpp-rt.so" + ) + +# Make a config file to make this usable as a CMake Package +# Start by adding the version in a CMake understandable way +include(CMakePackageConfigHelpers) + +configure_package_config_file( + ${ADAPTIVE_CPP_SOURCE_DIR}/cmake/adaptivecpp-config.cmake.in + ${ADAPTIVE_CPP_BINARY_DIR}/lib/cmake/AdaptiveCpp/adaptivecpp-config.cmake + INSTALL_DESTINATION ${ADAPTIVECPP_INSTALL_CMAKE_DIR} + PATH_VARS + ADAPTIVECPP_INSTALL_COMPILER_DIR + ADAPTIVECPP_INSTALL_LAUNCHER_DIR + ADAPTIVECPP_INSTALL_LAUNCHER_RULE_DIR +) diff --git a/interpreter/CMakeLists.txt b/interpreter/CMakeLists.txt index 9a4674d700884..6e2ac03cfb9c7 100644 --- a/interpreter/CMakeLists.txt +++ b/interpreter/CMakeLists.txt @@ -214,6 +214,13 @@ if(builtin_llvm) set(LLVM_ENABLE_PROJECTS "clang" CACHE STRING "") + if(experimental_adaptivecpp) + # Register AdaptiveCpp as an external project + set(LLVM_EXTERNAL_PROJECTS "AdaptiveCpp" CACHE STRING "") + set(LLVM_EXTERNAL_ADAPTIVECPP_SOURCE_DIR "${ADAPTIVE_CPP_SOURCE_DIR}" CACHE STRING "") + set(LLVM_ADAPTIVECPP_LINK_INTO_TOOLS ON CACHE BOOL "") # To force-link the plugin into clang + endif() + # Always build LLVM with C++17. It is not necessary to compile with the same # C++ standard as the rest of ROOT and sometimes it doesn't even work. set(_cxx_standard ${CMAKE_CXX_STANDARD}) 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..7d2838b1edf4c --- /dev/null +++ b/math/experimental/genvectorx/CMakeLists.txt @@ -0,0 +1,73 @@ +# 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_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 + ) + +set(ACPP_EXPORTS acpp-rt acpp-common) + +foreach(target IN LISTS ACPP_EXPORTS) + install(TARGETS ${target} EXPORT ROOTExports) +endforeach() + +target_link_libraries(GenVectorSYCL PUBLIC m stdc++) + +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..e2bb0646eee4e --- /dev/null +++ b/math/experimental/genvectorx/doc/index.md @@ -0,0 +1,14 @@ +\defgroup GenVectorX Physics Vectors +\ingroup Math +\brief Vector classes (2D, 3D and 4D / Lorentz vector) and their transformations to be used in SYCL or CUDA kernels for heterogeneous computing. + +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::MathSYCL::PtEtaPhiMVector or ROOT::MathCUDA::PtEtaPhiMVector, respectively a typedef to ROOT::MathSYCL::LorentzVector < ROOT::MathSYCL::PtEtaPhiM4D < double > > and ROOT::MathCUDA::LorentzVector < ROOT::MathCUDA::PtEtaPhiM4D < double > >. + + +## Additional Documentation + +A more detailed description of the GenVectorX package is available in this [document](https://arxiv.org/pdf/2312.02756). diff --git a/math/experimental/genvectorx/inc/MathX/AxisAngle.h b/math/experimental/genvectorx/inc/MathX/AxisAngle.h new file mode 100644 index 0000000000000..e57cdcf0944f9 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/AxisAngle.h @@ -0,0 +1,9 @@ +// @(#)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..fcdfb8cd8c949 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Boost.h @@ -0,0 +1,9 @@ +// @(#)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..c06446756ac77 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/BoostX.h @@ -0,0 +1,9 @@ +// @(#)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..6169e0a16061e --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/BoostY.h @@ -0,0 +1,9 @@ +// @(#)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..c453785686b57 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/BoostZ.h @@ -0,0 +1,9 @@ +// @(#)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..31ed9aa540a0a --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Cartesian2D.h @@ -0,0 +1,9 @@ +// @(#)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..48bc8f8347ef3 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Cartesian3D.h @@ -0,0 +1,9 @@ +// @(#)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..989d13f08cd89 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Cylindrical3D.h @@ -0,0 +1,9 @@ +// @(#)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..cdb281090b50b --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/CylindricalEta3D.h @@ -0,0 +1,9 @@ +// @(#)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..ba7c898614e54 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/DisplacementVector2D.h @@ -0,0 +1,9 @@ +// @(#)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..242d6ab1b3d27 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/DisplacementVector3D.h @@ -0,0 +1,9 @@ +// @(#)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..f67d980426077 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/EulerAngles.h @@ -0,0 +1,9 @@ +// @(#)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..ab386830e3719 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/3DConversions.h @@ -0,0 +1,124 @@ +// @(#)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 ROOT_MATH_ARCH +} // 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..b5cc451100cfc --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/3DDistances.h @@ -0,0 +1,146 @@ +// @(#)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 ROOT_MATH_ARCH +} // 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..c98fc12764ebf --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/AccHeaders.h @@ -0,0 +1,41 @@ +#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..7cde185dea359 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/AxisAngle.h @@ -0,0 +1,371 @@ +// @(#)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> xyz(v.X(), v.Y(), v.Z()); + DisplacementVector3D> rxyz = operator()(xyz); + DisplacementVector3D 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, Tag> xyz(p); + DisplacementVector3D, 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> xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector> 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> xyz(v); + DisplacementVector3D> 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 ROOT_MATH_ARCH +} // 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..847ce3f2409d6 --- /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 ROOT_MATH_ARCH +} // 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..61ad0858ef0a4 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BitReproducible.h @@ -0,0 +1,135 @@ +// @(#)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 ROOT_MATH_ARCH +} // 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..2963cc20e6c39 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Boost.h @@ -0,0 +1,324 @@ +// @(#)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> operator()(const LorentzVector> &v) const; + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector operator()(const LorentzVector &v) const + { + LorentzVector> xyzt(v); + LorentzVector> 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> xyzt(v); + LorentzVector> 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 ROOT_MATH_ARCH +} // 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..5eb7bea9f82fb --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostX.h @@ -0,0 +1,228 @@ +// @(#)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> operator()(const LorentzVector> &v) const; + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector operator()(const LorentzVector &v) const + { + LorentzVector> xyzt(v); + LorentzVector> 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> xyzt(v); + LorentzVector> 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 ROOT_MATH_ARCH +} // 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..8c9ce592a6135 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostXfwd.h @@ -0,0 +1,22 @@ +// @(#)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 ROOT_MATH_ARCH +} // 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..8196086bf4ace --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostY.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 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> operator()(const LorentzVector> &v) const; + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector operator()(const LorentzVector &v) const + { + LorentzVector> xyzt(v); + LorentzVector> 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> xyzt(v); + LorentzVector> 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 ROOT_MATH_ARCH +} // 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..a3fb5a2b915a3 --- /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 ROOT_MATH_ARCH +} // 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..2acb54c4db985 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/BoostZ.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 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> operator()(const LorentzVector> &v) const; + + /** + Lorentz transformation operation on a LorentzVector in any + coordinate system + */ + template + LorentzVector operator()(const LorentzVector &v) const + { + LorentzVector> xyzt(v); + LorentzVector> 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> xyzt(v); + LorentzVector> 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 ROOT_MATH_ARCH +} // 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..020f0d78a2882 --- /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 ROOT_MATH_ARCH +} // 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..0b38e9176c666 --- /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 ROOT_MATH_ARCH +} // 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..221cc1f6f8f55 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian2D.h @@ -0,0 +1,269 @@ +// @(#)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); +} + +} // namespace ROOT_MATH_ARCH + +} // 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..241def290254a --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian2Dfwd.h @@ -0,0 +1,20 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH + +} // 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..c25fb14f8934f --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian3D.h @@ -0,0 +1,343 @@ +// @(#)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..0b4fb1bc8708a --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cartesian3Dfwd.h @@ -0,0 +1,16 @@ +// @(#)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 { + +template +class Cartesian3D; + +} // namespace ROOT_MATH_ARCH + +#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..d4876a4825f77 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/CoordinateSystemTags.h @@ -0,0 +1,63 @@ +// @(#)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 ROOT_MATH_ARCH + +} // 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..41f0d0821b87b --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Cylindrical3D.h @@ -0,0 +1,343 @@ +// @(#)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..8686c5f0c8ed3 --- /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; + +} // namespace ROOT_MATH_ARCH +} // namespace ROOT + +#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..04258575d4856 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/CylindricalEta3D.h @@ -0,0 +1,375 @@ +// @(#)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..ea5ebd223cfd4 --- /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; + +} // namespace ROOT_MATH_ARCH +} // namespace ROOT + +#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..8377b450073a0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector2D.h @@ -0,0 +1,509 @@ +// @(#)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 + 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 + 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 +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 +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..696bc0d2775cf --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector2Dfwd.h @@ -0,0 +1,21 @@ +// @(#)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 DisplacementVector2D; + +} // namespace ROOT_MATH_ARCH +} // 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..a08ca1756b8c0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector3D.h @@ -0,0 +1,729 @@ +// @(#)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 + 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 + 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 < + 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, 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 < + 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, 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 +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..7c20821b35712 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/DisplacementVector3Dfwd.h @@ -0,0 +1,21 @@ +// @(#)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 DisplacementVector3D; + +} // namespace ROOT_MATH_ARCH +} // 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..1fccb6b903da1 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/EulerAngles.h @@ -0,0 +1,413 @@ +// @(#)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, U> xyz(v); + DisplacementVector3D, 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> xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector> 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> xyz(v); + DisplacementVector3D> 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 ROOT_MATH_ARCH +} // 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..f28abf5fba4a6 --- /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 ROOT_MATH_ARCH +} // 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..a7584ae3f2b9c --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/GenVectorIO.h @@ -0,0 +1,182 @@ +// @(#)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 +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 +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 manipulator { +public: + explicit manipulator(manip_t m, char_t ch = 0) : fMan(m), fChar(ch) {} + + template + void set(std::basic_ios &ios) const + { + set_manip(ios, fMan, fChar); + } + +private: + manip_t fMan; + char_t fChar; + +}; // manipulator<> + +template +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 +inline std::basic_ostream & +operator<<(std::basic_ostream &os, detail::manipulator const &manip) + +{ + manip.set(os); + return os; + +} // op<< <>() + +template +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 +inline detail::manipulator set_open(char_t ch) +{ + return detail::manipulator(detail::open, ch); + +} // set_open<>() + +template +inline detail::manipulator set_separator(char_t ch) +{ + return detail::manipulator(detail::sep, ch); + +} // set_separator<>() + +template +inline detail::manipulator set_close(char_t ch) +{ + return detail::manipulator(detail::close, ch); + +} // set_close<>() + +template +inline std::basic_ios &human_readable(std::basic_ios &ios) +{ + ios.iword(ios_data(detail::bitforbit)) = 0L; + return ios; + +} // human_readable<>() + +template +inline std::basic_ios &machine_readable(std::basic_ios &ios) +{ + ios.iword(ios_data(detail::bitforbit)) = 1L; + return ios; + +} // machine_readable<>() + +} // namespace ROOT_MATH_ARCH +} // namespace ROOT + +#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..a3310ca614f64 --- /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 ROOT_MATH_ARCH +} // 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..b7a4d20928efe --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzRotation.h @@ -0,0 +1,586 @@ +// @(#)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> operator()(const LorentzVector> &v) const + { + Scalar x = v.Px(); + Scalar y = v.Py(); + Scalar z = v.Pz(); + Scalar t = v.E(); + return LorentzVector>( + 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> xyzt(v); + LorentzVector> 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> xyzt(v); + LorentzVector> 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 ROOT_MATH_ARCH +} // 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..674b516c10805 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzRotationfwd.h @@ -0,0 +1,29 @@ +// @(#)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; +} // namespace ROOT_MATH_ARCH +} // 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..6e30cdcabe2bd --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzVector.h @@ -0,0 +1,839 @@ +// @(#)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 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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> 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> 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 +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 +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 +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..ed608742e87c9 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/LorentzVectorfwd.h @@ -0,0 +1,35 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH + +} // 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..b214213ebc7af --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/MathHeaders.h @@ -0,0 +1,465 @@ +/* + * 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..2167fd71e526d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Plane3D.h @@ -0,0 +1,311 @@ +// @(#)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 ROOT_MATH_ARCH { + +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 ROOT_MATH_ARCH + +} // 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..951acd921ff07 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar2D.h @@ -0,0 +1,273 @@ +// @(#)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..c40d71e5cbf8c --- /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; + +} // namespace ROOT_MATH_ARCH +} // namespace ROOT + +#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..cebced53f29be --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Polar3D.h @@ -0,0 +1,338 @@ +// @(#)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..6e862c0b4da40 --- /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; + +} // namespace ROOT_MATH_ARCH +} // namespace ROOT + +#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..54aa8d3f6d811 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector2D.h @@ -0,0 +1,494 @@ +// @(#)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 + 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 +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 +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..dda3d338ad418 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector2Dfwd.h @@ -0,0 +1,23 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH +} // namespace ROOT + +#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..569a67bd41fab --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector3D.h @@ -0,0 +1,693 @@ +// @(#)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 + 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 + 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 ::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 +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..0316757bc10e9 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PositionVector3Dfwd.h @@ -0,0 +1,23 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH +} // namespace ROOT + +#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..fbcdc56786ce3 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiE4D.h @@ -0,0 +1,467 @@ + +// @(#)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..539ed69239666 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiE4Dfwd.h @@ -0,0 +1,20 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH + +} // 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..5cd8dd8f3d6f7 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiM4D.h @@ -0,0 +1,487 @@ +// @(#)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..5508af3417587 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PtEtaPhiM4Dfwd.h @@ -0,0 +1,20 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH + +} // 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..36b7b6bfda3d7 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzE4D.h @@ -0,0 +1,428 @@ +// @(#)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..d7c71e9d194ea --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzE4Dfwd.h @@ -0,0 +1,20 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH + +} // 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..728c8a3a06726 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzM4D.h @@ -0,0 +1,467 @@ +// @(#)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..58815732d5100 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/PxPyPzM4Dfwd.h @@ -0,0 +1,20 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH + +} // 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..848cc585e540c --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Quaternion.h @@ -0,0 +1,373 @@ +// @(#)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> xyz(v.X(), v.Y(), v.Z()); + DisplacementVector3D> rxyz = operator()(xyz); + DisplacementVector3D 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, Tag> xyz(p); + DisplacementVector3D, 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> xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector> 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> xyz(v); + DisplacementVector3D> 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 ROOT_MATH_ARCH +} // 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..244b358641206 --- /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 ROOT_MATH_ARCH +} // 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..3b779a8b5c068 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Rotation3D.h @@ -0,0 +1,565 @@ +// @(#)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, 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, U> xyz(v); + DisplacementVector3D, 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> xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector> 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> xyz(v); + DisplacementVector3D> 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 ROOT_MATH_ARCH +} // 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..aec5fbe9e0fe5 --- /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 ROOT_MATH_ARCH +} // 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..78a3c1ac6de7f --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationX.h @@ -0,0 +1,260 @@ +// @(#)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, 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, U> xyz(v); + DisplacementVector3D, 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> xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector> 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> xyz(v); + DisplacementVector3D> 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 ROOT_MATH_ARCH +} // 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..e4a446f8e267e --- /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 ROOT_MATH_ARCH +} // 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..3719a7712d81b --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationY.h @@ -0,0 +1,260 @@ +// @(#)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, 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, U> xyz(v); + DisplacementVector3D, 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> xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector> 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> xyz(v); + DisplacementVector3D> 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 ROOT_MATH_ARCH +} // 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..c58541d8abb12 --- /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 ROOT_MATH_ARCH +} // 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..ec6d4f9e2c269 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZ.h @@ -0,0 +1,261 @@ +// @(#)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, 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, U> xyz(v); + DisplacementVector3D, 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> xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector> 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> xyz(v); + DisplacementVector3D> 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 ROOT_MATH_ARCH +} // 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..4859ca4c43340 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/RotationZYX.h @@ -0,0 +1,382 @@ +// @(#)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, U> xyz(v); + DisplacementVector3D, 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> xyz(v.Vect()); + xyz = operator()(xyz); + LorentzVector> 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> xyz(v); + DisplacementVector3D> 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 ROOT_MATH_ARCH +} // 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..8e35db2f1e862 --- /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 ROOT_MATH_ARCH +} // 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..68ded3ad38519 --- /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 ROOT_MATH_ARCH +} // 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..a97dea16db64e --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Transform3D.h @@ -0,0 +1,1330 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH + +} // 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..96525590f2b1d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/Translation3D.h @@ -0,0 +1,314 @@ +// @(#)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; + +} // namespace ROOT_MATH_ARCH + +} // 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..cfa10bb78bdb0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/VectorUtil.h @@ -0,0 +1,527 @@ +// @(#)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); + +} // namespace VectorUtil + +} // namespace ROOT_MATH_ARCH + +} // 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..b6df4fe0c32b5 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/eta.h @@ -0,0 +1,99 @@ +// @(#)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..1e8a789be58de --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/GenVectorX/etaMax.h @@ -0,0 +1,64 @@ +// @(#)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..f180f59a3ab67 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector.h @@ -0,0 +1,704 @@ +// @(#)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 < double> + ; +#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 < double> + ; +#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 < double> + ; +#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 < double> + ; +#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 < double> + ; +#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 < double> + ; +#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 < ROOT::Math::Cartesian2D < double>> + ; +#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 < ROOT::Math::Polar2D < double>> + ; +#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 < ROOT::Math::Cartesian2D < double>> + ; +#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 < ROOT::Math::Polar2D < double>> + ; +#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 < ROOT::Math::Cartesian3D < double>> + ; +#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 < ROOT::Math::Polar3D < double>> + ; +#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 < ROOT::Math::Cylindrical3D < double>> + ; +#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 < ROOT::Math::CylindricalEta3D < double>> + ; +#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 < ROOT::Math::Cartesian3D < double>> + ; +#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 < ROOT::Math::Polar3D < double>> + ; +#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 < ROOT::Math::Cylindrical3D < double>> + ; +#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 < ROOT::Math::CylindricalEta3D < double>> + ; +#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::Cartesian3D < double>, \ + 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::Polar3D < double>, \ + 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::Cylindrical3D < double>, \ + 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::CylindricalEta3D < double>, \ + 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::Cartesian3D < double>, \ + 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::Polar3D < double>, \ + 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::Cylindrical3D < double>, \ + 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::CylindricalEta3D < double>, \ + 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 < double> + ; +#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 < double> + ; +#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 < double> + ; +#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 < double> + ; +#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 < ROOT::Math::PxPyPzE4D < double>> + ; +#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 < ROOT::Math::PtEtaPhiE4D < double>> + ; +#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 < ROOT::Math::PxPyPzM4D < double>> + ; +#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 < ROOT::Math::PtEtaPhiM4D < double>> + ; +#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 < float> + ; +#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 < float> + ; +#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 < float> + ; +#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 < float> + ; +#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 < float> + ; +#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 < float> + ; +#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 < ROOT::Math::Cartesian2D < float>> + ; +#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 < ROOT::Math::Polar2D < float>> + ; +#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 < ROOT::Math::Cartesian2D < float>> + ; +#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 < ROOT::Math::Polar2D < float>> + ; +#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 < ROOT::Math::Cartesian3D < float>> + ; +#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 < ROOT::Math::Polar3D < float>> + ; +#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 < ROOT::Math::Cylindrical3D < float>> + ; +#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 < ROOT::Math::CylindricalEta3D < float>> + ; +#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 < ROOT::Math::Cartesian3D < float>> + ; +#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 < ROOT::Math::Polar3D < float>> + ; +#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 < ROOT::Math::Cylindrical3D < float>> + ; +#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 < ROOT::Math::CylindricalEta3D < float>> + ; +#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::Cartesian3D < float>, \ + 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::Polar3D < float>, \ + 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::Cylindrical3D < float>, \ + 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::CylindricalEta3D < float>, \ + 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::Cartesian3D < float>, \ + 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::Polar3D < float>, \ + 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::Cylindrical3D < float>, \ + 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::CylindricalEta3D < float>, \ + 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 < float> + ; +#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 < float> + ; +#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 < float> + ; +#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 < float> + ; +#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 < ROOT::Math::PxPyPzE4D < float>> + ; +#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 < ROOT::Math::PtEtaPhiE4D < float>> + ; +#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 < ROOT::Math::PxPyPzM4D < float>> + ; +#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 < ROOT::Math::PtEtaPhiM4D < float>> + ; +#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..1e91fcbf000b5 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector2.h @@ -0,0 +1,24 @@ +// 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 < ROOT::Math::XYZTVector> + ; +#pragma link C++ class std::vector < ROOT::Math::PtEtaPhiEVector> + ; +#endif + +#pragma link C++ class std::vector < ROOT::Math::XYZVector> + ; +#pragma link C++ class std::vector < ROOT::Math::XYZPoint> + ; + +#pragma link C++ class std::vector < ROOT::Math::RhoEtaPhiVector> + ; +#pragma link C++ class std::vector < ROOT::Math::RhoEtaPhiPoint> + ; + +// for floating types + +#pragma link C++ class std::vector < ROOT::Math::XYZVectorF> + ; +#pragma link C++ class std::vector < ROOT::Math::XYZPointF> + ; +#pragma link C++ class std::vector < ROOT::Math::XYZTVectorF> + ; 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..594734d8dfe87 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVector32.h @@ -0,0 +1,353 @@ +// @(#)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 < Double32_t> + ; +#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 < Double32_t> + ; +#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 < ROOT::Math::Cartesian2D < Double32_t>> + ; +#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 < ROOT::Math::Polar2D < Double32_t>> + ; +#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 < Double32_t> + ; +#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 < Double32_t> + ; +#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 < Double32_t> + ; +#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 < Double32_t> + ; +#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 < ROOT::Math::Cartesian3D < Double32_t>> + ; +#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 < ROOT::Math::CylindricalEta3D < Double32_t>> + ; +#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 < ROOT::Math::Polar3D < Double32_t>> + ; +#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 < ROOT::Math::Cylindrical3D < Double32_t>> + ; +#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 < ROOT::Math::Cartesian3D < Double32_t>> + ; +#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 < ROOT::Math::CylindricalEta3D < Double32_t>> + ; +#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 < ROOT::Math::Polar3D < Double32_t>> + ; +#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 < ROOT::Math::Cylindrical3D < Double32_t>> + ; +#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::Cartesian3D < Double32_t>, \ + 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::CylindricalEta3D < Double32_t>, \ + 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::Cartesian3D < Double32_t>, \ + 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::CylindricalEta3D < Double32_t>, \ + 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::Cartesian3D < Double32_t>, \ + 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::CylindricalEta3D < Double32_t>, \ + 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::Cartesian3D < Double32_t>, \ + 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::CylindricalEta3D < Double32_t>, \ + 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::Cartesian3D < Double32_t>, \ + 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::CylindricalEta3D < Double32_t>, \ + 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::Cartesian3D < Double32_t>, \ + 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::CylindricalEta3D < Double32_t>, \ + 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 < Double32_t> + ; +#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 < Double32_t> + ; +#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 < Double32_t> + ; +#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 < Double32_t> + ; +#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 < ROOT::Math::PxPyPzE4D < Double32_t>> + ; +#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 < ROOT::Math::PtEtaPhiE4D < Double32_t>> + ; +#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 < ROOT::Math::PtEtaPhiM4D < Double32_t>> + ; +#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 < ROOT::Math::PxPyPzM4D < Double32_t>> + ; +#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..970ae2cf01d21 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LinkDef_GenVectorAll.h @@ -0,0 +1,2 @@ +#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..3423e5b287511 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LorentzRotation.h @@ -0,0 +1,9 @@ +// @(#)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..8c9049df10ffc --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/LorentzVector.h @@ -0,0 +1,9 @@ +// @(#)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..0c23e597d2ac0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Plane3D.h @@ -0,0 +1,9 @@ +// @(#)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..69336413fdd4d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Point2D.h @@ -0,0 +1,17 @@ +// @(#)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..99c00a51ca7c3 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Point2Dfwd.h @@ -0,0 +1,65 @@ +// @(#)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, DefaultCoordinateSystemTag> XYPoint; +typedef XYPoint XYPointD; + +/** + 2D Point based on the cartesian coordinates x,y,z in single precision +*/ +typedef PositionVector2D, DefaultCoordinateSystemTag> XYPointF; + +/** + 2D Point based on the polar coordinates rho, theta, phi in double precision. +*/ +typedef PositionVector2D, DefaultCoordinateSystemTag> Polar2DPoint; +typedef Polar2DPoint Polar2DPointD; + +/** + 2D Point based on the polar coordinates rho, theta, phi in single precision. +*/ +typedef PositionVector2D, DefaultCoordinateSystemTag> Polar2DPointF; + +} // namespace ROOT_MATH_ARCH + +} // 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..57f750ae09685 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Point3D.h @@ -0,0 +1,19 @@ +// @(#)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..6cb635b4bf1c3 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Point3Dfwd.h @@ -0,0 +1,87 @@ +// @(#)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, DefaultCoordinateSystemTag> XYZPoint; + +/** + 3D Point based on the cartesian coordinates x,y,z in single precision +*/ +typedef PositionVector3D, DefaultCoordinateSystemTag> XYZPointF; +typedef XYZPoint XYZPointD; + +/** + 3D Point based on the eta based cylindrical coordinates rho, eta, phi in double precision. +*/ +typedef PositionVector3D, DefaultCoordinateSystemTag> RhoEtaPhiPoint; +/** + 3D Point based on the eta based cylindrical coordinates rho, eta, phi in single precision. +*/ +typedef PositionVector3D, DefaultCoordinateSystemTag> RhoEtaPhiPointF; +typedef RhoEtaPhiPoint RhoEtaPhiPointD; + +/** + 3D Point based on the polar coordinates rho, theta, phi in double precision. +*/ +typedef PositionVector3D, DefaultCoordinateSystemTag> Polar3DPoint; +/** + 3D Point based on the polar coordinates rho, theta, phi in single precision. +*/ +typedef PositionVector3D, DefaultCoordinateSystemTag> Polar3DPointF; +typedef Polar3DPoint Polar3DPointD; + +/** + 3D Point based on the cylindrical coordinates rho, z, phi in double precision. +*/ +typedef PositionVector3D, DefaultCoordinateSystemTag> RhoZPhiPoint; +/** + 3D Point based on the cylindrical coordinates rho, z, phi in single precision. +*/ +typedef PositionVector3D, DefaultCoordinateSystemTag> RhoZPhiPointF; +typedef RhoZPhiPoint RhoZPhiPointD; + +} // namespace ROOT_MATH_ARCH + +} // 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..3c0040637b46d --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Polar2D.h @@ -0,0 +1,9 @@ +// @(#)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..935cc512aa01c --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Polar3D.h @@ -0,0 +1,9 @@ +// @(#)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..5eecd396bccef --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PositionVector2D.h @@ -0,0 +1,9 @@ +// @(#)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..26c81cc947108 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PositionVector3D.h @@ -0,0 +1,9 @@ +// @(#)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..d0926fcc7074a --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PtEtaPhiE4D.h @@ -0,0 +1,9 @@ +// @(#)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..62e053d0386e1 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PtEtaPhiM4D.h @@ -0,0 +1,9 @@ +// @(#)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..448fdf0cc7ac6 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PxPyPzE4D.h @@ -0,0 +1,9 @@ +// @(#)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..b7e0fbc9a6092 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/PxPyPzM4D.h @@ -0,0 +1,9 @@ +// @(#)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..ebca1fc8fad93 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Quaternion.h @@ -0,0 +1,9 @@ +// @(#)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..3165e08f16f03 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Rotation3D.h @@ -0,0 +1,9 @@ +// @(#)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..0bbd25b4314eb --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/RotationX.h @@ -0,0 +1,9 @@ +// @(#)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..e954c941d4953 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/RotationY.h @@ -0,0 +1,9 @@ +// @(#)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..cc56ff8f41489 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/RotationZ.h @@ -0,0 +1,9 @@ +// @(#)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..080da83071975 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/RotationZYX.h @@ -0,0 +1,9 @@ +// @(#)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..7edef406d1486 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Transform3D.h @@ -0,0 +1,9 @@ +// @(#)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..ca44ca8e174db --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Translation3D.h @@ -0,0 +1,9 @@ +// @(#)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..e859da6300dc2 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector2Dfwd.h @@ -0,0 +1,79 @@ +// @(#)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, 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, 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, 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, DefaultCoordinateSystemTag> Polar2DVectorF; + +} // namespace ROOT_MATH_ARCH + +} // 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..1fd4a7b7b1546 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector3Dfwd.h @@ -0,0 +1,118 @@ +// @(#)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, 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, 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, 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, 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, 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, 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, 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, DefaultCoordinateSystemTag> RhoZPhiVectorF; +typedef RhoZPhiVector RhoZPhiVectorD; + +} // namespace ROOT_MATH_ARCH + +} // 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..3845e6158078c --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector4D.h @@ -0,0 +1,22 @@ +// @(#)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..97f7bd10ea2a0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/Vector4Dfwd.h @@ -0,0 +1,100 @@ +// @(#)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> 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; + +} // namespace ROOT_MATH_ARCH + +} // 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..597247e7792c0 --- /dev/null +++ b/math/experimental/genvectorx/inc/MathX/VectorUtil.h @@ -0,0 +1,9 @@ +// @(#)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..2dbd89f92b224 --- /dev/null +++ b/math/experimental/genvectorx/src/3DConversions.cxx @@ -0,0 +1,746 @@ +// @(#)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> 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> 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> 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> 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> 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> 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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/3DDistances.cxx b/math/experimental/genvectorx/src/3DDistances.cxx new file mode 100644 index 0000000000000..a9ef4c16e6175 --- /dev/null +++ b/math/experimental/genvectorx/src/3DDistances.cxx @@ -0,0 +1,396 @@ +// @(#)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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/AxisAngle.cxx b/math/experimental/genvectorx/src/AxisAngle.cxx new file mode 100644 index 0000000000000..dd8f5f010b9a6 --- /dev/null +++ b/math/experimental/genvectorx/src/AxisAngle.cxx @@ -0,0 +1,108 @@ +// @(#)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> 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>( + 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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/AxisAngleXother.cxx b/math/experimental/genvectorx/src/AxisAngleXother.cxx new file mode 100644 index 0000000000000..2422f93b95b18 --- /dev/null +++ b/math/experimental/genvectorx/src/AxisAngleXother.cxx @@ -0,0 +1,237 @@ +// @(#)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> 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> 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> 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> 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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/BitReproducible.cxx b/math/experimental/genvectorx/src/BitReproducible.cxx new file mode 100644 index 0000000000000..fa71ec349bf47 --- /dev/null +++ b/math/experimental/genvectorx/src/BitReproducible.cxx @@ -0,0 +1,128 @@ +// @(#)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 ROOT_MATH_ARCH +} // 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..f4ed88c5ddc60 --- /dev/null +++ b/math/experimental/genvectorx/src/Boost.cxx @@ -0,0 +1,218 @@ +// @(#)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> Boost::BetaVector() const +{ + // get boost beta vector + Scalar gaminv = 1.0 / fM[kTT]; + return DisplacementVector3D>(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> 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> Boost::operator()(const LorentzVector> &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>( + 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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/BoostX.cxx b/math/experimental/genvectorx/src/BoostX.cxx new file mode 100644 index 0000000000000..22bc6d2fd7031 --- /dev/null +++ b/math/experimental/genvectorx/src/BoostX.cxx @@ -0,0 +1,137 @@ +// @(#)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> BoostX::BetaVector() const +{ + // return beta vector + return DisplacementVector3D>(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> BoostX::operator()(const LorentzVector> &v) const +{ + // apply boost to a LV + Scalar x = v.Px(); + Scalar t = v.E(); + return LorentzVector>(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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/BoostY.cxx b/math/experimental/genvectorx/src/BoostY.cxx new file mode 100644 index 0000000000000..d232a1c7afeb2 --- /dev/null +++ b/math/experimental/genvectorx/src/BoostY.cxx @@ -0,0 +1,137 @@ +// @(#)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> BoostY::BetaVector() const +{ + // return beta vector + return DisplacementVector3D>(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> BoostY::operator()(const LorentzVector> &v) const +{ + // apply boost to a LV + Scalar y = v.Py(); + Scalar t = v.E(); + return LorentzVector>(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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/BoostZ.cxx b/math/experimental/genvectorx/src/BoostZ.cxx new file mode 100644 index 0000000000000..32da06635364d --- /dev/null +++ b/math/experimental/genvectorx/src/BoostZ.cxx @@ -0,0 +1,137 @@ +// @(#)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> BoostZ::BetaVector() const +{ + // return beta vector + return DisplacementVector3D>(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> BoostZ::operator()(const LorentzVector> &v) const +{ + // apply boost to a LV + Scalar z = v.Pz(); + Scalar t = v.E(); + return LorentzVector>(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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/EulerAngles.cxx b/math/experimental/genvectorx/src/EulerAngles.cxx new file mode 100644 index 0000000000000..6a95dcdee46bd --- /dev/null +++ b/math/experimental/genvectorx/src/EulerAngles.cxx @@ -0,0 +1,149 @@ +// @(#)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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/LorentzRotation.cxx b/math/experimental/genvectorx/src/LorentzRotation.cxx new file mode 100644 index 0000000000000..c82eb8ac381ca --- /dev/null +++ b/math/experimental/genvectorx/src/LorentzRotation.cxx @@ -0,0 +1,312 @@ +// @(#)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> 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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/Quaternion.cxx b/math/experimental/genvectorx/src/Quaternion.cxx new file mode 100644 index 0000000000000..4c291a083f5b6 --- /dev/null +++ b/math/experimental/genvectorx/src/Quaternion.cxx @@ -0,0 +1,123 @@ +// @(#)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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/QuaternionXaxial.cxx b/math/experimental/genvectorx/src/QuaternionXaxial.cxx new file mode 100644 index 0000000000000..a52cc2319e34f --- /dev/null +++ b/math/experimental/genvectorx/src/QuaternionXaxial.cxx @@ -0,0 +1,72 @@ +// @(#)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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/Rotation3D.cxx b/math/experimental/genvectorx/src/Rotation3D.cxx new file mode 100644 index 0000000000000..ef62c98a2c39c --- /dev/null +++ b/math/experimental/genvectorx/src/Rotation3D.cxx @@ -0,0 +1,167 @@ +// @(#)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]; + for (size_t i = 0; i < 9; i++) { + mA[i] = fM[i]; + } + + 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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/Rotation3DxAxial.cxx b/math/experimental/genvectorx/src/Rotation3DxAxial.cxx new file mode 100644 index 0000000000000..a776494d80a60 --- /dev/null +++ b/math/experimental/genvectorx/src/Rotation3DxAxial.cxx @@ -0,0 +1,129 @@ +// @(#)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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/RotationZYX.cxx b/math/experimental/genvectorx/src/RotationZYX.cxx new file mode 100644 index 0000000000000..334b6c7cf0f02 --- /dev/null +++ b/math/experimental/genvectorx/src/RotationZYX.cxx @@ -0,0 +1,174 @@ +// @(#)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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/src/VectorUtil.cxx b/math/experimental/genvectorx/src/VectorUtil.cxx new file mode 100644 index 0000000000000..55927be34fe04 --- /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 ROOT_MATH_ARCH +} // namespace ROOT diff --git a/math/experimental/genvectorx/test/CMakeLists.txt b/math/experimental/genvectorx/test/CMakeLists.txt new file mode 100644 index 0000000000000..c6fbe4aa55952 --- /dev/null +++ b/math/experimental/genvectorx/test/CMakeLists.txt @@ -0,0 +1,21 @@ +# 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 Monica Dessole CERN + + + ROOT_EXECUTABLE(testGenvectorSYCL testGenVectorSYCL.cxx) # LIBRARIES GenVectorSYCL) + if (oneapi) + target_link_options(testGenvectorSYCL PUBLIC -E) + endif() + target_link_libraries(testGenvectorSYCL PUBLIC GenVectorSYCL ) + 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/testGenVectorSYCL.cxx b/math/experimental/genvectorx/test/testGenVectorSYCL.cxx new file mode 100644 index 0000000000000..9718322a396e0 --- /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::ROOT_MATH_ARCH::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 = rotZ * (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[0] |= 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() +{ + + int iret_host = 0; + std::cout << "testing 3D Transform\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([=]() { + EulerAngles r(1., 2., 3.); + + GlobalPolar3DVector v(1., 2., 3.); + GlobalXYZVector w(v); + + Transform3D t1(v); + GlobalXYZPoint pg; + t1.Transform(LocalXYZPoint(), pg); + iret[0] |= compare(pg.X(), v.X(), 10); + iret[0] |= compare(pg.Y(), v.Y(), 10); + iret[0] |= compare(pg.Z(), v.Z(), 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[0] |= compare(tr1 == tr2, 1, 1); +#else + // add a dummy test to have the same outputfile for roottest + // otherwise it will complain that the output is different ! + iret[0] |= compare(0, 0, 1); +#endif + + Translation3D tr3 = tr1 * tr1.Inverse(); + GlobalPolar3DVector vp2 = tr3 * v; + iret[0] |= compare(vp2.X(), v.X(), 10); + iret[0] |= compare(vp2.Y(), v.Y(), 10); + iret[0] |= compare(vp2.Z(), v.Z(), 10); + + Transform3D t2b = tr1 * Rotation3D(r); + // this above fails on Windows - use a comparison with tolerance + // 12 is size of Transform3D internal vector + iret[0] |= compare(IsEqual(t2, t2b, 12), true, 1); + // iret[0] |= compare(t2 ==t2b, 1,"eq1 transf",1 ); + Transform3D t2c(r, tr1); + iret[0] |= compare(IsEqual(t2, t2c, 12), true, 1); + // iret[0] |= compare(t2 ==t2c, 1,"eq2 transf",1 ); + + Transform3D t3 = Rotation3D(r) * Translation3D(vr); + + Rotation3D rrr; + XYZVector vvv; + t2b.GetDecomposition(rrr, vvv); + iret[0] |= compare(Rotation3D(r) == rrr, 1, 1); + iret[0] |= compare(tr1.Vect() == vvv, 1, 1); + // if (iret) std::cout << vvv << std::endl; + // if (iret) std::cout << Translation3D(vr) << std::endl; + + Translation3D ttt; + t2b.GetDecomposition(rrr, ttt); + iret[0] |= compare(tr1 == ttt, 1, 1); + // if (iret) std::cout << ttt << std::endl; + + EulerAngles err2; + GlobalPolar3DVector vvv2; + t2b.GetDecomposition(err2, vvv2); + iret[0] |= compare(r.Phi(), err2.Phi(), 4); + iret[0] |= compare(r.Theta(), err2.Theta(), 1); + iret[0] |= compare(r.Psi(), err2.Psi(), 1); + + // iret[0] |= compare( v == vvv2, 1,"eq transf g vec",1 ); + iret[0] |= compare(v.X(), vvv2.X(), 4); + iret[0] |= compare(v.Y(), vvv2.Y(), 1); + iret[0] |= compare(v.Z(), vvv2.Z(), 1); + + // create from other rotations + RotationZYX rzyx(r); + Transform3D t4(rzyx); + iret[0] |= compare(t4.Rotation() == Rotation3D(rzyx), 1, 1); + + Transform3D trf2 = tr1 * r; + iret[0] |= compare(trf2 == t2b, 1, 1); + Transform3D trf3 = r * Translation3D(vr); + // iret[0] |= compare( trf3 == t3, 1,"e rot * transl",1 ); + // this above fails on i686-slc5-gcc43-opt - use a comparison with tolerance + iret[0] |= compare(IsEqual(trf3, t3, 12), true, 1); + + Transform3D t5(rzyx, v); + Transform3D trf5 = Translation3D(v) * rzyx; + // iret[0] |= compare( trf5 == t5, 1,"trasl * rzyx",1 ); + iret[0] |= compare(IsEqual(trf5, t5, 12), true, 1); + + Transform3D t6(rzyx, rzyx * Translation3D(v).Vect()); + Transform3D trf6 = rzyx * Translation3D(v); + iret[0] |= compare(trf6 == t6, 1, 1); + // if (iret) + // std::cout << t6 << "\n---\n" << trf6 << std::endl; + + Transform3D trf7 = t4 * Translation3D(v); + // iret[0] |= compare( trf7 == trf6, 1,"tranf * transl",1 ); + iret[0] |= compare(IsEqual(trf7, trf6, 12), true, 1); + Transform3D trf8 = Translation3D(v) * t4; + iret[0] |= compare(trf8 == trf5, 1, 1); + + Transform3D trf9 = Transform3D(v) * rzyx; + iret[0] |= compare(trf9 == trf5, 1, 1); + Transform3D trf10 = rzyx * Transform3D(v); + iret[0] |= compare(trf10 == trf6, 1, 1); + Transform3D trf11 = Rotation3D(rzyx) * Transform3D(v); + iret[0] |= compare(trf11 == trf10, 1, 1); + + RotationZYX rrr2 = trf10.Rotation(); + // iret[0] |= compare( rzyx == rrr2, 1,"gen Rotation()",1 ); + iret[0] |= compare(rzyx.Phi(), rrr2.Phi(), 1); + iret[0] |= compare(rzyx.Theta(), rrr2.Theta(), 10); + iret[0] |= compare(rzyx.Psi(), rrr2.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[0] |= compare(p3.X(), p2.X(), 10); + iret[0] |= compare(p3.Y(), p2.Y(), 10); + iret[0] |= compare(p3.Z(), p2.Z(), 10); + + GlobalXYZVector v1(1., 2., 3.); + LocalXYZVector v2; + t2.Transform(v1, v2); + GlobalPolar3DVector v3; + t3.Transform(GlobalPolar3DVector(v1), v3); + + iret[0] |= compare(v3.X(), v2.X(), 10); + iret[0] |= compare(v3.Y(), v2.Y(), 10); + iret[0] |= compare(v3.Z(), v2.Z(), 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[0] |= compare(qt3.X(), qt4.X(), 10); + iret[0] |= compare(qt3.Y(), qt4.Y(), 10); + iret[0] |= compare(qt3.Z(), qt4.Z(), 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; + + { + // 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[0] |= compare(r0.X(), point.X(), 100); + iret[0] |= compare(r0_2.X(), point.X(), 100); + iret[0] |= compare(r0.Y(), point.Y(), 10); + iret[0] |= compare(r0_2.Y(), point.Y(), 10); + iret[0] |= compare(r0.Z(), point.Z(), 10); + iret[0] |= compare(r0_2.Z(), point.Z(), 10); + + // compare ApplyInverse with Inverse() + auto r1 = tr.ApplyInverse(point); + auto r2 = tr.Inverse()(point); + iret[0] |= compare(r1.X(), r2.X(), 10); + iret[0] |= compare(r1.Y(), r2.Y(), 10); + iret[0] |= compare(r1.Z(), r2.Z(), 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[0] |= compare(r1.X(), r2.X(), 10); + iret[0] |= compare(r1.Y(), r2.Y(), 10); + iret[0] |= compare(r1.Z(), r2.Z(), 10); + } + }); + }); + } + + if (iret_host == 0) + std::cout << "\tOK\n"; + else + std::cout << "\t FAILED\n"; + + return iret_host; +} + +int testVectorUtil() +{ + int iret_host = 0; + std::cout << "testing VectorUtil \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 new perp functions + XYZVector v(1., 2., 3.); + + XYZVector vx = ProjVector(v, XYZVector(3, 0, 0)); + iret[0] |= compare(vx.X(), v.X(), 1); + iret[0] |= compare(vx.Y(), 0, 1); + iret[0] |= compare(vx.Z(), 0, 1); + + XYZVector vpx = PerpVector(v, XYZVector(2, 0, 0)); + iret[0] |= compare(vpx.X(), 0, 1); + iret[0] |= compare(vpx.Y(), v.Y(), 1); + iret[0] |= compare(vpx.Z(), v.Z(), 1); + + double perpy = Perp(v, XYZVector(0, 2, 0)); + iret[0] |= compare(perpy, std::sqrt(v.Mag2() - v.y() * v.y())); + + XYZPoint u(1, 1, 1); + XYZPoint un = u / u.R(); + + XYZVector vl = ProjVector(v, u); + XYZVector vl2 = XYZVector(un) * (v.Dot(un)); + + iret[0] |= compare(vl.X(), vl2.X(), 1); + iret[0] |= compare(vl.Y(), vl2.Y(), 1); + iret[0] |= compare(vl.Z(), vl2.Z(), 1); + + XYZVector vp = PerpVector(v, u); + XYZVector vp2 = v - XYZVector(un * (v.Dot(un))); + iret[0] |= compare(vp.X(), vp2.X(), 10); + iret[0] |= compare(vp.Y(), vp2.Y(), 10); + iret[0] |= compare(vp.Z(), vp2.Z(), 10); + + double perp = Perp(v, u); + iret[0] |= compare(perp, vp.R(), 1); + double perp2 = Perp2(v, u); + iret[0] |= compare(perp2, vp.Mag2(), 1); + + // test rotations + double angle = 1; + XYZVector vr1 = RotateX(v, angle); + XYZVector vr2 = RotationX(angle) * v; + iret[0] |= compare(vr1.Y(), vr2.Y(), 1); + iret[0] |= compare(vr1.Z(), vr2.Z(), 1); + + vr1 = RotateY(v, angle); + vr2 = RotationY(angle) * v; + iret[0] |= compare(vr1.X(), vr2.X(), 1); + iret[0] |= compare(vr1.Z(), vr2.Z(), 1); + + vr1 = RotateZ(v, angle); + vr2 = RotationZ(angle) * v; + iret[0] |= compare(vr1.X(), vr2.X(), 1); + iret[0] |= compare(vr1.Y(), vr2.Y(), 1); + }); + }); + } + + if (iret_host == 0) + std::cout << "\tOK\n"; + else + std::cout << "\t FAILED\n"; + + return iret_host; +} + +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; +}