11#ifndef BOTAN_PQ_CRYSTALS_ENCODING_H_
12#define BOTAN_PQ_CRYSTALS_ENCODING_H_
18#include <botan/internal/loadstor.h>
19#include <botan/internal/pqcrystals.h>
20#include <botan/internal/pqcrystals_helpers.h>
21#include <botan/internal/stl_util.h>
23#if defined(BOTAN_HAS_XOF)
24 #include <botan/xof.h>
31 return [&](std::span<uint8_t> out) { slicer.
copy_into(out); };
34#if defined(BOTAN_HAS_XOF)
36 return [&](std::span<uint8_t> out) { xof.
output(out); };
46template <
typename T,
typename PolyCoeffT>
47concept coeff_map_fn = std::signed_integral<PolyCoeffT> &&
requires(
T fn, PolyCoeffT coeff) {
48 { fn(coeff) } -> std::same_as<std::make_unsigned_t<PolyCoeffT>>;
51template <
typename T,
typename PolyCoeffT>
53 std::signed_integral<PolyCoeffT> &&
requires(
T fn, std::make_unsigned_t<PolyCoeffT> coeff_value) {
54 { fn(coeff_value) } -> std::same_as<PolyCoeffT>;
65template <
int32_t range, crystals_trait PolyTrait>
67 using T =
typename PolyTrait::T;
71 static_assert(range <= std::numeric_limits<T>::max());
78 size_t smallest_aligned_pack = std::lcm(
bits_per_coeff,
size_t(8));
81 : smallest_aligned_pack;
115template <
int32_t range, crystals_trait PolyTrait, Domain D, coeff_map_fn<
typename PolyTrait::T> MapFnT>
133 for(
size_t i = 0; i < p.
size(); i += trait::coeffs_per_pack) {
137 typename trait::collector_array collectors = {0};
138 for(
size_t j = 0, bit_offset = 0, c = 0; j < trait::coeffs_per_pack; ++j) {
140 const typename trait::unsigned_T mapped_coeff = map(p[i + j]);
141 const auto coeff_value =
static_cast<typename trait::sink_t
>(mapped_coeff);
150 collectors[c] |= coeff_value << bit_offset;
151 bit_offset += trait::bits_per_coeff;
156 if(bit_offset > trait::bits_in_collector) {
157 bit_offset = bit_offset - trait::bits_in_collector;
158 collectors[++c] = coeff_value >> (trait::bits_per_coeff - bit_offset);
165 const auto bytes =
store_le(collectors);
166 stuffer.
append(std::span{bytes}.template first<trait::bytes_per_pack>());
185template <int32_t range,
186 byte_source ByteSourceT,
187 crystals_trait PolyTrait,
189 coeff_unmap_fn<typename PolyTrait::T> UnmapFnT>
194 typename trait::collector_bytearray bytes = {0};
198 for(
size_t i = 0; i < p.
size(); i += trait::coeffs_per_pack) {
199 get_bytes(std::span{bytes}.template first<trait::bytes_per_pack>());
202 for(
size_t j = 0, bit_offset = 0, c = 0; j < trait::coeffs_per_pack; ++j) {
203 typename trait::sink_t coeff_value = collectors[c] >> bit_offset;
204 bit_offset += trait::bits_per_coeff;
205 if(bit_offset > trait::bits_in_collector) {
206 bit_offset = bit_offset - trait::bits_in_collector;
207 coeff_value |= collectors[++c] << (trait::bits_per_coeff - bit_offset);
215 p[i + j] = unmap(
static_cast<typename trait::unsigned_T
>(coeff_value & trait::value_mask));
221template <
int32_t range, crystals_trait PolyTrait, Domain D>
223 using unsigned_T = std::make_unsigned_t<typename PolyTrait::T>;
224 pack<range>(p, stuffer, [](
typename PolyTrait::T x) {
return static_cast<unsigned_T
>(x); });
228template <
int32_t range,
byte_source ByteSourceT, crystals_trait PolyTrait, Domain D>
230 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
int(* final)(unsigned char *, CTX *)
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