Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
markov.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <pulp/music/detail/random_range.hpp>
4
5#include <array>
6#include <cstddef>
7#include <cstdint>
8#include <limits>
9#include <optional>
10#include <span>
11
12namespace pulp::music {
13
21
22// Fixed-capacity prepared transition table. prepare() is the control-thread
23// operation; next() is const, bounded, allocation-free evaluation.
24template <std::size_t MaxStates = 16>
26 public:
27 static_assert(MaxStates > 0, "Markov capacity must be positive");
28 static_assert(MaxStates <= std::numeric_limits<std::size_t>::max() / MaxStates,
29 "Markov table dimensions overflow size_t");
30 static constexpr std::size_t capacity = MaxStates;
31
32 [[nodiscard]] constexpr MarkovError
33 prepare(std::size_t state_count,
34 std::span<const std::uint32_t> weights) noexcept {
35 clear();
36 if (state_count == 0)
38 if (state_count > MaxStates)
40 if (weights.size() != state_count * state_count)
42
43 for (std::size_t row = 0; row < state_count; ++row) {
44 std::uint64_t total = 0;
45 for (std::size_t column = 0; column < state_count; ++column) {
46 const auto weight = weights[row * state_count + column];
47 total += weight;
48 cumulative_[row * MaxStates + column] = total;
49 }
50 if (total == 0) {
51 clear();
53 }
54 totals_[row] = total;
55 }
56 state_count_ = state_count;
57 return MarkovError::none;
58 }
59
60 constexpr void clear() noexcept {
61 cumulative_.fill(0);
62 totals_.fill(0);
63 state_count_ = 0;
64 }
65
66 constexpr std::size_t state_count() const noexcept { return state_count_; }
67
68 [[nodiscard]] constexpr std::optional<std::size_t>
69 next(std::size_t current_state, std::uint64_t random_word) const noexcept {
70 if (current_state >= state_count_)
71 return std::nullopt;
72 const auto draw = detail::reduce_random_word(random_word, totals_[current_state]);
73 for (std::size_t column = 0; column < state_count_; ++column)
74 if (draw < cumulative_[current_state * MaxStates + column])
75 return column;
76 return std::nullopt;
77 }
78
79 private:
80 std::array<std::uint64_t, MaxStates * MaxStates> cumulative_{};
81 std::array<std::uint64_t, MaxStates> totals_{};
82 std::size_t state_count_ = 0;
83};
84
85} // namespace pulp::music
Definition markov.hpp:25
constexpr void clear() noexcept
Definition markov.hpp:60
constexpr std::size_t state_count() const noexcept
Definition markov.hpp:66
constexpr MarkovError prepare(std::size_t state_count, std::span< const std::uint32_t > weights) noexcept
Definition markov.hpp:33
constexpr std::optional< std::size_t > next(std::size_t current_state, std::uint64_t random_word) const noexcept
Definition markov.hpp:69
static constexpr std::size_t capacity
Definition markov.hpp:30
Definition chord.hpp:14
MarkovError
Definition markov.hpp:14
@ none
Definition markov.hpp:15
@ empty_transition_row
Definition markov.hpp:19
@ capacity_exceeded
Definition markov.hpp:17
@ empty_model
Definition markov.hpp:16
@ weight_count_mismatch
Definition markov.hpp:18