2013-07-30 19 views
8

Znalazłem lewę z AGGREGATE Magic dla szybkiego obliczania wartości maksymalnych. Jedyny problem, który dotyczy liczb całkowitych, i jakkolwiek próbowałem pewnych rzeczy, nie mam pojęcia, jak utworzyć wersję dla liczb całkowitych bez znaku.Szybkie max bez branchless dla liczb całkowitych bez znaku

inline int32_t max(int32_t a, int32_t b) 
{ 
    return a - ((a-b) & (a-b)>>31); 
} 

Jakaś radę?

EDIT

nie korzystać z tego, bo jak inni stwierdził produkuje niezdefiniowanej zachowanie. W przypadku dowolnej nowoczesnej architektury kompilator będzie w stanie emitować warunkową instrukcję ruchu bez rozgałęzienia z return (a > b) ? a : b, która będzie szybsza niż dana funkcja.

+24

Czekaj, jesteś naprawdę pewien, że to szybciej niż 'powrócić a> b ? a: b'? –

+10

Ta funkcja jest praktycznie bezużyteczna. Użyj 'std :: max'. –

+2

Tak, na nowoczesnych procesorach z potokiem, gałęzie są wolne. Zmierzyłem, ta wersja jest tak szybka jak wersja SSE, jeśli nie szybsza. – plasmacel

Odpowiedz

9

Co robi ten kod? Przyjmuje wartość a i różnicę a - b. Oczywiście, a - (a - b) jest b. I (a - b) >> 31 po prostu tworzy maskę z nich iff a - b jest ujemna.

Ten kod jest niepoprawny, iff posiada nadmiar w odejmowaniu. Jest to jednak ta sama historia, co w przypadku liczb całkowitych bez znaku. Więc IFF jesteś zadowolony z faktu, że kod nie jest prawidłowy dla całego zakresu wartości, można po prostu zignorować unsignedness i użyć tego:

inline uint32_t umax(uint32_t a, uint32_t b) { 
    return (uint32_t)max((int32_t)a, (int32_t)b); 
} 
Powiązane problemy