LCOV - code coverage report
Current view: top level - core/include/scipp/core/element - to_unit.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 19 22 86.4 %
Date: 2024-04-28 01:25:40 Functions: 19 23 82.6 %

          Line data    Source code
       1             : // SPDX-License-Identifier: BSD-3-Clause
       2             : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
       3             : /// @file
       4             : /// @author Simon Heybrock
       5             : #pragma once
       6             : 
       7             : #include <cmath>
       8             : #include <limits>
       9             : 
      10             : #include "scipp/common/overloaded.h"
      11             : #include "scipp/core/eigen.h"
      12             : #include "scipp/core/element/arg_list.h"
      13             : #include "scipp/core/time_point.h"
      14             : #include "scipp/core/transform_common.h"
      15             : 
      16             : namespace scipp::core::element {
      17             : 
      18             : namespace {
      19             : 
      20             : // Source: https://stackoverflow.com/a/26584177/1458281
      21         236 : template <class T, class U> T safe_cast(const U x) {
      22         236 :   if (std::isnan(x))
      23           0 :     return std::numeric_limits<T>::min(); // behavior as numpy
      24             :   int exp;
      25         236 :   std::frexp(x, &exp);
      26         236 :   if (std::isfinite(x) && exp <= 8 * static_cast<int>(sizeof(T)) - 1)
      27         236 :     return x;
      28           0 :   return std::signbit(x) ? std::numeric_limits<T>::min()
      29           0 :                          : std::numeric_limits<T>::max();
      30             : }
      31             : 
      32             : template <class T>
      33        9357 : constexpr auto round = [](const auto x) {
      34             :   if constexpr (std::is_integral_v<T>)
      35         236 :     return safe_cast<T>(x < 0 ? x - 0.5 : x + 0.5);
      36             :   else
      37        9121 :     return static_cast<T>(x);
      38             : };
      39             : } // namespace
      40             : 
      41             : constexpr auto to_unit = overloaded{
      42             :     arg_list<double, std::tuple<float, double>, std::tuple<int64_t, double>,
      43             :              std::tuple<int64_t, int64_t>, std::tuple<int32_t, double>,
      44             :              std::tuple<time_point, double>, std::tuple<time_point, int64_t>,
      45             :              std::tuple<Eigen::Vector3d, double>,
      46             :              std::tuple<Eigen::Affine3d, double>,
      47             :              std::tuple<Translation, double>>,
      48             :     transform_flags::expect_no_variance_arg<1>,
      49        9144 :     [](const units::Unit &, const units::Unit &target) { return target; },
      50         210 :     [](const time_point &x, const auto &scale) {
      51         210 :       return time_point{round<int64_t>(x.time_since_epoch() * scale)};
      52             :     },
      53           1 :     [](const Eigen::Affine3d &x, const auto &scale) {
      54           1 :       auto out = x;
      55           1 :       out.translation() *= scale;
      56           1 :       return out;
      57             :     },
      58           1 :     [](const Translation &x, const auto &scale) {
      59           1 :       return Translation(x.vector() * scale);
      60             :     },
      61        9147 :     [](const auto &x, const auto &scale) {
      62        9147 :       return round<std::decay_t<decltype(x)>>(x * scale);
      63             :     }};
      64             : 
      65             : } // namespace scipp::core::element

Generated by: LCOV version 1.14