81 return lhs.onset < rhs.onset || (lhs.onset == rhs.onset && lhs.id < rhs.id);
86 coordinate.tick =
event.onset;
87 coordinate.stream ^=
event.id;
98 return static_cast<std::uint64_t
>(high - low);
99 const auto low_magnitude =
static_cast<std::uint64_t
>(-(low + 1)) + 1u;
101 return low_magnitude - (
static_cast<std::uint64_t
>(-(high + 1)) + 1u);
102 return low_magnitude +
static_cast<std::uint64_t
>(high);
105constexpr std::int64_t
add_unsigned(std::int64_t value, std::uint64_t amount)
noexcept {
107 return value +
static_cast<std::int64_t
>(amount);
108 const auto magnitude =
static_cast<std::uint64_t
>(-(value + 1)) + 1u;
109 if (amount < magnitude) {
110 const auto remaining = magnitude - amount;
111 return -
static_cast<std::int64_t
>(remaining - 1u) - 1;
113 return static_cast<std::int64_t
>(amount - magnitude);
118 const auto magnitude =
static_cast<std::uint64_t
>(-(value + 1)) + 1u;
119 const auto result_magnitude = magnitude + amount;
120 return -
static_cast<std::int64_t
>(result_magnitude - 1u) - 1;
122 const auto positive =
static_cast<std::uint64_t
>(value);
123 if (amount <= positive)
124 return static_cast<std::int64_t
>(positive - amount);
125 const auto magnitude = amount - positive;
126 return -
static_cast<std::int64_t
>(magnitude - 1u) - 1;
129constexpr std::uint64_t
scale_distance(std::uint64_t distance, std::uint16_t amount)
noexcept {
130 return (distance / 1000u) * amount + ((distance % 1000u) * amount) / 1000u;
134 std::uint16_t amount)
noexcept {
159 static_assert(MaxEvents > 0,
"DevelopmentPattern capacity must be positive");
160 static_assert(MaxEvents <= 64,
"Pattern development is bounded to 64 events");
167 if (
events.size() > MaxEvents)
172 const auto error = candidate.insert(
event);
182 if (size_ == MaxEvents)
188 if (
event.accent > 1000)
190 for (std::size_t index = 0; index < size_; ++index) {
191 if (events_[index].
id ==
event.id)
193 if (events_[index].onset ==
event.onset)
197 std::size_t insertion = size_;
199 events_[insertion] = events_[insertion - 1];
202 events_[insertion] =
event;
208 constexpr std::size_t
size() const noexcept {
212 constexpr bool empty() const noexcept {
217 [[nodiscard]]
constexpr std::optional<PatternEvent>
event(std::size_t index)
const noexcept {
220 return events_[index];
225 for (std::size_t index = 0; index < size_; ++index)
226 if (events_[index].
id ==
id)
227 return events_[index];
232 [[nodiscard]]
constexpr std::optional<PatternEvent>
234 for (std::size_t index = 0; index < size_; ++index)
235 if (events_[index].onset == onset)
236 return events_[index];
242 std::size_t result = 0;
243 for (std::size_t index = 0; index < size_; ++index)
251 std::array<PatternEvent, MaxEvents> events_{};
252 std::size_t size_ = 0;
263 constexpr explicit operator bool() const noexcept {
285template <std::
size_t MaxEvents = 64>
286[[nodiscard]]
constexpr PatternDevelopmentResult<MaxEvents>
298 for (std::size_t index = 0; index < lhs.size(); ++index) {
299 const auto event = *lhs.event(index);
300 const auto other = rhs.find_onset(event.onset);
321 for (std::size_t index = 0; index < rhs.size(); ++index) {
322 const auto event = *rhs.event(index);
323 if (lhs.find_onset(event.onset))
348template <std::
size_t MaxEvents = 64>
349[[nodiscard]]
constexpr PatternDevelopmentResult<MaxEvents>
353 if (selection.target_onsets > source.size()) {
357 const auto anchors = source.anchor_count();
358 if (selection.target_onsets < anchors) {
363 const auto selected_nonanchors = selection.target_onsets - anchors;
364 for (std::size_t index = 0; index < source.size(); ++index) {
365 const auto event = *source.event(index);
368 const auto priority =
370 std::size_t rank = 0;
371 for (std::size_t other_index = 0; other_index < source.size(); ++other_index) {
372 const auto other = *source.event(other_index);
375 const auto other_priority =
377 rank += other_priority < priority ||
378 (other_priority == priority && other.id <
event.id);
380 include = rank < selected_nonanchors;
409template <std::
size_t MaxEvents = 64>
410[[nodiscard]]
constexpr PatternDevelopmentResult<MaxEvents>
415 if (selection.begin >= selection.end) {
420 std::size_t region_events = 0;
421 std::size_t region_anchors = 0;
422 std::size_t outside_events = 0;
423 for (std::size_t index = 0; index < base.size(); ++index) {
424 const auto event = *base.event(index);
425 if (event.onset < selection.begin || event.onset >= selection.end) {
437 for (std::size_t index = 0; index < candidates.size(); ++index) {
438 const auto event = *candidates.event(index);
439 if (event.onset < selection.begin || event.onset >= selection.end)
441 const auto base_event = base.find_id(event.id);
442 if (base_event && *base_event != event) {
447 const auto existing = base.find_onset(event.onset);
449 if (*existing != event) {
459 if (selection.target_region_onsets > region_events) {
464 if (selection.target_region_onsets < region_anchors) {
469 if (outside_events + selection.target_region_onsets > MaxEvents) {
475 const auto selected_nonanchors = selection.target_region_onsets - region_anchors;
476 const auto rank = [&](
const PatternEvent& event)
constexpr noexcept {
478 std::size_t result_rank = 0;
479 const auto add_to_rank = [&](
const PatternEvent& other)
constexpr noexcept {
480 const auto other_priority =
483 other_priority < priority || (other_priority == priority && other.id <
event.id);
485 for (std::size_t index = 0; index < base.size(); ++index) {
486 const auto other = *base.event(index);
487 if (other.onset >= selection.begin && other.onset < selection.end &&
491 for (std::size_t index = 0; index < candidates.size(); ++index) {
492 const auto other = *candidates.event(index);
493 if (other.onset < selection.begin || other.onset >= selection.end ||
494 base.find_onset(other.onset))
501 for (std::size_t index = 0; index < base.size(); ++index) {
502 const auto event = *base.event(index);
503 if (event.onset < selection.begin || event.onset >= selection.end)
513 for (std::size_t index = 0; index < candidates.size(); ++index) {
514 const auto event = *candidates.event(index);
515 if (event.onset < selection.begin || event.onset >= selection.end ||
516 base.find_onset(event.onset) || rank(event) >= selected_nonanchors)
541template <std::
size_t MaxEvents = 64>
542[[nodiscard]]
constexpr PatternDevelopmentResult<MaxEvents>
546 if (selection.amount > 1000) {
550 if (selection.amount == 0) {
554 if (selection.amount == 1000) {
559 for (std::size_t index = 0; index <
a.size(); ++index) {
560 auto event = *
a.event(index);
561 const auto other =
b.find_id(event.id);
566 const auto accent_delta =
567 static_cast<std::int32_t
>(other->accent) -
static_cast<std::int32_t
>(event.accent);
568 event.accent =
static_cast<std::uint16_t
>(
static_cast<std::int32_t
>(
event.accent) +
569 accent_delta * selection.amount / 1000);
570 if (selection.amount >= 500)
571 event.role = other->role;
573 const auto threshold =
575 include = selection.amount <= threshold;
585 for (std::size_t index = 0; index <
b.size(); ++index) {
586 const auto event = *
b.event(index);
587 if (
a.find_id(event.id))
590 if (selection.amount <= threshold)
Fixed-capacity, onset-ordered collection used by development operations.
Definition pattern_development.hpp:157
constexpr std::size_t size() const noexcept
Returns the number of stored events.
Definition pattern_development.hpp:208
constexpr auto operator<=>(const DevelopmentPattern &) const =default
constexpr std::optional< PatternEvent > find_onset(timebase::TickPosition onset) const noexcept
Finds an event at an exact timeline onset.
Definition pattern_development.hpp:233
constexpr std::optional< PatternEvent > find_id(PatternEventId id) const noexcept
Finds an event by stable identity.
Definition pattern_development.hpp:224
static constexpr std::size_t capacity
Maximum number of events the pattern can hold.
Definition pattern_development.hpp:162
constexpr PatternDevelopmentError assign(std::span< const PatternEvent > events) noexcept
Replaces the pattern with validated events, preserving the old value on error.
Definition pattern_development.hpp:166
constexpr std::optional< PatternEvent > event(std::size_t index) const noexcept
Returns the event at an onset-ordered index, or no value when out of range.
Definition pattern_development.hpp:217
constexpr PatternDevelopmentError insert(PatternEvent event) noexcept
Inserts one validated event in onset order.
Definition pattern_development.hpp:181
constexpr bool empty() const noexcept
Returns true when the pattern contains no events.
Definition pattern_development.hpp:212
constexpr std::size_t anchor_count() const noexcept
Returns the number of mandatory anchor events.
Definition pattern_development.hpp:241
Definition child_process_manager.hpp:18
constexpr std::uint64_t positive_distance(std::int64_t low, std::int64_t high) noexcept
Definition pattern_development.hpp:96
constexpr std::int64_t add_unsigned(std::int64_t value, std::uint64_t amount) noexcept
Definition pattern_development.hpp:105
constexpr bool event_less(const PatternEvent &lhs, const PatternEvent &rhs) noexcept
Definition pattern_development.hpp:80
constexpr std::uint64_t event_priority(std::uint64_t seed, timebase::RandomCoordinate coordinate, const PatternEvent &event) noexcept
Definition pattern_development.hpp:84
constexpr std::int64_t subtract_unsigned(std::int64_t value, std::uint64_t amount) noexcept
Definition pattern_development.hpp:116
constexpr std::uint64_t event_threshold(std::uint64_t seed, timebase::RandomCoordinate coordinate, const PatternEvent &event) noexcept
Definition pattern_development.hpp:91
constexpr bool valid_pattern_event_role(PatternEventRole role) noexcept
Definition pattern_development.hpp:75
constexpr std::uint64_t scale_distance(std::uint64_t distance, std::uint16_t amount) noexcept
Definition pattern_development.hpp:129
constexpr std::int64_t interpolate_integer(std::int64_t from, std::int64_t to, std::uint16_t amount) noexcept
Definition pattern_development.hpp:133
constexpr PatternEventId make_pattern_event_id(std::uint64_t seed, timebase::RandomCoordinate coordinate) noexcept
Produces a stable nonzero ID from a seed and musical coordinate.
Definition pattern_development.hpp:151
constexpr PatternDevelopmentResult< MaxEvents > apply_regional_fill(const DevelopmentPattern< MaxEvents > &base, const DevelopmentPattern< MaxEvents > &candidates, RegionalFillSelection selection) noexcept
Applies candidate events within a selected half-open region.
Definition pattern_development.hpp:411
PatternEventRole
Describes how an event participates in density, fill, and morph operations.
Definition pattern_development.hpp:18
@ primary
Ordinary event eligible for deterministic selection.
Definition pattern_development.hpp:22
@ ornament
Decorative event eligible for deterministic selection.
Definition pattern_development.hpp:24
@ anchor
Mandatory structural event that density operations always retain.
Definition pattern_development.hpp:20
@ fill
Event intended to supply regional variation.
Definition pattern_development.hpp:26
PatternSetOperation
Supported onset-keyed set operations.
Definition pattern_development.hpp:269
@ intersection
Include events found in both inputs.
Definition pattern_development.hpp:273
@ set_union
Include events found in either input.
Definition pattern_development.hpp:271
@ symmetric_difference
Include events found in exactly one input.
Definition pattern_development.hpp:277
@ difference
Include events found only in the left input.
Definition pattern_development.hpp:275
@ a
Definition pitch.hpp:29
@ b
Definition pitch.hpp:31
constexpr PatternDevelopmentResult< MaxEvents > select_pattern_density(const DevelopmentPattern< MaxEvents > &source, DensitySelection selection) noexcept
Selects an exact event count while retaining every anchor.
Definition pattern_development.hpp:350
std::uint64_t PatternEventId
Stable, nonzero identity for an event across pattern transformations.
Definition pattern_development.hpp:15
@ none
Definition markov.hpp:15
@ capacity_exceeded
Definition markov.hpp:17
PatternDevelopmentError
Result codes returned by bounded pattern-development operations.
Definition pattern_development.hpp:44
@ morph_amount_out_of_range
A morph amount exceeded 1000.
Definition pattern_development.hpp:70
@ accent_out_of_range
An event accent exceeded 1000.
Definition pattern_development.hpp:58
@ conflicting_event
Two inputs disagreed about the event at one identity or onset.
Definition pattern_development.hpp:62
@ none
The operation completed successfully.
Definition pattern_development.hpp:46
@ density_out_of_range
A requested density exceeded the available event count.
Definition pattern_development.hpp:64
@ zero_event_id
An event used the reserved zero identity.
Definition pattern_development.hpp:50
@ invalid_set_operation
A set operation was outside the declared enumeration.
Definition pattern_development.hpp:60
@ invalid_role
An event role was outside the declared enumeration.
Definition pattern_development.hpp:56
@ duplicate_onset
Two events occupied the same onset.
Definition pattern_development.hpp:54
@ duplicate_event_id
Two events used the same identity.
Definition pattern_development.hpp:52
@ capacity_exceeded
The result would exceed the pattern's fixed capacity.
Definition pattern_development.hpp:48
@ invalid_region
A regional operation used an empty or reversed half-open interval.
Definition pattern_development.hpp:68
@ density_below_anchor_count
A requested density could not retain every anchor.
Definition pattern_development.hpp:66
constexpr PatternDevelopmentResult< MaxEvents > morph_patterns(const DevelopmentPattern< MaxEvents > &a, const DevelopmentPattern< MaxEvents > &b, PatternMorphSelection selection) noexcept
Morphs two patterns using exact integer interpolation and stable thresholds.
Definition pattern_development.hpp:543
constexpr PatternDevelopmentResult< MaxEvents > pattern_set(const DevelopmentPattern< MaxEvents > &lhs, const DevelopmentPattern< MaxEvents > &rhs, PatternSetOperation operation) noexcept
Applies an onset-keyed set operation to two patterns.
Definition pattern_development.hpp:287
constexpr std::uint64_t multiply_high(std::uint64_t lhs, std::uint64_t rhs) noexcept
Definition coordinate_random.hpp:31
constexpr std::uint64_t coordinate_random(std::uint64_t seed, RandomCoordinate coordinate) noexcept
Definition coordinate_random.hpp:47
Parameters for deterministic density selection.
Definition pattern_development.hpp:335
std::size_t target_onsets
Exact number of output onsets, including mandatory anchors.
Definition pattern_development.hpp:337
timebase::RandomCoordinate coordinate
Coordinate namespace used to rank non-anchor events.
Definition pattern_development.hpp:341
std::uint64_t seed
Stable recipe seed.
Definition pattern_development.hpp:339
Pattern-development output paired with an explicit result code.
Definition pattern_development.hpp:256
PatternDevelopmentError error
Operation result code.
Definition pattern_development.hpp:260
DevelopmentPattern< MaxEvents > pattern
Result pattern, empty when the operation cannot produce a valid value.
Definition pattern_development.hpp:258
One uniquely identified onset in a development pattern.
Definition pattern_development.hpp:30
std::uint16_t accent
Relative emphasis in the inclusive range [0, 1000].
Definition pattern_development.hpp:36
timebase::TickPosition onset
Musical onset in timeline ticks.
Definition pattern_development.hpp:34
PatternEventRole role
Structural role used by development operations.
Definition pattern_development.hpp:38
constexpr auto operator<=>(const PatternEvent &) const =default
Parameters for deterministic interpolation between two patterns.
Definition pattern_development.hpp:528
std::uint64_t seed
Stable recipe seed for events unique to one input.
Definition pattern_development.hpp:532
timebase::RandomCoordinate coordinate
Coordinate namespace for unique-event thresholds.
Definition pattern_development.hpp:534
std::uint16_t amount
Interpolation amount in the inclusive range [0, 1000].
Definition pattern_development.hpp:530
Parameters for deterministic replacement within a half-open region.
Definition pattern_development.hpp:392
std::uint64_t seed
Stable recipe seed.
Definition pattern_development.hpp:400
timebase::RandomCoordinate coordinate
Coordinate namespace used to rank region events.
Definition pattern_development.hpp:402
timebase::TickPosition end
Exclusive end of the edited region.
Definition pattern_development.hpp:396
std::size_t target_region_onsets
Exact number of onsets to retain inside the region.
Definition pattern_development.hpp:398
timebase::TickPosition begin
Inclusive start of the edited region.
Definition pattern_development.hpp:394
Definition coordinate_random.hpp:14