Каков наиболее эффективный метод сопоставления индексов с требуемым набором чисел?

В небольшом фрагменте кода на C++ я перебираю массив с индексами (0–7) и требую наилучшего способа вычисления заданного набора значений a и b из некоторой функции, принимающей i в качестве входных данных.

i:  0  1  2  3  4  5  6  7 
---------------------------
a: -1  1 -2  2  1 -1  2 -2
b:  2  2  1  1 -2 -2 -1 -1 

Очевидным решением является использование операторов if. Немного покопавшись и почитав, это лучшее, что я смог придумать:

int a = (i%4 == i%2) ? (!(i>=4 ^ i%2) ? -1 : 1) : (!(i>=4 ^ i%2) ? -2 : 2);
int b = (i%4 == i%2) ? (i>=4 ? -2 : 2) : (i>=4 ? -1 : 1);

Я считаю этот код очень неуклюжим и хотел бы знать наиболее оптимизированный способ сделать то же самое.

Пожалуйста, определите критерии «наиболее эффективного метода».

3CxEZiVlQ 05.04.2024 23:13

Если вы выполняете поиск много раз, вы можете использовать встроенную функцию ssse3 в качестве справочной таблицы. См. intel.com/content/www/us/en/docs/intrinsics-guide/…

Simon Goater 05.04.2024 23:18

Общее практическое правило: никогда не просите о самом лучшем, лучшем и т. д. при переполнении стека. Это быстро меняющиеся цели, которые требуют от вас написания полной спецификации системы, а ответы, которые вы получаете, практически бесполезны для тех, кто задает тот же вопрос. К тому же в реальной жизни никто не платит вам за то, чтобы вы предоставляли самое лучшее. Они платят вам достаточно хорошо, чтобы удовлетворить требования.

user4581301 05.04.2024 23:22

Почему бы просто не использовать два базовых массива? Это происходит быстро на всех последних основных процессорах (x86-64), пока данные находятся в кеше. Например, начиная с хотя бы Intel Skylake (2015) и AMD Zen (2017), вы можете загружать 2 элемента за такт (с задержкой 3-4 такта в L1). Ваш запутанный код неэффективен, и ему также необходимо извлекать данные из кеша... Простой доступ к массиву всегда должен быть лучше на таком процессоре. Это также должно быть верно для большинства архитектур ARM. Сначала сделайте это просто (см. KISS), а затем профилируйте для оптимизации на целевом процессоре.

Jérôme Richard 05.04.2024 23:55

Очевидным решением является использование операторов if (я не согласен). Очевидное решение — создать таблицу выходных значений и просто проиндексировать ее. Вы заранее знаете, каковы выходные значения для каждого значения i, так зачем же что-либо вычислять?

PaulMcKenzie 06.04.2024 00:47
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
73
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я бы выбрал парные массивы constexpr, или c-массив и структуру, или любую их комбинацию.

Полностью непроверенный код

using PairsArray = std::array<std::pair<int, int>, 8>;
constexpr PairsArray PA {
  { -1,2 }, { 1,2 }, { -2, 1 }, {2, 1} // and so on
}

constexpr int DoStuff(int i) {
  return PA[i].first*3+PA[i]*-2;
}

Потенциальный расчет вызовов DoStuff, если это можно сделать во время компиляции.

Другие вопросы по теме

Как я могу придумать алгоритм для разделения ряда чисел в заданном соотношении, чтобы округленные разделения складывались в исходное число?
При попытке проверить условие сравнения двух случайных массивов Python иногда делает это неправильно
PyTorch, как факторизовать матрицу, пока не получится 1 матрица, которая не изменится?
Вычтите беззнаковые целые числа в длинный результат со знаком. Никогда не отрицательный?
Алгоритм разделения целого числа на группы определенных меньших целых чисел
Как найти мод 2 линейной зависимости в Python
Результат БПФ не является «симметричным»
Неизвестная ошибка при поиске точек внутри многоугольника и расчете объединения нескольких многоугольников
Изменение нескольких значений элемента одновременно на заданную долю
Требуется разъяснение по выражениям VHDL, включающим std_logic_vector, беззнаковые и литералы, неуверенность в интерпретации компилятора