From 7a427d0041f1b49bd10f98026962908f3f924712 Mon Sep 17 00:00:00 2001 From: Max Podkorytov <4273004+tenpercent@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:50:01 +0000 Subject: [PATCH 1/3] Replace O(N) recursive sequence_map_inverse with O(1) pack expansion --- include/ck/utility/sequence.hpp | 56 ++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/include/ck/utility/sequence.hpp b/include/ck/utility/sequence.hpp index 3a45d52bd3a6..372337796e64 100644 --- a/include/ck/utility/sequence.hpp +++ b/include/ck/utility/sequence.hpp @@ -597,31 +597,49 @@ struct is_valid_sequence_map : is_same -struct sequence_map_inverse +// Invert a permutation sequence: given X2Y = {a, b, c, ...}, compute Y2X where Y2X[X2Y[i]] = i +// Example: Sequence<2,0,1> (meaning pos0->2, pos1->0, pos2->1) inverts to Sequence<1,2,0> +// +// Why this implementation is faster to compile than recursive templates: +// +// The old recursive approach created a new template type for each element: +// sequence_map_inverse> -> sequence_map_inverse> -> +// sequence_map_inverse> +// Each "->" is a new type the compiler must create, track, and manage. For N elements, that's +// N template types, each with overhead (name mangling, debug info, symbol table entries). +// +// This implementation uses O(N) direct assignment with a fold expression: +// For input Sequence<2,0,1>, the fold expression ((result[Is] = pos++), ...) expands to: +// result[2]=0, result[0]=1, result[1]=2 +// This builds the inverse permutation in a single pass without any searching. +// +template +struct sequence_map_inverse> { - template - struct sequence_map_inverse_impl + private: + struct InverseArray { - static constexpr auto new_y2x = - WorkingY2X::Modify(X2Y::At(Number{}), Number{}); - - using type = - typename sequence_map_inverse_impl:: - type; + index_t data[sizeof...(Is)] = {}; }; - template - struct sequence_map_inverse_impl + static constexpr auto build_inverse() { - using type = WorkingY2X; - }; + InverseArray result{}; + index_t pos = 0; + ((result.data[Is] = pos++), ...); + return result; + } - using type = - typename sequence_map_inverse_impl::type, - 0, - SeqMap::Size()>::type; + static constexpr InverseArray inverse = build_inverse(); + + template + static constexpr auto compute(Sequence) + { + return Sequence{}; + } + + public: + using type = decltype(compute(make_index_sequence{})); }; template From 5d0b96e1798580d55e75f94f521a3e91d1e98af6 Mon Sep 17 00:00:00 2001 From: Max Podkorytov <4273004+tenpercent@users.noreply.github.com> Date: Wed, 28 Jan 2026 13:07:36 -0500 Subject: [PATCH 2/3] Retrigger CI Co-Authored-By: Claude From 027528f8980273df8deaf40baa5135e0890b82c1 Mon Sep 17 00:00:00 2001 From: Max Podkorytov <4273004+tenpercent@users.noreply.github.com> Date: Tue, 10 Feb 2026 22:03:11 +0000 Subject: [PATCH 3/3] [CK] Replace fold expression with for loop in sequence_map_inverse Use explicit for loop instead of fold expression to build the inverse permutation array. This avoids potential issues with fold expression depth limits while maintaining the same O(1) template instantiation depth optimization. Co-Authored-By: Claude Opus 4.6 --- .../include/ck/utility/sequence.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/projects/composablekernel/include/ck/utility/sequence.hpp b/projects/composablekernel/include/ck/utility/sequence.hpp index 372337796e64..07d6af7d32d6 100644 --- a/projects/composablekernel/include/ck/utility/sequence.hpp +++ b/projects/composablekernel/include/ck/utility/sequence.hpp @@ -608,10 +608,10 @@ struct is_valid_sequence_map : is_same" is a new type the compiler must create, track, and manage. For N elements, that's // N template types, each with overhead (name mangling, debug info, symbol table entries). // -// This implementation uses O(N) direct assignment with a fold expression: -// For input Sequence<2,0,1>, the fold expression ((result[Is] = pos++), ...) expands to: -// result[2]=0, result[0]=1, result[1]=2 -// This builds the inverse permutation in a single pass without any searching. +// This implementation uses a constexpr for loop to build the inverse in O(N) operations: +// For input Sequence<2,0,1>, the loop sets result[input[pos]] = pos for each position: +// pos=0: result[2]=0, pos=1: result[0]=1, pos=2: result[1]=2 +// This builds the inverse permutation in a single pass with O(1) template instantiation depth. // template struct sequence_map_inverse> @@ -625,8 +625,11 @@ struct sequence_map_inverse> static constexpr auto build_inverse() { InverseArray result{}; - index_t pos = 0; - ((result.data[Is] = pos++), ...); + constexpr index_t input[] = {Is...}; + for(index_t pos = 0; pos < static_cast(sizeof...(Is)); ++pos) + { + result.data[input[pos]] = pos; + } return result; }