[llvm-commits] CVS: llvm-test/SingleSource/UnitTests/Integer/APInt/gptest.cpp

Reid Spencer reid at x10sys.com
Tue Feb 20 12:44:17 PST 2007



Changes in directory llvm-test/SingleSource/UnitTests/Integer/APInt:

gptest.cpp added (r1.1)
---
Log message:

A test program to test APInt against the results produced by pari/gp. If
there's no output other than the bit size banners, everything is fine. If
outputs vary from pari/gp, they are printed. Program requires "gp" to be
in the user's path.


---
Diffs of the changes:  (+380 -0)

 gptest.cpp |  380 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 380 insertions(+)


Index: llvm-test/SingleSource/UnitTests/Integer/APInt/gptest.cpp
diff -c /dev/null llvm-test/SingleSource/UnitTests/Integer/APInt/gptest.cpp:1.1
*** /dev/null	Tue Feb 20 14:44:11 2007
--- llvm-test/SingleSource/UnitTests/Integer/APInt/gptest.cpp	Tue Feb 20 14:44:00 2007
***************
*** 0 ****
--- 1,380 ----
+ //===--- gptest.cpp --- Test Cases for Bit Accurate Types -----------------===//
+ //
+ // This file was developed by Guoling Han and is distributed under the 
+ // University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This is a validating test for arithmetic operations that uses the gp (pari)
+ // calculator to validate APInt's computations.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #include "llvm/ADT/APInt.h"
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+ #include "llvm/System/Signals.h"
+ 
+ using namespace llvm;
+ 
+ APInt x(21, 0x1fffff);
+ APInt y(21, 0x0fffff);
+ 
+ void print(const APInt& X, bool wantSigned = false, bool withNL = true) {
+   std::string decstr = X.toString(10,wantSigned);
+   printf("%s", decstr.c_str());
+   if (withNL)
+     printf("\n");
+ }
+ 
+ APInt randomAPInt(unsigned bits) {
+   APInt val(bits, 0u);
+   for (unsigned i = 0; i < bits; ++i) {
+     unsigned bit = rand() % 2;
+     val = val.shl(1);
+     val |= APInt(bits, bit);
+   }
+   return val;
+ }
+ 
+ void test_interface(const APInt &val) {
+   printf("INTERFACE TEST: val = "); print(val);
+   unsigned bitwidth = val.getBitWidth();
+   unsigned pos = rand() % bitwidth;
+   printf("val[%u] = %d\n", pos, val[pos]);
+   APInt smax(APInt::getMaxValue(bitwidth, true));
+   APInt umax(APInt::getMaxValue(bitwidth, false));
+   APInt smin(APInt::getMinValue(bitwidth, true));
+   APInt umin(APInt::getMinValue(bitwidth, false));
+   printf("APInt::getMinValue(%d, true)  = ", bitwidth); print(smin,true);
+   printf("APInt::getMaxValue(%d, true)  = ", bitwidth); print(smax,true);
+   printf("APInt::getMinValue(%d, false) = ", bitwidth); print(umin);
+   printf("APInt::getMaxValue(%d, false) = ", bitwidth); print(umax);
+   APInt null = APInt::getNullValue(bitwidth);
+   APInt allone = APInt::getAllOnesValue(bitwidth);
+   printf("APInt::getNullValue(%d) = ", bitwidth); print(null);
+   printf("APInt::getAllOnesValue(%d) = ", bitwidth); print(allone);
+   APInt x(val);
+   x.set(pos);
+   printf("val.set(%d) = ", pos);  print(x);
+   x.set();
+   printf("val.set() = "); print(x);
+   x = val;
+   x.clear(pos);
+   printf("val.clear(%d) = ", pos);  print(x);
+   x.clear();
+   printf("val.clear() = "); print(x);
+   x = val;
+   x.flip(pos);
+   printf("val.flip(%d) = ", pos); print(x);
+   x = val;
+   x.flip();
+   printf("val.flip() = "); print(x);
+   unsigned bitsize = bitwidth / 2;
+   printf("val.getHiBits(%d) = ", bitsize); print(val.getHiBits(bitsize));
+   printf("val.getLoBits(%d) = ", bitsize); print(val.getLoBits(bitsize));
+   printf("val.isIntN(%d) = %d\n", bitwidth, val.isIntN(bitwidth));
+ }
+ 
+ void test_unops(const APInt &val) {
+   printf("UNARY OPERATORS TEST: val = "); print(val);
+   APInt x(val);
+   x++;
+   printf("val++ = "); print(x);
+   x = val;
+   ++x;
+   printf("++val = "); print(x);
+   x = val;
+   x--;
+   printf("val-- = "); print(x);
+   x = val;
+   --x;
+   printf("--val = "); print(x);
+   x = -val;
+   printf("-val = "); print(x);
+   x = ~val;
+   printf("~val = "); print(x);
+   printf("!val = %d\n", !val);
+   printf("val.isPowerOf2() = %d\n", val.isPowerOf2());
+   printf("val.logBase2() = %d\n", val.logBase2());
+   printf("val.countLeadingZeros() = %d\n", val.countLeadingZeros());
+   printf("val.countTrailingZeros() = %d\n", val.countTrailingZeros());
+   printf("val.countPopulation() = %d\n", val.countPopulation());
+   printf("val.getBitWidth() = %d\n", val.getBitWidth());
+   if (val.getBitWidth() >= 16 && val.getBitWidth() % 16 == 0) {
+     x = val.byteSwap();
+     printf("val.byteSwap() = "); print(x);
+   }
+   printf("val.roundToDouble(false) = %f\n", val.roundToDouble(false));
+   printf("val.roundToDouble(true)  = %f\n", val.roundToDouble(true));
+   printf("val.getValue() = ");
+   if (val.getBitWidth() > 64)
+     printf("too wide\n");
+   else
+     printf("%lu\n", val.getValue());
+ }
+ 
+ void old_test_binops(const APInt &v1, const APInt &v2) {
+   printf("BINARY OPERATORS TEST: \n      vl: "); print(v1,false,false);
+   printf("\n      v2: "); print(v2);
+   APInt result(v1);
+   result &= v2;
+   printf("v1 &= v2: "); print(result);
+   result = v1;
+   result |= v2;
+   printf("v1 |= v2: "); print(result);
+   result = v1;
+   result ^= v2;
+   printf("v1 ^= v2: "); print(result);
+   result = v1;
+   result *= v2;
+   printf("v1 *= v2: "); print(result);
+   result = v1;
+   result += v2;
+   printf("v1 += v2: "); print(result);
+   result = v1;
+   result -= v2;
+   printf("v1 -= v2: "); print(result);
+   result = v1 & v2;
+   printf("v1 &  v2: "); print(result);
+   result = v1 | v2;
+   printf("v1 |  v2: "); print(result);
+   result = v1 ^ v2;
+   printf("v1 ^  v2: "); print(result);
+   result = v1 * v2;
+   printf("v1 *  v2: "); print(result);
+   result = v1 + v2;
+   printf("v1 +  v2: "); print(result);
+   result = v1 - v2;
+   printf("v1 -  v2: "); print(result);
+   printf("v1 == v2: %d\n", v1 == v2);
+   printf("v1 != v2: %d\n", v1 != v2);
+   printf("v1.eq(v2): %d\n", v1.eq(v2));
+   printf("v1.ne(v2): %d\n", v1.ne(v2));
+   printf("v1.ult(v2): %d\n", v1.ult(v2));
+   printf("v1.slt(v2): %d\n", v1.slt(v2));
+   printf("v1.ule(v2): %d\n", v1.ule(v2));
+   printf("v1.sle(v2): %d\n", v1.sle(v2));
+   printf("v1.ugt(v2): %d\n", v1.ugt(v2));
+   printf("v1.sgt(v2): %d\n", v1.sgt(v2));
+   printf("v1.uge(v2): %d\n", v1.uge(v2));
+   printf("v1.sge(v2): %d\n", v1.sge(v2));
+   {
+     using namespace APIntOps;
+     unsigned shiftAmt = rand() % v1.getBitWidth();
+     result = ashr(v1,shiftAmt);
+     printf("ashr(v1,%d) = ", shiftAmt); print(result);
+     result = lshr(v1,shiftAmt);
+     printf("lshr(v1,%d) = ", shiftAmt); print(result);
+     result = shl(v1,shiftAmt);
+     printf("shl(v1,%d) = ", shiftAmt); print(result);
+     if (v2 == APInt(v2.getBitWidth(), 0))
+       printf("sdiv/udiv/srem/urem not tested, v2 == 0\n");
+     else {
+       result = sdiv(v1,v2);
+       printf("sdiv(v1,v2) = "); print(result);
+       result = udiv(v1,v2);
+       printf("udiv(v1,v2) = "); print(result);
+       result = srem(v1,v2);
+       printf("srem(v1,v2) = "); print(result);
+       result = urem(v1,v2);
+       printf("urem(v1,v2) = "); print(result);
+     }
+   }
+ }
+ 
+ static int input = 0, output = 0;
+ 
+ std::string getBinopCmd(const APInt &v1, std::string op, const APInt &v2, 
+                      bool wantSigned = false) {
+   std::string Result;
+   Result += "truncate(";
+   Result += v1.toString(10,wantSigned);
+   Result += " " + op + " ";
+   Result += v2.toString(10,wantSigned);
+   Result += ")\n";
+   return Result;
+ }
+ 
+ std::string getResult(const std::string& cmd) {
+   const char *command = cmd.c_str();
+   if (-1 == write(output, command, cmd.size())) {
+     std::string msg = "write: " + cmd;
+     perror(msg.c_str());
+     exit(1);
+   }
+   usleep(1000); // try to switch contexts
+   char buf[1024];
+   int len = read(input, buf, 1024);
+   if (-1 == len) {
+     std::string msg = "read: " + cmd;
+     perror(msg.c_str());
+     exit(1);
+   }
+   // We're only interested in the last line.
+   if (char * nl = strrchr(buf, '\n')) {
+     *nl = 0;
+     if (char *nnl = strrchr(nl, '\n'))
+       return std::string(nnl+1);
+   }
+   return std::string(buf);
+ }
+ 
+ void doMultiply(const APInt &v1, const APInt &v2) {
+   std::string cmd = getBinopCmd(v1, "*", v2);
+   std::string result = getResult(cmd);
+   APInt r = v1 * v2;
+   std::string apresult = r.toString(10, false);
+   if (result != apresult) {
+     printf("ERROR: ");
+     print(v1, false, false);
+     printf(" * ");
+     print(v2, false, false);
+     printf(" = %s (not %s)\n", result.c_str(), apresult.c_str());
+   }
+ }
+ 
+ void test_binops(const APInt &v1, const APInt &v2) {
+   doMultiply(v1, v2);
+ }
+ 
+ void Shutdown() {
+   close(input);
+   close(output);
+ }
+ 
+ /* function executed by the user-interacting process. */
+ void test_driver(int input_pipe[], int output_pipe[]) {
+ 
+   int c;    /* user input - must be 'int', to recognize EOF (= -1). */
+   char ch;  /* the same - as a char. */
+   int rc;   /* return values of functions. */
+ 
+   /* first, close unnecessary file descriptors */
+   close(input_pipe[1]); /* we don't need to write to this pipe.  */
+   close(output_pipe[0]); /* we don't need to read from this pipe. */
+ 
+   // Simplify input/output file descriptors
+   input = input_pipe[0];
+   output = output_pipe[1];
+ 
+   // Make sure we close these to give gp an eof and terminate it
+   sys::SetInterruptFunction(Shutdown);
+ 
+   // Initialize random number generator
+   srand(0);
+ 
+   // Start loop over the range of bits of interest
+   for (unsigned bits = 1; bits <= 256; ++bits) {
+     // Indicate which test case we are running
+     printf("\nTEST CASE: %d BITS\n\n", bits);
+     // Gather some test data
+     APInt zero(bits,0);
+     APInt one(bits,1);
+     APInt two(bits,2);
+     APInt three(bits,3);
+     APInt min = APInt::getMinValue(bits, true);
+     APInt max = APInt::getMaxValue(bits, true);
+     APInt mid = APIntOps::lshr(max, bits/2);
+     APInt r1 = randomAPInt(bits);
+     APInt r2 = randomAPInt(bits);
+     APInt *list[9];
+     list[0] = &zero;
+     list[1] = &one;
+     list[2] = &two;
+     list[3] = &three;
+     list[4] = &min;
+     list[5] = &r1;
+     list[6] = ∣
+     list[7] = &r2;
+     list[8] = &max;
+ 
+     // Generate and issue commands to calculator for
+     // all combinations of pairs of values.
+     for (unsigned i = 0; i < 9; ++i) {
+       for (unsigned j = 0; j < 9; ++j) {
+         test_binops(*(list[i]), *(list[j]));
+       }
+     }
+   }
+ 
+   /* close pipes and exit. */
+   Shutdown();
+   exit(0);
+ }
+ 
+ /* now comes the function executed by the translator process. */
+ void calculator(int input_pipe[], int output_pipe[])
+ {
+     int c;    /* user input - must be 'int', to recognize EOF (= -1). */
+     char ch;  /* the same - as a char. */
+     int rc;   /* return values of functions. */
+ 
+     printf("In translator\n");
+ 
+     /* first, close unnecessary file descriptors */
+     close(input_pipe[1]); /* we don't need to write to this pipe.  */
+     close(output_pipe[0]); /* we don't need to read from this pipe. */
+ 
+     /* set up the stdin/stdout */
+     if (-1 == dup2(input_pipe[0], STDIN_FILENO)) {
+       perror("dup2 for stdin");
+       exit(1);
+     }
+     if (-1 == dup2(output_pipe[1], STDOUT_FILENO)) {
+       perror("dup2 for stdout");
+       exit(1);
+     }
+ 
+     // exec gp with modes:
+     //   --quiet (don't print banner), 
+     //   --fast (don't read init files) 
+     //   --test (no history, wrap long lines)
+     execlp("gp", "gp", "--quiet", "--fast", "--test", (char*)NULL);
+     perror("execlp");
+     exit(1);
+ }
+ 
+ /* and finally, the main function: spawn off two processes, */
+ /* and let each of them execute its function.               */
+ int main(int argc, char* argv[])
+ {
+     /* 2 arrays to contain file descriptors, for two pipes. */
+     int user_to_translator[2];
+     int translator_to_user[2];
+     int pid;       /* pid of child process, or 0, as returned via fork.    */
+     int rc;        /* stores return values of various routines.            */
+ 
+     /* first, create one pipe. */
+     rc = pipe(user_to_translator);
+     if (rc == -1) {
+ 	perror("main: pipe user_to_translator");
+ 	exit(1);
+     }
+     /* then, create another pipe. */
+     rc = pipe(translator_to_user);
+     if (rc == -1) {
+ 	perror("main: pipe translator_to_user");
+ 	exit(1);
+     }
+ 
+     /* now fork off a child process, and set their handling routines. */
+     pid = fork();
+ 
+     switch (pid) {
+ 	case -1:	/* fork failed. */
+ 	    perror("main: fork");
+ 	    exit(1);
+ 	case 0:		/* inside child process.  */
+ 	    calculator(user_to_translator, translator_to_user); /* line 'A' */
+ 	    /* NOT REACHED */
+ 	default:	/* inside parent process. */
+ 	    test_driver(translator_to_user, user_to_translator); /* line 'B' */
+ 	    /* NOT REACHED */
+     }
+ 
+     return 0;	/* NOT REACHED */
+ }
+ 






More information about the llvm-commits mailing list