11#ifndef BOTAN_PQ_CRYSTALS_ENCODING_H_
12#define BOTAN_PQ_CRYSTALS_ENCODING_H_
18#include <botan/internal/buffer_slicer.h>
19#include <botan/internal/buffer_stuffer.h>
20#include <botan/internal/loadstor.h>
21#include <botan/internal/pqcrystals.h>
22#include <botan/internal/pqcrystals_helpers.h>
24#if defined(BOTAN_HAS_XOF)
25 #include <botan/xof.h>
32 return [&](std::span<uint8_t> out) { slicer.
copy_into(out); };
35#if defined(BOTAN_HAS_XOF)
37 return [&](std::span<uint8_t> out) { xof.
output(out); };
47template <
typename T,
typename PolyCoeffT>
48concept coeff_map_fn = std::signed_integral<PolyCoeffT> &&
requires(T fn, PolyCoeffT coeff) {
49 { fn(coeff) } -> std::same_as<std::make_unsigned_t<PolyCoeffT>>;
52template <
typename T,
typename PolyCoeffT>
54 std::signed_integral<PolyCoeffT> &&
requires(T fn, std::make_unsigned_t<PolyCoeffT> coeff_value) {
55 { fn(coeff_value) } -> std::same_as<PolyCoeffT>;
66template <
int32_t range, crystals_trait PolyTrait>
68 using T =
typename PolyTrait::T;
72 static_assert(range <= std::numeric_limits<T>::max());
79 const size_t smallest_aligned_pack = std::lcm(
bits_per_coeff,
size_t(8));
82 : smallest_aligned_pack;
116template <
int32_t range, crystals_trait PolyTrait, Domain D, coeff_map_fn<
typename PolyTrait::T> MapFnT>
134 for(
size_t i = 0; i < p.
size(); i += trait::coeffs_per_pack) {
138 typename trait::collector_array collectors = {0};
139 for(
size_t j = 0, bit_offset = 0, c = 0; j < trait::coeffs_per_pack; ++j) {
141 const typename trait::unsigned_T mapped_coeff = map(p[i + j]);
142 const auto coeff_value =
static_cast<typename trait::sink_t
>(mapped_coeff);
151 collectors[c] |= coeff_value << bit_offset;
152 bit_offset += trait::bits_per_coeff;
157 if(bit_offset > trait::bits_in_collector) {
158 bit_offset = bit_offset - trait::bits_in_collector;
159 collectors[++c] = coeff_value >> (trait::bits_per_coeff - bit_offset);
166 const auto bytes =
store_le(collectors);
167 stuffer.
append(std::span{bytes}.template first<trait::bytes_per_pack>());
186template <int32_t range,
187 byte_source ByteSourceT,
188 crystals_trait PolyTrait,
190 coeff_unmap_fn<typename PolyTrait::T> UnmapFnT>
195 typename trait::collector_bytearray bytes = {0};
199 for(
size_t i = 0; i < p.
size(); i += trait::coeffs_per_pack) {
200 get_bytes(std::span{bytes}.template first<trait::bytes_per_pack>());
203 for(
size_t j = 0, bit_offset = 0, c = 0; j < trait::coeffs_per_pack; ++j) {
204 typename trait::sink_t coeff_value = collectors[c] >> bit_offset;
205 bit_offset += trait::bits_per_coeff;
206 if(bit_offset > trait::bits_in_collector) {
207 bit_offset = bit_offset - trait::bits_in_collector;
208 coeff_value |= collectors[++c] << (trait::bits_per_coeff - bit_offset);
216 p[i + j] = unmap(
static_cast<typename trait::unsigned_T
>(coeff_value & trait::value_mask));
222template <
int32_t range, crystals_trait PolyTrait, Domain D>
224 using unsigned_T = std::make_unsigned_t<typename PolyTrait::T>;
225 pack<range>(p, stuffer, [](
typename PolyTrait::T x) {
return static_cast<unsigned_T
>(x); });
229template <
int32_t range,
byte_source ByteSourceT, crystals_trait PolyTrait, Domain D>
231 using unsigned_T = std::make_unsigned_t<typename PolyTrait::T>;
#define BOTAN_DEBUG_ASSERT(expr)
void copy_into(std::span< uint8_t > sink)
Helper class to ease in-place marshalling of concatenated fixed-length values.
constexpr void append(std::span< const uint8_t > buffer)
constexpr size_t remaining_capacity() const
constexpr size_t size() const
constexpr auto as_byte_source(BufferSlicer &slicer)
constexpr void unpack(Polynomial< PolyTrait, D > &p, ByteSourceT &byte_source, UnmapFnT unmap)
constexpr void pack(const Polynomial< PolyTrait, D > &p, BufferStuffer &stuffer, MapFnT map)
constexpr auto store_le(ParamTs &&... params)
constexpr auto load_le(ParamTs &&... params)
constexpr auto bitlen(size_t x)
static constexpr size_t coeffs_per_pack
static constexpr size_t collectors_per_pack
static constexpr size_t bits_per_pack
static constexpr size_t bits_in_collector
static constexpr size_t bits_per_coeff
std::array< sink_t, collectors_per_pack > collector_array
static constexpr sink_t value_mask
std::array< uint8_t, collector_bytes_per_pack > collector_bytearray
std::make_unsigned_t< T > unsigned_T
static constexpr size_t bytes_per_pack
static constexpr size_t collector_bytes_per_pack