Skip to content

Commit

Permalink
feat: add 4 dimensional vector object (#248)
Browse files Browse the repository at this point in the history
  • Loading branch information
osbornjd authored Jan 8, 2024
1 parent ca6396f commit 65547db
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 30 deletions.
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,30 @@ A generic event data model for future HEP collider experiments.

| | | |
|-|-|-|
| [Vector3f](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L11) | [Vector3d](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L26) | [Vector2i](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L42) |
| [Vector2f](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L56) | [TrackState](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L70) | [ObjectID](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L93) |
| [Quantity](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L105) | [Hypothesis](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L113) | [HitLevelData](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L120) |
| [Vector4f](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L9) | [Vector3f](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L26) | [Vector3d](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L41) | [Vector2i](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L57) |
| [Vector2f](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L71) | [TrackState](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L85) | [ObjectID](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L108) |
| [Quantity](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L120) | [Hypothesis](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L128) | [HitLevelData](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L135) |


**Datatypes**

| | | |
|-|-|-|
| [EventHeader](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L130) | [MCParticle](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L140) | [SimTrackerHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L209) |
| [CaloHitContribution](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L243) | [SimCalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L255) | [RawCalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L267) |
| [CalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L276) | [ParticleID](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L288) | [Cluster](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L301) |
| [TrackerHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L322) | [TrackerHitPlane](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L339) | [RawTimeSeries](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L360) |
| [Track](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L373) | [Vertex](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L392) | [ReconstructedParticle](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L409) |
| [SimPrimaryIonizationCluster](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L513) | [TrackerPulse](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L531) | [RecIonizationCluster](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L544) |
| [TimeSeries](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L555) | [RecDqdx](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L567) | |
| [EventHeader](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L145) | [MCParticle](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L155) | [SimTrackerHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L224) |
| [CaloHitContribution](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L258) | [SimCalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L270) | [RawCalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L282) |
| [CalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L291) | [ParticleID](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L303) | [Cluster](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L316) |
| [TrackerHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L337) | [TrackerHitPlane](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L354) | [RawTimeSeries](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L375) |
| [Track](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L388) | [Vertex](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L407) | [ReconstructedParticle](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L424) |
| [SimPrimaryIonizationCluster](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L528) | [TrackerPulse](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L546) | [RecIonizationCluster](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L559) |
| [TimeSeries](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L570) | [RecDqdx](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L582) | |

**Associations**

| | | |
|-|-|-|
| [MCRecoParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L439) | [MCRecoCaloAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L448) | [MCRecoTrackerAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L457) |
| [MCRecoTrackerHitPlaneAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L466) | [MCRecoCaloParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L475) | [MCRecoClusterParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L484) |
| [MCRecoTrackParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L493) | [RecoParticleVertexAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L502) | |
| [MCRecoParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L454) | [MCRecoCaloAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L463) | [MCRecoTrackerAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L472) |
| [MCRecoTrackerHitPlaneAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L481) | [MCRecoCaloParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L490) | [MCRecoClusterParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L499) |
| [MCRecoTrackParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L508) | [RecoParticleVertexAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L517) | |

The tests and examples in the `tests` directory show how to read, write, and use these types in your code.

Expand Down
15 changes: 15 additions & 0 deletions edm4hep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ options:
includeSubfolder: True

components:
edm4hep::Vector4f:
Description: "Generic vector for storing classical 4D coordinates in memory. Four momentum helper functions are in edm4hep::utils"
Members:
- float x
- float y
- float z
- float t
ExtraCode:
declaration: "
constexpr Vector4f() : x(0),y(0),z(0),t(0) {}\n
constexpr Vector4f(float xx, float yy, float zz, float tt) : x(xx),y(yy),z(zz),t(tt) {}\n
constexpr Vector4f(const float* v) : x(v[0]),y(v[1]),z(v[2]),t(v[3]) {}\n
constexpr bool operator==(const Vector4f& v) const { return (x==v.x&&y==v.y&&z==v.z&&t==v.t) ; }\n
constexpr float operator[](unsigned i) const { return *( &x + i ) ; }\n
"

# Vector3D with floats
edm4hep::Vector3f:
Expand Down
20 changes: 16 additions & 4 deletions test/utils/test_vector_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@
#include "edm4hep/Vector2i.h"
#include "edm4hep/Vector3d.h"
#include "edm4hep/Vector3f.h"
#include "edm4hep/Vector4f.h"

#include <tuple>
#include <type_traits>

using AllVectorTypes = std::tuple<edm4hep::Vector3f, edm4hep::Vector3d, edm4hep::Vector2i, edm4hep::Vector2f>;
using Vector2And3Types = std::tuple<edm4hep::Vector3f, edm4hep::Vector3d, edm4hep::Vector2i, edm4hep::Vector2f>;
using AllVectorTypes =
std::tuple<edm4hep::Vector4f, edm4hep::Vector3f, edm4hep::Vector3d, edm4hep::Vector2i, edm4hep::Vector2f>;

template <typename V>
constexpr V create();

template <>
constexpr edm4hep::Vector4f create() {
return edm4hep::Vector4f{1.0f, 2.0f, 3.0f, 4.0f};
}

template <>
constexpr edm4hep::Vector3f create() {
return edm4hep::Vector3f{1.0f, 2.0f, 3.0f};
Expand Down Expand Up @@ -47,6 +54,8 @@ TEMPLATE_LIST_TEST_CASE("Vector uniform getters", "[vector_utils]", AllVectorTyp
// 2D vectors fill z component with 0
if constexpr (std::is_same_v<TestType, edm4hep::Vector2i> || std::is_same_v<TestType, edm4hep::Vector2f>) {
STATIC_REQUIRE(utils::vector_z(vector) == utils::ValueType<TestType>(0.0));
} else if constexpr (std::is_same_v<TestType, edm4hep::Vector4f>) {
STATIC_REQUIRE(utils::vector_t(vector) == utils::ValueType<TestType>(4.0));
} else {
STATIC_REQUIRE(utils::vector_z(vector) == utils::ValueType<TestType>(3.0));
}
Expand All @@ -58,6 +67,7 @@ TEST_CASE("Vector ValueType", "[vector_utils]") {
STATIC_REQUIRE(std::is_same_v<float, utils::ValueType<Vector2f>>);
STATIC_REQUIRE(std::is_same_v<float, utils::ValueType<Vector3f>>);
STATIC_REQUIRE(std::is_same_v<double, utils::ValueType<Vector3d>>);
STATIC_REQUIRE(std::is_same_v<float, utils::ValueType<Vector4f>>);
}

TEMPLATE_LIST_TEST_CASE("Vector operators", "[vector_utils]", AllVectorTypes) {
Expand All @@ -78,12 +88,14 @@ TEMPLATE_LIST_TEST_CASE("Vector operators", "[vector_utils]", AllVectorTypes) {
// Vector product (depends again on whether it is 2D or 3D)
if constexpr (std::is_same_v<TestType, edm4hep::Vector2i> || std::is_same_v<TestType, edm4hep::Vector2f>) {
STATIC_REQUIRE(vector1 * vector2 == utils::ValueType<TestType>(5));
} else {
} else if constexpr (std::is_same_v<TestType, edm4hep::Vector3f> || std::is_same_v<TestType, edm4hep::Vector3d>) {
STATIC_REQUIRE(vector1 * vector2 == utils::ValueType<TestType>(14));
} else {
STATIC_REQUIRE(vector1 * vector2 == utils::ValueType<TestType>(-2));
}
}

TEMPLATE_LIST_TEST_CASE("Vector utility functionality", "[vector_utils]", AllVectorTypes) {
TEMPLATE_LIST_TEST_CASE("Vector utility functionality", "[vector_utils]", Vector2And3Types) {
const auto vector = create<TestType>();

using namespace edm4hep;
Expand Down
83 changes: 70 additions & 13 deletions utils/include/edm4hep/utils/vector_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ concept VectorHasZ = requires(V v) {
v.z;
};

template <class V>
concept VectorHasT = requires(V v) {
v.t;
};

template <class V>
concept VectorHasA = requires(V v) {
v.a;
Expand All @@ -44,22 +49,28 @@ concept ClassVector = requires(V v) {
};

template <class V>
concept Vector2D_XY = VectorHasX<V> && VectorHasY<V> && !VectorHasZ<V> && !ClassVector<V>;
concept Vector2D_XY = VectorHasX<V> && VectorHasY<V> && !VectorHasZ<V> && !VectorHasT<V> && !ClassVector<V>;

template <class V>
concept Vector2D_AB = VectorHasA<V> && VectorHasB<V> && !VectorHasZ<V> && !ClassVector<V>;
concept Vector2D_AB = VectorHasA<V> && VectorHasB<V> && !VectorHasZ<V> && !VectorHasT<V> && !ClassVector<V>;

template <class V>
concept Vector2D = Vector2D_XY<V> || Vector2D_AB<V>;

template <class V>
concept Vector3D = VectorHasX<V> && VectorHasY<V> && VectorHasZ<V> && !ClassVector<V>;
concept Vector3D = VectorHasX<V> && VectorHasY<V> && VectorHasZ<V> && !VectorHasT<V> && !ClassVector<V>;

template <class V>
concept Vector4D = VectorHasX<V> && VectorHasY<V> && VectorHasZ<V> && VectorHasT<V> && !ClassVector<V>;

template <class V>
concept Vector2or3D = Vector2D<V> || Vector3D<V>;

template <class V>
concept VectorND = Vector2D<V> || Vector3D<V>;
concept VectorND = Vector2D<V> || Vector3D<V> || Vector4D<V>;

template <class V>
concept VectorND_XYZ = Vector2D_XY<V> || Vector3D<V>;
concept VectorND_XYZ = Vector2D_XY<V> || Vector3D<V> || Vector4D<V>;

namespace utils {
// Utility getters to accomodate different vector types
Expand All @@ -73,11 +84,31 @@ namespace utils {
return v.y;
}

template <Vector2D V>
constexpr auto vector_z(const V&) {
return 0;
}

template <Vector3D V>
constexpr auto vector_z(const V& v) {
return v.z;
}

template <Vector4D V>
constexpr auto vector_z(const V& v) {
return v.z;
}

template <Vector4D V>
constexpr auto vector_t(const V& v) {
return v.t;
}

template <Vector2or3D V>
constexpr auto vector_t(const V&) {
return 0;
}

template <Vector2D_AB V>
constexpr auto vector_x(const V& v) {
return v.a;
Expand All @@ -88,11 +119,6 @@ namespace utils {
return v.b;
}

template <Vector2D V>
constexpr auto vector_z(const V&) {
return 0;
}

namespace detail {
/// Helper struct to determine the underlying type of edm4hep vector types
template <typename V>
Expand Down Expand Up @@ -153,11 +179,16 @@ namespace utils {
return angleToEta(anglePolar(v));
}

template <VectorND V>
template <Vector2or3D V>
double magnitude(const V& v) {
return std::hypot(vector_x(v), vector_y(v), vector_z(v));
}

template <Vector4D V>
double magnitude(const V& v) {
return std::hypot(vector_x(v), vector_y(v), vector_z(v)) - vector_t(v) * vector_t(v);
}

template <Vector3D V>
double magnitudeTransverse(const V& v) {
return std::hypot(vector_x(v), vector_y(v));
Expand Down Expand Up @@ -188,7 +219,7 @@ namespace utils {
}

// Two vector functions
template <VectorND V>
template <Vector2or3D V>
double angleBetween(const V& v1, const V& v2) {
const double dot = v1 * v2;
if (dot == 0) {
Expand All @@ -198,7 +229,7 @@ namespace utils {
}

// Project v onto v1
template <VectorND V>
template <Vector2or3D V>
double projection(const V& v, const V& v1) {
const double norm = magnitude(v1);
if (norm == 0) {
Expand All @@ -222,6 +253,14 @@ inline constexpr V operator+(const V& v1, const V& v2) {
edm4hep::utils::vector_z(v1) + edm4hep::utils::vector_z(v2)};
}

template <edm4hep::Vector4D V>
inline constexpr V operator+(const V& v1, const V& v2) {
return {edm4hep::utils::vector_x(v1) + edm4hep::utils::vector_x(v2),
edm4hep::utils::vector_y(v1) + edm4hep::utils::vector_y(v2),
edm4hep::utils::vector_z(v1) + edm4hep::utils::vector_z(v2),
edm4hep::utils::vector_t(v1) + edm4hep::utils::vector_t(v2)};
}

template <edm4hep::Vector2D V>
inline constexpr auto operator*(const V& v1, const V& v2) {
return edm4hep::utils::vector_x(v1) * edm4hep::utils::vector_x(v2) +
Expand All @@ -235,6 +274,14 @@ inline constexpr auto operator*(const V& v1, const V& v2) {
edm4hep::utils::vector_z(v1) * edm4hep::utils::vector_z(v2);
}

template <edm4hep::Vector4D V>
inline constexpr auto operator*(const V& v1, const V& v2) {
return (edm4hep::utils::vector_x(v1) * edm4hep::utils::vector_x(v2) +
edm4hep::utils::vector_y(v1) * edm4hep::utils::vector_y(v2) +
edm4hep::utils::vector_z(v1) * edm4hep::utils::vector_z(v2)) -
edm4hep::utils::vector_t(v1) * edm4hep::utils::vector_t(v2);
}

template <edm4hep::Vector2D V>
inline constexpr V operator*(const double d, const V& v) {
using VT = edm4hep::utils::ValueType<V>;
Expand All @@ -252,6 +299,16 @@ inline constexpr V operator*(const double d, const V& v) {
return {x, y, z};
}

template <edm4hep::Vector4D V>
inline constexpr V operator*(const double d, const V& v) {
using VT = edm4hep::utils::ValueType<V>;
const VT x = d * edm4hep::utils::vector_x(v);
const VT y = d * edm4hep::utils::vector_y(v);
const VT z = d * edm4hep::utils::vector_z(v);
const VT t = d * edm4hep::utils::vector_t(v);
return {x, y, z, t};
}

template <edm4hep::VectorND V>
inline constexpr V operator*(const V& v, const double d) {
return d * v;
Expand Down
36 changes: 36 additions & 0 deletions utils/include/edm4hep/utils/vector_utils_legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <edm4hep/Vector2i.h>
#include <edm4hep/Vector3d.h>
#include <edm4hep/Vector3f.h>
#include <edm4hep/Vector4f.h>

#include <cmath>
#include <tuple>
Expand Down Expand Up @@ -44,6 +45,11 @@ namespace utils {
return v.z;
}

template <class V>
constexpr auto vector_t(const V& v) {
return v.t;
}

// 2D vector uses a,b instead of x,y
template <>
inline constexpr auto vector_x<edm4hep::Vector2i>(const edm4hep::Vector2i& v) {
Expand Down Expand Up @@ -98,6 +104,7 @@ namespace utils {
using ValueType = typename detail::ValueTypeHelper<V>::type;

using EDM4hepVectorTypes = std::tuple<edm4hep::Vector3f, edm4hep::Vector3d, edm4hep::Vector2i, edm4hep::Vector2f>;
using EDM4hepVector4DTypes = std::tuple<edm4hep::Vector4f>;
using EDM4hepVector3DTypes = std::tuple<edm4hep::Vector3f, edm4hep::Vector3d>;
using EDM4hepVector2DTypes = std::tuple<edm4hep::Vector2f, edm4hep::Vector2i>;
using EDM4hepFloatVectorTypes = std::tuple<edm4hep::Vector2f, edm4hep::Vector3f, edm4hep::Vector3d>;
Expand All @@ -111,6 +118,8 @@ namespace utils {
template <typename V>
using EnableIfEDM4hepVector3DType = std::enable_if_t<detail::isInTuple<V, EDM4hepVector3DTypes>, bool>;

template <typename V>
using EnableIfEdm4hepVector4DType = std::enable_if_t<detail::isInTuple<V, EDM4hepVector4DTypes>, bool>;
template <typename V>
using EnableIfEDM4hepFloatVectorType = std::enable_if_t<detail::isInTuple<V, EDM4hepFloatVectorTypes>, bool>;

Expand Down Expand Up @@ -218,6 +227,15 @@ inline constexpr V operator+(const V& v1, const V& v2) {
return {x, y, z};
}

template <typename V, edm4hep::utils::EnableIfEdm4hepVector4DType<V> = false>
inline constexpr V operator+(const V& v1, const V& v2) {
const auto x = edm4hep::utils::vector_x(v1) + edm4hep::utils::vector_x(v2);
const auto y = edm4hep::utils::vector_y(v1) + edm4hep::utils::vector_y(v2);
const auto z = edm4hep::utils::vector_z(v1) + edm4hep::utils::vector_z(v2);
const auto t = edm4hep::utils::vector_t(v1) + edm4hep::utils::vector_t(v2);
return {x, y, z, t};
}

template <typename V, edm4hep::utils::EnableIfEDM4hepVector2DType<V> = false>
inline constexpr double operator*(const V& v1, const V& v2) {
return edm4hep::utils::vector_x(v1) * edm4hep::utils::vector_x(v2) +
Expand All @@ -231,6 +249,14 @@ inline constexpr double operator*(const V& v1, const V& v2) {
edm4hep::utils::vector_z(v1) * edm4hep::utils::vector_z(v2);
}

template <typename V, edm4hep::utils::EnableIfEdm4hepVector4DType<V> = false>
inline constexpr double operator*(const V& v1, const V& v2) {
return (edm4hep::utils::vector_x(v1) * edm4hep::utils::vector_x(v2) +
edm4hep::utils::vector_y(v1) * edm4hep::utils::vector_y(v2) +
edm4hep::utils::vector_z(v1) * edm4hep::utils::vector_z(v2)) -
edm4hep::utils::vector_t(v1) * edm4hep::utils::vector_t(v2);
}

template <typename V, edm4hep::utils::EnableIfEDM4hepVector2DType<V> = false>
inline constexpr V operator*(const double d, const V& v) {
using VT = edm4hep::utils::ValueType<V>;
Expand All @@ -248,6 +274,16 @@ inline constexpr V operator*(const double d, const V& v) {
return {x, y, z};
}

template <typename V, edm4hep::utils::EnableIfEdm4hepVector4DType<V> = false>
inline constexpr V operator*(const double d, const V& v) {
using VT = edm4hep::utils::ValueType<V>;
const VT x = d * edm4hep::utils::vector_x(v);
const VT y = d * edm4hep::utils::vector_y(v);
const VT z = d * edm4hep::utils::vector_z(v);
const VT t = d * edm4hep::utils::vector_t(v);
return {x, y, z, t};
}

template <typename V>
inline constexpr V operator*(const V& v, const double d) {
return d * v;
Expand Down

0 comments on commit 65547db

Please sign in to comment.