Dodawanie n-bitowe za pomocą rejestrów n/2-bitowych, ale za pomocą operacji na bitach

0

Ta funkcja dodaje dwie liczby 16-bitowe. Wynik może być niekiedy większy niż 16-bitów i ta funkcja zwraca te wyższe 16-bitów. Ten overflow to jest zawsze 1 albo 0.

uint16_t carry_hi(uint16_t a, uint16_t b)
{
    uint16_t sum = a + b;
    return sum < a;
}

Pytanie, czy warunek sum < a i całą funkcję można jakoś zapisać za pomocą operacji na bitach, coś w rodzaju:


carry_hi = ((a+b) >> 1) & a

Ewentualnie jakieś mnożenie lub modulo, ale to by było już nieco wolniejsze. Kombinuję i nic nie umiem wymyślić.

1

((a+b)>>16) nie wystarczy?

Po doprecyzowaniu z komentarzy:

auto carry = [](uint64_t a, uint64_t b) -> int { return uint64_t{a+b} < a; };

Coś takiego powinno być zadowalające.

2

Co prawda nie tak jak prosiłeś, ale still użyteczna magia. Ma też szanse się lepiej optymalizować przez kompilator (ale polecam samemu sprawdzić co wychodzi lepiej):

uint64_t carry_hi(uint64_t a, uint64_t b) {
    uint64_t dummy;
    return static_cast<uint64_t>(__builtin_add_overflow(a, b, &dummy));
}

edit: https://godbolt.org/z/1s7xcGj53
asembler dokładnie taki sam

0
Tomasz_D napisał(a):

Ta funkcja dodaje dwie liczby 16-bitowe. Wynik może być niekiedy większy niż 16-bitów i ta funkcja zwraca te wyższe 16-bitów. Ten overflow to jest zawsze 1 albo 0.

uint16_t carry_hi(uint16_t a, uint16_t b)
{
    uint16_t sum = a + b;
    return sum < a;
}

Pytanie, czy warunek sum < a i całą funkcję można jakoś zapisać za pomocą operacji na bitach, coś w rodzaju:

carry_hi = ((a+b) >> 1) & a

Ewentualnie jakieś mnożenie lub modulo, ale to by było już nieco wolniejsze. Kombinuję i nic nie umiem wymyślić.

Nie kombinuj. Wzorzec z pierwszej wersji jest powszechnie używany, więc autorzy kompilatora wykrywają ten wzorzec i generują optymalny kod.
Druga wersja może nie zostać rozpoznana przez kompilator i wygenerowany kod może być gorszy - zresztą jak zauważył kq poniżej to jest niepoprawny kod.

1

Ta druga wersja jest zwyczajnie niepoprawna. Chociażby dla par liczb 3 i 0 (1), lub 7 i 8 (7)

1 użytkowników online, w tym zalogowanych: 0, gości: 1