Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-10-29 06:08:31

0001 #include <cassert>
0002 
0003 #include "L1Trigger/L1THGCal/interface/HGCalVFECompressionImpl.h"
0004 
0005 #include "FWCore/Utilities/interface/Exception.h"
0006 
0007 HGCalVFECompressionImpl::HGCalVFECompressionImpl(const edm::ParameterSet& conf)
0008     : exponentBits_(conf.getParameter<uint32_t>("exponentBits")),
0009       mantissaBits_(conf.getParameter<uint32_t>("mantissaBits")),
0010       truncationBits_(conf.getParameter<uint32_t>("truncationBits")),
0011       rounding_(conf.getParameter<bool>("rounding")) {
0012   if (((1 << exponentBits_) + mantissaBits_ - 1) >= 64) {
0013     throw cms::Exception("CodespaceCannotFit") << "The code space cannot fit into the unsigned 64-bit space.\n";
0014   }
0015   saturationCode_ = (1 << (exponentBits_ + mantissaBits_)) - 1;
0016   saturationValue_ = (exponentBits_ == 0)
0017                          ? saturationCode_
0018                          : ((1ULL << (mantissaBits_ + truncationBits_ + 1)) - 1) << ((1 << exponentBits_) - 2);
0019 }
0020 
0021 void HGCalVFECompressionImpl::compressSingle(const uint64_t value,
0022                                              uint32_t& compressedCode,
0023                                              uint64_t& compressedValue) const {
0024   // check for saturation
0025   if (value > saturationValue_) {
0026     compressedCode = saturationCode_;
0027     compressedValue = saturationValue_;
0028     return;
0029   }
0030 
0031   // count bit length
0032   uint32_t bitlen;
0033   uint64_t shifted_value = value >> truncationBits_;
0034   uint64_t valcopy = shifted_value;
0035   for (bitlen = 0; valcopy != 0; valcopy >>= 1, bitlen++) {
0036   }
0037   if (bitlen <= mantissaBits_) {
0038     compressedCode = shifted_value;
0039     compressedValue = shifted_value << truncationBits_;
0040     return;
0041   }
0042 
0043   // build exponent and mantissa
0044   const uint32_t exponent = bitlen - mantissaBits_;
0045   assert(exponent - 1 < 64);
0046   const uint64_t mantissa = (shifted_value >> (exponent - 1)) & ~(1ULL << mantissaBits_);
0047 
0048   // assemble floating-point
0049   const uint32_t floatval = (exponent << mantissaBits_) | mantissa;
0050 
0051   // we will never want to round up maximum code here
0052   // Also, rounding doesn't apply if exponent==1 since there is no actual compression
0053   // from the conversion to floating point in that case
0054   if (!rounding_ || floatval == saturationCode_ || exponent <= 1) {
0055     compressedCode = floatval;
0056     compressedValue = ((1ULL << mantissaBits_) | mantissa) << (exponent - 1);
0057   } else {
0058     const bool roundup = ((shifted_value >> (exponent - 2)) & 1ULL) == 1ULL;
0059     if (!roundup) {
0060       compressedCode = floatval;
0061       compressedValue = ((1ULL << mantissaBits_) | mantissa) << (exponent - 1);
0062     } else {
0063       compressedCode = floatval + 1;
0064       uint64_t rmantissa = mantissa + 1;
0065       uint32_t rexponent = exponent;
0066       if (rmantissa >= (1ULL << mantissaBits_)) {
0067         rexponent++;
0068         rmantissa &= ~(1ULL << mantissaBits_);
0069       }
0070       compressedValue = ((1ULL << mantissaBits_) | rmantissa) << (rexponent - 1);
0071     }
0072   }
0073   compressedValue <<= truncationBits_;
0074 }
0075 
0076 void HGCalVFECompressionImpl::compress(const std::unordered_map<uint32_t, uint32_t>& payload,
0077                                        std::unordered_map<uint32_t, std::array<uint64_t, 2> >& compressed_payload) {
0078   for (const auto& item : payload) {
0079     const uint64_t value = static_cast<uint64_t>(item.second);
0080     uint32_t code(0);
0081     uint64_t compressed_value(0);
0082     compressSingle(value, code, compressed_value);
0083     std::array<uint64_t, 2> compressed_item = {{static_cast<uint64_t>(code), compressed_value}};
0084     compressed_payload.emplace(item.first, compressed_item);
0085   }
0086 }