How to do unsigned saturating addition in C?

前端 未结 17 1865
孤独总比滥情好
孤独总比滥情好 2020-11-27 02:31

What is the best (cleanest, most efficient) way to write saturating addition in C?

The function or macro should add two unsigned inputs (need both 16- and 32-bit ver

17条回答
  •  谎友^
    谎友^ (楼主)
    2020-11-27 03:16

    You probably want portable C code here, which your compiler will turn into proper ARM assembly. ARM has conditional moves, and these can be conditional on overflow. The algorithm then becomes: add and conditionally set the destination to unsigned(-1), if overflow was detected.

    uint16_t add16(uint16_t a, uint16_t b)
    {
      uint16_t c = a + b;
      if (c < a)  /* Can only happen due to overflow */
        c = -1;
      return c;
    }
    

    Note that this differs from the other algorithms in that it corrects overflow, instead of relying on another calculation to detect overflow.

    x86-64 clang 3.7 -O3 output for adds32: significantly better than any other answer:

    add     edi, esi
    mov     eax, -1
    cmovae  eax, edi
    ret
    

    ARMv7: gcc 4.8 -O3 -mcpu=cortex-a15 -fverbose-asm output for adds32:

    adds    r0, r0, r1      @ c, a, b
    it      cs
    movcs   r0, #-1         @ conditional-move
    bx      lr
    

    16bit: still doesn't use ARM's unsigned-saturating add instruction (UADD16)

    add     r1, r1, r0        @ tmp114, a
    movw    r3, #65535      @ tmp116,
    uxth    r1, r1  @ c, tmp114
    cmp     r0, r1    @ a, c
    ite     ls        @
    movls   r0, r1        @,, c
    movhi   r0, r3        @,, tmp116
    bx      lr  @
    

提交回复
热议问题