Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
110
libs/routing/coding.hpp
Normal file
110
libs/routing/coding.hpp
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/routing_exceptions.hpp"
|
||||
|
||||
#include "coding/bit_streams.hpp"
|
||||
#include "coding/elias_coder.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/bits.hpp"
|
||||
#include "base/checked_cast.hpp"
|
||||
#include "base/macros.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace routing
|
||||
{
|
||||
template <typename T, typename Source>
|
||||
T ReadDelta(BitReader<Source> & reader)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>::value, "T should be an unsigned type");
|
||||
uint64_t const decoded = coding::DeltaCoder::Decode(reader);
|
||||
if (decoded > std::numeric_limits<T>::max())
|
||||
MYTHROW(CorruptedDataException, ("Decoded value", decoded, "out of limit", std::numeric_limits<T>::max()));
|
||||
|
||||
return static_cast<T>(decoded);
|
||||
}
|
||||
|
||||
template <typename T, typename Sink>
|
||||
void WriteDelta(BitWriter<Sink> & writer, T value)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>::value, "T should be an unsigned type");
|
||||
ASSERT_GREATER(value, 0, ());
|
||||
|
||||
bool const success = coding::DeltaCoder::Encode(writer, static_cast<uint64_t>(value));
|
||||
ASSERT(success, ());
|
||||
UNUSED_VALUE(success);
|
||||
}
|
||||
|
||||
template <typename T, typename Source>
|
||||
T ReadGamma(BitReader<Source> & reader)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>::value, "T should be an unsigned type");
|
||||
uint64_t const decoded = coding::GammaCoder::Decode(reader);
|
||||
if (decoded > std::numeric_limits<T>::max())
|
||||
MYTHROW(CorruptedDataException, ("Decoded value", decoded, "out of limit", std::numeric_limits<T>::max()));
|
||||
|
||||
return static_cast<T>(decoded);
|
||||
}
|
||||
|
||||
template <typename T, typename Sink>
|
||||
void WriteGamma(BitWriter<Sink> & writer, T value)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>::value, "T should be an unsigned type");
|
||||
ASSERT_GREATER(value, 0, ());
|
||||
|
||||
bool const success = coding::GammaCoder::Encode(writer, static_cast<uint64_t>(value));
|
||||
ASSERT(success, ());
|
||||
UNUSED_VALUE(success);
|
||||
}
|
||||
|
||||
// C++ standard says:
|
||||
// if the value can't be represented in the destination unsigned type,
|
||||
// the result is implementation-defined.
|
||||
//
|
||||
// ModularCast makes unambiguous conversion from unsigned value to signed.
|
||||
// The resulting value is the least signed integer congruent to the source integer
|
||||
// (modulo 2^n where n is the number of bits used to represent the unsigned type)
|
||||
template <typename Unsigned, typename Signed = std::make_signed_t<Unsigned>>
|
||||
Signed ModularCast(Unsigned value)
|
||||
{
|
||||
static_assert(std::is_unsigned<Unsigned>::value, "T should be an unsigned type");
|
||||
|
||||
if (value <= static_cast<Unsigned>(std::numeric_limits<Signed>::max()))
|
||||
return static_cast<Signed>(value);
|
||||
|
||||
auto constexpr minSignedT = std::numeric_limits<Signed>::min();
|
||||
return static_cast<Signed>(value - static_cast<Unsigned>(minSignedT)) + minSignedT;
|
||||
}
|
||||
|
||||
// Encodes current as delta compared with prev.
|
||||
template <typename T, typename UnsignedT = std::make_unsigned_t<T>>
|
||||
UnsignedT EncodeZigZagDelta(T prev, T current)
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "T should be an integral type");
|
||||
|
||||
auto const unsignedPrev = static_cast<UnsignedT>(prev);
|
||||
auto const unsignedCurrent = static_cast<UnsignedT>(current);
|
||||
auto originalDelta = ModularCast(static_cast<UnsignedT>(unsignedCurrent - unsignedPrev));
|
||||
static_assert(std::is_same<decltype(originalDelta), std::make_signed_t<T>>::value,
|
||||
"It's expected that ModuleCast returns SignedT");
|
||||
|
||||
auto encodedDelta = bits::ZigZagEncode(originalDelta);
|
||||
static_assert(std::is_same<decltype(encodedDelta), UnsignedT>::value,
|
||||
"It's expected that bits::ZigZagEncode returns UnsignedT");
|
||||
return encodedDelta;
|
||||
}
|
||||
|
||||
// Reverse function for EncodeZigZagDelta.
|
||||
template <typename T, typename UnsignedT = std::make_unsigned_t<T>>
|
||||
T DecodeZigZagDelta(T prev, UnsignedT delta)
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "T should be an integral type");
|
||||
|
||||
auto decoded = bits::ZigZagDecode(delta);
|
||||
static_assert(std::is_same<decltype(decoded), std::make_signed_t<T>>::value,
|
||||
"It's expected that bits::ZigZagDecode returns SignedT");
|
||||
return prev + static_cast<T>(decoded);
|
||||
}
|
||||
} // namespace routing
|
||||
Loading…
Add table
Add a link
Reference in a new issue