- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
void add_SSE(uint8_t a[static 7], uint8_t b[static 7], uint8_t out[static 7])
{
uint64_t a_64 = 0;
uint64_t b_64 = 0;
for (size_t i = 0; i < 7; i++) // можно наанроллить
{
a_64 |= (uint64_t)a[i] << (i*9);
b_64 |= (uint64_t)b[i] << (i*9);
}
uint64_t c_64 = a_64 + b_64;
for (size_t i = 0; i < 7; i++) // можно наанроллить
{
out[i] = (uint64_t)c_64 >> (i*9);
}
}
https://wandbox.org/permlink/y5oFcXGjMxDTh5KW
1. Упаковка для побитовых операций.
2. Упаковка для сложения: каждое число будет расширено на один бит.
Последний вариант ещё может быть знаковым и беззнаковым.
А ещё можно упаковать для умножения на скаляр, тогда каждое число будет расширено в два раза.
P.S. Тут чувак накостылил __int128 через перегрузку операторов:
https://stackoverflow.com/a/37907522
Лучше б сделали тупо произвольно-длинную арифметику, потом бы запилили специализацию под конечный размер. И тогда для произвольно-длинной арифметики можно было б сделать всякие умные оптимизации, типа
Только вот это нихера не выйдет с говном, которое есть в крестопомойной параше (разве что компилятор допилить специально под эту дрисню). Шаблонами нельзя определять всякие свойства коммутативности, ассоциативности и стратегии оптимизации.
>> В частности, комиссия всё-таки попросила в wide_int оперировать количеством машинных слов.
Вот уроды. Они хотят, чтобы при перекококомпиляции на другой платформе программа оперировала числами другого размера? Т. е. опять придётся потеть с мокросами и ифдефами?
Из 64-битного MSVC убрали встроенный асм, так что приходится использовать интринсики. Интринсики –— хорошая штука, так как на первый взгляд позволяют писа́ть код, не привязанный к кокококонкретному процессору. Однако, они оказались привязанными к кокококомпилятору:
Причём даже семантика не совпадает:
Полная жопа, короче.
Оператор in выполняется через инструкции BT и SETC. Вот с добавлением элемента хуже (оптимизатор не хочет выкидывать call fpc_varset_add_sets; видимо, задел для больших множеств) и цикл не хочет выкидывать, хотя задача должна решаться одной итерацией. Оптимизатор –— питух.
«GPC» (ныне заброшен) использует вызов библиотечной функции (call __p_set_in).
«TMT Pascal» (похоже, что тоже заброшен) тоже всё делает через вызов библиотечных функций и инлайнить не хочет.
«WDSibyl» мне не удалось даже запустить.
Компиляторы, основанные не на «Object Pascal», а на «Standard Pascal» или «Extended Pascal», я не тестировал.
Итого: ныне развивающиеся компиляторы в нативный код («Delphi» и «FPC») при работе со множествами из специнструкций используют только BT.
Фигню написал. Надо просто tempset := tempset + [n]. Сдвиг не нужен.
Всё равно использует только BT, а установку/сброс делает через сдвиг + OR/XOR.
Хотя тут теперь два сложения на 8 элементов (против одного сложения на 7 элементов), думаю что на сдвигах проебется больше времени.