text: #include "CondFormats/SiStripObjects/interface/SiStripPedestals.h"
  #include "FWCore/Utilities/interface/Exception.h"
  #include <algorithm>
  
  bool SiStripPedestals::put(const uint32_t& DetId, InputVector& input) {
    // put in SiStripPedestals of DetId
    std::vector<unsigned char>      Vo_CHAR;
    encode(input, Vo_CHAR);
  
    Registry::iterator p = std::lower_bound(indexes.begin(),indexes.end(),DetId,SiStripPedestals::StrictWeakOrdering());
    if (p!=indexes.end() && p->detid==DetId)
      return false;
  
    //size_t sd= input.second-input.first;
    size_t sd= Vo_CHAR.end() - Vo_CHAR.begin();
    DetRegistry detregistry;
    detregistry.detid=DetId;
    detregistry.ibegin=v_pedestals.size();
    detregistry.iend=v_pedestals.size()+sd;
    indexes.insert(p,detregistry);
  
    //v_pedestals.insert(v_pedestals.end(),input.first,input.second);
    v_pedestals.insert(v_pedestals.end(),Vo_CHAR.begin(),Vo_CHAR.end());
    return true;
  }
  
  const SiStripPedestals::Range SiStripPedestals::getRange(const uint32_t& DetId) const {
    // get SiStripPedestals Range of DetId
  
    RegistryIterator p = std::lower_bound(indexes.begin(),indexes.end(),DetId,SiStripPedestals::StrictWeakOrdering());
    if (p==indexes.end()|| p->detid!=DetId) 
      return SiStripPedestals::Range(v_pedestals.end(),v_pedestals.end()); 
    else 
      return SiStripPedestals::Range(v_pedestals.begin()+p->ibegin,v_pedestals.begin()+p->iend);
  }
  
  void SiStripPedestals::getDetIds(std::vector<uint32_t>& DetIds_) const {
    // returns vector of DetIds in map
    SiStripPedestals::RegistryIterator begin = indexes.begin();
    SiStripPedestals::RegistryIterator end   = indexes.end();
    for (SiStripPedestals::RegistryIterator p=begin; p != end; ++p) {
      DetIds_.push_back(p->detid);
    }
  }
  
  
  void SiStripPedestals::setData(float ped, SiStripPedestals::InputVector& vped){
    vped.push_back((static_cast<uint16_t>  (ped) & 0x3FF)) ;
  }
  
  float SiStripPedestals::getPed(const uint16_t& strip, const Range& range) const {
    if (10*strip>=(range.second-range.first)*8){
      throw cms::Exception("CorruptedData")
        << "[SiStripPedestals::getPed] looking for SiStripPedestals for a strip out of range: strip " << strip;
    }
    return   static_cast<float> (decode(strip,range));
  }
  
  void SiStripPedestals::encode(InputVector& Vi, std::vector<unsigned char>& Vo){
    static const uint16_t  BITS_PER_STRIP  = 10;
    const size_t           VoSize          = (size_t)((Vi.size() *       BITS_PER_STRIP)/8+.999);
    Vo.resize(VoSize);
    for(size_t i = 0; i<Vo.size(); ++i)
      Vo[i]   &=      0x00u;
    
    for(unsigned int stripIndex =0; stripIndex<Vi.size(); ++stripIndex){
      unsigned char*  data    =       &Vo[Vo.size()-1];
      uint32_t lowBit         =       stripIndex * BITS_PER_STRIP;
      uint8_t firstByteBit    =       (lowBit & 0x6);
      uint8_t firstByteNBits  =       8 - firstByteBit;
      uint8_t firstByteMask   =       0xffu << firstByteBit;
      uint8_t secondByteNbits =       (BITS_PER_STRIP - firstByteNBits);
      uint8_t secondByteMask  =       ~(0xffu << secondByteNbits);
  
      *(data-lowBit/8)        =       (*(data-lowBit/8)   & ~(firstByteMask))         | ((Vi[stripIndex] & 0xffu) <<firstByteBit);
      *(data-lowBit/8-1)      =       (*(data-lowBit/8-1) & ~(secondByteMask))        | ((Vi[stripIndex] >> firstByteNBits) & secondByteMask);
  
      /*
        if(stripIndex   < 25 ){
        std::cout       << "***************ENCODE*********************"<<std::endl
        << "\tdata-lowBit/8     :"<<print_as_binary((*(data-lowBit/8)   & ~(firstByteMask)))
        << "-"<<print_as_binary(((Vi[stripIndex] & 0xffu) <<firstByteBit))
        << "\tdata-lowBit/8-1   :"<<print_as_binary((*(data-lowBit/8-1)   & ~(secondByteMask)))
        << "-"<<print_as_binary((((Vi[stripIndex]>> firstByteNBits) & secondByteMask)))
        << std::endl;
        std::cout       << "strip "<<stripIndex<<"\tvi: " << Vi[stripIndex] <<"\t"
        << print_short_as_binary(Vi[stripIndex])
        << "\tvo1:"<< print_char_as_binary(*(data-lowBit/8))
        << "\tvo2:"<< print_char_as_binary(*(data-lowBit/8-1))
        << "\tlowBit:"<< lowBit
        << "\tfirstByteMask :"<<print_as_binary(firstByteMask)
        << "\tsecondByteMask:"<<print_as_binary(secondByteMask)
        << "\tfirstByteBit:"<<print_as_binary(firstByteBit)
        << std::endl;
        }
      */
    }
  }
  
  uint16_t SiStripPedestals::decode (const uint16_t& strip, const Range& range) const{
    const char *data = &*(range.second -1);  // pointer to the last byte of data
    static const uint16_t BITS_PER_STRIP = 10;
  
    uint32_t lowBit        = strip * BITS_PER_STRIP;
    uint8_t firstByteBit   = (lowBit & 6);//module 
    uint8_t firstByteNBits = 8 - firstByteBit;
    uint8_t firstByteMask  = 0xffu << firstByteBit;
    uint8_t secondByteMask = ~(0xffu << (BITS_PER_STRIP - firstByteNBits));
    uint16_t value         =   ((uint16_t(*(data-lowBit/8  )) & firstByteMask) >> firstByteBit) | ((uint16_t(*(data-lowBit/8-1)) & secondByteMask) << firstByteNBits);
    
    /*
      if(strip  < 25){
      std::cout       << "***************DECODE*********************"<<"\n"
      << "strip "<<strip << " " 
      << value 
      <<"\t   :"<<print_as_binary(value) 
      <<"\t  :"<<print_as_binary(    ((uint16_t(*(data-lowBit/8  )) & firstByteMask) >>   firstByteBit)       )
      << "-"<<print_as_binary(  ((uint16_t(*(data-lowBit/8-1)) & secondByteMask) <<firstByteNBits)    )
      << "\t *(data-lowBit/8) " << print_as_binary(    *(data-lowBit/8 ))
      << "\t *(data-lowBit/8-1) " << print_as_binary(    *(data-lowBit/8 -1 ))
      << "\tlowBit:"<< lowBit
      << "\tfirstByteMask :"<<print_as_binary(firstByteMask)
      << "\tsecondByteMask:"<<print_as_binary(secondByteMask)
      << "\tfirstByteBit:"<<print_as_binary(firstByteBit)
      << std::endl;
      }
    */
    return value;
  }
  
  /// Get 9 bit words from a bit stream, starting from the right, skipping the first 'skip' bits (0 < skip < 7).
  /// Ptr must point to the rightmost byte that has some bits of this word, and is updated by this function
  inline uint16_t SiStripPedestals::get10bits(const uint8_t * &ptr, int8_t skip) const {
      uint8_t maskThis = (0xFF << skip);
      uint8_t maskThat = ((4 << skip) - 1);
      uint16_t ret = ( ((*ptr) & maskThis) >> skip );
      --ptr;
      return ret | ( ((*ptr) & maskThat) << (8 - skip) );
  }
  
  void
  SiStripPedestals::allPeds  (std::vector<int>   & peds,  const Range& range) const {
      size_t mysize  = ((range.second-range.first) << 3) / 10;
      size_t size = peds.size();
      if (mysize < size) throw cms::Exception("CorruptedData") 
              << "[SiStripPedestals::allPeds] Requested pedestals for " << peds.size() << " strips, I have it only for " << mysize << " strips\n";
      size_t size4 = size & (~0x3), carry = size & 0x3; // we have an optimized way of unpacking 4 strips
      const uint8_t *ptr = reinterpret_cast<const uint8_t *>(&*range.second) - 1;
      std::vector<int>::iterator out = peds.begin(), end4 = peds.begin() + size4;
      // we do it this baroque way instead of just loopin on all the strips because it's faster
      // as the value of 'skip' is a constant, so the compiler can compute the masks directly
     while (out < end4) {
          *out = static_cast<int> ( get10bits(ptr, 0) ); ++out;
          *out = static_cast<int> ( get10bits(ptr, 2) ); ++out;
          *out = static_cast<int> ( get10bits(ptr, 4) ); ++out;
          *out = static_cast<int> ( get10bits(ptr, 6) ); ++out;
          --ptr; // every 4 strips we have to skip one more bit
      } 
      for (size_t rem = 0; rem < carry; ++rem ) {
          *out = static_cast<int> ( get10bits(ptr, 2*rem) ); ++out;
      }
  }
  
  void SiStripPedestals::printSummary(std::stringstream& ss) const
  {
    std::vector<uint32_t> detid;
    getDetIds(detid);
    SiStripDetSummary summary;
    for( size_t id = 0; id < detid.size(); ++id ) {
      SiStripPedestals::Range range = getRange(detid[id]);
      for( int it=0; it < (range.second-range.first)*8/10; ++it ){
        summary.add( detid[id], getPed(it,range) );
      }
    }
    ss << "Summary of pedestals:" << std::endl;
    summary.print(ss);
  }
  
  
  void SiStripPedestals::printDebug(std::stringstream& ss) const
  {
    std::vector<uint32_t> detid;
    getDetIds(detid);
  
    ss << "Number of detids = " << detid.size() << std::endl;
  
    for( size_t id = 0; id < detid.size(); ++id ) {
      SiStripPedestals::Range range = getRange(detid[id]);
  
      int strip = 0;
      ss << "detid" << std::setw(15) << "strip" << std::setw(10) << "pedestal" << std::endl;
      int detId = 0;
      int oldDetId = 0;
      for( int it=0; it < (range.second-range.first)*8/10; ++it ){
        detId = detid[id];
        if( detId != oldDetId ) {
          oldDetId = detId;
          ss << detid[id];
        }
        else ss << "   ";
        ss << std::setw(15) << strip++ << std::setw(10) << getPed(it,range) << std::endl;
      }
    }
  }
  
  
  /**
    const std::string SiStripNoises::print_as_binary(const uint8_t ch) const
    {
    std::string     str;
    int i = CHAR_BIT;
    while (i > 0)
    {
    -- i;
    str.push_back((ch&(1 << i) ? '1' : '0'));
    }
    return str;
    }
  
    std::string SiStripNoises::print_char_as_binary(const unsigned char ch) const
    {
    std::string     str;
    int i = CHAR_BIT;
    while (i > 0)
    {
    -- i;
    str.push_back((ch&(1 << i) ? '1' : '0'));
    }
    return str;
    }
  
    std::string SiStripNoises::print_short_as_binary(const short ch) const
    {
    std::string     str;
    int i = CHAR_BIT*2;
    while (i > 0)
    {
    -- i;
    str.push_back((ch&(1 << i) ? '1' : '0'));
    }
    return str;
    }
  **/
  