| 1 | #ifndef _UNSIGNED_ARITH
|
|---|
| 2 | #define _UNSIGNED_ARITH
|
|---|
| 3 |
|
|---|
| 4 | $system int $remainder(int x, int y);
|
|---|
| 5 |
|
|---|
| 6 | /* This file defines certain arithmetic functions on unsigned integers
|
|---|
| 7 | * in terms of ordinary integer arithmetic operations.
|
|---|
| 8 | * Each function consumes the integer arguments for the operation, and
|
|---|
| 9 | * an additional parameter named bound. The bound should be one
|
|---|
| 10 | * greater than the maximum unsigned value of the particular type.
|
|---|
| 11 | * Hence these functions can be used for all unsigned integer types
|
|---|
| 12 | * by invoking with the appropriate bound: unsigned char, unsigned
|
|---|
| 13 | * short, unsigned int, unsigned long, unsigned long long.
|
|---|
| 14 | *
|
|---|
| 15 | * There is no need for division or modulus operations, since the
|
|---|
| 16 | * usual integer operations can be used for these. (As they
|
|---|
| 17 | * cannot overflow or underflow.)
|
|---|
| 18 | *
|
|---|
| 19 | * For an expression x, the expression x++ can be translated as
|
|---|
| 20 | * (x<bound-1 ? x++ : ((x=0), bound-1)).
|
|---|
| 21 | *
|
|---|
| 22 | * The expression ++x can be translated as
|
|---|
| 23 | * (x<bound-1 ? ++x : (x=0))
|
|---|
| 24 | * or
|
|---|
| 25 | * (x=(x<bound-1 ? x+1 : 0)).
|
|---|
| 26 | *
|
|---|
| 27 | * x--:
|
|---|
| 28 | * (x<1-bound ? ((x=0), -bound) : x--)
|
|---|
| 29 | *
|
|---|
| 30 | * --x:
|
|---|
| 31 | * (x<1-bound ? (x=0) : --x)
|
|---|
| 32 | */
|
|---|
| 33 |
|
|---|
| 34 | /* Computes sum of two unsigned values.
|
|---|
| 35 | * Preconditions: 0<bound and 0<=x,y<bound.
|
|---|
| 36 | * Postconditions: 0<=result<bound and result=x+y mod bound.
|
|---|
| 37 | */
|
|---|
| 38 | int $unsigned_add(int x, int y, int bound) {
|
|---|
| 39 | if (x+y < bound)
|
|---|
| 40 | return x+y;
|
|---|
| 41 | else
|
|---|
| 42 | return x+y-bound;
|
|---|
| 43 | }
|
|---|
| 44 |
|
|---|
| 45 | /* Computes difference of two unsigned values.
|
|---|
| 46 | * Preconditions: 0<bound and 0<=x,y<bound.
|
|---|
| 47 | * Postconditions: 0<=result<bound and result=x-y mod bound.
|
|---|
| 48 | */
|
|---|
| 49 | int $unsigned_subtract(int x, int y, int bound) {
|
|---|
| 50 | if (x>=y)
|
|---|
| 51 | return x-y;
|
|---|
| 52 | else
|
|---|
| 53 | return x-y+bound;
|
|---|
| 54 | }
|
|---|
| 55 |
|
|---|
| 56 | /* Computes product of two unsigned values.
|
|---|
| 57 | * Preconditions: 0<bound and 0<=x,y<bound.
|
|---|
| 58 | * Postconditions: 0<=result<bound and result=x*y mod bound.
|
|---|
| 59 | */
|
|---|
| 60 | int $unsigned_multiply(int x, int y, int bound) {
|
|---|
| 61 | if (x*y < bound)
|
|---|
| 62 | return x*y;
|
|---|
| 63 | else
|
|---|
| 64 | return $remainder((x*y),bound);
|
|---|
| 65 | }
|
|---|
| 66 |
|
|---|
| 67 | /* Converts a signed integer to an unsigned integer.
|
|---|
| 68 | * According to the C Standard, the result is obtained by repeatedly
|
|---|
| 69 | * adding bound to x until the result is nonnegative.
|
|---|
| 70 | *
|
|---|
| 71 | * Preconditions: 0<bound and 0<=x<bound.
|
|---|
| 72 | * Postconditions: 0<=result<bound and result=x mod bound.
|
|---|
| 73 | */
|
|---|
| 74 | int $signed_to_unsigned(int x, int bound) {
|
|---|
| 75 | if (x >= 0) {
|
|---|
| 76 | if (x < bound)
|
|---|
| 77 | return x;
|
|---|
| 78 | else
|
|---|
| 79 | return $remainder(x,bound);
|
|---|
| 80 | } else {
|
|---|
| 81 | if (-x <= bound)
|
|---|
| 82 | return bound + x;
|
|---|
| 83 | else
|
|---|
| 84 | return bound - $remainder(-x,bound);
|
|---|
| 85 | }
|
|---|
| 86 | }
|
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 | /* Computes -x for an unsigned integer x.
|
|---|
| 90 | * Preconditions: 0<bound and 0<=x<bound
|
|---|
| 91 | * Postconditions: 0<=result<bound and result=-x mod bound.
|
|---|
| 92 | */
|
|---|
| 93 | int $unsigned_neg(int x, int bound) {
|
|---|
| 94 | if (x==0)
|
|---|
| 95 | return 0;
|
|---|
| 96 | else
|
|---|
| 97 | return bound - x;
|
|---|
| 98 | }
|
|---|
| 99 |
|
|---|
| 100 | #endif
|
|---|