// Timing comparisons for various unsigned integer ops. // Compile with three defines. // Saturation: // -DNOSAT simple operation // -DDOUBLESAT convert to double for operation // -DSAT check if the result will be/has been saturated // Type: // -DCHAR 8 bit // -DSHORT 16 bit // -DLONG 32 bit // -DLONGLONG 64 bit // Operation: // -DMULT multiply // -DADD add/subtract // // Run the loop n times using // time ./a.out n // If n is zero, it does not run the loop but instead simply prints the // condition that will be tested to detect saturation. #include #if defined(CHAR) typedef unsigned char uinttype; typedef unsigned short int nexttype; #define MX 0xFFU #define LO 0x0FU #define HI 0xF0U #define HALF 4 #elif defined(SHORT) typedef unsigned short int uinttype; typedef unsigned long int nexttype; #define MX 0xFFFFU #define LO 0x00FFU #define HI 0xFF00U #define HALF 8 #elif defined(LONG) typedef unsigned long uinttype; typedef unsigned long long nexttype; #define MX 0xFFFFFFFFUL #define LO 0x0000FFFFUL #define HI 0xFFFF0000UL #define HALF 16 #elif defined(LONGLONG) typedef unsigned long long uinttype; #define MX 0xFFFFFFFFFFFFFFFFULL #define LO 0x00000000FFFFFFFFULL #define HI 0xFFFFFFFF00000000ULL #define MASK 0xFFFFFFFFULL #define HALF 32 #else #error Use -DUSE_XXX where XXX is CHAR SHORT LONG or LONGLONG #endif void check(void) { uinttype z; uinttype x = MX; uinttype y = MX/2; #if defined(ADD) z = x+y; printf("%llu < %llu ?\n",(unsigned long long)z,(unsigned long long)x); z = y-x; printf("%llu > %llu ?\n",(unsigned long long)z,(unsigned long long)y); #elif defined(LONGLONG) if ((x > LO && (y > LO || (x>>HALF)*y > LO)) || (y>LO && (y>>HALF)*x > LO)) printf("multiply overflow correctly detected.\n"); #else nexttype p = (nexttype)x * (nexttype)y; printf("%llu > %llu ?\n",(unsigned long long)p,(unsigned long long)MX); #endif } uinttype loop(int n) { int i; uinttype total = 0; while (n--) for (i=0; i < 10000000; i++) { uinttype x = i, y=i<<(HALF-1), z; #ifdef ADD # if defined(NOSAT) z = x + y; # elif defined(DOUBLESAT) double res = (double)x + (double)y; z = (res > MX ? MX : (res < 0 ? 0 : res) ); # else z = x + y; if (z < x) z = MX; # endif #else # if defined(NOSAT) z = x*y; # elif defined(DOUBLESAT) double res = (double)x * (double)y; z = (res > MX ? MX : (res < 0 ? 0 : res) ); # elif defined(LONGLONG) if ((x > LO && (y > LO || (x>>HALF)*y > LO)) || (y>LO && (y>>HALF)*x > LO)) z = MX; else z = x * y; # else nexttype p = (nexttype)x * (nexttype)y; z = (uinttype)(p>MX ? MX : p); # endif #endif total += z; } return total; } int main(int argc, char *argv[]) { int n; if (argc > 1) n = atoi(argv[1]); else n=10; if (n) loop(n); else check(); }