LCOV - code coverage report
Current view: top level - include/utils - RayTracingPackingUtils.h (source / functions) Hit Total Coverage
Test: idaholab/moose ray_tracing: #31405 (292dce) with base fef103 Lines: 28 28 100.0 %
Date: 2025-09-04 07:56:07 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include "libmesh/elem.h"
      13             : #include "libmesh/mesh_base.h"
      14             : 
      15             : namespace RayTracingPackingUtils
      16             : {
      17             : 
      18             : /**
      19             :  * Like std::copy, but passes the input iterator by reference
      20             :  */
      21             : template <class Cont, class InputIt>
      22             : void unpackCopy(Cont & container, InputIt & input_iterator);
      23             : 
      24             : /**
      25             :  * Packs the data in \p values into the iterator \p out and minimizes memory
      26             :  * storage in said iterator.
      27             :  *
      28             :  * In specific, ValueType is packed into BufferType at a byte level. That is,
      29             :  * if sizeof(ValueType) == 4 and sizeof(BufferType) == 8, two values of type ValueType
      30             :  * objects will be stored in a single value of type BufferType.
      31             :  */
      32             : template <typename BufferType, typename BufferIter, typename ValueType>
      33             : void reinterpretPackCopy(const std::vector<ValueType> & values, BufferIter & out);
      34             : 
      35             : /**
      36             :  * Packs the data from \p in into the vector \p values.
      37             :  *
      38             :  * \p values MUST be resized ahead of time in order to know how much to advance \p in.
      39             :  *
      40             :  * This is to be used in the unpacking of values stored by reinterpretPackCopy().
      41             :  */
      42             : template <typename BufferType, typename BufferIter, typename ValueType>
      43             : void reinterpretUnpackCopy(std::vector<ValueType> & values, BufferIter & in);
      44             : 
      45             : /**
      46             :  * Gets the minimum number of values of BufferType needed to represent
      47             :  * \p input_size values of ValueType
      48             :  *
      49             :  * To be used with sizing for reinterpretPackCopy() and reinterpretUnpackCopy().
      50             :  */
      51             : template <typename ValueType, typename BufferType>
      52             : std::size_t reinterpretCopySize(const std::size_t input_size);
      53             : 
      54             : /**
      55             :  * Unpacks the mixed-values from \p in into \p values that were packed with mixedPack().
      56             :  */
      57             : template <typename BufferType, typename BufferIter, typename... ValueTypes>
      58             : void mixedUnpack(BufferIter & in, ValueTypes &... values);
      59             : 
      60             : /**
      61             :  * Packs the mixed-type values in \p values into \p out to be unpacked with mixedUnpack().
      62             :  *
      63             :  * Uses as few entries in \p out needed to represent \p values in order.
      64             :  */
      65             : template <typename BufferType, typename BufferIter, typename... ValueTypes>
      66             : void mixedPack(BufferIter & out, ValueTypes const &... values);
      67             : 
      68             : /**
      69             :  * Gets the number of BufferType required to store the expanded InputTypes for use with
      70             :  * mixedPack() and mixedUnpack().
      71             :  *
      72             :  * Can be stored as constexpr to evaluate the size at compile time only.
      73             :  */
      74             : template <typename BufferType, typename... InputTypes>
      75             : constexpr std::size_t mixedPackSize();
      76             : 
      77             : /**
      78             :  * Packs \p value into a value of type BufferType at a byte level, to be unpacked with
      79             :  * the unpack() routines in this namespace.
      80             :  */
      81             : template <typename BufferType, typename ValueType>
      82             : BufferType pack(const ValueType value);
      83             : 
      84             : /**
      85             :  * Unpacks \p value_as_buffer_type (which is packed with pack()) into \p value at a byte level.
      86             :  */
      87             : template <typename BufferType, typename ValueType>
      88             : void unpack(const BufferType value_as_buffer_type, ValueType & value);
      89             : 
      90             : /**
      91             :  * Packs the ID of \p elem into a type of BufferType to be unpacked later into another const Elem *
      92             :  * with unpack().
      93             :  */
      94             : template <typename BufferType>
      95             : BufferType pack(const Elem * elem, MeshBase * mesh_base = nullptr);
      96             : 
      97             : /**
      98             :  * Unpacks the const Elem * from \p id_as_buffer_type (packed using pack()) into \p elem.
      99             :  */
     100             : template <typename BufferType>
     101             : void unpack(const Elem *& elem, const BufferType id_as_buffer_type, MeshBase * mesh_base);
     102             : 
     103             : namespace detail
     104             : {
     105             : 
     106             : /**
     107             :  * Helper for mixedPackSize().
     108             :  *
     109             :  * Called after evaluating the last InputType, and increases the size
     110             :  * if any offset remains
     111             :  */
     112             : template <typename BufferType>
     113             : constexpr std::size_t
     114             : mixedPackSizeHelper(const std::size_t offset, const std::size_t size)
     115             : {
     116             :   return offset ? size + 1 : size;
     117             : }
     118             : 
     119             : /**
     120             :  * Recursive helper for mixedPackSize().
     121             :  *
     122             :  * Recurses through the types (in InputType and rest), and increments the
     123             :  * offset and size as needed
     124             :  */
     125             : template <typename BufferType, typename InputType, typename... Rest>
     126             : constexpr std::size_t
     127             : mixedPackSizeHelper(std::size_t offset, std::size_t size)
     128             : {
     129             :   return offset + sizeof(InputType) > sizeof(BufferType)
     130             :              ? mixedPackSizeHelper<BufferType, Rest...>(sizeof(InputType), ++size)
     131             :              : mixedPackSizeHelper<BufferType, Rest...>(offset + sizeof(InputType), size);
     132             : }
     133             : 
     134             : /**
     135             :  * Helper for mixedUnpack()
     136             :  */
     137             : template <typename BufferType, typename BufferIter, typename ValueType>
     138             : void
     139     6375870 : mixedUnpackHelper(BufferIter & in,
     140             :                   const BufferType *& src,
     141             :                   std::size_t & src_offset,
     142             :                   ValueType & output)
     143             : {
     144             :   static_assert(sizeof(ValueType) <= sizeof(BufferType), "ValueType will not fit into BufferType");
     145             : 
     146     6375870 :   if (src_offset + sizeof(ValueType) > sizeof(BufferType))
     147             :   {
     148     2550348 :     src = &(*in++);
     149     2550348 :     src_offset = 0;
     150             :   }
     151             : 
     152     6375870 :   std::memcpy(&output, (char *)src + src_offset, sizeof(ValueType));
     153     6375870 :   src_offset += sizeof(ValueType);
     154     6375870 : }
     155             : 
     156             : /**
     157             :  * Helper for mixedPack()
     158             :  */
     159             : template <typename BufferIter, typename BufferType, typename ValueType>
     160             : void
     161     6375870 : mixedPackHelper(BufferIter & out,
     162             :                 BufferType & dest,
     163             :                 std::size_t & dest_offset,
     164             :                 const ValueType & input)
     165             : {
     166             :   static_assert(sizeof(ValueType) <= sizeof(BufferType), "ValueType will not fit into BufferType");
     167             : 
     168     6375870 :   if (dest_offset + sizeof(ValueType) > sizeof(BufferType))
     169             :   {
     170             :     out++ = dest;
     171     1275174 :     dest_offset = 0;
     172             :   }
     173             : 
     174     6375870 :   std::memcpy((char *)&dest + dest_offset, &input, sizeof(ValueType));
     175     6375870 :   dest_offset += sizeof(ValueType);
     176     6375870 : }
     177             : }
     178             : 
     179             : template <class Cont, class InputIt>
     180             : void
     181             : unpackCopy(Cont & container, InputIt & input_iterator)
     182             : {
     183             :   auto first = container.begin();
     184     1631284 :   while (first != container.end())
     185      356110 :     *first++ = *input_iterator++;
     186             : }
     187             : 
     188             : template <typename BufferType, typename BufferIter, typename ValueType>
     189             : void
     190             : reinterpretPackCopy(const std::vector<ValueType> & values, BufferIter & out)
     191             : {
     192             :   static_assert(sizeof(ValueType) <= sizeof(BufferType), "ValueType will not fit into BufferType");
     193             : 
     194             :   BufferType dest;
     195             :   const ValueType * src = values.data();
     196             : 
     197             :   std::size_t dest_offset = 0;
     198             :   for (std::size_t i = 0; i < values.size(); ++i)
     199             :   {
     200             :     if (dest_offset + sizeof(ValueType) > sizeof(BufferType))
     201             :     {
     202             :       out++ = dest;
     203             :       dest_offset = 0;
     204             :     }
     205             : 
     206             :     std::memcpy((char *)&dest + dest_offset, &src[i], sizeof(ValueType));
     207             :     dest_offset += sizeof(ValueType);
     208             :   }
     209             : 
     210             :   if (dest_offset)
     211             :     out++ = dest;
     212             : }
     213             : 
     214             : template <typename BufferType, typename BufferIter, typename ValueType>
     215             : void
     216             : reinterpretUnpackCopy(std::vector<ValueType> & values, BufferIter & in)
     217             : {
     218             :   static_assert(sizeof(ValueType) <= sizeof(BufferType), "ValueType will not fit into BufferType");
     219             : 
     220             :   ValueType * dest = values.data();
     221             :   const BufferType * src = nullptr;
     222             : 
     223             :   std::size_t src_offset = sizeof(BufferType);
     224             :   for (std::size_t i = 0; i < values.size(); ++i)
     225             :   {
     226             :     if (src_offset + sizeof(ValueType) > sizeof(BufferType))
     227             :     {
     228             :       src = &(*in++);
     229             :       src_offset = 0;
     230             :     }
     231             : 
     232             :     std::memcpy(&dest[i], (char *)src + src_offset, sizeof(ValueType));
     233             :     src_offset += sizeof(ValueType);
     234             :   }
     235             : }
     236             : 
     237             : template <typename ValueType, typename BufferType>
     238             : std::size_t
     239             : reinterpretCopySize(const std::size_t input_size)
     240             : {
     241             :   const double input_per_output = std::floor(sizeof(BufferType) / sizeof(ValueType));
     242             :   return (std::size_t)std::ceil((double)input_size / input_per_output);
     243             : }
     244             : 
     245             : template <typename BufferType, typename BufferIter, typename... ValueTypes>
     246             : void
     247     1275174 : mixedUnpack(BufferIter & in, ValueTypes &... values)
     248             : {
     249     1275174 :   std::size_t src_offset = sizeof(BufferType);
     250     1275174 :   const BufferType * src = nullptr;
     251             : 
     252             :   int expander[] = {
     253             :       0,
     254     1275174 :       ((void)detail::mixedUnpackHelper(in, src, src_offset, std::forward<ValueTypes &>(values)),
     255             :        0)...};
     256             :   (void)expander;
     257     1275174 : }
     258             : 
     259             : template <typename BufferType, typename BufferIter, typename... ValueTypes>
     260             : void
     261     1275174 : mixedPack(BufferIter & out, ValueTypes const &... values)
     262             : {
     263     1275174 :   std::size_t dest_offset = 0;
     264             :   BufferType dest;
     265             : 
     266             :   int expander[] = {0,
     267     1275174 :                     ((void)detail::mixedPackHelper(
     268             :                          out, dest, dest_offset, std::forward<ValueTypes const &>(values)),
     269             :                      0)...};
     270             :   (void)expander;
     271             : 
     272     1275174 :   if (dest_offset)
     273             :     out++ = dest;
     274     1275174 : }
     275             : 
     276             : template <typename BufferType, typename... InputTypes>
     277             : constexpr std::size_t
     278             : mixedPackSize()
     279             : {
     280             :   // Call the recursive helper with an initial offset and size of 0
     281             :   return detail::mixedPackSizeHelper<BufferType, InputTypes...>(/* offset = */ 0, /* size = */ 0);
     282             : }
     283             : 
     284             : template <typename BufferType, typename ValueType>
     285             : BufferType
     286             : pack(const ValueType value)
     287             : {
     288             :   static_assert(sizeof(ValueType) <= sizeof(BufferType), "Value will won't fit into buffer type");
     289             : 
     290             :   BufferType value_as_buffer_type;
     291             :   std::memcpy(&value_as_buffer_type, &value, sizeof(ValueType));
     292             :   return value_as_buffer_type;
     293             : }
     294             : 
     295             : template <typename BufferType, typename ValueType>
     296             : void
     297             : unpack(const BufferType value_as_buffer_type, ValueType & value)
     298             : {
     299             :   static_assert(sizeof(ValueType) <= sizeof(BufferType), "Value will won't fit into buffer type");
     300     1275174 :   std::memcpy(&value, &value_as_buffer_type, sizeof(ValueType));
     301             : }
     302             : 
     303             : template <typename BufferType>
     304             : BufferType
     305             : pack(const Elem * elem, MeshBase * libmesh_dbg_var(mesh_base /* = nullptr */))
     306             : {
     307     1275174 :   const dof_id_type id = elem ? elem->id() : libMesh::DofObject::invalid_id;
     308             :   mooseAssert(mesh_base ? mesh_base->query_elem_ptr(id) == elem : true,
     309             :               "Elem doesn't exist in mesh");
     310             : 
     311             :   return pack<BufferType>(id);
     312             : }
     313             : 
     314             : template <typename BufferType>
     315             : void
     316             : unpack(const Elem *& elem, const BufferType id_as_buffer_type, MeshBase * mesh_base)
     317             : {
     318             :   dof_id_type id;
     319             :   unpack<BufferType>(id_as_buffer_type, id);
     320             : 
     321     1275174 :   elem = (id == libMesh::DofObject::invalid_id ? nullptr : mesh_base->query_elem_ptr(id));
     322             : }
     323             : }

Generated by: LCOV version 1.14